Replace lerna with turborepo (#2073)

This change allows our ui libraries to be built separately. It is therefore to utilize different build tools for individual projects, as well as using build caches for the local build.

Co-authored-by: Sebastian Sdorra <sebastian.sdorra@cloudogu.com>
Co-authored-by: Matthias Thieroff <matthias.thieroff@cloudogu.com>
This commit is contained in:
Konstantin Schaper
2022-06-22 11:49:26 +02:00
committed by GitHub
parent 77ab43c93b
commit 84f220e5b2
43 changed files with 1216 additions and 2969 deletions

2
.gitignore vendored
View File

@@ -38,3 +38,5 @@ rebel.xml
**/build
.npm
.cache
.turbo

4
Jenkinsfile vendored
View File

@@ -31,7 +31,7 @@ pipeline {
steps {
// read version from branch, set it and commit it
gradle "setVersion -PnewVersion=${releaseVersion}"
sh "git add gradle.properties lerna.json '**.json'"
sh "git add gradle.properties '**.json'"
commit "Release version ${releaseVersion}"
// fetch all remotes from origin
@@ -183,7 +183,7 @@ pipeline {
gradle "setVersionToNextSnapshot"
sh "git add gradle.properties lerna.json '**.json'"
sh "git add gradle.properties '**.json'"
commit 'Prepare for next development iteration'
authGit 'cesmarvin-github', 'push origin develop'
}

View File

@@ -37,10 +37,17 @@ class RunPlugin implements Plugin<Project> {
project.plugins.apply("com.github.node-gradle.node")
def nodeExt = NodeExtension.get(project)
nodeExt.setDownload(true)
nodeExt.setVersion('16.13.0')
nodeExt.setYarnVersion('1.22.15')
nodeExt.setVersion('16.14.2')
nodeExt.setYarnVersion('1.22.18')
nodeExt.setNodeModulesDir( project.rootProject.projectDir )
project.tasks.getByName('yarn_install').configure {
inputs.file( project.rootProject.file('yarn.lock') )
outputs.dir( project.rootProject.file('node_modules') )
description = "Install ui dependencies"
}
project.tasks.register('write-server-config', WriteServerConfigTask) {
it.extension = extension
dependsOn 'dev-war'

View File

@@ -62,7 +62,7 @@ class RunTask extends DefaultTask {
@TaskAction
void exec() {
List<Closure<Void>> actions = new ArrayList<>();
List<Closure<Void>> actions = new ArrayList<>()
actions.add(createBackend())
if (frontend) {
actions.add(createFrontend())
@@ -79,8 +79,8 @@ class RunTask extends DefaultTask {
int retries = 180
for (int i = 0; i < retries; i++) {
try {
URL urlConnect = new URL("http://localhost:${extension.port}/scm/api/v2");
URLConnection conn = (HttpURLConnection) urlConnect.openConnection();
URL urlConnect = new URL("http://localhost:${extension.port}/scm/api/v2")
URLConnection conn = (HttpURLConnection) urlConnect.openConnection()
if (conn.getResponseCode() == 200) {
return
}
@@ -140,8 +140,8 @@ class RunTask extends DefaultTask {
private Closure<Void> createFrontend() {
def frontend = project.tasks.create('boot-frontend', NodeTask) {
script = new File(project.rootProject.projectDir, 'scm-ui/ui-scripts/bin/ui-scripts.js')
args = ['serve']
script = new File(project.rootProject.projectDir, 'scm-ui/ui-scripts/bin/turbo-runner.js')
args = ['run', 'serve', '--filter=@scm-manager/ui-webapp']
environment = [
'NODE_ENV': 'development',
'ANALYZE_BUNDLES': analyzeBundles

View File

@@ -23,8 +23,8 @@ ext {
jerseyClientVersion = '1.19.4'
micrometerVersion = '1.6.4'
nodeVersion = '16.13.0'
yarnVersion = '1.22.15'
nodeVersion = '16.14.2'
yarnVersion = '1.22.18'
libraries = [
// lombok

View File

@@ -1,9 +0,0 @@
{
"packages": [
"scm-ui/*",
"scm-plugins/*"
],
"npmClient": "yarn",
"useWorkspaces": true,
"version": "2.36.2-SNAPSHOT"
}

View File

@@ -6,26 +6,27 @@
"scm-plugins/*"
],
"scripts": {
"build": "webpack-cli --mode=production --config=scm-ui/ui-scripts/src/webpack.config.js",
"build:dev": "webpack-cli --mode=development --config=scm-ui/ui-scripts/src/webpack.config.js",
"test": "lerna run --scope '@scm-manager/ui-*' test --no-bail",
"e2e-tests": "lerna run --scope '@scm-manager/e2e-tests' ci",
"typecheck": "lerna run --scope '@scm-manager/ui-*' typecheck",
"lint": "lerna run --scope '@scm-manager/ui-*' lint",
"serve": "ui-scripts serve development",
"build": "turbo run build --filter=\"@scm-manager/ui-webapp\"",
"build:dev": "cross-env NODE_ENV=development turbo run build --filter=\"@scm-manager/ui-webapp\"",
"test": "turbo run test --continue --filter=\"@scm-manager/ui-*\"",
"e2e-tests": "turbo run ci --filter=\"@scm-manager/e2e-tests\"",
"typecheck": "turbo run typecheck --filter=\"@scm-manager/ui-*\"",
"lint": "turbo run lint --filter=\"@scm-manager/ui-*\"",
"predeploy": "turbo run build --filter=\"@scm-manager/ui-*\"",
"deploy": "ui-scripts publish",
"set-version": "ui-scripts version"
},
"dependencies": {
"@scm-manager/eslint-config": "2.15.0"
"@scm-manager/eslint-config": "^2.15.1"
},
"devDependencies": {
"@scm-manager/remark-preset-lint": "^1.0.0",
"babel-plugin-reflow": "^0.2.7",
"husky": "^4.2.5",
"lerna": "^3.17.0",
"lint-staged": "^10.2.11",
"remark-cli": "^9.0.0"
"remark-cli": "^9.0.0",
"turbo": "^1.2.5",
"cross-env": "^7.0.3"
},
"resolutions": {
"babel-core": "7.0.0-bridge.0",

View File

@@ -93,6 +93,11 @@ node {
nodeModulesDir = file(project.rootProject.projectDir)
}
tasks.getByName('yarn_install').configure {
inputs.file( project.rootProject.file('yarn.lock') )
outputs.dir( project.rootProject.file('node_modules') )
}
task e2eTests(type: YarnTask) {
inputs.files(fileTree(project.project(":scm-ui").projectDir) {
include 'e2e-*/**'

View File

@@ -177,22 +177,17 @@ artifacts {
// In order to publish the packages to npm we have to do some tricks
// 1. If we deploy a snapshot version, we replace the snapshot version in the package.json files with a unique version.
// This causes lerna to fail, because it does a dirty working copy check before publish.
// To trick lerna we move the git folder to .git-disabled before publishing and restore it afterwards.
// 2. Authentication with yarn/npm requires a .npmrc file which contains the token and a .yarnrc file which contains
// the registry url and some settings. Those files are normally stored in the home directory of the user, but
// fortunately they could be stored in the current working directory as well. So we create an .npmrc file from a
// a project property "npmToken" and a .yarnrc in the root directory of the project. Both files are removed after
// publishing.
File dotGit = new File(project.rootDir, ".git")
File dotGitDisabled = new File(project.rootDir, ".git-disabled")
File npmrc = new File(project.rootDir, ".npmrc")
File yarnrc = new File(project.rootDir, ".yarnrc")
task publish(type: YarnTask) {
doFirst {
dotGit.renameTo(dotGitDisabled)
if (project.hasProperty("npmToken")) {
npmrc.createNewFile()
npmrc.append "//registry.npmjs.org/:_authToken=${project.property('npmToken')}\n"
@@ -211,7 +206,6 @@ task publish(type: YarnTask) {
task cleanUpAfterPublishing {
doLast {
dotGitDisabled.renameTo(dotGit)
if (npmrc.exists()) {
npmrc.delete()
}

View File

@@ -2,17 +2,20 @@
"name": "@scm-manager/ui-api",
"version": "2.36.2-SNAPSHOT",
"description": "React hook api for the SCM-Manager backend",
"main": "src/index.ts",
"main": "build/index.js",
"module": "build/index.mjs",
"types": "build/index.d.ts",
"files": [
"dist",
"src"
"build"
],
"repository": "https://github.com/scm-manager/scm-manager",
"author": "SCM Team <scm-team@cloudogu.com>",
"license": "MIT",
"scripts": {
"test": "jest src/",
"typecheck": "tsc"
"build": "tsup ./src/index.ts -d build --format esm,cjs --dts",
"typecheck": "tsc",
"lint": "eslint src",
"test": "jest src/"
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
@@ -22,7 +25,8 @@
"@scm-manager/tsconfig": "^2.13.0",
"@testing-library/react-hooks": "^5.0.3",
"@types/react": "^17.0.1",
"react-test-renderer": "^17.0.1"
"react-test-renderer": "^17.0.1",
"tsup": "^5.12.6"
},
"dependencies": {
"@scm-manager/ui-types": "^2.36.2-SNAPSHOT",
@@ -30,7 +34,8 @@
"gitdiff-parser": "^0.2.2",
"query-string": "6.14.1",
"react": "^17.0.1",
"react-query": "^3.25.1"
"react-query": "^3.25.1",
"react-router-dom": "^5.3.1"
},
"babel": {
"presets": [

View File

@@ -227,7 +227,7 @@ describe("Test base api hooks", () => {
_links: {}
});
const { result } = renderHook(() => useIndexJsonResource<{}>("spaceships"), {
const { result } = renderHook(() => useIndexJsonResource<Record<string, unknown>>("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
});

View File

@@ -74,6 +74,8 @@ export const useConfigLink = <C extends HalRepresentation>(link: string) => {
});
}
},
// eslint means we should add C to the dependency array, but C is only a type
// eslint-disable-next-line react-hooks/exhaustive-deps
[mutate, data, isReadOnly]
);

View File

@@ -24,14 +24,8 @@
import { apiClient } from "./apiclient";
import { useQuery } from "react-query";
import { ApiResultWithFetching } from "./base";
export type ContentType = {
type: string;
language?: string;
aceMode?: string;
codemirrorMode?: string;
prismMode?: string;
};
import type { ContentType } from "@scm-manager/ui-types";
export type { ContentType } from "@scm-manager/ui-types";
function getContentType(url: string): Promise<ContentType> {
return apiClient.head(url).then((response) => {

View File

@@ -0,0 +1,31 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import modalEn from "./modal.en";
import modalDe from "./modal.de";
export default {
de: modalDe,
en: modalEn,
} as const;

View File

@@ -0,0 +1,31 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import syntaxEn from "./syntax.en";
import syntaxDe from "./syntax.de";
export default {
de: syntaxDe,
en: syntaxEn,
} as const;

View File

@@ -83,9 +83,6 @@ export const useLogin = () => {
);
const login = (username: string, password: string) => {
// grant_type is specified by the oauth standard with the underscore
// so we stick with it, even if eslint does not like it.
// eslint-disable-next-line @typescript-eslint/camelcase
mutate({ cookie: true, grant_type: "password", username, password });
};

View File

@@ -28,6 +28,8 @@ import { apiClient } from "./apiclient";
import { createQueryString } from "./utils";
import { useQueries, useQuery } from "react-query";
import { useEffect, useState } from "react";
import SYNTAX from "./help/search/syntax";
import MODAL from "./help/search/modal";
export type SearchOptions = {
type: string;
@@ -118,36 +120,45 @@ export const useSearch = (query: string, optionParam = defaultSearchOptions): Ap
);
};
const useObserveAsync = <D extends any[], R, E = Error>(fn: (...args: D) => Promise<R>, deps: D) => {
const useObserveAsync = <D extends unknown[], R, E = Error>(fn: (...args: D) => Promise<R>, deps: D) => {
const [data, setData] = useState<R>();
const [isLoading, setLoading] = useState(false);
const [error, setError] = useState<E>();
useEffect(() => {
setLoading(true);
fn(...deps)
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, deps);
useEffect(
() => {
setLoading(true);
fn(...deps)
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
},
// eslint-disable-next-line react-hooks/exhaustive-deps
deps
);
return { data, isLoading, error };
};
const supportedLanguages = ["de", "en"];
const getTypedKeys = <K extends string>(input: { readonly [_ in K]: unknown }) => Object.keys(input) as K[];
const pickLang = (language: string) => {
if (!supportedLanguages.includes(language)) {
return "en";
}
return language;
};
const isSupportedLanguage = <T>(input: unknown, supportedLanguages: T[]): input is T =>
supportedLanguages.includes(input as T);
const pickLang = <T>(language: unknown, supportedLanguages: T[], fallback: T): T =>
isSupportedLanguage(language, supportedLanguages) ? language : fallback;
const SUPPORTED_MODAL_LANGUAGES = getTypedKeys(MODAL);
const SUPPORTED_SYNTAX_LANGUAGES = getTypedKeys(SYNTAX);
const FALLBACK_LANGUAGE = "en";
export const useSearchHelpContent = (language: string) =>
useObserveAsync(
(lang) => import(`./help/search/modal.${pickLang(lang)}`).then((module) => module.default),
(lang) => Promise.resolve(MODAL[pickLang(lang, SUPPORTED_MODAL_LANGUAGES, FALLBACK_LANGUAGE)]),
[language]
);
export const useSearchSyntaxContent = (language: string) =>
useObserveAsync(
(lang) => import(`./help/search/syntax.${pickLang(lang)}`).then((module) => module.default),
(lang) => Promise.resolve(SYNTAX[pickLang(lang, SUPPORTED_SYNTAX_LANGUAGES, FALLBACK_LANGUAGE)]),
[language]
);

View File

@@ -73,7 +73,7 @@ export const useSources = (repository: Repository, opts: UseSourcesOptions = Use
}
}, options.refetchPartialInterval);
return () => clearInterval(intervalId);
}, [options.refetchPartialInterval, file]);
}, [options.refetchPartialInterval, file, refetch]);
return {
isLoading,

View File

@@ -1,6 +1,6 @@
{
"extends": "@scm-manager/tsconfig",
"exclude": [
"./scripts"
"include": [
"./src"
]
}

View File

@@ -78,6 +78,10 @@ module.exports = {
// force node version of "decode-named-character-reference" instead of browser version which does not work in web worker
config.resolve.alias["decode-named-character-reference"] = require.resolve("decode-named-character-reference");
// force cjs instead of esm
// https://github.com/tannerlinsley/react-query/issues/3513
config.resolve.alias["react-query/devtools"] = require.resolve("react-query/devtools");
return config;
},
};

View File

@@ -1,12 +1,19 @@
{
"name": "@scm-manager/ui-extensions",
"version": "2.36.2-SNAPSHOT",
"main": "src/index.ts",
"license": "MIT",
"private": false,
"author": "Sebastian Sdorra <sebastian.sdorra@cloudogu.com>",
"main": "build/index.js",
"module": "build/index.mjs",
"types": "build/index.d.ts",
"files": [
"build"
],
"scripts": {
"build": "tsup ./src/index.ts -d build --format esm,cjs --dts",
"typecheck": "tsc",
"lint": "eslint src",
"test": "jest"
},
"dependencies": {
@@ -21,7 +28,8 @@
"@scm-manager/tsconfig": "^2.13.0",
"@types/enzyme": "^3.10.3",
"@types/jest": "^24.0.19",
"@types/react": "^17.0.1"
"@types/react": "^17.0.1",
"tsup": "^5.12.6"
},
"babel": {
"presets": [

View File

@@ -136,7 +136,7 @@ export default function ExtensionPoint<
E extends RenderableExtensionPointDefinition<string, any> = RenderableExtensionPointDefinition<string, any>
>({ name, propTransformer, props, renderAll, wrapper, children }: PropsWithChildren<Props<E>>): JSX.Element | null {
const binder = useBinder();
const renderProps: E["props"] | {} = createRenderProps(propTransformer, {
const renderProps: E["props"] | Record<string, unknown> = createRenderProps(propTransformer, {
...(props || {}),
children,
});

View File

@@ -44,11 +44,11 @@ import {
RepositoryTypeCollection,
Tag,
User,
ContentType
} from "@scm-manager/ui-types";
import { ExtensionPointDefinition } from "./binder";
import { RenderableExtensionPointDefinition, SimpleRenderableDynamicExtensionPointDefinition } from "./ExtensionPoint";
import ExtractProps from "./extractProps";
import { ContentType } from "@scm-manager/ui-api";
type RepositoryCreatorSubFormProps = {
repository: RepositoryCreation;

View File

@@ -24,7 +24,7 @@
import useBinder, { BinderContext } from "./useBinder";
import { Binder } from "./binder";
import { mount } from "enzyme";
import "@scm-manager/ui-tests/enzyme";
import "@scm-manager/ui-tests";
import React from "react";
describe("useBinder tests", () => {

View File

@@ -1,3 +1,6 @@
{
"extends": "@scm-manager/tsconfig"
"extends": "@scm-manager/tsconfig",
"include": [
"./src"
]
}

View File

@@ -2,10 +2,14 @@
"name": "@scm-manager/ui-legacy",
"version": "2.36.2-SNAPSHOT",
"private": true,
"main": "src/index.ts",
"main": "build/index.js",
"module": "build/index.mjs",
"types": "build/index.d.ts",
"scripts": {
"test": "jest --passWithNoTests",
"lint": "eslint src"
"build": "tsup ./src/index.ts -d build --format esm,cjs --dts",
"typecheck": "tsc",
"lint": "eslint src",
"test": "jest --passWithNoTests"
},
"dependencies": {
"@scm-manager/ui-api": "^2.36.2-SNAPSHOT",
@@ -21,7 +25,8 @@
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@types/react": "^17.0.1",
"@types/react-redux": "5.0.7"
"@types/react-redux": "5.0.7",
"tsup": "^5.12.6"
},
"babel": {
"presets": [

View File

@@ -1,3 +1,6 @@
{
"extends": "@scm-manager/tsconfig"
"extends": "@scm-manager/tsconfig",
"include": [
"./src"
]
}

View File

@@ -2,16 +2,24 @@
"name": "@scm-manager/ui-modules",
"version": "2.36.2-SNAPSHOT",
"private": true,
"main": "src/index.ts",
"main": "build/index.js",
"module": "build/index.mjs",
"types": "build/index.d.ts",
"files": [
"build"
],
"scripts": {
"test": "jest --passWithNoTests",
"lint": "eslint src"
"build": "tsup ./src/index.ts -d build --format esm,cjs --dts",
"typecheck": "tsc",
"lint": "eslint src",
"test": "jest --passWithNoTests"
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.15.1",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1"
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/eslint-config": "^2.15.1",
"tsup": "^5.12.6"
},
"babel": {
"presets": [

View File

@@ -1,3 +1,6 @@
{
"extends": "@scm-manager/tsconfig"
"extends": "@scm-manager/tsconfig",
"include": [
"./src"
]
}

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env node
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// eslint-disable-next-line import/no-extraneous-dependencies
const { generateBinPath } = require("turbo/node-platform");
const { spawn } = require("child_process");
const turbo = spawn(generateBinPath(), process.argv.slice(2), { stdio: "inherit" });
turbo.on("close", (code) => {
process.exit(code);
});
process.once("SIGTERM", () => {
turbo.kill();
});
if (process.ppid) {
const { ppid } = process;
setInterval(() => {
if (ppid !== process.ppid) {
turbo.kill();
}
}, 500);
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
const lerna = require("../lerna");
const yarn = require("../yarn");
const versions = require("../versions");
module.exports = args => {
@@ -35,11 +35,11 @@ module.exports = args => {
if (index > 0) {
const snapshotVersion = `${version.substring(0, index)}-${versions.createSnapshotVersion()}`;
console.log(`publish snapshot release ${snapshotVersion}`);
lerna.version(snapshotVersion);
lerna.publish();
lerna.version(version);
yarn.workspaceVersion(snapshotVersion);
yarn.workspacePublish(snapshotVersion);
yarn.workspaceVersion(version);
} else {
// ?? not sure
lerna.publish();
yarn.workspacePublish();
}
};

View File

@@ -21,7 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
const lerna = require("../lerna");
const yarn = require("../yarn");
module.exports = args => {
if (args.length < 1) {
@@ -30,6 +31,5 @@ module.exports = args => {
}
const version = args[0];
lerna.version(version);
yarn.workspaceVersion(version);
};

View File

@@ -30,7 +30,7 @@ const createIndexMiddleware = require("./middleware/IndexMiddleware");
const createContextPathMiddleware = require("./middleware/ContextPathMiddleware");
const isDevelopment = process.env.NODE_ENV === "development";
const root = path.resolve(process.cwd(), "scm-ui");
const root = path.resolve(process.cwd(), "..");
const babelPlugins = [];
const webpackPlugins = [];
@@ -88,7 +88,7 @@ module.exports = [
module: {
rules: [
{
test: /\.(js|ts|jsx|tsx)$/i,
test: /\.(mjs|js|ts|jsx|tsx)$/i,
exclude: /node_modules/,
use: [
{
@@ -127,7 +127,7 @@ module.exports = [
],
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx", ".css", ".scss", ".json"],
extensions: [".ts", ".tsx", ".mjs", ".js", ".jsx", ".css", ".scss", ".json"],
fallback: {
fs: false,
net: false,
@@ -135,6 +135,9 @@ module.exports = [
},
alias: {
"decode-named-character-reference": require.resolve("decode-named-character-reference"),
// force cjs instead of esm
// https://github.com/tannerlinsley/react-query/issues/3513
"react-query/devtools": require.resolve("react-query/devtools"),
},
},
output: {

View File

@@ -23,11 +23,13 @@
*/
const { spawnSync } = require("child_process");
const os = require("os");
const path = require("path");
const fs = require("fs");
const yarnCmd = os.platform() === "win32" ? "yarn.cmd" : "yarn";
const yarn = args => {
const result = spawnSync(yarnCmd, args, { stdio: "inherit" });
const yarn = (args, cwd) => {
const result = spawnSync(yarnCmd, args, { stdio: "inherit", cwd });
if (result.error) {
console.log("could not start yarn command:", result.error);
process.exit(2);
@@ -45,8 +47,63 @@ const publish = v => {
yarn(["publish", "--new-version", v]);
};
const findWorkspaces = () => {
const result = spawnSync(yarnCmd, ["workspaces", "info"]);
return JSON.parse(result.stdout);
};
const updateDependencies = (workspaces, dependencies, v) => {
if (dependencies) {
Object.keys(dependencies).forEach(dep => {
if (workspaces[dep]) {
dependencies[dep] = v;
}
});
}
};
const workspaceVersion = v => {
const workspaces = findWorkspaces();
Object.keys(workspaces).forEach(name => {
const workspace = workspaces[name];
const packageJsonPath = path.join(process.cwd(), workspace.location, "package.json");
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, { encoding: "utf8" }));
packageJson.version = v;
updateDependencies(workspaces, packageJson.dependencies, v);
updateDependencies(workspaces, packageJson.devDependencies, v);
updateDependencies(workspaces, packageJson.peerDependencies, v);
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), { encoding: "utf8" });
});
};
const forEachModule = fn => {
const workspaces = findWorkspaces();
Object.keys(workspaces).forEach(name => {
const workspace = workspaces[name];
const cwd = path.join(process.cwd(), workspace.location);
const packageJson = JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), { encoding: "utf8" }));
fn(packageJson, cwd)
});
};
const workspacePublish = v => {
forEachModule((module, cwd) => {
if (!module.private) {
console.log(`publish module ${module.name}`)
yarn(["publish", "--new-version", v], cwd)
} else {
console.log(`skip private module ${module.name}`)
}
});
};
module.exports = {
version,
publish,
yarn
yarn,
workspaceVersion,
workspacePublish
};

View File

@@ -6,7 +6,8 @@
"scripts": {
"test": "jest --passWithNoTests",
"lint": "eslint src",
"storybook": "start-storybook -p 6006",
"typecheck": "tsc",
"storybook": "start-storybook",
"build-storybook": "build-storybook",
"write-mapping": "node scripts/write-mapping.mjs"
},

View File

@@ -1,4 +1,9 @@
{
"extends": "@scm-manager/tsconfig",
"exclude": ["./scripts"]
"include": [
"./src"
],
"exclude": [
"./scripts"
]
}

View File

@@ -2,10 +2,17 @@
"name": "@scm-manager/ui-text",
"version": "2.36.2-SNAPSHOT",
"private": true,
"main": "src/index.ts",
"main": "build/index.js",
"module": "build/index.mjs",
"types": "build/index.d.ts",
"files": [
"build"
],
"scripts": {
"build": "tsup ./src/index.ts -d build --format esm,cjs --dts",
"test": "jest",
"lint": "eslint src",
"typecheck": "tsc",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
@@ -24,7 +31,8 @@
"@storybook/react": "^6.4.20",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"webpack": "^5.71.0"
"webpack": "^5.71.0",
"tsup": "^5.12.6"
},
"babel": {
"presets": [

View File

@@ -1,3 +1,6 @@
{
"extends": "@scm-manager/tsconfig"
"extends": "@scm-manager/tsconfig",
"include": [
"./src"
]
}

View File

@@ -21,17 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
const { yarn } = require("./yarn");
const version = v => {
yarn(["run", "lerna", "--no-git-tag-version", "--no-push", "version", "--force-publish", "--yes", v]);
};
const publish = () => {
yarn(["run", "lerna", "publish", "from-package", "--yes"]);
};
module.exports = {
version,
publish
export type ContentType = {
type: string;
language?: string;
aceMode?: string;
codemirrorMode?: string;
prismMode?: string;
};

View File

@@ -73,3 +73,4 @@ export * from "./PublicKeys";
export * from "./GlobalPermissions";
export * from "./Search";
export * from "./General";
export * from "./ContentType";

View File

@@ -10,6 +10,7 @@
"@scm-manager/ui-modules": "^2.36.2-SNAPSHOT",
"@scm-manager/ui-syntaxhighlighting": "^2.36.2-SNAPSHOT",
"@scm-manager/ui-text": "^2.36.2-SNAPSHOT",
"@scm-manager/ui-legacy": "^2.36.2-SNAPSHOT",
"classnames": "^2.2.5",
"history": "^4.10.1",
"i18next": "^19.6.0",
@@ -20,30 +21,30 @@
"react-dom": "^17.0.1",
"react-hook-form": "^7.5.1",
"react-i18next": "^10.13.1",
"react-redux": "^5.0.7",
"react-router": "^5.3.1",
"react-router-dom": "^5.3.1",
"react-select": "^2.1.2",
"redux": "^4.0.0",
"string_score": "^0.1.22",
"styled-components": "^5.3.5",
"systemjs": "0.21.6"
},
"scripts": {
"test": "jest",
"lint": "eslint src"
"lint": "eslint src",
"serve": "ui-scripts serve development",
"build": "webpack-cli --mode=production --config=../ui-scripts/src/webpack.config.js"
},
"devDependencies": {
"@scm-manager/eslint-config": "^2.15.1",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/ui-tests": "^2.36.2-SNAPSHOT",
"@scm-manager/ui-tests": "^2.36.2-SNAPSHOT",
"@types/classnames": "^2.2.9",
"@types/enzyme": "^3.10.3",
"@types/fetch-mock": "^7.3.1",
"@types/jest": "^24.0.19",
"@types/react": "^17.0.1",
"@types/react-dom": "^17.0.1",
"@types/react-redux": "5.0.7",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.25",
"@types/systemjs": "^0.20.6",

26
turbo.json Normal file
View File

@@ -0,0 +1,26 @@
{
"$schema": "https://turborepo.org/schema.json",
"baseBranch": "origin/main",
"globalDependencies": [
"$NODE_ENV"
],
"pipeline": {
"typecheck": {
},
"lint": {
},
"test": {
"outputs": ["build/jest-reports"]
},
"ci": {
},
"build": {
"dependsOn": ["^build"],
"outputs": ["build"]
},
"serve": {
"dependsOn": ["^build"],
"cache": false
}
}
}

3681
yarn.lock

File diff suppressed because it is too large Load Diff