diff --git a/.scripts/copy-openapi.mjs b/.scripts/copy-openapi.mjs new file mode 100644 index 000000000000..569563bf018f --- /dev/null +++ b/.scripts/copy-openapi.mjs @@ -0,0 +1,50 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; + +const [fromArg, toArg] = process.argv.slice(2); + +if (!fromArg || !toArg) { + console.error('Usage: node .scripts/copy-openapi.mjs '); + process.exit(1); +} + +const fromDir = path.resolve(process.cwd(), fromArg); +const toDir = path.resolve(process.cwd(), toArg); + +const ensureDir = async (dirPath) => { + await fs.mkdir(dirPath, { recursive: true }); +}; + +const copyOpenapi = async (currentFrom) => { + let entries; + try { + entries = await fs.readdir(currentFrom, { withFileTypes: true }); + } catch { + // Source dir might not exist yet; keep behavior lenient like rsync. + return; + } + + await Promise.all( + entries.map(async (entry) => { + const entryFrom = path.join(currentFrom, entry.name); + const relative = path.relative(fromDir, entryFrom); + const entryTo = path.join(toDir, relative); + + if (entry.isDirectory()) { + await copyOpenapi(entryFrom); + return; + } + + if (!entry.isFile() || !entry.name.endsWith('.openapi.json')) { + return; + } + + await ensureDir(path.dirname(entryTo)); + await fs.copyFile(entryFrom, entryTo); + }) + ); +}; + +await ensureDir(toDir); +await copyOpenapi(fromDir); + diff --git a/.scripts/rm.mjs b/.scripts/rm.mjs new file mode 100644 index 000000000000..a20ac67e99fb --- /dev/null +++ b/.scripts/rm.mjs @@ -0,0 +1,17 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; + +const targets = process.argv.slice(2); + +if (targets.length === 0) { + console.error('Usage: node .scripts/rm.mjs [path...]'); + process.exit(1); +} + +await Promise.all( + targets.map(async (target) => { + const resolved = path.resolve(process.cwd(), target); + await fs.rm(resolved, { recursive: true, force: true }); + }) +); + diff --git a/.scripts/start-dev.mjs b/.scripts/start-dev.mjs new file mode 100644 index 000000000000..67aced9e4bde --- /dev/null +++ b/.scripts/start-dev.mjs @@ -0,0 +1,26 @@ +import { spawn } from 'node:child_process'; + +const pnpmArgs = [ + '-r', + '--parallel', + '--filter', + '!@logto/integration-tests', + '--filter', + '!./packages/connectors/connector-*', + 'dev', +]; + +const isWindows = process.platform === 'win32'; + +// On Windows, pnpm is typically a .cmd shim which can't be spawned directly via CreateProcess; +// run it through cmd.exe instead. +const command = isWindows ? (process.env.ComSpec ?? 'cmd.exe') : 'pnpm'; +const args = isWindows ? ['/d', '/s', '/c', 'pnpm', ...pnpmArgs] : pnpmArgs; + +const child = spawn(command, args, { stdio: 'inherit' }); +child.on('exit', (code, signal) => { + if (typeof code === 'number') { + process.exit(code); + } + process.exit(signal ? 1 : 0); +}); diff --git a/package.json b/package.json index 050733d3ef2d..816688061582 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "prepack": "pnpm -r prepack", "dev": "pnpm -r prepack && pnpm start:dev", "dev:cloud": "IS_CLOUD=1 CONSOLE_PUBLIC_URL=/ pnpm dev", - "start:dev": "pnpm -r --parallel --filter=!@logto/integration-tests --filter \"!./packages/connectors/connector-*\" dev", + "start:dev": "node .scripts/start-dev.mjs", "start": "cd packages/core && NODE_ENV=production node .", "cli": "logto", "translate": "logto-translate", @@ -67,5 +67,6 @@ "dependencies": { "@logto/cli": "workspace:^", "@logto/translate": "workspace:^" - } + }, + "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" } diff --git a/packages/app-insights/package.json b/packages/app-insights/package.json index 73a0a1cec39c..d160b346f5d6 100644 --- a/packages/app-insights/package.json +++ b/packages/app-insights/package.json @@ -19,7 +19,7 @@ }, "scripts": { "precommit": "lint-staged", - "build": "rm -rf lib/ && tsc -p tsconfig.build.json", + "build": "node ../../.scripts/rm.mjs lib && tsc -p tsconfig.build.json", "build:test": "pnpm build", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", "lint": "eslint --ext .ts src", diff --git a/packages/cli/package.json b/packages/cli/package.json index e68c6a7499f0..e09d45857224 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ "scripts": { "precommit": "lint-staged", "prepare:package-json": "node -p \"'export const packageJson = ' + JSON.stringify(require('./package.json'), undefined, 2) + ';'\" > src/package-json.ts", - "build": "rm -rf lib && pnpm prepare:package-json && tsc -p tsconfig.build.json", + "build": "node ../../.scripts/rm.mjs lib && pnpm prepare:package-json && tsc -p tsconfig.build.json", "build:test": "pnpm build", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", "start": "node .", diff --git a/packages/console/package.json b/packages/console/package.json index 443e22a2b2e9..a9f60a92cf2c 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -12,7 +12,7 @@ ], "scripts": { "prepack": "pnpm generate", - "generate": "./generate.sh", + "generate": "node scripts/generate.mjs", "precommit": "lint-staged", "start": "vite", "dev": "vite", diff --git a/packages/console/scripts/generate.mjs b/packages/console/scripts/generate.mjs new file mode 100644 index 000000000000..28fe1a755413 --- /dev/null +++ b/packages/console/scripts/generate.mjs @@ -0,0 +1,17 @@ +import { spawnSync } from 'node:child_process'; +import fs from 'node:fs/promises'; +import path from 'node:path'; + +const run = (command, args) => { + const result = spawnSync(command, args, { stdio: 'inherit', shell: true }); + if (result.status !== 0) { + process.exit(result.status ?? 1); + } +}; + +await fs.rm(path.resolve('scripts-js'), { recursive: true, force: true }); +run('pnpm', ['exec', 'tsc', '-p', 'tsconfig.scripts.gen.json']); +await fs.rm(path.resolve('src/consts/jwt-customizer-type-definition.ts'), { force: true }); +run('node', ['scripts-js/generate-jwt-customizer-type-definition.js']); +await fs.rm(path.resolve('scripts-js'), { recursive: true, force: true }); + diff --git a/packages/core/package.json b/packages/core/package.json index 6a4eede8d509..e1530c29bc21 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -12,10 +12,10 @@ }, "scripts": { "precommit": "lint-staged", - "copy:apidocs": "rsync -a -m --include '*/' --include '*.openapi.json' --exclude '*' src/routes/ build/routes/", + "copy:apidocs": "node ../../.scripts/copy-openapi.mjs src/routes build/routes", "check": "tsc --noEmit", "build": "tsup", - "build:test": "rm -rf build/ && tsc -p tsconfig.test.json --sourcemap && pnpm run copy:apidocs", + "build:test": "node ../../.scripts/rm.mjs build && tsc -p tsconfig.test.json --sourcemap && pnpm run copy:apidocs", "lint": "eslint --ext .ts --ext .json src", "lint:report": "pnpm lint --format json --output-file report.json", "dev": "tsup --config tsup.dev.config.ts", diff --git a/packages/core/src/middleware/koa-spa-proxy.ts b/packages/core/src/middleware/koa-spa-proxy.ts index df7f3b31d7e8..cea48e7a92ae 100644 --- a/packages/core/src/middleware/koa-spa-proxy.ts +++ b/packages/core/src/middleware/koa-spa-proxy.ts @@ -44,7 +44,11 @@ export default function koaSpaProxy ${target}`); }, rewrite: (requestPath) => { - return '/' + path.join(prefix, requestPath); + // `rewrite` is for URLs, so we must use POSIX separators and avoid Windows absolute-path + // semantics (e.g. `path.join('console', '/@fs/...')` would drop the prefix on win32). + const normalized = requestPath.replace(/^\/+/, ''); + const joined = prefix ? path.posix.join(prefix, normalized) : normalized; + return '/' + joined; }, }); diff --git a/packages/phrases-experience/package.json b/packages/phrases-experience/package.json index 6efe7d8f6cf5..1c5febfba856 100644 --- a/packages/phrases-experience/package.json +++ b/packages/phrases-experience/package.json @@ -22,7 +22,7 @@ }, "scripts": { "precommit": "lint-staged", - "build": "rm -rf lib/ && tsc", + "build": "node ../../.scripts/rm.mjs lib && tsc", "build:test": "pnpm build", "dev": "tsc --watch --preserveWatchOutput --incremental", "lint": "eslint --ext .ts src", diff --git a/packages/phrases/package.json b/packages/phrases/package.json index b4348cfe9b09..85ed81ad9e5f 100644 --- a/packages/phrases/package.json +++ b/packages/phrases/package.json @@ -19,7 +19,7 @@ }, "scripts": { "precommit": "lint-staged", - "build": "rm -rf lib/ && tsc", + "build": "node ../../.scripts/rm.mjs lib && tsc", "build:test": "pnpm build", "dev": "tsc --watch --preserveWatchOutput --incremental", "lint": "eslint --ext .ts src", diff --git a/packages/schemas/package.json b/packages/schemas/package.json index c5676174b5f2..81c86ec8b3e4 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -23,9 +23,9 @@ "scripts": { "precommit": "lint-staged", "version": "./update-next.sh && git add alterations/", - "generate": "./generate.sh", - "build:alterations": "rm -rf alterations-js && tsc -p tsconfig.build.alterations.json", - "build": "pnpm generate && rm -rf lib/ && tsc -p tsconfig.build.json && pnpm build:alterations", + "generate": "node scripts/generate.mjs", + "build:alterations": "node ../../.scripts/rm.mjs alterations-js && tsc -p tsconfig.build.alterations.json", + "build": "pnpm generate && node ../../.scripts/rm.mjs lib && tsc -p tsconfig.build.json && pnpm build:alterations", "build:test": "pnpm build", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", "lint": "eslint --ext .ts src", diff --git a/packages/schemas/scripts/generate.mjs b/packages/schemas/scripts/generate.mjs new file mode 100644 index 000000000000..c1daf6f63d44 --- /dev/null +++ b/packages/schemas/scripts/generate.mjs @@ -0,0 +1,16 @@ +import { spawnSync } from 'node:child_process'; +import fs from 'node:fs/promises'; +import path from 'node:path'; + +const run = (command, args) => { + const result = spawnSync(command, args, { stdio: 'inherit', shell: true }); + if (result.status !== 0) { + process.exit(result.status ?? 1); + } +}; + +await fs.rm(path.resolve('lib'), { recursive: true, force: true }); +run('pnpm', ['exec', 'tsc', '-p', 'tsconfig.build.gen.json']); +await fs.rm(path.resolve('src/db-entries'), { recursive: true, force: true }); +run('node', ['lib/index.js']); + diff --git a/packages/shared/package.json b/packages/shared/package.json index ef13063b51f3..47a922dc07b1 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -27,7 +27,7 @@ }, "scripts": { "precommit": "lint-staged", - "build": "rm -rf lib/ && tsc -p tsconfig.build.json", + "build": "node ../../.scripts/rm.mjs lib && tsc -p tsconfig.build.json", "build:test": "pnpm build", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", "lint": "eslint --ext .ts src", diff --git a/packages/toolkit/connector-kit/package.json b/packages/toolkit/connector-kit/package.json index 268c5a3cecaf..42858570cdd5 100644 --- a/packages/toolkit/connector-kit/package.json +++ b/packages/toolkit/connector-kit/package.json @@ -25,7 +25,7 @@ "scripts": { "precommit": "lint-staged", "dev": "tsc --watch --preserveWatchOutput --incremental", - "build": "rm -rf lib/ && tsc", + "build": "node ../../../.scripts/rm.mjs lib && tsc", "build:test": "pnpm build", "lint": "eslint --ext .ts src", "lint:report": "pnpm lint --format json --output-file report.json", diff --git a/packages/toolkit/core-kit/package.json b/packages/toolkit/core-kit/package.json index b45817ffd242..b44d2f4a99f7 100644 --- a/packages/toolkit/core-kit/package.json +++ b/packages/toolkit/core-kit/package.json @@ -32,7 +32,7 @@ "scripts": { "precommit": "lint-staged", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", - "build": "rm -rf lib/ && tsc -p tsconfig.build.json", + "build": "node ../../../.scripts/rm.mjs lib && tsc -p tsconfig.build.json", "build:test": "pnpm build", "lint": "eslint --ext .ts src", "lint:report": "pnpm lint --format json --output-file report.json", diff --git a/packages/toolkit/language-kit/package.json b/packages/toolkit/language-kit/package.json index 36baad1480de..75a71c253c3c 100644 --- a/packages/toolkit/language-kit/package.json +++ b/packages/toolkit/language-kit/package.json @@ -21,7 +21,7 @@ ], "scripts": { "precommit": "lint-staged", - "build": "rm -rf lib/ && tsc -p tsconfig.build.json", + "build": "node ../../../.scripts/rm.mjs lib && tsc -p tsconfig.build.json", "build:test": "pnpm build", "lint": "eslint --ext .ts src", "lint:report": "pnpm lint --format json --output-file report.json", diff --git a/packages/translate/package.json b/packages/translate/package.json index 0b7996e42e02..7715699f4dba 100644 --- a/packages/translate/package.json +++ b/packages/translate/package.json @@ -24,7 +24,7 @@ "scripts": { "precommit": "lint-staged", "prepare:package-json": "node -p \"'export const packageJson = ' + JSON.stringify(require('./package.json'), undefined, 2) + ';'\" > src/package-json.ts", - "build": "rm -rf lib && pnpm prepare:package-json && tsc -p tsconfig.build.json", + "build": "node ../../.scripts/rm.mjs lib && pnpm prepare:package-json && tsc -p tsconfig.build.json", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", "start": "node .", "start:dev": "pnpm build && node .", diff --git a/packages/tunnel/package.json b/packages/tunnel/package.json index 7e7f508c8887..65262579fa77 100644 --- a/packages/tunnel/package.json +++ b/packages/tunnel/package.json @@ -24,7 +24,7 @@ "scripts": { "precommit": "lint-staged", "prepare:package-json": "node -p \"'export const packageJson = ' + JSON.stringify(require('./package.json'), undefined, 2) + ';'\" > src/package-json.ts", - "build": "rm -rf lib && pnpm prepare:package-json && tsc -p tsconfig.build.json", + "build": "node ../../.scripts/rm.mjs lib && pnpm prepare:package-json && tsc -p tsconfig.build.json", "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental", "start": "node .", "start:dev": "pnpm build && node .",