@orkestrel/scaffold 0.0.50 → 0.0.51
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 +46 -17
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +2 -2
- package/dist/host/agents/orchestration.md +14 -12
- package/dist/host/claude/agents/orkestrel.md +10 -10
- package/dist/host/claude/rules/architecture.md +6 -6
- package/dist/host/claude/rules/tests.md +4 -2
- package/dist/host/claude/rules/workspace.md +1 -1
- package/dist/host/codex/config.toml +1 -1
- package/dist/host/guides/scaffold.md +48 -44
- package/dist/host/manifest.json +10 -10
- package/dist/host/tests/config.test.ts +57 -0
- package/dist/src/core/index.cjs +452 -405
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +51 -48
- package/dist/src/core/index.d.ts +51 -48
- package/dist/src/core/index.js +452 -405
- package/dist/src/core/index.js.map +1 -1
- package/package.json +1 -1
package/dist/src/core/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { fillTemplate } from "@orkestrel/template";
|
|
|
3
3
|
import { Emitter } from "@orkestrel/emitter";
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@orkestrel/scaffold",
|
|
6
|
-
version: "0.0.
|
|
6
|
+
version: "0.0.51",
|
|
7
7
|
description: "Scaffold workspaces with five commands: new, audit, repair, catalog, and overwrite.",
|
|
8
8
|
keywords: [
|
|
9
9
|
"audit",
|
|
@@ -560,7 +560,7 @@ var CONFIG_TEMPLATES = Object.freeze({
|
|
|
560
560
|
}
|
|
561
561
|
`,
|
|
562
562
|
vite: `import type { {{viteTypes}} } from 'vite'
|
|
563
|
-
{{imports}}import { defineConfig
|
|
563
|
+
{{imports}}import { defineConfig } from 'vitest/config'
|
|
564
564
|
import manifest from './package.json' with { type: 'json' }
|
|
565
565
|
import tsconfig from './tsconfig.json' with { type: 'json' }
|
|
566
566
|
{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'
|
|
@@ -599,160 +599,140 @@ const resolve = {
|
|
|
599
599
|
}),
|
|
600
600
|
factories: Object.freeze({
|
|
601
601
|
src: Object.freeze({
|
|
602
|
-
core: `export const srcCore = (
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
},
|
|
620
|
-
},
|
|
621
|
-
options ?? {},
|
|
622
|
-
)
|
|
602
|
+
core: `export const srcCore = (): UserConfig => ({
|
|
603
|
+
resolve,
|
|
604
|
+
publicDir: false,
|
|
605
|
+
build: {
|
|
606
|
+
emptyOutDir: true,
|
|
607
|
+
sourcemap: true,
|
|
608
|
+
minify: false,
|
|
609
|
+
rolldownOptions: { onLog: enforceBuildLog },
|
|
610
|
+
},
|
|
611
|
+
test: {
|
|
612
|
+
name: { label: 'src:core', color: 'magenta' },
|
|
613
|
+
include: ['tests/src/core/**/*.test.ts'],
|
|
614
|
+
setupFiles: ['./tests/setup.ts'],
|
|
615
|
+
environment: 'node',
|
|
616
|
+
browser: { enabled: false },
|
|
617
|
+
},
|
|
618
|
+
})
|
|
623
619
|
`,
|
|
624
|
-
browser: `export const srcBrowser = (
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
onLog: enforceBuildLog,
|
|
642
|
-
{{external}}
|
|
620
|
+
browser: `export const srcBrowser = (): UserConfig => ({
|
|
621
|
+
resolve,
|
|
622
|
+
publicDir: false,
|
|
623
|
+
plugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],
|
|
624
|
+
build: {
|
|
625
|
+
emptyOutDir: true,
|
|
626
|
+
sourcemap: true,
|
|
627
|
+
minify: false,
|
|
628
|
+
lib: {
|
|
629
|
+
entry: resolveWorkspacePath('src/browser/index.ts'),
|
|
630
|
+
formats: ['es'],
|
|
631
|
+
fileName: () => 'index.js',
|
|
632
|
+
},
|
|
633
|
+
outDir: 'dist/src/browser',
|
|
634
|
+
rolldownOptions: {
|
|
635
|
+
onLog: enforceBuildLog,
|
|
636
|
+
{{external}}
|
|
643
637
|
{{output}}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
{{exclude}}
|
|
638
|
+
},
|
|
639
|
+
},
|
|
640
|
+
test: {
|
|
641
|
+
name: { label: 'src:browser', color: 'yellow' },
|
|
642
|
+
include: ['tests/src/browser/**/*.test.ts'],
|
|
643
|
+
{{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
|
|
650
644
|
{{global}}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
},
|
|
656
|
-
fileParallelism: false,
|
|
657
|
-
},
|
|
645
|
+
browser: {
|
|
646
|
+
enabled: true,
|
|
647
|
+
provider: playwright(browserOptions),
|
|
648
|
+
instances: [{ browser: 'chromium', headless: true }],
|
|
658
649
|
},
|
|
659
|
-
|
|
660
|
-
|
|
650
|
+
fileParallelism: false,
|
|
651
|
+
},
|
|
652
|
+
})
|
|
661
653
|
`,
|
|
662
|
-
server: `export const srcServer = (
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
platform: 'node',
|
|
682
|
-
{{external}}
|
|
654
|
+
server: `export const srcServer = (): UserConfig => ({
|
|
655
|
+
resolve,
|
|
656
|
+
publicDir: false,
|
|
657
|
+
plugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],
|
|
658
|
+
build: {
|
|
659
|
+
emptyOutDir: true,
|
|
660
|
+
sourcemap: true,
|
|
661
|
+
minify: false,
|
|
662
|
+
lib: {
|
|
663
|
+
entry: resolveWorkspacePath('src/server/index.ts'),
|
|
664
|
+
formats: ['es', 'cjs'],
|
|
665
|
+
fileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),
|
|
666
|
+
},
|
|
667
|
+
outDir: 'dist/src/server',
|
|
668
|
+
target: 'node22',
|
|
669
|
+
rolldownOptions: {
|
|
670
|
+
onLog: enforceBuildLog,
|
|
671
|
+
platform: 'node',
|
|
672
|
+
{{external}}
|
|
683
673
|
{{output}}
|
|
684
|
-
},
|
|
685
|
-
},
|
|
686
|
-
test: {
|
|
687
|
-
name: { label: 'src:server', color: 'red' },
|
|
688
|
-
include: ['tests/src/server/**/*.test.ts'],
|
|
689
|
-
{{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
|
|
690
|
-
environment: 'node',
|
|
691
|
-
browser: { enabled: false },
|
|
692
|
-
},
|
|
693
674
|
},
|
|
694
|
-
|
|
695
|
-
|
|
675
|
+
},
|
|
676
|
+
test: {
|
|
677
|
+
name: { label: 'src:server', color: 'red' },
|
|
678
|
+
include: ['tests/src/server/**/*.test.ts'],
|
|
679
|
+
{{exclude}} setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
|
|
680
|
+
environment: 'node',
|
|
681
|
+
browser: { enabled: false },
|
|
682
|
+
},
|
|
683
|
+
})
|
|
696
684
|
`,
|
|
697
|
-
bin: `export const srcBin = (
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
formats: ['es'],
|
|
710
|
-
fileName: () => 'main.js',
|
|
711
|
-
},
|
|
712
|
-
outDir: 'dist/bin',
|
|
713
|
-
target: 'node22',
|
|
714
|
-
rolldownOptions: {
|
|
715
|
-
onLog: enforceBuildLog,
|
|
716
|
-
external: (id: string) =>
|
|
717
|
-
id.startsWith('node:') ||
|
|
718
|
-
id.startsWith('@orkestrel/') ||
|
|
719
|
-
id.startsWith('@src/') ||
|
|
720
|
-
peers.some((peer) => id === peer || id.startsWith(peer + '/')),
|
|
721
|
-
},
|
|
722
|
-
},
|
|
723
|
-
test: {
|
|
724
|
-
name: { label: 'src:bin', color: 'yellow' },
|
|
725
|
-
include: ['tests/src/bin/**/*.test.ts'],
|
|
726
|
-
setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
|
|
727
|
-
environment: 'node',
|
|
728
|
-
browser: { enabled: false },
|
|
729
|
-
// A bin test drives the real executable over a real temporary repository, so it
|
|
730
|
-
// spends seconds in process startup and filesystem work rather than milliseconds.
|
|
731
|
-
// Vitest's five-second default clears one alone and times out under a full suite.
|
|
732
|
-
testTimeout: 15_000,
|
|
733
|
-
},
|
|
685
|
+
bin: `export const srcBin = (): UserConfig => ({
|
|
686
|
+
resolve,
|
|
687
|
+
publicDir: false,
|
|
688
|
+
plugins: [outputBoundary('dist/bin')],
|
|
689
|
+
build: {
|
|
690
|
+
emptyOutDir: true,
|
|
691
|
+
sourcemap: true,
|
|
692
|
+
minify: false,
|
|
693
|
+
lib: {
|
|
694
|
+
entry: resolveWorkspacePath('${BIN_ENTRY_PATH}'),
|
|
695
|
+
formats: ['es'],
|
|
696
|
+
fileName: () => 'main.js',
|
|
734
697
|
},
|
|
735
|
-
|
|
736
|
-
|
|
698
|
+
outDir: 'dist/bin',
|
|
699
|
+
target: 'node22',
|
|
700
|
+
rolldownOptions: {
|
|
701
|
+
onLog: enforceBuildLog,
|
|
702
|
+
external: (id: string) =>
|
|
703
|
+
id.startsWith('node:') ||
|
|
704
|
+
id.startsWith('@orkestrel/') ||
|
|
705
|
+
id.startsWith('@src/') ||
|
|
706
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),
|
|
707
|
+
},
|
|
708
|
+
},
|
|
709
|
+
test: {
|
|
710
|
+
name: { label: 'src:bin', color: 'yellow' },
|
|
711
|
+
include: ['tests/src/bin/**/*.test.ts'],
|
|
712
|
+
setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
|
|
713
|
+
environment: 'node',
|
|
714
|
+
browser: { enabled: false },
|
|
715
|
+
// A bin test drives the real executable over a real temporary repository, so it
|
|
716
|
+
// spends seconds in process startup and filesystem work rather than milliseconds.
|
|
717
|
+
// Vitest's five-second default clears one alone and times out under a full suite.
|
|
718
|
+
testTimeout: 15_000,
|
|
719
|
+
},
|
|
720
|
+
})
|
|
737
721
|
`
|
|
738
722
|
}),
|
|
739
723
|
app: Object.freeze({
|
|
740
|
-
core: `export const appCore = (
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
},
|
|
753
|
-
},
|
|
754
|
-
options ?? {},
|
|
755
|
-
)
|
|
724
|
+
core: `export const appCore = (): UserConfig => ({
|
|
725
|
+
resolve,
|
|
726
|
+
publicDir: false,
|
|
727
|
+
plugins: [environmentBoundary('app/core')],
|
|
728
|
+
test: {
|
|
729
|
+
name: { label: 'app:core', color: 'cyan' },
|
|
730
|
+
include: ['tests/app/core/**/*.test.ts'],
|
|
731
|
+
setupFiles: ['./tests/setup.ts'],
|
|
732
|
+
environment: 'node',
|
|
733
|
+
browser: { enabled: false },
|
|
734
|
+
},
|
|
735
|
+
})
|
|
756
736
|
`,
|
|
757
737
|
browser: `function applicationBrowser(showcase: boolean): UserConfig {
|
|
758
738
|
const output = showcase ? 'dist/showcase' : 'dist/app/browser'
|
|
@@ -784,197 +764,157 @@ const resolve = {
|
|
|
784
764
|
}
|
|
785
765
|
}
|
|
786
766
|
|
|
787
|
-
export function appBrowser(
|
|
788
|
-
return
|
|
767
|
+
export function appBrowser(): UserConfig {
|
|
768
|
+
return applicationBrowser(false)
|
|
789
769
|
}
|
|
790
770
|
{{showcaseFactory}}`,
|
|
791
|
-
server: `export const appServer = (
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
formats: ['cjs'],
|
|
802
|
-
fileName: () => 'main.cjs',
|
|
803
|
-
},
|
|
804
|
-
outDir: resolveWorkspacePath('dist/app/server'),
|
|
805
|
-
target: 'node22',
|
|
806
|
-
rolldownOptions: {
|
|
807
|
-
onLog: enforceBuildLog,
|
|
808
|
-
external: (id: string) => id.startsWith('node:'),
|
|
809
|
-
},
|
|
810
|
-
},
|
|
811
|
-
test: {
|
|
812
|
-
name: { label: 'app:server', color: 'green' },
|
|
813
|
-
include: ['tests/app/server/**/*.test.ts'],
|
|
814
|
-
setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
|
|
815
|
-
environment: 'node',
|
|
816
|
-
browser: { enabled: false },
|
|
817
|
-
},
|
|
771
|
+
server: `export const appServer = (): UserConfig => ({
|
|
772
|
+
resolve,
|
|
773
|
+
publicDir: false,
|
|
774
|
+
plugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],
|
|
775
|
+
build: {
|
|
776
|
+
emptyOutDir: true,
|
|
777
|
+
lib: {
|
|
778
|
+
entry: resolveWorkspacePath('app/server/main.ts'),
|
|
779
|
+
formats: ['cjs'],
|
|
780
|
+
fileName: () => 'main.cjs',
|
|
818
781
|
},
|
|
819
|
-
|
|
820
|
-
|
|
782
|
+
outDir: resolveWorkspacePath('dist/app/server'),
|
|
783
|
+
target: 'node22',
|
|
784
|
+
rolldownOptions: {
|
|
785
|
+
onLog: enforceBuildLog,
|
|
786
|
+
external: (id: string) => id.startsWith('node:'),
|
|
787
|
+
},
|
|
788
|
+
},
|
|
789
|
+
test: {
|
|
790
|
+
name: { label: 'app:server', color: 'green' },
|
|
791
|
+
include: ['tests/app/server/**/*.test.ts'],
|
|
792
|
+
setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
|
|
793
|
+
environment: 'node',
|
|
794
|
+
browser: { enabled: false },
|
|
795
|
+
},
|
|
796
|
+
})
|
|
821
797
|
`
|
|
822
798
|
}),
|
|
823
|
-
policy: `export const policy = (
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
},
|
|
834
|
-
},
|
|
835
|
-
options ?? {},
|
|
836
|
-
)
|
|
799
|
+
policy: `export const policy = (): UserConfig => ({
|
|
800
|
+
resolve,
|
|
801
|
+
test: {
|
|
802
|
+
name: { label: 'policy', color: 'white' },
|
|
803
|
+
include: ['tests/policy.test.ts'],
|
|
804
|
+
setupFiles: ['./tests/setup.ts'],
|
|
805
|
+
environment: 'node',
|
|
806
|
+
browser: { enabled: false },
|
|
807
|
+
},
|
|
808
|
+
})
|
|
837
809
|
`,
|
|
838
|
-
config: `export const config = (
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
},
|
|
852
|
-
},
|
|
853
|
-
options ?? {},
|
|
854
|
-
)
|
|
810
|
+
config: `export const config = (): UserConfig => ({
|
|
811
|
+
resolve,
|
|
812
|
+
test: {
|
|
813
|
+
name: { label: 'config', color: 'yellow' },
|
|
814
|
+
include: ['tests/config.test.ts'],
|
|
815
|
+
setupFiles: ['./tests/setup.ts'],
|
|
816
|
+
environment: 'node',
|
|
817
|
+
browser: { enabled: false },
|
|
818
|
+
// A config test validates every target wrapper and runs the real linter twice with
|
|
819
|
+
// 15-second child caps, so this budget clears both caps and reports their diagnostics.
|
|
820
|
+
testTimeout: 45_000,
|
|
821
|
+
},
|
|
822
|
+
})
|
|
855
823
|
`,
|
|
856
|
-
setup: `export const setup = (
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
},
|
|
867
|
-
},
|
|
868
|
-
options ?? {},
|
|
869
|
-
)
|
|
824
|
+
setup: `export const setup = (): UserConfig => ({
|
|
825
|
+
resolve,
|
|
826
|
+
test: {
|
|
827
|
+
name: { label: 'setup', color: 'white' },
|
|
828
|
+
include: ['tests/setup*.test.ts'],
|
|
829
|
+
setupFiles: ['./tests/setup.ts'],
|
|
830
|
+
environment: 'node',
|
|
831
|
+
browser: { enabled: false },
|
|
832
|
+
},
|
|
833
|
+
})
|
|
870
834
|
`,
|
|
871
|
-
guides: `export const guides = (
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
},
|
|
883
|
-
},
|
|
884
|
-
options ?? {},
|
|
885
|
-
)
|
|
835
|
+
guides: `export const guides = (): UserConfig => ({
|
|
836
|
+
resolve,
|
|
837
|
+
test: {
|
|
838
|
+
name: { label: 'guides', color: 'green' },
|
|
839
|
+
include: ['${GUIDES_TEST_PATH}'],
|
|
840
|
+
exclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],
|
|
841
|
+
setupFiles: ['./tests/setup.ts'],
|
|
842
|
+
environment: 'node',
|
|
843
|
+
browser: { enabled: false },
|
|
844
|
+
},
|
|
845
|
+
})
|
|
886
846
|
`,
|
|
887
847
|
conformance: `// Where this package drifts from the official tooling it stays compatible with.
|
|
888
848
|
// The subject is this package, so the proof is hermetic and stays in \`npm test\`.
|
|
889
|
-
export const conformance = (
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
},
|
|
900
|
-
},
|
|
901
|
-
options ?? {},
|
|
902
|
-
)
|
|
849
|
+
export const conformance = (): UserConfig => ({
|
|
850
|
+
resolve,
|
|
851
|
+
test: {
|
|
852
|
+
name: { label: 'conformance', color: 'magenta' },
|
|
853
|
+
include: ['${CONFORMANCE_TEST_PATH}'],
|
|
854
|
+
setupFiles: ['./tests/setup.ts'],
|
|
855
|
+
environment: 'node',
|
|
856
|
+
browser: { enabled: false },
|
|
857
|
+
},
|
|
858
|
+
})
|
|
903
859
|
`,
|
|
904
860
|
service: `// The live external services this package drives. It starts nothing itself:
|
|
905
861
|
// \`scripts/service.sh\` provisions, \`tests/setupService.ts\` proves readiness, and
|
|
906
862
|
// the project stays out of \`npm test\` because a real service answers it.
|
|
907
|
-
export const service = (
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
},
|
|
921
|
-
},
|
|
922
|
-
options ?? {},
|
|
923
|
-
)
|
|
863
|
+
export const service = (): UserConfig => ({
|
|
864
|
+
resolve,
|
|
865
|
+
test: {
|
|
866
|
+
name: { label: 'service', color: 'red' },
|
|
867
|
+
include: ['${SERVICE_TEST_INCLUDE}'],
|
|
868
|
+
setupFiles: ['./tests/setup.ts', './tests/setupService.ts'],
|
|
869
|
+
environment: 'node',
|
|
870
|
+
browser: { enabled: false },
|
|
871
|
+
testTimeout: 120_000,
|
|
872
|
+
hookTimeout: 120_000,
|
|
873
|
+
fileParallelism: false,
|
|
874
|
+
},
|
|
875
|
+
})
|
|
924
876
|
`,
|
|
925
|
-
distribution: `export const distribution = (
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
},
|
|
938
|
-
},
|
|
939
|
-
options ?? {},
|
|
940
|
-
)
|
|
877
|
+
distribution: `export const distribution = (): UserConfig => ({
|
|
878
|
+
resolve,
|
|
879
|
+
test: {
|
|
880
|
+
name: { label: 'distribution', color: 'cyan' },
|
|
881
|
+
include: ['${DISTRIBUTION_TEST_PATH}'],
|
|
882
|
+
setupFiles: ['./tests/setup.ts'],
|
|
883
|
+
environment: 'node',
|
|
884
|
+
testTimeout: 120_000,
|
|
885
|
+
hookTimeout: 120_000,
|
|
886
|
+
fileParallelism: false,
|
|
887
|
+
},
|
|
888
|
+
})
|
|
941
889
|
`,
|
|
942
890
|
probe: `// A workbench, not a proof. No gate selects this project. Run in test mode by the
|
|
943
891
|
// \`test:probe\` script, it collects \`tmp/probe/**/*.test.ts\`. Run in benchmark mode by the
|
|
944
892
|
// \`test:bench\` script, the same workbench also collects \`tests/**/*.test.ts\` for a \`bench\` block,
|
|
945
893
|
// so a suite may carry a bench beside its ordinary tests without a second project. The mode
|
|
946
894
|
// guard around each \`bench\` call keeps it out of test mode, so it never executes there.
|
|
947
|
-
export const probe = (
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
},
|
|
961
|
-
},
|
|
962
|
-
options ?? {},
|
|
963
|
-
)
|
|
895
|
+
export const probe = (): UserConfig => ({
|
|
896
|
+
resolve,
|
|
897
|
+
test: {
|
|
898
|
+
name: { label: 'probe', color: 'black' },
|
|
899
|
+
include: ['tmp/probe/**/*.test.ts'],
|
|
900
|
+
setupFiles: ['./tests/setup.ts'],
|
|
901
|
+
environment: 'node',
|
|
902
|
+
browser: { enabled: false },
|
|
903
|
+
fileParallelism: false,
|
|
904
|
+
pool: 'threads',
|
|
905
|
+
benchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },
|
|
906
|
+
},
|
|
907
|
+
})
|
|
964
908
|
`,
|
|
965
|
-
integration: `export const integration = (
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
},
|
|
975
|
-
},
|
|
976
|
-
options ?? {},
|
|
977
|
-
)
|
|
909
|
+
integration: `export const integration = (): UserConfig => ({
|
|
910
|
+
resolve,
|
|
911
|
+
test: {
|
|
912
|
+
name: { label: 'integration', color: 'blue' },
|
|
913
|
+
include: ['${INTEGRATION_TEST_PATH}'],
|
|
914
|
+
setupFiles: ['./tests/setup.ts'],
|
|
915
|
+
{{global}} environment: 'node',
|
|
916
|
+
},
|
|
917
|
+
})
|
|
978
918
|
`
|
|
979
919
|
}),
|
|
980
920
|
tsconfigs: Object.freeze({
|
|
@@ -1102,13 +1042,13 @@ export const probe = (options?: UserConfig): UserConfig =>
|
|
|
1102
1042
|
}),
|
|
1103
1043
|
vites: Object.freeze({
|
|
1104
1044
|
src: Object.freeze({
|
|
1105
|
-
core: `import { defineConfig } from 'vite'
|
|
1045
|
+
core: `import { defineConfig, mergeConfig } from 'vite'
|
|
1106
1046
|
import dts from 'vite-plugin-dts'
|
|
1107
1047
|
import { environmentBoundary, outputBoundary } from '../helpers.js'
|
|
1108
1048
|
import { peers, srcCore, resolveWorkspacePath } from '../../vite.config.ts'
|
|
1109
1049
|
|
|
1110
1050
|
export default defineConfig(
|
|
1111
|
-
srcCore({
|
|
1051
|
+
mergeConfig(srcCore(), {
|
|
1112
1052
|
publicDir: false,
|
|
1113
1053
|
plugins: [
|
|
1114
1054
|
outputBoundary('dist/src/core'),
|
|
@@ -1130,7 +1070,7 @@ export default defineConfig(
|
|
|
1130
1070
|
lib: {
|
|
1131
1071
|
entry: resolveWorkspacePath('src/core/index.ts'),
|
|
1132
1072
|
formats: ['es', 'cjs'],
|
|
1133
|
-
fileName: (format) => (format === 'es' ? 'index.js' : 'index.cjs'),
|
|
1073
|
+
fileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),
|
|
1134
1074
|
},
|
|
1135
1075
|
outDir: 'dist/src/core',
|
|
1136
1076
|
rolldownOptions: {
|
|
@@ -1143,17 +1083,17 @@ export default defineConfig(
|
|
|
1143
1083
|
}),
|
|
1144
1084
|
)
|
|
1145
1085
|
`,
|
|
1146
|
-
browser: `import { defineConfig } from 'vite'
|
|
1086
|
+
browser: `import { defineConfig, mergeConfig } from 'vite'
|
|
1147
1087
|
import dts from 'vite-plugin-dts'
|
|
1148
1088
|
import { srcBrowser, resolveWorkspacePath } from '../../vite.config.ts'
|
|
1149
1089
|
|
|
1150
1090
|
// vite-plugin-dts rolls this face into one declaration, and the roll-up reaches
|
|
1151
1091
|
// src/core through a relative source path the tarball does not carry. The path
|
|
1152
1092
|
// keeps each source module's own depth, so a module in a browser subfolder emits
|
|
1153
|
-
// one that leaves dist/src entirely. The rewrite
|
|
1154
|
-
// the package's own published root export, on the final roll-up only.
|
|
1093
|
+
// one that leaves dist/src entirely. The following rewrite externalizes core
|
|
1094
|
+
// through the package's own published root export, on the final roll-up only.
|
|
1155
1095
|
export default defineConfig(
|
|
1156
|
-
srcBrowser({
|
|
1096
|
+
mergeConfig(srcBrowser(), {
|
|
1157
1097
|
plugins: [
|
|
1158
1098
|
dts({
|
|
1159
1099
|
tsconfigPath: resolveWorkspacePath('configs/src/tsconfig.browser.json'),
|
|
@@ -1168,16 +1108,16 @@ export default defineConfig(
|
|
|
1168
1108
|
}),
|
|
1169
1109
|
)
|
|
1170
1110
|
`,
|
|
1171
|
-
server: `import { defineConfig } from 'vite'
|
|
1111
|
+
server: `import { defineConfig, mergeConfig } from 'vite'
|
|
1172
1112
|
import dts from 'vite-plugin-dts'
|
|
1173
1113
|
import { srcServer, resolveWorkspacePath } from '../../vite.config.ts'
|
|
1174
1114
|
|
|
1175
1115
|
// vite-plugin-dts rolls this face into one declaration, and the roll-up reaches
|
|
1176
|
-
// src/core through a relative source path the tarball does not carry. The
|
|
1177
|
-
//
|
|
1178
|
-
// final roll-up only.
|
|
1116
|
+
// src/core through a relative source path the tarball does not carry. The
|
|
1117
|
+
// following rewrite externalizes core through the package's own published root
|
|
1118
|
+
// export, on the final roll-up only.
|
|
1179
1119
|
export default defineConfig(
|
|
1180
|
-
srcServer({
|
|
1120
|
+
mergeConfig(srcServer(), {
|
|
1181
1121
|
plugins: [
|
|
1182
1122
|
dts({
|
|
1183
1123
|
tsconfigPath: resolveWorkspacePath('configs/src/tsconfig.server.json'),
|
|
@@ -1193,7 +1133,7 @@ export default defineConfig(
|
|
|
1193
1133
|
)
|
|
1194
1134
|
`
|
|
1195
1135
|
}),
|
|
1196
|
-
bin: `import { defineConfig } from 'vite'
|
|
1136
|
+
bin: `import { defineConfig, mergeConfig } from 'vite'
|
|
1197
1137
|
import { srcBin } from '../../vite.config.ts'
|
|
1198
1138
|
|
|
1199
1139
|
// The \`scaffold\` executable build — a single ESM lib file, no declarations (an
|
|
@@ -1202,7 +1142,7 @@ import { srcBin } from '../../vite.config.ts'
|
|
|
1202
1142
|
// \`output.paths\` rewriting the externalized \`@src/*\` specifiers to the built sibling
|
|
1203
1143
|
// src environments (relative to \`dist/bin/\`), so the emitted bin resolves at runtime.
|
|
1204
1144
|
export default defineConfig(
|
|
1205
|
-
srcBin({
|
|
1145
|
+
mergeConfig(srcBin(), {
|
|
1206
1146
|
build: {
|
|
1207
1147
|
rolldownOptions: {
|
|
1208
1148
|
output: {
|
|
@@ -1640,8 +1580,8 @@ const SHELL = process.platform === 'win32'
|
|
|
1640
1580
|
// Release is the publish gate, so evidence it cannot obtain fails there and skips
|
|
1641
1581
|
// everywhere else: a gate that passes on missing evidence proves nothing.
|
|
1642
1582
|
const RELEASE = import.meta.env.MODE === 'release'
|
|
1643
|
-
// The built output directory a browser face
|
|
1644
|
-
// reads this prefix off the export
|
|
1583
|
+
// The built output directory convention a browser face may publish from. Every
|
|
1584
|
+
// selection reads this prefix off the export target and never off the subpath name. A
|
|
1645
1585
|
// workspace whose only published face is the browser one publishes that face at the
|
|
1646
1586
|
// root subpath, so a rule keyed on the subpath name drives a browser bundle through
|
|
1647
1587
|
// Node and the miss is silent.
|
|
@@ -1929,11 +1869,33 @@ function readPackageType(installed: string, target: string): unknown {
|
|
|
1929
1869
|
}
|
|
1930
1870
|
}
|
|
1931
1871
|
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1872
|
+
function resolvesBrowser(entry: unknown): boolean {
|
|
1873
|
+
const module = resolveTarget(entry, RUNTIME_CONDITIONS.browser)
|
|
1874
|
+
if (module !== undefined && module.startsWith(BROWSER_OUTPUT)) return true
|
|
1875
|
+
if (module === undefined) return false
|
|
1876
|
+
const imported = resolveTarget(entry, RUNTIME_CONDITIONS.module)
|
|
1877
|
+
const required = resolveTarget(entry, RUNTIME_CONDITIONS.commonjs)
|
|
1878
|
+
return module !== imported && module !== required
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
// Whether the target selected by Node's CommonJS conditions is a module require can
|
|
1882
|
+
// load. A JavaScript target takes its own nearest package scope. Native addons and
|
|
1883
|
+
// extensionless targets have their own CommonJS handlers.
|
|
1936
1884
|
function resolvesCommonJS(entry: unknown, installed: string): boolean {
|
|
1885
|
+
const target = resolveTarget(entry, RUNTIME_CONDITIONS.commonjs)
|
|
1886
|
+
if (target === undefined) return false
|
|
1887
|
+
const name = target.slice(target.lastIndexOf('/') + 1)
|
|
1888
|
+
if (name.endsWith('.cjs')) return true
|
|
1889
|
+
if (name.endsWith('.mjs')) return false
|
|
1890
|
+
if (name.endsWith('.node')) return true
|
|
1891
|
+
if (!name.includes('.')) return true
|
|
1892
|
+
return name.endsWith('.js') && readPackageType(installed, target) !== 'module'
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
// Whether the declaration selected by a typed CommonJS consumer admits that entry.
|
|
1896
|
+
// A \`.d.cts\` declaration admits and a \`.d.mts\` declaration refuses. A \`.d.ts\`
|
|
1897
|
+
// declaration takes its own nearest package scope.
|
|
1898
|
+
function declaresCommonJS(entry: unknown, installed: string): boolean {
|
|
1937
1899
|
const declaration = resolveDeclaration(entry, DECLARATION_CONDITIONS.commonjs, installed)
|
|
1938
1900
|
if (declaration === undefined) return false
|
|
1939
1901
|
if (declaration.endsWith('.d.cts')) return true
|
|
@@ -1996,13 +1958,13 @@ function selectEntries(entries: readonly Entry[], conditions: readonly string[])
|
|
|
1996
1958
|
// Require-loadable entries that declare CommonJS support but a typed CommonJS
|
|
1997
1959
|
// consumer cannot compile against. A default branch resolving under the require
|
|
1998
1960
|
// condition set makes no CommonJS claim.
|
|
1999
|
-
function selectUntypable(entries: readonly Entry[]): readonly Entry[] {
|
|
1961
|
+
function selectUntypable(entries: readonly Entry[], installed: string): readonly Entry[] {
|
|
2000
1962
|
return entries.filter(
|
|
2001
1963
|
(entry) =>
|
|
2002
1964
|
entry.required &&
|
|
2003
1965
|
isRecord(entry.mapping) &&
|
|
2004
1966
|
Object.hasOwn(entry.mapping, 'require') &&
|
|
2005
|
-
!entry.
|
|
1967
|
+
!declaresCommonJS(entry.mapping, installed),
|
|
2006
1968
|
)
|
|
2007
1969
|
}
|
|
2008
1970
|
|
|
@@ -2135,9 +2097,11 @@ function buildStage(): Stage {
|
|
|
2135
2097
|
continue
|
|
2136
2098
|
}
|
|
2137
2099
|
const imported = resolveTarget(entry, RUNTIME_CONDITIONS.module)
|
|
2138
|
-
const
|
|
2139
|
-
const
|
|
2140
|
-
const
|
|
2100
|
+
const requiredTarget = resolveTarget(entry, RUNTIME_CONDITIONS.commonjs)
|
|
2101
|
+
const browserTarget = resolveTarget(entry, RUNTIME_CONDITIONS.browser)
|
|
2102
|
+
const browser = resolvesBrowser(entry)
|
|
2103
|
+
const required = requiredTarget !== undefined && !(browser && requiredTarget === browserTarget)
|
|
2104
|
+
const commonjs = required && resolvesCommonJS(entry, installed)
|
|
2141
2105
|
entries.push({
|
|
2142
2106
|
subpath,
|
|
2143
2107
|
specifier: subpath === '.' ? name : \`\${name}\${subpath.slice(1)}\`,
|
|
@@ -2149,8 +2113,8 @@ function buildStage(): Stage {
|
|
|
2149
2113
|
browser:
|
|
2150
2114
|
declaration.browser === undefined ? undefined : join(installed, declaration.browser),
|
|
2151
2115
|
},
|
|
2152
|
-
browser
|
|
2153
|
-
module: imported !== undefined,
|
|
2116
|
+
browser,
|
|
2117
|
+
module: imported !== undefined && !(browser && imported === browserTarget),
|
|
2154
2118
|
commonjs,
|
|
2155
2119
|
required,
|
|
2156
2120
|
})
|
|
@@ -2191,6 +2155,74 @@ function openStage(): Stage | undefined {
|
|
|
2191
2155
|
const STAGE = openStage()
|
|
2192
2156
|
const STAGED = STAGE !== undefined
|
|
2193
2157
|
|
|
2158
|
+
describe('distribution classifiers', () => {
|
|
2159
|
+
it('classifies synthetic export mappings without a registry stage', () => {
|
|
2160
|
+
const root = join(SCRATCH, 'classifiers')
|
|
2161
|
+
writeFile(
|
|
2162
|
+
join(root, 'package.json'),
|
|
2163
|
+
JSON.stringify({
|
|
2164
|
+
type: 'commonjs',
|
|
2165
|
+
exports: {
|
|
2166
|
+
condition: { browser: './b.js', default: './n.js' },
|
|
2167
|
+
convention: { default: './dist/src/browser/index.js' },
|
|
2168
|
+
universal: { default: './shared.js' },
|
|
2169
|
+
'import-shared': {
|
|
2170
|
+
browser: './shared.mjs',
|
|
2171
|
+
import: './shared.mjs',
|
|
2172
|
+
default: './node.js',
|
|
2173
|
+
},
|
|
2174
|
+
'require-shared': {
|
|
2175
|
+
browser: './shared.cjs',
|
|
2176
|
+
require: './shared.cjs',
|
|
2177
|
+
default: './node.js',
|
|
2178
|
+
},
|
|
2179
|
+
node: { node: './node.js', default: './node.js' },
|
|
2180
|
+
silent: { 'module-sync': './x.cjs', import: './x.mjs' },
|
|
2181
|
+
module: { require: './x.mjs' },
|
|
2182
|
+
'nested-module': { require: './module/x.js' },
|
|
2183
|
+
'nested-commonjs': { require: './commonjs/x.js' },
|
|
2184
|
+
esm: { import: './x.mjs' },
|
|
2185
|
+
},
|
|
2186
|
+
}),
|
|
2187
|
+
)
|
|
2188
|
+
writeFile(join(root, 'module/package.json'), '{ "type": "module" }\\n')
|
|
2189
|
+
writeFile(join(root, 'commonjs/package.json'), '{ "type": "commonjs" }\\n')
|
|
2190
|
+
const manifest = readJson(join(root, 'package.json'))
|
|
2191
|
+
if (!isRecord(manifest) || !isRecord(manifest.exports)) {
|
|
2192
|
+
throw new Error('The classifier fixture declares no exports map')
|
|
2193
|
+
}
|
|
2194
|
+
const mappings = manifest.exports
|
|
2195
|
+
expect({
|
|
2196
|
+
condition: resolvesBrowser(mappings.condition),
|
|
2197
|
+
convention: resolvesBrowser(mappings.convention),
|
|
2198
|
+
universal: resolvesBrowser(mappings.universal),
|
|
2199
|
+
import: resolvesBrowser(mappings['import-shared']),
|
|
2200
|
+
require: resolvesBrowser(mappings['require-shared']),
|
|
2201
|
+
node: resolvesBrowser(mappings.node),
|
|
2202
|
+
}).toStrictEqual({
|
|
2203
|
+
condition: true,
|
|
2204
|
+
convention: true,
|
|
2205
|
+
universal: false,
|
|
2206
|
+
import: false,
|
|
2207
|
+
require: false,
|
|
2208
|
+
node: false,
|
|
2209
|
+
})
|
|
2210
|
+
expect({
|
|
2211
|
+
silent: resolvesCommonJS(mappings.silent, root),
|
|
2212
|
+
module: resolvesCommonJS(mappings.module, root),
|
|
2213
|
+
nestedModule: resolvesCommonJS(mappings['nested-module'], root),
|
|
2214
|
+
nestedCommonJS: resolvesCommonJS(mappings['nested-commonjs'], root),
|
|
2215
|
+
esm: resolvesCommonJS(mappings.esm, root),
|
|
2216
|
+
}).toStrictEqual({
|
|
2217
|
+
silent: true,
|
|
2218
|
+
module: false,
|
|
2219
|
+
nestedModule: false,
|
|
2220
|
+
nestedCommonJS: true,
|
|
2221
|
+
esm: false,
|
|
2222
|
+
})
|
|
2223
|
+
})
|
|
2224
|
+
})
|
|
2225
|
+
|
|
2194
2226
|
// The staged consumer, or a skip naming what the run could not reach. \`it.skipIf\`
|
|
2195
2227
|
// carries no reason, so the gate sits here where the test context can state one.
|
|
2196
2228
|
function requireStage(context: TestContext): Stage {
|
|
@@ -2238,7 +2270,7 @@ describe('installed package consumer', () => {
|
|
|
2238
2270
|
(entry) => !entry.module && !entry.required && !entry.browser,
|
|
2239
2271
|
)
|
|
2240
2272
|
expect(unreachable.map((entry) => entry.subpath)).toStrictEqual([])
|
|
2241
|
-
const untypable = selectUntypable(stage.entries)
|
|
2273
|
+
const untypable = selectUntypable(stage.entries, stage.installed)
|
|
2242
2274
|
expect(untypable.map((entry) => entry.subpath)).toStrictEqual([])
|
|
2243
2275
|
})
|
|
2244
2276
|
|
|
@@ -2283,7 +2315,7 @@ describe('installed package consumer', () => {
|
|
|
2283
2315
|
|
|
2284
2316
|
for (const entry of STAGE?.entries ?? []) {
|
|
2285
2317
|
describe(\`installed entry \${entry.subpath}\`, () => {
|
|
2286
|
-
it.runIf(entry.module
|
|
2318
|
+
it.runIf(entry.module)(
|
|
2287
2319
|
'publishes what it declares to a Node import, and no more',
|
|
2288
2320
|
(context) => {
|
|
2289
2321
|
const declaration = entry.declaration.module
|
|
@@ -2295,7 +2327,7 @@ for (const entry of STAGE?.entries ?? []) {
|
|
|
2295
2327
|
},
|
|
2296
2328
|
)
|
|
2297
2329
|
|
|
2298
|
-
it.runIf(
|
|
2330
|
+
it.runIf(entry.required)(
|
|
2299
2331
|
'publishes what it declares to a Node require, and no more',
|
|
2300
2332
|
(context) => {
|
|
2301
2333
|
const declaration = entry.declaration.commonjs
|
|
@@ -4317,7 +4349,7 @@ function blueprintToScripts(blueprint) {
|
|
|
4317
4349
|
scripts["serve:build"] = "npm run build:app:server && npm run serve";
|
|
4318
4350
|
}
|
|
4319
4351
|
if (publishes) {
|
|
4320
|
-
scripts.prepack =
|
|
4352
|
+
scripts.prepack = "npm run build";
|
|
4321
4353
|
scripts.prepublishOnly = [
|
|
4322
4354
|
"npm run format:check && npm run lint:check && npm run check && npm run build && npm test",
|
|
4323
4355
|
RELEASE_PROOF_COMMAND,
|
|
@@ -4330,19 +4362,21 @@ function blueprintToScripts(blueprint) {
|
|
|
4330
4362
|
* Project a blueprint into the manifest scripts a region write may replace.
|
|
4331
4363
|
*
|
|
4332
4364
|
* @param blueprint - The workspace specification.
|
|
4333
|
-
* @returns One entry per writable script
|
|
4334
|
-
* nothing and therefore declares neither script.
|
|
4365
|
+
* @returns One entry per writable script.
|
|
4335
4366
|
*
|
|
4336
4367
|
* @remarks
|
|
4337
|
-
*
|
|
4338
|
-
*
|
|
4339
|
-
*
|
|
4340
|
-
*
|
|
4341
|
-
*
|
|
4368
|
+
* Every direct `test:<project>` script is writable, together with the probe and
|
|
4369
|
+
* benchmark workbench scripts. Publishing adds the pack and publication
|
|
4370
|
+
* lifecycle scripts. Aggregate test scripts and maintainer-owned gate chains
|
|
4371
|
+
* stay outside the region.
|
|
4372
|
+
*
|
|
4373
|
+
* `accepted` carries each generated predecessor the region can replace. The
|
|
4374
|
+
* pack hook accepts the build chain emitted before it delegated to `build`. The
|
|
4375
|
+
* publication hook accepts the same gate chain without
|
|
4342
4376
|
* {@link RELEASE_PROOF_COMMAND}. The value being written is always writable, so
|
|
4343
|
-
* it is not repeated there. Any other value is a
|
|
4344
|
-
* customized, and {@link replaceManifestScripts}
|
|
4345
|
-
*
|
|
4377
|
+
* it is not repeated there. Any other value is a script the workspace author
|
|
4378
|
+
* customized, and {@link replaceManifestScripts} retains it while writing the
|
|
4379
|
+
* other named scripts independently.
|
|
4346
4380
|
*
|
|
4347
4381
|
* @example
|
|
4348
4382
|
* ```ts
|
|
@@ -4350,23 +4384,36 @@ function blueprintToScripts(blueprint) {
|
|
|
4350
4384
|
*
|
|
4351
4385
|
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
4352
4386
|
*
|
|
4353
|
-
* blueprintToWritableScripts(blueprint)[0]?.name // 'test:
|
|
4387
|
+
* blueprintToWritableScripts(blueprint)[0]?.name // 'test:src:core'
|
|
4354
4388
|
* ```
|
|
4355
4389
|
*/
|
|
4356
4390
|
function blueprintToWritableScripts(blueprint) {
|
|
4357
4391
|
const scripts = blueprintToScripts(blueprint);
|
|
4358
|
-
const
|
|
4392
|
+
const writable = [];
|
|
4393
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
4394
|
+
if (!name.startsWith("test:") || name === "test:src" || name === "test:app") continue;
|
|
4395
|
+
writable.push({
|
|
4396
|
+
name,
|
|
4397
|
+
command,
|
|
4398
|
+
accepted: []
|
|
4399
|
+
});
|
|
4400
|
+
}
|
|
4401
|
+
const prepack = scripts.prepack;
|
|
4402
|
+
if (prepack !== void 0) {
|
|
4403
|
+
const predecessor = scripts.build;
|
|
4404
|
+
writable.push({
|
|
4405
|
+
name: "prepack",
|
|
4406
|
+
command: prepack,
|
|
4407
|
+
accepted: predecessor === void 0 ? [] : [predecessor]
|
|
4408
|
+
});
|
|
4409
|
+
}
|
|
4359
4410
|
const prepublish = scripts.prepublishOnly;
|
|
4360
|
-
if (
|
|
4361
|
-
return [{
|
|
4362
|
-
name: "test:distribution",
|
|
4363
|
-
command: distribution,
|
|
4364
|
-
accepted: []
|
|
4365
|
-
}, {
|
|
4411
|
+
if (prepublish !== void 0) writable.push({
|
|
4366
4412
|
name: "prepublishOnly",
|
|
4367
4413
|
command: prepublish,
|
|
4368
4414
|
accepted: [prepublish.replace(` && ${RELEASE_PROOF_COMMAND}`, "")]
|
|
4369
|
-
}
|
|
4415
|
+
});
|
|
4416
|
+
return writable;
|
|
4370
4417
|
}
|
|
4371
4418
|
/**
|
|
4372
4419
|
* Compile a blueprint into its `package.json` content.
|
|
@@ -4549,14 +4596,14 @@ function blueprintToRootVite(blueprint) {
|
|
|
4549
4596
|
const core = blueprint.src.includes("core");
|
|
4550
4597
|
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.browser, {
|
|
4551
4598
|
external: core ? `external: (id: string) =>
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
output: core ? "
|
|
4558
|
-
exclude: core ? "
|
|
4559
|
-
global: blueprint.global ? "
|
|
4599
|
+
id === '@src/core' ||
|
|
4600
|
+
id.startsWith('@orkestrel/') ||
|
|
4601
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
|
|
4602
|
+
id.startsWith('@orkestrel/') ||
|
|
4603
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
|
|
4604
|
+
output: core ? " output: { paths: { '@src/core': '../core/index.js' } }," : " output: {},",
|
|
4605
|
+
exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : "",
|
|
4606
|
+
global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : ""
|
|
4560
4607
|
}));
|
|
4561
4608
|
projects.push("srcBrowser");
|
|
4562
4609
|
}
|
|
@@ -4564,26 +4611,26 @@ function blueprintToRootVite(blueprint) {
|
|
|
4564
4611
|
const core = blueprint.src.includes("core");
|
|
4565
4612
|
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
|
|
4566
4613
|
external: core ? `external: (id: string) =>
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
output: core ? `\t\t\
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
exclude: core ? "
|
|
4614
|
+
id === '@src/core' ||
|
|
4615
|
+
id.startsWith('node:') ||
|
|
4616
|
+
id.startsWith('@orkestrel/') ||
|
|
4617
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),` : `external: (id: string) =>
|
|
4618
|
+
id.startsWith('node:') ||
|
|
4619
|
+
id.startsWith('@orkestrel/') ||
|
|
4620
|
+
peers.some((peer) => id === peer || id.startsWith(peer + '/')),`,
|
|
4621
|
+
output: core ? `\t\t\toutput: [
|
|
4622
|
+
{
|
|
4623
|
+
format: 'es',
|
|
4624
|
+
entryFileNames: 'index.js',
|
|
4625
|
+
paths: { '@src/core': '../core/index.js' },
|
|
4626
|
+
},
|
|
4627
|
+
{
|
|
4628
|
+
format: 'cjs',
|
|
4629
|
+
entryFileNames: 'index.cjs',
|
|
4630
|
+
paths: { '@src/core': '../core/index.cjs' },
|
|
4631
|
+
},
|
|
4632
|
+
],` : " output: {},",
|
|
4633
|
+
exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : ""
|
|
4587
4634
|
}));
|
|
4588
4635
|
projects.push("srcServer");
|
|
4589
4636
|
}
|
|
@@ -4678,7 +4725,7 @@ export function appShowcase(): UserConfig {
|
|
|
4678
4725
|
projects.push("distribution");
|
|
4679
4726
|
}
|
|
4680
4727
|
if (blueprint.integration) {
|
|
4681
|
-
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.integration, { global: blueprint.global ? "
|
|
4728
|
+
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.integration, { global: blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : "" }));
|
|
4682
4729
|
projects.push("integration");
|
|
4683
4730
|
}
|
|
4684
4731
|
factories.push(CONFIG_TEMPLATES.factories.probe);
|
|
@@ -5381,24 +5428,23 @@ function replaceManifestRanges(manifest, pins) {
|
|
|
5381
5428
|
*
|
|
5382
5429
|
* @param manifest - The manifest text to compile.
|
|
5383
5430
|
* @param scripts - The scripts to write, each with the predecessors it accepts.
|
|
5384
|
-
* @returns The manifest carrying every
|
|
5385
|
-
*
|
|
5386
|
-
* no readable `scripts` object to
|
|
5431
|
+
* @returns The manifest carrying every absent or accepted named script and
|
|
5432
|
+
* retaining every differing string value, or `undefined` when a planned key
|
|
5433
|
+
* holds a non-string value or the text carries no readable `scripts` object to
|
|
5434
|
+
* write into.
|
|
5387
5435
|
*
|
|
5388
5436
|
* @remarks
|
|
5389
5437
|
* The compiler replaces values in place instead of serializing the manifest, so
|
|
5390
5438
|
* description, keywords, dependencies, key order, indentation, and every byte
|
|
5391
5439
|
* outside the replaced ranges survive. A named script the manifest already
|
|
5392
|
-
* declares is overwritten only when its value is
|
|
5393
|
-
*
|
|
5394
|
-
*
|
|
5395
|
-
* byte
|
|
5396
|
-
* the
|
|
5397
|
-
*
|
|
5398
|
-
*
|
|
5399
|
-
*
|
|
5400
|
-
* The refusal is whole rather than per script, so a manifest never ends up
|
|
5401
|
-
* holding one written script beside one refused one.
|
|
5440
|
+
* declares is overwritten only when its value is one of its
|
|
5441
|
+
* {@link ManifestScript.accepted} predecessors. The planned value stands. Any
|
|
5442
|
+
* other string is a chain the workspace author customized, so it stays
|
|
5443
|
+
* byte-identical while the other named scripts are written independently. A
|
|
5444
|
+
* named script the manifest does not declare is appended after the last
|
|
5445
|
+
* declared script, copying that section's indentation. A region declaring
|
|
5446
|
+
* nothing takes every named script as its first entries, indented from the line
|
|
5447
|
+
* its own opening brace sits on.
|
|
5402
5448
|
*
|
|
5403
5449
|
* @example
|
|
5404
5450
|
* ```ts
|
|
@@ -5420,7 +5466,6 @@ function replaceManifestScripts(manifest, scripts) {
|
|
|
5420
5466
|
if (!Object.hasOwn(declared, script.name)) continue;
|
|
5421
5467
|
const value = declared[script.name];
|
|
5422
5468
|
if (!isString(value)) return void 0;
|
|
5423
|
-
if (value !== script.command && !script.accepted.includes(value)) return void 0;
|
|
5424
5469
|
}
|
|
5425
5470
|
let depth = 0;
|
|
5426
5471
|
let cursor = 0;
|
|
@@ -5548,6 +5593,8 @@ function replaceManifestScripts(manifest, scripts) {
|
|
|
5548
5593
|
const script = scripts.find((entry) => entry.name === key);
|
|
5549
5594
|
if (script === void 0) continue;
|
|
5550
5595
|
written.add(script.name);
|
|
5596
|
+
const value = declared[script.name];
|
|
5597
|
+
if (value === script.command || !isString(value) || !script.accepted.includes(value)) continue;
|
|
5551
5598
|
edits.push({
|
|
5552
5599
|
start: valueStart,
|
|
5553
5600
|
end: valueEnd + 1,
|