@orkestrel/scaffold 0.0.39 → 0.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/main.js +8 -1
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +2 -2
- package/dist/host/agents/orchestration.md +33 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +16 -16
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +3 -3
- package/dist/host/agents/skills/orkestrel-align-packages/references/integration.md +1 -1
- package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +7 -2
- package/dist/host/claude/agents/builder.md +2 -2
- package/dist/host/claude/agents/orkestrel.md +48 -48
- package/dist/host/claude/rules/application.md +6 -4
- package/dist/host/claude/rules/architecture.md +2 -0
- package/dist/host/claude/rules/documentation.md +6 -0
- package/dist/host/claude/rules/tests.md +11 -1
- package/dist/host/claude/rules/typescript.md +15 -1
- package/dist/host/claude/rules/workspace.md +43 -13
- package/dist/host/claude/rules/writing.md +125 -0
- package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +10 -1
- package/dist/host/claude/skills/orkestrel-align-packages/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-build-application/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-harden-package/SKILL.md +1 -1
- package/dist/host/configs/policy.ts +185 -0
- package/dist/host/dotfiles/oxlintrc.json +13 -1
- package/dist/host/dotfiles/prettierignore +3 -0
- package/dist/host/guides/scaffold.md +13 -7
- package/dist/host/manifest.json +11 -7
- package/dist/host/tests/config.test.ts +195 -4
- package/dist/host/tests/policy.test.ts +82 -0
- package/dist/host/tests/setupPolicy.ts +863 -21
- package/dist/src/core/index.cjs +68 -6
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +11 -9
- package/dist/src/core/index.d.ts +11 -9
- package/dist/src/core/index.js +68 -6
- package/dist/src/core/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/host/agents/skills/orkestrel-build-application/references/application.md +0 -129
|
@@ -235,11 +235,11 @@ export declare const BIN_ENTRY_PATH = "src/bin/main.ts";
|
|
|
235
235
|
* application-only, and mixed workspaces are all first class. `dependencies`
|
|
236
236
|
* and `peers` are runtime `@orkestrel/*` packages; `extras` are
|
|
237
237
|
* package-specific development dependencies and may carry any valid npm name.
|
|
238
|
-
* `bin`, `guides`, `distribution`, `integration`, `conformance`,
|
|
239
|
-
* `vendors`, `global`, and `showcase` are structural facts: each is
|
|
240
|
-
* when the workspace physically ships the directory or exact-case file
|
|
241
|
-
* defines it, never because of the workspace's name and never because a
|
|
242
|
-
* fact is set.
|
|
238
|
+
* `bin`, `setup`, `guides`, `distribution`, `integration`, `conformance`,
|
|
239
|
+
* `service`, `vendors`, `global`, and `showcase` are structural facts: each is
|
|
240
|
+
* set only when the workspace physically ships the directory or exact-case file
|
|
241
|
+
* that defines it, never because of the workspace's name and never because a
|
|
242
|
+
* sibling fact is set.
|
|
243
243
|
* `showcase` projects only a browser `app`. The gate answers an absent browser
|
|
244
244
|
* axis with a non-blocking question, so a caller that set the flag learns it
|
|
245
245
|
* emitted nothing and the compile still completes.
|
|
@@ -264,6 +264,7 @@ export declare interface Blueprint {
|
|
|
264
264
|
readonly engines: string;
|
|
265
265
|
readonly overrides: readonly Override[];
|
|
266
266
|
readonly bin: boolean;
|
|
267
|
+
readonly setup: boolean;
|
|
267
268
|
readonly guides: boolean;
|
|
268
269
|
readonly distribution: boolean;
|
|
269
270
|
readonly integration: boolean;
|
|
@@ -1034,14 +1035,14 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1034
1035
|
export declare const CONFIG_TEMPLATES: Readonly<{
|
|
1035
1036
|
root: Readonly<{
|
|
1036
1037
|
tsconfig: "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ESNext\",\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"bundler\",\n\t\t\"allowImportingTsExtensions\": true,\n\t\t\"lib\": [\"ESNext\", \"DOM\", \"DOM.Iterable\"],\n\t\t\"types\": [\"node\", \"vite/client\", \"vitest/globals\"],\n\t\t\"moduleDetection\": \"force\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"strict\": true,\n\t\t\"verbatimModuleSyntax\": true,\n\t\t\"noUncheckedIndexedAccess\": true,\n\t\t\"noUncheckedSideEffectImports\": true,\n\t\t\"exactOptionalPropertyTypes\": true,\n\t\t\"noUnusedLocals\": true,\n\t\t\"noUnusedParameters\": true,\n\t\t\"noImplicitOverride\": true,\n\t\t\"noFallthroughCasesInSwitch\": true,\n\t\t\"forceConsistentCasingInFileNames\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"noEmit\": true,\n\t\t\"paths\": {\n{{paths}}\n\t\t}\n\t},\n\t\"exclude\": [\"node_modules\", \"dist\", \"tmp\"]\n}\n";
|
|
1037
|
-
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'\n\n{{options}}export function resolveWorkspacePath(relativePath: string): string {\n\treturn fileURLToPath(new URL(relativePath, import.meta.url))\n}\n\nconst resolve = {\n\talias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {\n\t\tconst [path] = values\n\t\tif (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')\n\t\treturn Object.assign(aliases, { [key]: resolveWorkspacePath(path) })\n\t}, {}),\n}\n\n{{factories}}export default defineConfig({\n\tresolve,\n\ttest: {\n{{projects}}\n\t},\n})\n";
|
|
1038
|
+
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport manifest from './package.json' with { type: 'json' }\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'\n\n{{options}}export function resolveWorkspacePath(relativePath: string): string {\n\treturn fileURLToPath(new URL(relativePath, import.meta.url))\n}\n\nconst peerDependencies = 'peerDependencies' in manifest ? manifest.peerDependencies : undefined\nif (\n\tpeerDependencies !== undefined &&\n\t(typeof peerDependencies !== 'object' ||\n\t\tpeerDependencies === null ||\n\t\tArray.isArray(peerDependencies))\n) {\n\tthrow new Error('package peerDependencies must be an object')\n}\nexport const peers: readonly string[] =\n\tpeerDependencies === undefined ? [] : Object.keys(peerDependencies)\n\nconst resolve = {\n\talias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {\n\t\tconst [path] = values\n\t\tif (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')\n\t\treturn Object.assign(aliases, { [key]: resolveWorkspacePath(path) })\n\t}, {}),\n}\n\n{{factories}}export default defineConfig({\n\tresolve,\n\ttest: {\n{{projects}}\n\t},\n})\n";
|
|
1038
1039
|
}>;
|
|
1039
1040
|
factories: Readonly<{
|
|
1040
1041
|
src: Readonly<{
|
|
1041
1042
|
core: "export const srcCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:core', color: 'magenta' },\n\t\t\t\tinclude: ['tests/src/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1042
1043
|
browser: "export const srcBrowser = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/browser/index.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'index.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/browser',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:browser', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/browser/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n{{global}}\n\t\t\t\tbrowser: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t\t},\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1043
1044
|
server: "export const srcServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/server/index.ts'),\n\t\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\t\tfileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/server',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\tplatform: 'node',\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:server', color: 'red' },\n\t\t\t\tinclude: ['tests/src/server/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1044
|
-
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {
|
|
1045
|
+
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\texternal: (id: string) =>\n\t\t\t\t\t\tid.startsWith('node:') ||\n\t\t\t\t\t\tid.startsWith('@orkestrel/') ||\n\t\t\t\t\t\tid.startsWith('@src/') ||\n\t\t\t\t\t\tpeers.some((peer) => id === peer || id.startsWith(peer + '/')),\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:bin', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/bin/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\t// A bin test drives the real executable over a real temporary repository, so it\n\t\t\t\t// spends seconds in process startup and filesystem work rather than milliseconds.\n\t\t\t\t// Vitest's five-second default clears one alone and times out under a full suite.\n\t\t\t\ttestTimeout: 15_000,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1045
1046
|
}>;
|
|
1046
1047
|
app: Readonly<{
|
|
1047
1048
|
core: "export const appCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [environmentBoundary('app/core')],\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:core', color: 'cyan' },\n\t\t\t\tinclude: ['tests/app/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
@@ -1049,7 +1050,8 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1049
1050
|
server: "export const appServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('app/server/main.ts'),\n\t\t\t\t\tformats: ['cjs'],\n\t\t\t\t\tfileName: () => 'main.cjs',\n\t\t\t\t},\n\t\t\t\toutDir: resolveWorkspacePath('dist/app/server'),\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: (id: string) => id.startsWith('node:') },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:server', color: 'green' },\n\t\t\t\tinclude: ['tests/app/server/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1050
1051
|
}>;
|
|
1051
1052
|
policy: "export const policy = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'policy', color: 'white' },\n\t\t\t\tinclude: ['tests/policy.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1052
|
-
config: "export const config = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'config', color: 'yellow' },\n\t\t\t\tinclude: ['tests/config.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1053
|
+
config: "export const config = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'config', color: 'yellow' },\n\t\t\t\tinclude: ['tests/config.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\t// A config test validates every target wrapper and runs the real linter twice with\n\t\t\t\t// 15-second child caps, so this budget clears both caps and reports their diagnostics.\n\t\t\t\ttestTimeout: 45_000,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1054
|
+
setup: "export const setup = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'setup', color: 'white' },\n\t\t\t\tinclude: ['tests/setup*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1053
1055
|
guides: "export const guides = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'guides', color: 'green' },\n\t\t\t\tinclude: ['tests/guides.test.ts'],\n\t\t\t\texclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1054
1056
|
conformance: "// Where this package drifts from the official tooling it stays compatible with.\n// The subject is this package, so the proof is hermetic and stays in `npm test`.\nexport const conformance = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'conformance', color: 'magenta' },\n\t\t\t\tinclude: ['tests/conformance.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1055
1057
|
service: "// The live external services this package drives. It starts nothing itself:\n// `scripts/service.sh` provisions, `tests/setupService.ts` proves readiness, and\n// the project stays out of `npm test` because a real service answers it.\nexport const service = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'service', color: 'red' },\n\t\t\t\tinclude: ['tests/service/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupService.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
@@ -1072,7 +1074,7 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1072
1074
|
}>;
|
|
1073
1075
|
vites: Readonly<{
|
|
1074
1076
|
src: Readonly<{
|
|
1075
|
-
core: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { environmentBoundary, outputBoundary } from '../helpers.js'\nimport { srcCore, resolveWorkspacePath } from '../../vite.config.ts'\n\nexport default defineConfig(\n\tsrcCore({\n\t\tpublicDir: false,\n\t\tplugins: [\n\t\t\toutputBoundary('dist/src/core'),\n\t\t\tenvironmentBoundary('src/core'),\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.core.json'),\n\t\t\t\tbundleTypes: {\n\t\t\t\t\textractorConfig: {\n\t\t\t\t\t\tcompiler: {\n\t\t\t\t\t\t\toverrideTsconfig: {\n\t\t\t\t\t\t\t\tcompilerOptions: { types: ['node'] },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t\tbuild: {\n\t\t\tlib: {\n\t\t\t\tentry: resolveWorkspacePath('src/core/index.ts'),\n\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\tfileName: (format) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t},\n\t\t\toutDir: 'dist/src/core',\n\t\t\trolldownOptions: {
|
|
1077
|
+
core: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { environmentBoundary, outputBoundary } from '../helpers.js'\nimport { peers, srcCore, resolveWorkspacePath } from '../../vite.config.ts'\n\nexport default defineConfig(\n\tsrcCore({\n\t\tpublicDir: false,\n\t\tplugins: [\n\t\t\toutputBoundary('dist/src/core'),\n\t\t\tenvironmentBoundary('src/core'),\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.core.json'),\n\t\t\t\tbundleTypes: {\n\t\t\t\t\textractorConfig: {\n\t\t\t\t\t\tcompiler: {\n\t\t\t\t\t\t\toverrideTsconfig: {\n\t\t\t\t\t\t\t\tcompilerOptions: { types: ['node'] },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t\tbuild: {\n\t\t\tlib: {\n\t\t\t\tentry: resolveWorkspacePath('src/core/index.ts'),\n\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\tfileName: (format) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t},\n\t\t\toutDir: 'dist/src/core',\n\t\t\trolldownOptions: {\n\t\t\t\texternal: (id: string) =>\n\t\t\t\t\tid.startsWith('node:') ||\n\t\t\t\t\tid.startsWith('@orkestrel/') ||\n\t\t\t\t\tpeers.some((peer) => id === peer || id.startsWith(peer + '/')),\n\t\t\t},\n\t\t},\n\t}),\n)\n";
|
|
1076
1078
|
browser: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { srcBrowser, resolveWorkspacePath } from '../../vite.config.ts'\n\n// vite-plugin-dts rolls this face into one declaration, and the roll-up reaches\n// src/core through a relative source path the tarball does not carry. The path\n// keeps each source module's own depth, so a module in a browser subfolder emits\n// one that leaves dist/src entirely. The rewrite below externalizes core through\n// the package's own published root export, on the final roll-up only.\nexport default defineConfig(\n\tsrcBrowser({\n\t\tplugins: [\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.browser.json'),\n\t\t\t\tbundleTypes: true,\n\t\t\t\tbeforeWriteFile: (path, content) => ({\n\t\t\t\t\tcontent: /[\\\\/]dist[\\\\/]src[\\\\/]browser[\\\\/]index\\.d\\.ts$/.test(path)\n{{replacement}}\n\t\t\t\t\t\t: content,\n\t\t\t\t}),\n\t\t\t}),\n\t\t],\n\t}),\n)\n";
|
|
1077
1079
|
server: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { srcServer, resolveWorkspacePath } from '../../vite.config.ts'\n\n// vite-plugin-dts rolls this face into one declaration, and the roll-up reaches\n// src/core through a relative source path the tarball does not carry. The rewrite\n// below externalizes core through the package's own published root export, on the\n// final roll-up only.\nexport default defineConfig(\n\tsrcServer({\n\t\tplugins: [\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.server.json'),\n\t\t\t\tbundleTypes: true,\n\t\t\t\tbeforeWriteFile: (path, content) => ({\n\t\t\t\t\tcontent: /[\\\\/]dist[\\\\/]src[\\\\/]server[\\\\/]index\\.d\\.ts$/.test(path)\n{{replacement}}\n\t\t\t\t\t\t: content,\n\t\t\t\t}),\n\t\t\t}),\n\t\t],\n\t}),\n)\n";
|
|
1078
1080
|
}>;
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -235,11 +235,11 @@ export declare const BIN_ENTRY_PATH = "src/bin/main.ts";
|
|
|
235
235
|
* application-only, and mixed workspaces are all first class. `dependencies`
|
|
236
236
|
* and `peers` are runtime `@orkestrel/*` packages; `extras` are
|
|
237
237
|
* package-specific development dependencies and may carry any valid npm name.
|
|
238
|
-
* `bin`, `guides`, `distribution`, `integration`, `conformance`,
|
|
239
|
-
* `vendors`, `global`, and `showcase` are structural facts: each is
|
|
240
|
-
* when the workspace physically ships the directory or exact-case file
|
|
241
|
-
* defines it, never because of the workspace's name and never because a
|
|
242
|
-
* fact is set.
|
|
238
|
+
* `bin`, `setup`, `guides`, `distribution`, `integration`, `conformance`,
|
|
239
|
+
* `service`, `vendors`, `global`, and `showcase` are structural facts: each is
|
|
240
|
+
* set only when the workspace physically ships the directory or exact-case file
|
|
241
|
+
* that defines it, never because of the workspace's name and never because a
|
|
242
|
+
* sibling fact is set.
|
|
243
243
|
* `showcase` projects only a browser `app`. The gate answers an absent browser
|
|
244
244
|
* axis with a non-blocking question, so a caller that set the flag learns it
|
|
245
245
|
* emitted nothing and the compile still completes.
|
|
@@ -264,6 +264,7 @@ export declare interface Blueprint {
|
|
|
264
264
|
readonly engines: string;
|
|
265
265
|
readonly overrides: readonly Override[];
|
|
266
266
|
readonly bin: boolean;
|
|
267
|
+
readonly setup: boolean;
|
|
267
268
|
readonly guides: boolean;
|
|
268
269
|
readonly distribution: boolean;
|
|
269
270
|
readonly integration: boolean;
|
|
@@ -1034,14 +1035,14 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1034
1035
|
export declare const CONFIG_TEMPLATES: Readonly<{
|
|
1035
1036
|
root: Readonly<{
|
|
1036
1037
|
tsconfig: "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ESNext\",\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"bundler\",\n\t\t\"allowImportingTsExtensions\": true,\n\t\t\"lib\": [\"ESNext\", \"DOM\", \"DOM.Iterable\"],\n\t\t\"types\": [\"node\", \"vite/client\", \"vitest/globals\"],\n\t\t\"moduleDetection\": \"force\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"strict\": true,\n\t\t\"verbatimModuleSyntax\": true,\n\t\t\"noUncheckedIndexedAccess\": true,\n\t\t\"noUncheckedSideEffectImports\": true,\n\t\t\"exactOptionalPropertyTypes\": true,\n\t\t\"noUnusedLocals\": true,\n\t\t\"noUnusedParameters\": true,\n\t\t\"noImplicitOverride\": true,\n\t\t\"noFallthroughCasesInSwitch\": true,\n\t\t\"forceConsistentCasingInFileNames\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"noEmit\": true,\n\t\t\"paths\": {\n{{paths}}\n\t\t}\n\t},\n\t\"exclude\": [\"node_modules\", \"dist\", \"tmp\"]\n}\n";
|
|
1037
|
-
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'\n\n{{options}}export function resolveWorkspacePath(relativePath: string): string {\n\treturn fileURLToPath(new URL(relativePath, import.meta.url))\n}\n\nconst resolve = {\n\talias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {\n\t\tconst [path] = values\n\t\tif (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')\n\t\treturn Object.assign(aliases, { [key]: resolveWorkspacePath(path) })\n\t}, {}),\n}\n\n{{factories}}export default defineConfig({\n\tresolve,\n\ttest: {\n{{projects}}\n\t},\n})\n";
|
|
1038
|
+
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport manifest from './package.json' with { type: 'json' }\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'\n\n{{options}}export function resolveWorkspacePath(relativePath: string): string {\n\treturn fileURLToPath(new URL(relativePath, import.meta.url))\n}\n\nconst peerDependencies = 'peerDependencies' in manifest ? manifest.peerDependencies : undefined\nif (\n\tpeerDependencies !== undefined &&\n\t(typeof peerDependencies !== 'object' ||\n\t\tpeerDependencies === null ||\n\t\tArray.isArray(peerDependencies))\n) {\n\tthrow new Error('package peerDependencies must be an object')\n}\nexport const peers: readonly string[] =\n\tpeerDependencies === undefined ? [] : Object.keys(peerDependencies)\n\nconst resolve = {\n\talias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {\n\t\tconst [path] = values\n\t\tif (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')\n\t\treturn Object.assign(aliases, { [key]: resolveWorkspacePath(path) })\n\t}, {}),\n}\n\n{{factories}}export default defineConfig({\n\tresolve,\n\ttest: {\n{{projects}}\n\t},\n})\n";
|
|
1038
1039
|
}>;
|
|
1039
1040
|
factories: Readonly<{
|
|
1040
1041
|
src: Readonly<{
|
|
1041
1042
|
core: "export const srcCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:core', color: 'magenta' },\n\t\t\t\tinclude: ['tests/src/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1042
1043
|
browser: "export const srcBrowser = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/browser/index.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'index.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/browser',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:browser', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/browser/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n{{global}}\n\t\t\t\tbrowser: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t\t},\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1043
1044
|
server: "export const srcServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/server/index.ts'),\n\t\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\t\tfileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/server',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\tplatform: 'node',\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:server', color: 'red' },\n\t\t\t\tinclude: ['tests/src/server/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1044
|
-
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {
|
|
1045
|
+
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\texternal: (id: string) =>\n\t\t\t\t\t\tid.startsWith('node:') ||\n\t\t\t\t\t\tid.startsWith('@orkestrel/') ||\n\t\t\t\t\t\tid.startsWith('@src/') ||\n\t\t\t\t\t\tpeers.some((peer) => id === peer || id.startsWith(peer + '/')),\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:bin', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/bin/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\t// A bin test drives the real executable over a real temporary repository, so it\n\t\t\t\t// spends seconds in process startup and filesystem work rather than milliseconds.\n\t\t\t\t// Vitest's five-second default clears one alone and times out under a full suite.\n\t\t\t\ttestTimeout: 15_000,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1045
1046
|
}>;
|
|
1046
1047
|
app: Readonly<{
|
|
1047
1048
|
core: "export const appCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [environmentBoundary('app/core')],\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:core', color: 'cyan' },\n\t\t\t\tinclude: ['tests/app/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
@@ -1049,7 +1050,8 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1049
1050
|
server: "export const appServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('app/server/main.ts'),\n\t\t\t\t\tformats: ['cjs'],\n\t\t\t\t\tfileName: () => 'main.cjs',\n\t\t\t\t},\n\t\t\t\toutDir: resolveWorkspacePath('dist/app/server'),\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: (id: string) => id.startsWith('node:') },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:server', color: 'green' },\n\t\t\t\tinclude: ['tests/app/server/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1050
1051
|
}>;
|
|
1051
1052
|
policy: "export const policy = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'policy', color: 'white' },\n\t\t\t\tinclude: ['tests/policy.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1052
|
-
config: "export const config = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'config', color: 'yellow' },\n\t\t\t\tinclude: ['tests/config.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1053
|
+
config: "export const config = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'config', color: 'yellow' },\n\t\t\t\tinclude: ['tests/config.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\t// A config test validates every target wrapper and runs the real linter twice with\n\t\t\t\t// 15-second child caps, so this budget clears both caps and reports their diagnostics.\n\t\t\t\ttestTimeout: 45_000,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1054
|
+
setup: "export const setup = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'setup', color: 'white' },\n\t\t\t\tinclude: ['tests/setup*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1053
1055
|
guides: "export const guides = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'guides', color: 'green' },\n\t\t\t\tinclude: ['tests/guides.test.ts'],\n\t\t\t\texclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1054
1056
|
conformance: "// Where this package drifts from the official tooling it stays compatible with.\n// The subject is this package, so the proof is hermetic and stays in `npm test`.\nexport const conformance = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'conformance', color: 'magenta' },\n\t\t\t\tinclude: ['tests/conformance.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1055
1057
|
service: "// The live external services this package drives. It starts nothing itself:\n// `scripts/service.sh` provisions, `tests/setupService.ts` proves readiness, and\n// the project stays out of `npm test` because a real service answers it.\nexport const service = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'service', color: 'red' },\n\t\t\t\tinclude: ['tests/service/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupService.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
@@ -1072,7 +1074,7 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1072
1074
|
}>;
|
|
1073
1075
|
vites: Readonly<{
|
|
1074
1076
|
src: Readonly<{
|
|
1075
|
-
core: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { environmentBoundary, outputBoundary } from '../helpers.js'\nimport { srcCore, resolveWorkspacePath } from '../../vite.config.ts'\n\nexport default defineConfig(\n\tsrcCore({\n\t\tpublicDir: false,\n\t\tplugins: [\n\t\t\toutputBoundary('dist/src/core'),\n\t\t\tenvironmentBoundary('src/core'),\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.core.json'),\n\t\t\t\tbundleTypes: {\n\t\t\t\t\textractorConfig: {\n\t\t\t\t\t\tcompiler: {\n\t\t\t\t\t\t\toverrideTsconfig: {\n\t\t\t\t\t\t\t\tcompilerOptions: { types: ['node'] },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t\tbuild: {\n\t\t\tlib: {\n\t\t\t\tentry: resolveWorkspacePath('src/core/index.ts'),\n\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\tfileName: (format) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t},\n\t\t\toutDir: 'dist/src/core',\n\t\t\trolldownOptions: {
|
|
1077
|
+
core: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { environmentBoundary, outputBoundary } from '../helpers.js'\nimport { peers, srcCore, resolveWorkspacePath } from '../../vite.config.ts'\n\nexport default defineConfig(\n\tsrcCore({\n\t\tpublicDir: false,\n\t\tplugins: [\n\t\t\toutputBoundary('dist/src/core'),\n\t\t\tenvironmentBoundary('src/core'),\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.core.json'),\n\t\t\t\tbundleTypes: {\n\t\t\t\t\textractorConfig: {\n\t\t\t\t\t\tcompiler: {\n\t\t\t\t\t\t\toverrideTsconfig: {\n\t\t\t\t\t\t\t\tcompilerOptions: { types: ['node'] },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t\tbuild: {\n\t\t\tlib: {\n\t\t\t\tentry: resolveWorkspacePath('src/core/index.ts'),\n\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\tfileName: (format) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t},\n\t\t\toutDir: 'dist/src/core',\n\t\t\trolldownOptions: {\n\t\t\t\texternal: (id: string) =>\n\t\t\t\t\tid.startsWith('node:') ||\n\t\t\t\t\tid.startsWith('@orkestrel/') ||\n\t\t\t\t\tpeers.some((peer) => id === peer || id.startsWith(peer + '/')),\n\t\t\t},\n\t\t},\n\t}),\n)\n";
|
|
1076
1078
|
browser: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { srcBrowser, resolveWorkspacePath } from '../../vite.config.ts'\n\n// vite-plugin-dts rolls this face into one declaration, and the roll-up reaches\n// src/core through a relative source path the tarball does not carry. The path\n// keeps each source module's own depth, so a module in a browser subfolder emits\n// one that leaves dist/src entirely. The rewrite below externalizes core through\n// the package's own published root export, on the final roll-up only.\nexport default defineConfig(\n\tsrcBrowser({\n\t\tplugins: [\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.browser.json'),\n\t\t\t\tbundleTypes: true,\n\t\t\t\tbeforeWriteFile: (path, content) => ({\n\t\t\t\t\tcontent: /[\\\\/]dist[\\\\/]src[\\\\/]browser[\\\\/]index\\.d\\.ts$/.test(path)\n{{replacement}}\n\t\t\t\t\t\t: content,\n\t\t\t\t}),\n\t\t\t}),\n\t\t],\n\t}),\n)\n";
|
|
1077
1079
|
server: "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\nimport { srcServer, resolveWorkspacePath } from '../../vite.config.ts'\n\n// vite-plugin-dts rolls this face into one declaration, and the roll-up reaches\n// src/core through a relative source path the tarball does not carry. The rewrite\n// below externalizes core through the package's own published root export, on the\n// final roll-up only.\nexport default defineConfig(\n\tsrcServer({\n\t\tplugins: [\n\t\t\tdts({\n\t\t\t\ttsconfigPath: resolveWorkspacePath('configs/src/tsconfig.server.json'),\n\t\t\t\tbundleTypes: true,\n\t\t\t\tbeforeWriteFile: (path, content) => ({\n\t\t\t\t\tcontent: /[\\\\/]dist[\\\\/]src[\\\\/]server[\\\\/]index\\.d\\.ts$/.test(path)\n{{replacement}}\n\t\t\t\t\t\t: content,\n\t\t\t\t}),\n\t\t\t}),\n\t\t],\n\t}),\n)\n";
|
|
1078
1080
|
}>;
|
package/dist/src/core/index.js
CHANGED
|
@@ -128,6 +128,7 @@ var HOST_PATHS = Object.freeze([
|
|
|
128
128
|
"tests/policy.test.ts",
|
|
129
129
|
"tests/config.test.ts",
|
|
130
130
|
"configs/helpers.ts",
|
|
131
|
+
"configs/policy.ts",
|
|
131
132
|
".editorconfig",
|
|
132
133
|
".gitattributes",
|
|
133
134
|
".gitignore",
|
|
@@ -304,7 +305,7 @@ var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
|
|
|
304
305
|
/** The tooling versions scaffold and every generated workspace share. */
|
|
305
306
|
var BASE_DEV_DEPENDENCIES = Object.freeze({
|
|
306
307
|
"@orkestrel/guide": "^0.0.12",
|
|
307
|
-
"@orkestrel/scaffold": "^0.0.
|
|
308
|
+
"@orkestrel/scaffold": "^0.0.41",
|
|
308
309
|
"@orkestrel/test": "^0.0.6",
|
|
309
310
|
"@types/node": "^26.2.0",
|
|
310
311
|
oxfmt: "^0.62.0",
|
|
@@ -404,6 +405,7 @@ var CONFIG_TEMPLATES = Object.freeze({
|
|
|
404
405
|
`,
|
|
405
406
|
vite: `import type { {{viteTypes}} } from 'vite'
|
|
406
407
|
{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'
|
|
408
|
+
import manifest from './package.json' with { type: 'json' }
|
|
407
409
|
import tsconfig from './tsconfig.json' with { type: 'json' }
|
|
408
410
|
{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'
|
|
409
411
|
|
|
@@ -411,6 +413,18 @@ import tsconfig from './tsconfig.json' with { type: 'json' }
|
|
|
411
413
|
return fileURLToPath(new URL(relativePath, import.meta.url))
|
|
412
414
|
}
|
|
413
415
|
|
|
416
|
+
const peerDependencies = 'peerDependencies' in manifest ? manifest.peerDependencies : undefined
|
|
417
|
+
if (
|
|
418
|
+
peerDependencies !== undefined &&
|
|
419
|
+
(typeof peerDependencies !== 'object' ||
|
|
420
|
+
peerDependencies === null ||
|
|
421
|
+
Array.isArray(peerDependencies))
|
|
422
|
+
) {
|
|
423
|
+
throw new Error('package peerDependencies must be an object')
|
|
424
|
+
}
|
|
425
|
+
export const peers: readonly string[] =
|
|
426
|
+
peerDependencies === undefined ? [] : Object.keys(peerDependencies)
|
|
427
|
+
|
|
414
428
|
const resolve = {
|
|
415
429
|
alias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {
|
|
416
430
|
const [path] = values
|
|
@@ -538,7 +552,13 @@ const resolve = {
|
|
|
538
552
|
},
|
|
539
553
|
outDir: 'dist/bin',
|
|
540
554
|
target: 'node22',
|
|
541
|
-
rolldownOptions: {
|
|
555
|
+
rolldownOptions: {
|
|
556
|
+
external: (id: string) =>
|
|
557
|
+
id.startsWith('node:') ||
|
|
558
|
+
id.startsWith('@orkestrel/') ||
|
|
559
|
+
id.startsWith('@src/') ||
|
|
560
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),
|
|
561
|
+
},
|
|
542
562
|
},
|
|
543
563
|
test: {
|
|
544
564
|
name: { label: 'src:bin', color: 'yellow' },
|
|
@@ -659,6 +679,24 @@ export function appBrowser(): UserConfig {
|
|
|
659
679
|
setupFiles: ['./tests/setup.ts'],
|
|
660
680
|
environment: 'node',
|
|
661
681
|
browser: { enabled: false },
|
|
682
|
+
// A config test validates every target wrapper and runs the real linter twice with
|
|
683
|
+
// 15-second child caps, so this budget clears both caps and reports their diagnostics.
|
|
684
|
+
testTimeout: 45_000,
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
options ?? {},
|
|
688
|
+
)
|
|
689
|
+
`,
|
|
690
|
+
setup: `export const setup = (options?: UserConfig): UserConfig =>
|
|
691
|
+
mergeConfig(
|
|
692
|
+
{
|
|
693
|
+
resolve,
|
|
694
|
+
test: {
|
|
695
|
+
name: { label: 'setup', color: 'white' },
|
|
696
|
+
include: ['tests/setup*.test.ts'],
|
|
697
|
+
setupFiles: ['./tests/setup.ts'],
|
|
698
|
+
environment: 'node',
|
|
699
|
+
browser: { enabled: false },
|
|
662
700
|
},
|
|
663
701
|
},
|
|
664
702
|
options ?? {},
|
|
@@ -894,7 +932,7 @@ export const probe = (options?: UserConfig): UserConfig =>
|
|
|
894
932
|
core: `import { defineConfig } from 'vite'
|
|
895
933
|
import dts from 'vite-plugin-dts'
|
|
896
934
|
import { environmentBoundary, outputBoundary } from '../helpers.js'
|
|
897
|
-
import { srcCore, resolveWorkspacePath } from '../../vite.config.ts'
|
|
935
|
+
import { peers, srcCore, resolveWorkspacePath } from '../../vite.config.ts'
|
|
898
936
|
|
|
899
937
|
export default defineConfig(
|
|
900
938
|
srcCore({
|
|
@@ -922,7 +960,12 @@ export default defineConfig(
|
|
|
922
960
|
fileName: (format) => (format === 'es' ? 'index.js' : 'index.cjs'),
|
|
923
961
|
},
|
|
924
962
|
outDir: 'dist/src/core',
|
|
925
|
-
rolldownOptions: {
|
|
963
|
+
rolldownOptions: {
|
|
964
|
+
external: (id: string) =>
|
|
965
|
+
id.startsWith('node:') ||
|
|
966
|
+
id.startsWith('@orkestrel/') ||
|
|
967
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),
|
|
968
|
+
},
|
|
926
969
|
},
|
|
927
970
|
}),
|
|
928
971
|
)
|
|
@@ -1715,6 +1758,7 @@ var isBlueprint = recordOf({
|
|
|
1715
1758
|
engines: isString,
|
|
1716
1759
|
overrides: andOf(isCollection, arrayOf(isOverride)),
|
|
1717
1760
|
bin: isBoolean,
|
|
1761
|
+
setup: isBoolean,
|
|
1718
1762
|
guides: isBoolean,
|
|
1719
1763
|
distribution: isBoolean,
|
|
1720
1764
|
integration: isBoolean,
|
|
@@ -3078,6 +3122,7 @@ function blueprintToScripts(blueprint) {
|
|
|
3078
3122
|
...blueprint.app.length > 0 ? ["npm run test:app"] : [],
|
|
3079
3123
|
"npm run test:policy",
|
|
3080
3124
|
"npm run test:config",
|
|
3125
|
+
...blueprint.setup ? ["npm run test:setup"] : [],
|
|
3081
3126
|
...blueprint.guides ? ["npm run test:guides"] : [],
|
|
3082
3127
|
...blueprint.conformance ? ["npm run test:conformance"] : [],
|
|
3083
3128
|
...integrates ? ["npm run test:integration"] : [],
|
|
@@ -3098,6 +3143,7 @@ function blueprintToScripts(blueprint) {
|
|
|
3098
3143
|
}
|
|
3099
3144
|
scripts["test:policy"] = `${vitest} --project policy`;
|
|
3100
3145
|
scripts["test:config"] = `${vitest} --project config`;
|
|
3146
|
+
if (blueprint.setup) scripts["test:setup"] = `${vitest} --project setup`;
|
|
3101
3147
|
if (blueprint.guides) scripts["test:guides"] = `${vitest} --project guides`;
|
|
3102
3148
|
if (blueprint.conformance) scripts["test:conformance"] = `${vitest} --project conformance`;
|
|
3103
3149
|
scripts["test:probe"] = "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe";
|
|
@@ -3321,7 +3367,12 @@ function blueprintToRootVite(blueprint) {
|
|
|
3321
3367
|
if (blueprint.src.includes("browser")) {
|
|
3322
3368
|
const core = blueprint.src.includes("core");
|
|
3323
3369
|
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.browser, {
|
|
3324
|
-
external: core ?
|
|
3370
|
+
external: core ? `external: (id: string) =>
|
|
3371
|
+
id === '@src/core' ||
|
|
3372
|
+
id.startsWith('@orkestrel/') ||
|
|
3373
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
|
|
3374
|
+
id.startsWith('@orkestrel/') ||
|
|
3375
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
|
|
3325
3376
|
output: core ? " output: { paths: { '@src/core': '../core/index.js' } }," : " output: {},",
|
|
3326
3377
|
exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : "",
|
|
3327
3378
|
global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : ""
|
|
@@ -3332,7 +3383,13 @@ function blueprintToRootVite(blueprint) {
|
|
|
3332
3383
|
const core = blueprint.src.includes("core");
|
|
3333
3384
|
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
|
|
3334
3385
|
external: core ? `external: (id: string) =>
|
|
3335
|
-
id === '@src/core' ||
|
|
3386
|
+
id === '@src/core' ||
|
|
3387
|
+
id.startsWith('node:') ||
|
|
3388
|
+
id.startsWith('@orkestrel/') ||
|
|
3389
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
|
|
3390
|
+
id.startsWith('node:') ||
|
|
3391
|
+
id.startsWith('@orkestrel/') ||
|
|
3392
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
|
|
3336
3393
|
output: core ? `\t\t\t\t\toutput: [
|
|
3337
3394
|
{
|
|
3338
3395
|
format: 'es',
|
|
@@ -3419,6 +3476,10 @@ export function appShowcase(): UserConfig {
|
|
|
3419
3476
|
projects.push("policy");
|
|
3420
3477
|
factories.push(CONFIG_TEMPLATES.factories.config);
|
|
3421
3478
|
projects.push("config");
|
|
3479
|
+
if (blueprint.setup) {
|
|
3480
|
+
factories.push(CONFIG_TEMPLATES.factories.setup);
|
|
3481
|
+
projects.push("setup");
|
|
3482
|
+
}
|
|
3422
3483
|
if (blueprint.guides) {
|
|
3423
3484
|
factories.push(CONFIG_TEMPLATES.factories.guides);
|
|
3424
3485
|
projects.push("guides");
|
|
@@ -4741,6 +4802,7 @@ function createBlueprint(name, input) {
|
|
|
4741
4802
|
engines: input?.engines ?? DEFAULT_ENGINES,
|
|
4742
4803
|
overrides: input?.overrides ?? [],
|
|
4743
4804
|
bin: input?.bin ?? false,
|
|
4805
|
+
setup: input?.setup ?? false,
|
|
4744
4806
|
guides: input?.guides ?? false,
|
|
4745
4807
|
distribution: input?.distribution ?? false,
|
|
4746
4808
|
integration: input?.integration ?? false,
|