@platforma-sdk/block-tools 2.10.13 → 2.10.15
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/cli.js +23 -2
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +1944 -100
- package/dist/cli.mjs.map +1 -1
- package/dist/cmd/index.d.ts +10 -4
- package/dist/cmd/structure/check.d.ts +10 -0
- package/dist/cmd/structure/init.d.ts +18 -0
- package/dist/cmd/structure/refresh.d.ts +11 -0
- package/dist/cmd/update-deps.d.ts +7 -0
- package/dist/structure/cli/run-structure.d.ts +19 -0
- package/dist/structure/engine/api.d.ts +55 -0
- package/dist/structure/engine/builders.d.ts +95 -0
- package/dist/structure/engine/content-rules.d.ts +148 -0
- package/dist/structure/engine/ctx.d.ts +34 -0
- package/dist/structure/engine/discovery-fs.d.ts +22 -0
- package/dist/structure/engine/discovery.d.ts +39 -0
- package/dist/structure/engine/flatten.d.ts +3 -0
- package/dist/structure/engine/fs/api.d.ts +27 -0
- package/dist/structure/engine/fs/memory.d.ts +16 -0
- package/dist/structure/engine/fs/node.d.ts +14 -0
- package/dist/structure/engine/glob.d.ts +4 -0
- package/dist/structure/engine/ir.d.ts +124 -0
- package/dist/structure/engine/parsers/json.d.ts +37 -0
- package/dist/structure/engine/parsers/lines.d.ts +9 -0
- package/dist/structure/engine/parsers/yaml.d.ts +18 -0
- package/dist/structure/engine/registry-client.d.ts +34 -0
- package/dist/structure/engine/runner.d.ts +45 -0
- package/dist/structure/engine/templates.d.ts +30 -0
- package/dist/structure/engine/testing.d.ts +34 -0
- package/dist/structure/engine/version.d.ts +18 -0
- package/dist/structure/init-block-constructor.d.ts +32 -0
- package/dist/structure/rules/block-package-json.d.ts +9 -0
- package/dist/structure/rules/block.d.ts +1 -0
- package/dist/structure/rules/migrations.d.ts +2 -0
- package/dist/structure/rules/model-package-json.d.ts +3 -0
- package/dist/structure/rules/model.d.ts +1 -0
- package/dist/structure/rules/root-catalog-bump.d.ts +1 -0
- package/dist/structure/rules/root-gitignore.d.ts +2 -0
- package/dist/structure/rules/root-package-json.d.ts +3 -0
- package/dist/structure/rules/root-pnpm-workspace.d.ts +15 -0
- package/dist/structure/rules/root.d.ts +1 -0
- package/dist/structure/rules/shared/colocated-tests.d.ts +2 -0
- package/dist/structure/rules/shared/key-order.d.ts +1 -0
- package/dist/structure/rules/software-package-json.d.ts +3 -0
- package/dist/structure/rules/software.d.ts +1 -0
- package/dist/structure/rules/test-package-json.d.ts +3 -0
- package/dist/structure/rules/test.d.ts +1 -0
- package/dist/structure/rules/ui-package-json.d.ts +3 -0
- package/dist/structure/rules/ui.d.ts +1 -0
- package/dist/structure/rules/workflow-package-json.d.ts +3 -0
- package/dist/structure/rules/workflow.d.ts +1 -0
- package/dist/structure/structure-definition.d.ts +1 -0
- package/package.json +8 -6
- package/src/cmd/index.ts +10 -4
- package/src/cmd/structure/check.ts +51 -0
- package/src/cmd/structure/init.ts +65 -0
- package/src/cmd/structure/refresh.ts +44 -0
- package/src/cmd/update-deps.ts +15 -3
- package/src/structure/__tests__/colocated-test-wiring.test.ts +107 -0
- package/src/structure/__tests__/floor-version.test.ts +52 -0
- package/src/structure/__tests__/init-catalog-resolution.test.ts +82 -0
- package/src/structure/__tests__/init-check-parity.test.ts +59 -0
- package/src/structure/__tests__/model-package-json.snapshot.test.ts +60 -0
- package/src/structure/__tests__/oxfmt-clean-init.test.ts +64 -0
- package/src/structure/__tests__/root-catalog-bump.test.ts +110 -0
- package/src/structure/__tests__/seed-disjointness.test.ts +79 -0
- package/src/structure/cli/run-structure.ts +89 -0
- package/src/structure/engine/__tests__/content-rules/active-state-guards.test.ts +61 -0
- package/src/structure/engine/__tests__/content-rules/catalog-pin.test.ts +46 -0
- package/src/structure/engine/__tests__/content-rules/enforce-alphabetical-order.test.ts +55 -0
- package/src/structure/engine/__tests__/content-rules/enforce-field-order.test.ts +73 -0
- package/src/structure/engine/__tests__/content-rules/ensure-catalog-absent.test.ts +29 -0
- package/src/structure/engine/__tests__/content-rules/ensure-catalog-latest.test.ts +70 -0
- package/src/structure/engine/__tests__/content-rules/ensure-dep.test.ts +63 -0
- package/src/structure/engine/__tests__/content-rules/ensure-deps-bulk.test.ts +46 -0
- package/src/structure/engine/__tests__/content-rules/ensure-field-entries.test.ts +35 -0
- package/src/structure/engine/__tests__/content-rules/ensure-field.test.ts +56 -0
- package/src/structure/engine/__tests__/content-rules/ensure-script.test.ts +39 -0
- package/src/structure/engine/__tests__/content-rules/ensure-workspace-scope-deps.test.ts +92 -0
- package/src/structure/engine/__tests__/content-rules/gitignore.test.ts +50 -0
- package/src/structure/engine/__tests__/content-rules/pin-catalog-to.test.ts +64 -0
- package/src/structure/engine/__tests__/content-rules/prune-keys.test.ts +59 -0
- package/src/structure/engine/__tests__/content-rules/registry-client.test.ts +116 -0
- package/src/structure/engine/__tests__/content-rules/remove-field.test.ts +49 -0
- package/src/structure/engine/__tests__/content-rules/require-field.test.ts +40 -0
- package/src/structure/engine/__tests__/content-rules/transform-at.test.ts +33 -0
- package/src/structure/engine/__tests__/content-rules/when-inner.test.ts +244 -0
- package/src/structure/engine/__tests__/content-rules/workspace-module-paths.test.ts +53 -0
- package/src/structure/engine/__tests__/discovery.test.ts +160 -0
- package/src/structure/engine/__tests__/fs-memory.test.ts +59 -0
- package/src/structure/engine/__tests__/glob.test.ts +43 -0
- package/src/structure/engine/__tests__/parsers-json.test.ts +189 -0
- package/src/structure/engine/__tests__/parsers-lines.test.ts +44 -0
- package/src/structure/engine/__tests__/parsers-yaml.test.ts +90 -0
- package/src/structure/engine/__tests__/recheck.test.ts +99 -0
- package/src/structure/engine/__tests__/registry-lookup.test.ts +49 -0
- package/src/structure/engine/__tests__/runner-when-inside-managed.test.ts +136 -0
- package/src/structure/engine/__tests__/runner.test.ts +136 -0
- package/src/structure/engine/__tests__/synthetic.test.ts +153 -0
- package/src/structure/engine/__tests__/version.test.ts +44 -0
- package/src/structure/engine/__tests__/when-files-exist.test.ts +89 -0
- package/src/structure/engine/api.ts +131 -0
- package/src/structure/engine/builders.ts +341 -0
- package/src/structure/engine/content-rules.ts +616 -0
- package/src/structure/engine/ctx.ts +94 -0
- package/src/structure/engine/discovery-fs.ts +209 -0
- package/src/structure/engine/discovery.ts +168 -0
- package/src/structure/engine/flatten.ts +117 -0
- package/src/structure/engine/fs/api.ts +40 -0
- package/src/structure/engine/fs/memory.ts +132 -0
- package/src/structure/engine/fs/node.ts +89 -0
- package/src/structure/engine/glob.ts +42 -0
- package/src/structure/engine/ir.ts +149 -0
- package/src/structure/engine/parsers/json.ts +212 -0
- package/src/structure/engine/parsers/lines.ts +42 -0
- package/src/structure/engine/parsers/yaml.ts +72 -0
- package/src/structure/engine/registry-client.ts +140 -0
- package/src/structure/engine/runner.ts +519 -0
- package/src/structure/engine/templates.ts +74 -0
- package/src/structure/engine/testing.ts +93 -0
- package/src/structure/engine/version.ts +60 -0
- package/src/structure/init-block-constructor.ts +164 -0
- package/src/structure/rules/block-package-json.ts +156 -0
- package/src/structure/rules/block.ts +29 -0
- package/src/structure/rules/migrations.ts +63 -0
- package/src/structure/rules/model-package-json.ts +123 -0
- package/src/structure/rules/model.ts +65 -0
- package/src/structure/rules/root-catalog-bump.ts +77 -0
- package/src/structure/rules/root-gitignore.ts +27 -0
- package/src/structure/rules/root-package-json.ts +119 -0
- package/src/structure/rules/root-pnpm-workspace.ts +103 -0
- package/src/structure/rules/root.ts +43 -0
- package/src/structure/rules/shared/colocated-tests.ts +11 -0
- package/src/structure/rules/shared/key-order.ts +34 -0
- package/src/structure/rules/software-package-json.ts +86 -0
- package/src/structure/rules/software.ts +33 -0
- package/src/structure/rules/test-package-json.ts +70 -0
- package/src/structure/rules/test.ts +40 -0
- package/src/structure/rules/ui-package-json.ts +108 -0
- package/src/structure/rules/ui.ts +75 -0
- package/src/structure/rules/workflow-package-json.ts +92 -0
- package/src/structure/rules/workflow.ts +51 -0
- package/src/structure/structure-definition.ts +28 -0
- package/src/structure/templates/static/block/index.d.ts +6 -0
- package/src/structure/templates/static/block/index.js +8 -0
- package/src/structure/templates/static/block/logos/block-logo.png +0 -0
- package/src/structure/templates/static/block/logos/organization-logo.png +0 -0
- package/src/structure/templates/static/model/.oxfmtrc.json +4 -0
- package/src/structure/templates/static/model/.oxlintrc.json +3 -0
- package/src/structure/templates/static/model/src/index.ts +13 -0
- package/src/structure/templates/static/model/tsconfig.json +4 -0
- package/src/structure/templates/static/root/.gitignore +13 -0
- package/src/structure/templates/static/root/.vscode/settings.json +3 -0
- package/src/structure/templates/static/root/turbo.json +35 -0
- package/src/structure/templates/static/test/tsconfig.json +5 -0
- package/src/structure/templates/static/test/vitest.config.mts +8 -0
- package/src/structure/templates/static/ui/.oxfmtrc.json +3 -0
- package/src/structure/templates/static/ui/.oxlintrc.json +3 -0
- package/src/structure/templates/static/ui/index.html +12 -0
- package/src/structure/templates/static/ui/src/main.ts +5 -0
- package/src/structure/templates/static/ui/tsconfig.json +4 -0
- package/src/structure/templates/static/workflow/format.el +42 -0
- package/src/structure/templates/static/workflow/tsconfig.json +16 -0
- package/src/structure/templates/static/workflow/vitest.config.mts +9 -0
- package/src/structure/templates/text/README.md +5 -0
- package/src/structure/templates/text/docs/description.md +3 -0
- package/src/structure/templates/text/ui/src/MainPage.tpl.vue +9 -0
- package/src/structure/templates/text/ui/src/app.tpl.ts +11 -0
- package/src/structure/templates/text/workflow/src/main.tpl.tengo +10 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Catalog version-resolution + seeding rules. The single `onInitOrUpdate(...)`
|
|
2
|
+
// frame here resolves the SDK catalog families to npm latest AND seeds any
|
|
3
|
+
// missing standard catalog keys (SDK families + the curated infra floor +
|
|
4
|
+
// the python runenv pin). Its leaves fire on `init` AND
|
|
5
|
+
// `refresh --update-deps-only` (mode "init" + "updateDeps") — both mean
|
|
6
|
+
// "write current versions" — and are skipped on a default refresh/check,
|
|
7
|
+
// which leaves catalog versions exactly as the author/lockfile has them.
|
|
8
|
+
//
|
|
9
|
+
// The network value lives in `ensureCatalogLatest`, which reads prefetched
|
|
10
|
+
// "latest" versions from the runner's `registryLookup` (the CLI / init
|
|
11
|
+
// constructor prefetches the SDK catalog membership list before the run;
|
|
12
|
+
// unit tests pass a mock). Seeding the SDK keys from the membership list
|
|
13
|
+
// (not the on-disk catalog) is what fixes the install failures: a
|
|
14
|
+
// migrated block that never carried `@milaboratories/ts-builder` etc. now
|
|
15
|
+
// gets them ADDED on `--update-deps-only`, no manual catalog seed required.
|
|
16
|
+
//
|
|
17
|
+
// Wrapped in the same root-scope `when(!isSdkInternal)` guard as the rest of
|
|
18
|
+
// the root rules — internal blocks get their catalog from the parent
|
|
19
|
+
// monorepo, so catalog resolution never applies there.
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
onInitOrUpdate,
|
|
23
|
+
scope,
|
|
24
|
+
when,
|
|
25
|
+
managed,
|
|
26
|
+
generate,
|
|
27
|
+
ensureCatalogLatest,
|
|
28
|
+
ensureCatalogVersion,
|
|
29
|
+
} from "../engine/api";
|
|
30
|
+
import { getActiveRunContext } from "../engine/builders";
|
|
31
|
+
import {
|
|
32
|
+
rootPnpmWorkspaceInitial,
|
|
33
|
+
SDK_CATALOG_PACKAGES,
|
|
34
|
+
INFRA_CATALOG_FLOOR,
|
|
35
|
+
RUNENV_PYTHON,
|
|
36
|
+
RUNENV_PYTHON_VERSION,
|
|
37
|
+
} from "./root-pnpm-workspace";
|
|
38
|
+
|
|
39
|
+
export function rootCatalogBumpRules(): void {
|
|
40
|
+
onInitOrUpdate(() => {
|
|
41
|
+
scope("root", () => {
|
|
42
|
+
when(
|
|
43
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
44
|
+
() => {
|
|
45
|
+
// On init, the default root rules create pnpm-workspace.yaml from
|
|
46
|
+
// this same generator (the curated SDK placeholders + infra
|
|
47
|
+
// floor); this leaf then overwrites the SDK entries with npm
|
|
48
|
+
// latest (the floor entries are add-if-absent no-ops). On
|
|
49
|
+
// update-deps the file already exists, so `initial` is not
|
|
50
|
+
// exercised — but a ContentForm is required, so reuse the
|
|
51
|
+
// generator.
|
|
52
|
+
managed(
|
|
53
|
+
"pnpm-workspace.yaml",
|
|
54
|
+
generate(() => rootPnpmWorkspaceInitial(getActiveRunContext())),
|
|
55
|
+
() => {
|
|
56
|
+
// SDK families → npm latest, ADD-IF-ABSENT (seeds a migrated
|
|
57
|
+
// block's missing standard keys + overwrites the init
|
|
58
|
+
// placeholder).
|
|
59
|
+
for (const name of SDK_CATALOG_PACKAGES) ensureCatalogLatest(name);
|
|
60
|
+
// Curated infra floor → fixed version, ADD-IF-ABSENT (seeds
|
|
61
|
+
// shx/turbo/vitest/vue/changesets when missing; never touches a
|
|
62
|
+
// version the block already pins).
|
|
63
|
+
for (const [name, version] of Object.entries(INFRA_CATALOG_FLOOR)) {
|
|
64
|
+
ensureCatalogVersion(name, version);
|
|
65
|
+
}
|
|
66
|
+
// The python runenv pin is relevant only to software-bearing
|
|
67
|
+
// blocks; seed it add-if-absent when one is present.
|
|
68
|
+
if (getActiveRunContext().modules.some((m) => m.scope === "software")) {
|
|
69
|
+
ensureCatalogVersion(RUNENV_PYTHON, RUNENV_PYTHON_VERSION);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Root `.gitignore` content rules.
|
|
2
|
+
// The static template under templates/static/root/.gitignore carries the
|
|
3
|
+
// canonical line set; the body re-asserts the same set via
|
|
4
|
+
// `ensureGitignoreEntries` so any future edit that drops a required line
|
|
5
|
+
// is restored.
|
|
6
|
+
|
|
7
|
+
import { ensureGitignoreEntries } from "../engine/api";
|
|
8
|
+
|
|
9
|
+
export const GITIGNORE_REQUIRED_LINES = [
|
|
10
|
+
".test_auth.json",
|
|
11
|
+
"node_modules/",
|
|
12
|
+
"dist/",
|
|
13
|
+
"block-pack/",
|
|
14
|
+
"dev/",
|
|
15
|
+
"work/",
|
|
16
|
+
"log/",
|
|
17
|
+
".turbo",
|
|
18
|
+
"vite.config.*.timestamp-*",
|
|
19
|
+
"software/**/*.tgz",
|
|
20
|
+
".DS_Store",
|
|
21
|
+
".vscode/sftp.json",
|
|
22
|
+
"test-dry-run.json",
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export function rootGitignoreRules(): void {
|
|
26
|
+
ensureGitignoreEntries(GITIGNORE_REQUIRED_LINES);
|
|
27
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Root `package.json`: the initial generator and the drift-correcting body
|
|
2
|
+
// rules, co-located. The body re-asserts the canonical scripts, devDeps,
|
|
3
|
+
// peerDeps, and the final field-order projection (enforceFieldOrder is the
|
|
4
|
+
// LAST call).
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
ensureField,
|
|
8
|
+
ensureScript,
|
|
9
|
+
ensureDevDeps,
|
|
10
|
+
ensurePeerDeps,
|
|
11
|
+
removeField,
|
|
12
|
+
pruneKeysMatching,
|
|
13
|
+
enforceAlphabeticalOrder,
|
|
14
|
+
enforceFieldOrder,
|
|
15
|
+
type RunContext,
|
|
16
|
+
} from "../engine/api";
|
|
17
|
+
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
18
|
+
|
|
19
|
+
export function rootPackageJsonInitial(_ctx: RunContext): Record<string, unknown> {
|
|
20
|
+
// No `name`: the root is never published. Body rules re-assert
|
|
21
|
+
// (removeField("name")) as a drift-corrector.
|
|
22
|
+
return {
|
|
23
|
+
version: "1.0.0",
|
|
24
|
+
private: true,
|
|
25
|
+
scripts: {
|
|
26
|
+
fmt: "turbo run fmt",
|
|
27
|
+
check: "turbo run check",
|
|
28
|
+
build: "turbo run build",
|
|
29
|
+
"build:dev": "env PL_PKG_DEV=local turbo run build",
|
|
30
|
+
test: "env PL_PKG_DEV=local turbo run test --concurrency 1",
|
|
31
|
+
"test:dry-run": "env PL_PKG_DEV=local turbo run test --dry-run=json",
|
|
32
|
+
"mark-stable": "turbo run mark-stable",
|
|
33
|
+
"do-pack": "turbo run do-pack",
|
|
34
|
+
watch: "turbo watch build",
|
|
35
|
+
changeset: "changeset",
|
|
36
|
+
"version-packages": "changeset version",
|
|
37
|
+
// Deprecated in favour of `update` (the full refresh → install →
|
|
38
|
+
// refresh → format flow); kept for compatibility.
|
|
39
|
+
"update-sdk": "block-tools structure refresh --update-deps-only",
|
|
40
|
+
update:
|
|
41
|
+
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm fmt",
|
|
42
|
+
},
|
|
43
|
+
peerDependencies: {
|
|
44
|
+
oxlint: "*",
|
|
45
|
+
oxfmt: "*",
|
|
46
|
+
},
|
|
47
|
+
devDependencies: {
|
|
48
|
+
"@changesets/cli": "catalog:",
|
|
49
|
+
"@milaboratories/ts-builder": "sdk:",
|
|
50
|
+
"@platforma-sdk/block-tools": "sdk:",
|
|
51
|
+
shx: "catalog:",
|
|
52
|
+
turbo: "catalog:",
|
|
53
|
+
},
|
|
54
|
+
packageManager: "pnpm@9.12.0",
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function rootPackageJsonRules(): void {
|
|
59
|
+
ensureField("packageManager", "pnpm@9.12.0");
|
|
60
|
+
|
|
61
|
+
// Root is never published — it carries no `name`; delete any stray one.
|
|
62
|
+
removeField("name");
|
|
63
|
+
|
|
64
|
+
// Canonical lifecycle script set. `test` / `test:dry-run` carry the
|
|
65
|
+
// PL_PKG_DEV wrapper; the live backend's env reaches the integration
|
|
66
|
+
// tests via the turbo `test` task's passThroughEnv (no --env-mode=loose
|
|
67
|
+
// needed).
|
|
68
|
+
ensureScript("fmt", "turbo run fmt");
|
|
69
|
+
ensureScript("check", "turbo run check");
|
|
70
|
+
ensureScript("build", "turbo run build");
|
|
71
|
+
ensureScript("build:dev", "env PL_PKG_DEV=local turbo run build");
|
|
72
|
+
ensureScript("test", "env PL_PKG_DEV=local turbo run test --concurrency 1");
|
|
73
|
+
ensureScript("test:dry-run", "env PL_PKG_DEV=local turbo run test --dry-run=json");
|
|
74
|
+
ensureScript("mark-stable", "turbo run mark-stable");
|
|
75
|
+
ensureScript("do-pack", "turbo run do-pack");
|
|
76
|
+
ensureScript("watch", "turbo watch build");
|
|
77
|
+
ensureScript("changeset", "changeset");
|
|
78
|
+
ensureScript("version-packages", "changeset version");
|
|
79
|
+
// Deprecated in favour of `update`; kept for compatibility.
|
|
80
|
+
ensureScript("update-sdk", "block-tools structure refresh --update-deps-only");
|
|
81
|
+
// Full SDK-update flow: bump catalog (deps-only) → install → re-apply
|
|
82
|
+
// structure against the freshly-pulled deps → format the result, wrapped
|
|
83
|
+
// as one script. `pnpm fmt` (turbo run fmt) leaves the tree oxfmt-clean
|
|
84
|
+
// after the structural rewrite so a follow-up `pnpm check` passes.
|
|
85
|
+
ensureScript(
|
|
86
|
+
"update",
|
|
87
|
+
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm fmt",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
ensureDevDeps({
|
|
91
|
+
"@changesets/cli": "catalog:",
|
|
92
|
+
"@milaboratories/ts-builder": "sdk:",
|
|
93
|
+
"@platforma-sdk/block-tools": "sdk:",
|
|
94
|
+
shx: "catalog:",
|
|
95
|
+
turbo: "catalog:",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
ensurePeerDeps({
|
|
99
|
+
oxlint: "*",
|
|
100
|
+
oxfmt: "*",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Strip committed dev-machine override clutter: keys like "//pnpm",
|
|
104
|
+
// "///pnpm", "--" carrying a pnpm/overrides sub-object (often absolute
|
|
105
|
+
// local paths). Left in place these are unknown top-level keys that oxfmt
|
|
106
|
+
// shoves past the canonical sections, breaking `oxfmt --check`.
|
|
107
|
+
pruneKeysMatching((key, value): boolean => {
|
|
108
|
+
if (!/^(\/\/|--)/.test(key)) return false;
|
|
109
|
+
if (typeof value !== "object" || value === null) return false;
|
|
110
|
+
const v = value as { pnpm?: unknown; overrides?: unknown };
|
|
111
|
+
return v.pnpm !== undefined || v.overrides !== undefined;
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
enforceAlphabeticalOrder("dependencies");
|
|
115
|
+
enforceAlphabeticalOrder("devDependencies");
|
|
116
|
+
enforceAlphabeticalOrder("peerDependencies");
|
|
117
|
+
enforceAlphabeticalOrder("optionalDependencies");
|
|
118
|
+
enforceFieldOrder([...canonicalPackageJsonOrder]);
|
|
119
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Root `pnpm-workspace.yaml`: the catalog membership, the initial generator,
|
|
2
|
+
// and the drift-correcting body rules, co-located.
|
|
3
|
+
//
|
|
4
|
+
// The catalog is split in two:
|
|
5
|
+
// - SDK packages: `SDK_CATALOG_PACKAGES` is a list of package NAMES (catalog
|
|
6
|
+
// membership only — no versions). On init the `onInitOrUpdate` frame fetches
|
|
7
|
+
// npm latest for each (init requires network) and writes it; the keys must
|
|
8
|
+
// exist in the catalog first for that in-place bump to land, so the initial
|
|
9
|
+
// generator seeds them with an obviously-invalid placeholder that the bump
|
|
10
|
+
// always overwrites. No version is stored here and there is no fallback.
|
|
11
|
+
// - infra / tooling: a `~`-floored set we control deliberately. No rule
|
|
12
|
+
// ever fetches these — refresh leaves them untouched and update-deps
|
|
13
|
+
// does not match them. Bump the floor here when authoring the scaffold.
|
|
14
|
+
//
|
|
15
|
+
// Default refresh is purely structural: it verifies the workspace
|
|
16
|
+
// `packages:` list matches the discovered modules and leaves every catalog
|
|
17
|
+
// version exactly as the author/lockfile has it. Version resolution (writing
|
|
18
|
+
// npm-latest for the SDK families) lives in the separate `onInitOrUpdate`
|
|
19
|
+
// frame (`rootCatalogBumpRules`), which fires on init + update-deps only.
|
|
20
|
+
|
|
21
|
+
import { ensureWorkspaceModulePaths, type RunContext } from "../engine/api";
|
|
22
|
+
import { matchesBumpPattern } from "../engine/registry-client";
|
|
23
|
+
|
|
24
|
+
/** SDK packages that live in the catalog (membership only — no versions).
|
|
25
|
+
* Init fetches npm latest for each; refresh leaves them as the lockfile has
|
|
26
|
+
* them. */
|
|
27
|
+
export const SDK_CATALOG_PACKAGES: readonly string[] = [
|
|
28
|
+
"@platforma-sdk/model",
|
|
29
|
+
"@platforma-sdk/ui-vue",
|
|
30
|
+
"@platforma-sdk/workflow-tengo",
|
|
31
|
+
"@platforma-sdk/test",
|
|
32
|
+
"@platforma-sdk/block-tools",
|
|
33
|
+
"@platforma-sdk/tengo-builder",
|
|
34
|
+
"@platforma-sdk/package-builder",
|
|
35
|
+
"@milaboratories/ts-builder",
|
|
36
|
+
"@milaboratories/ts-configs",
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/** Init-only catalog seed for every SDK package: an obviously-invalid version
|
|
40
|
+
* the `onInitOrUpdate` bump always overwrites with npm latest. It exists only
|
|
41
|
+
* so the catalog key is present for that in-place bump. It is never a
|
|
42
|
+
* fallback — a real init requires network and overwrites it; were it ever to
|
|
43
|
+
* reach a lockfile, `pnpm install` fails loudly on the unresolvable version. */
|
|
44
|
+
const SDK_CATALOG_INIT_PLACEHOLDER = "0.0.0-init-must-fetch";
|
|
45
|
+
|
|
46
|
+
// Invariant: every SDK package must be fetched on init (match a bump pattern),
|
|
47
|
+
// or its placeholder would ship un-resolved. Caught at load time.
|
|
48
|
+
for (const name of SDK_CATALOG_PACKAGES) {
|
|
49
|
+
if (!matchesBumpPattern(name)) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`SDK_CATALOG_PACKAGES entry '${name}' matches no catalog bump pattern; ` +
|
|
52
|
+
`its placeholder would never be resolved to npm latest on init. ` +
|
|
53
|
+
`Add it to CATALOG_BUMP_PATTERNS or move it to the infra floor.`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Infra / tooling — a `~`-floored curated set. Not exact-pinned on refresh
|
|
59
|
+
* and not bumped by update-deps. */
|
|
60
|
+
export const INFRA_CATALOG_FLOOR: Record<string, string> = {
|
|
61
|
+
turbo: "~2.8.11",
|
|
62
|
+
shx: "~0.4.0",
|
|
63
|
+
"@changesets/cli": "~2.29.8",
|
|
64
|
+
vitest: "~4.0.18",
|
|
65
|
+
// The seeded ui depends on `vue` (catalog:). `@platforma-sdk/ui-vue` pins
|
|
66
|
+
// vue as an EXACT regular dependency (not a peer), so the block must pin the
|
|
67
|
+
// SAME exact version — a floated `~` lets the ui resolve a newer 3.5.x than
|
|
68
|
+
// ui-vue's, yielding two vue instances and a SdkPluginV3-vs-Plugin type
|
|
69
|
+
// clash in `main.ts`. Keep this in lockstep with ui-vue's vue pin.
|
|
70
|
+
vue: "3.5.24",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** Catalog name of the python runenv. Added to a block's catalog only when
|
|
74
|
+
* the block carries a software module. Pinned to an EXACT version — updating
|
|
75
|
+
* the python runenv is an explicit author decision, never automatic. */
|
|
76
|
+
export const RUNENV_PYTHON = "@platforma-open/milaboratories.runenv-python-3";
|
|
77
|
+
export const RUNENV_PYTHON_VERSION = "1.8.2";
|
|
78
|
+
|
|
79
|
+
export function rootPnpmWorkspaceInitial(ctx: RunContext): Record<string, unknown> {
|
|
80
|
+
// Non-root module paths only. The block root ("") is discovered
|
|
81
|
+
// implicitly and must never be written as a "." entry — listing it breaks
|
|
82
|
+
// turbo's task graph. Root stays in ctx.modules for rule fan-out.
|
|
83
|
+
const paths = ctx.modules
|
|
84
|
+
.filter((m) => m.path !== "")
|
|
85
|
+
.map((m) => m.path)
|
|
86
|
+
.sort();
|
|
87
|
+
// SDK packages first (placeholder, overwritten by the init bump), then the
|
|
88
|
+
// infra floor — matching the order the catalog is written.
|
|
89
|
+
const catalog: Record<string, string> = {};
|
|
90
|
+
for (const name of SDK_CATALOG_PACKAGES) catalog[name] = SDK_CATALOG_INIT_PLACEHOLDER;
|
|
91
|
+
Object.assign(catalog, INFRA_CATALOG_FLOOR);
|
|
92
|
+
if (ctx.modules.some((m) => m.scope === "software")) {
|
|
93
|
+
catalog[RUNENV_PYTHON] = RUNENV_PYTHON_VERSION;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
packages: paths,
|
|
97
|
+
catalog,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function rootPnpmWorkspaceRules(): void {
|
|
102
|
+
ensureWorkspaceModulePaths();
|
|
103
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Root-scope rules — apply only to the standalone block layout (the
|
|
2
|
+
// pnpm workspace + tooling around the block). `--sdk-internal` blocks
|
|
3
|
+
// skip this whole scope: the parent monorepo owns root files. Hence the
|
|
4
|
+
// `when(({ ctx }) => !ctx.isSdkInternal, ...)` wrapper.
|
|
5
|
+
|
|
6
|
+
import { scope, when, fixed, managed, file, generate } from "../engine/api";
|
|
7
|
+
import { getActiveRunContext } from "../engine/builders";
|
|
8
|
+
import { rootPackageJsonInitial, rootPackageJsonRules } from "./root-package-json";
|
|
9
|
+
import { rootPnpmWorkspaceInitial, rootPnpmWorkspaceRules } from "./root-pnpm-workspace";
|
|
10
|
+
import { rootGitignoreRules } from "./root-gitignore";
|
|
11
|
+
|
|
12
|
+
export function rootRules(): void {
|
|
13
|
+
scope("root", () => {
|
|
14
|
+
when(
|
|
15
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
16
|
+
() => {
|
|
17
|
+
// see templates/static/root/turbo.json — verbatim canonical content.
|
|
18
|
+
fixed("turbo.json", file("root/turbo.json"));
|
|
19
|
+
fixed(".vscode/settings.json", file("root/.vscode/settings.json"));
|
|
20
|
+
|
|
21
|
+
managed(
|
|
22
|
+
"package.json",
|
|
23
|
+
generate(() => rootPackageJsonInitial(getActiveRunContext())),
|
|
24
|
+
() => {
|
|
25
|
+
rootPackageJsonRules();
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
managed(
|
|
30
|
+
"pnpm-workspace.yaml",
|
|
31
|
+
generate(() => rootPnpmWorkspaceInitial(getActiveRunContext())),
|
|
32
|
+
() => {
|
|
33
|
+
rootPnpmWorkspaceRules();
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
managed(".gitignore", file("root/.gitignore"), () => {
|
|
38
|
+
rootGitignoreRules();
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Shared definition for co-located unit-test handling.
|
|
2
|
+
//
|
|
3
|
+
// A block's model / ui / workflow scope MAY carry co-located vitest unit
|
|
4
|
+
// tests (`src/**/*.test.ts`, including nested `src/test/*.test.ts`). The
|
|
5
|
+
// structurer wires the vitest `test` script and (for ui/model) node ambient
|
|
6
|
+
// types into a scope ONLY when such files are present — so a test-less scope
|
|
7
|
+
// stays free of a `test` script it would never run, and a freshly-init'd
|
|
8
|
+
// (test-less) block remains a refresh fixpoint.
|
|
9
|
+
|
|
10
|
+
/** Glob (module-relative) for co-located unit tests in a scope's `src/`. */
|
|
11
|
+
export const COLOCATED_TEST_GLOB = "src/**/*.test.ts";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Canonical top-level key order for `package.json` files.
|
|
2
|
+
// Used by `enforceFieldOrder(canonicalPackageJsonOrder)` at the end of
|
|
3
|
+
// every `*-package-json.ts` body.
|
|
4
|
+
// Per-block extensions: rules call
|
|
5
|
+
// `enforceFieldOrder([...canonicalPackageJsonOrder, "customKey"])`.
|
|
6
|
+
//
|
|
7
|
+
// This order is derived EMPIRICALLY from oxfmt (the canonical formatter run
|
|
8
|
+
// by `ts-builder check`): a freshly-refreshed package.json must pass
|
|
9
|
+
// `oxfmt --check` so `pnpm check` is green without a prior `pnpm fmt`. oxfmt
|
|
10
|
+
// also alphabetises the dependency sections — the `*-package-json.ts` bodies
|
|
11
|
+
// call `enforceAlphabeticalOrder` on each dep section to match (scripts and
|
|
12
|
+
// `exports` keep source order; oxfmt does not reorder them).
|
|
13
|
+
export const canonicalPackageJsonOrder = [
|
|
14
|
+
"name",
|
|
15
|
+
"version",
|
|
16
|
+
"private",
|
|
17
|
+
"description",
|
|
18
|
+
"keywords",
|
|
19
|
+
"files",
|
|
20
|
+
"type",
|
|
21
|
+
"main",
|
|
22
|
+
"module",
|
|
23
|
+
"types",
|
|
24
|
+
"exports",
|
|
25
|
+
"scripts",
|
|
26
|
+
"dependencies",
|
|
27
|
+
"devDependencies",
|
|
28
|
+
"peerDependencies",
|
|
29
|
+
"optionalDependencies",
|
|
30
|
+
"packageManager",
|
|
31
|
+
"pnpm",
|
|
32
|
+
"block",
|
|
33
|
+
"block-software",
|
|
34
|
+
] as const;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Software `package.json`: the initial generator and the drift-correcting
|
|
2
|
+
// body rules, co-located. One body, N modules — fan-out is driven by
|
|
3
|
+
// `ctx.modules`.
|
|
4
|
+
//
|
|
5
|
+
// Drift-correctors only: identity (name/version), `description`, and the
|
|
6
|
+
// `block-software` descriptor are author-owned / opaque and left untouched
|
|
7
|
+
// — re-asserting them would clobber real multi-software blocks on refresh.
|
|
8
|
+
// The body enforces the structural essentials: ESM type, the publish
|
|
9
|
+
// `files` glob, the lifecycle scripts, and the canonical devDeps.
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
ensureField,
|
|
13
|
+
ensureScript,
|
|
14
|
+
ensureDevDeps,
|
|
15
|
+
enforceAlphabeticalOrder,
|
|
16
|
+
enforceFieldOrder,
|
|
17
|
+
type RunContext,
|
|
18
|
+
} from "../engine/api";
|
|
19
|
+
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
20
|
+
|
|
21
|
+
/** The `block-software` package-builder descriptor for a python
|
|
22
|
+
* entrypoint. Kept opaque by the engine; rule authors edit it via
|
|
23
|
+
* `transformAt("block-software", ...)`. The `:3.12.10` tag inside
|
|
24
|
+
* `environment` is the runenv artifact tag (python version), distinct
|
|
25
|
+
* from the npm catalog version. */
|
|
26
|
+
function pythonBlockSoftware(): Record<string, unknown> {
|
|
27
|
+
return {
|
|
28
|
+
entrypoints: {
|
|
29
|
+
main: {
|
|
30
|
+
binary: {
|
|
31
|
+
artifact: {
|
|
32
|
+
type: "python",
|
|
33
|
+
registry: "platforma-open",
|
|
34
|
+
environment: "@platforma-open/milaboratories.runenv-python-3:3.12.10",
|
|
35
|
+
dependencies: { toolset: "pip", requirements: "requirements.txt" },
|
|
36
|
+
root: "./src",
|
|
37
|
+
},
|
|
38
|
+
cmd: ["python", "{pkg}/main.py"],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function softwarePackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
46
|
+
const v = ctx.blockVars;
|
|
47
|
+
return {
|
|
48
|
+
name: `${v.facadeName}.software`,
|
|
49
|
+
version: "1.0.0",
|
|
50
|
+
type: "module",
|
|
51
|
+
description: "Block Software",
|
|
52
|
+
files: ["./dist/**/*"],
|
|
53
|
+
scripts: {
|
|
54
|
+
build: "pl-pkg build",
|
|
55
|
+
prepublishOnly: "pl-pkg prepublish",
|
|
56
|
+
changeset: "changeset",
|
|
57
|
+
"version-packages": "changeset version",
|
|
58
|
+
},
|
|
59
|
+
"block-software": pythonBlockSoftware(),
|
|
60
|
+
devDependencies: {
|
|
61
|
+
"@platforma-open/milaboratories.runenv-python-3": "catalog:",
|
|
62
|
+
"@platforma-sdk/package-builder": "sdk:",
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function softwarePackageJsonRules(): void {
|
|
68
|
+
ensureField("type", "module");
|
|
69
|
+
ensureField("files", ["./dist/**/*"]);
|
|
70
|
+
|
|
71
|
+
ensureScript("build", "pl-pkg build");
|
|
72
|
+
ensureScript("prepublishOnly", "pl-pkg prepublish");
|
|
73
|
+
ensureScript("changeset", "changeset");
|
|
74
|
+
ensureScript("version-packages", "changeset version");
|
|
75
|
+
|
|
76
|
+
ensureDevDeps({
|
|
77
|
+
"@platforma-open/milaboratories.runenv-python-3": "catalog:",
|
|
78
|
+
"@platforma-sdk/package-builder": "sdk:",
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
enforceAlphabeticalOrder("dependencies");
|
|
82
|
+
enforceAlphabeticalOrder("devDependencies");
|
|
83
|
+
enforceAlphabeticalOrder("peerDependencies");
|
|
84
|
+
enforceAlphabeticalOrder("optionalDependencies");
|
|
85
|
+
enforceFieldOrder([...canonicalPackageJsonOrder]);
|
|
86
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Software-scope rules. One scope body, N modules — the engine fans out
|
|
2
|
+
// once per discovered software module. Zero software modules → entire
|
|
3
|
+
// scope body no-ops.
|
|
4
|
+
//
|
|
5
|
+
// Seeds (`software/src/main.py` + `requirements.txt`) are written once by
|
|
6
|
+
// `init` and never touched again — the block author owns them.
|
|
7
|
+
|
|
8
|
+
import { scope, managed, seed, generate, text } from "../engine/api";
|
|
9
|
+
import { getActiveRunContext } from "../engine/builders";
|
|
10
|
+
import { softwarePackageJsonInitial, softwarePackageJsonRules } from "./software-package-json";
|
|
11
|
+
|
|
12
|
+
const MAIN_PY_SEED = `import sys
|
|
13
|
+
|
|
14
|
+
print("Hello from Python, " + sys.argv[1] + "!")
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const REQUIREMENTS_SEED = `# No dependencies specified for this script
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
export function softwareRules(): void {
|
|
21
|
+
scope("software", () => {
|
|
22
|
+
seed("src/main.py", text(MAIN_PY_SEED));
|
|
23
|
+
seed("src/requirements.txt", text(REQUIREMENTS_SEED));
|
|
24
|
+
|
|
25
|
+
managed(
|
|
26
|
+
"package.json",
|
|
27
|
+
generate(() => softwarePackageJsonInitial(getActiveRunContext())),
|
|
28
|
+
() => {
|
|
29
|
+
softwarePackageJsonRules();
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Test `package.json`: the initial generator and the drift-correcting body
|
|
2
|
+
// rules, co-located.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ensureField,
|
|
6
|
+
ensureScript,
|
|
7
|
+
ensureDevDeps,
|
|
8
|
+
ensurePeerDeps,
|
|
9
|
+
removeDep,
|
|
10
|
+
enforceAlphabeticalOrder,
|
|
11
|
+
enforceFieldOrder,
|
|
12
|
+
type RunContext,
|
|
13
|
+
} from "../engine/api";
|
|
14
|
+
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
15
|
+
|
|
16
|
+
export function testPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
17
|
+
const v = ctx.blockVars;
|
|
18
|
+
return {
|
|
19
|
+
name: `${v.facadeName}.test`,
|
|
20
|
+
version: "1.0.0",
|
|
21
|
+
private: true,
|
|
22
|
+
type: "module",
|
|
23
|
+
scripts: {
|
|
24
|
+
// Type-only check (no oxlint/oxfmt — the test scope ships no lint/fmt
|
|
25
|
+
// config). Slots into the turbo `check` task.
|
|
26
|
+
check: "ts-builder type-check --target block-test",
|
|
27
|
+
test: "vitest run --passWithNoTests",
|
|
28
|
+
},
|
|
29
|
+
peerDependencies: {
|
|
30
|
+
typescript: "*",
|
|
31
|
+
},
|
|
32
|
+
devDependencies: {
|
|
33
|
+
"@platforma-sdk/test": "sdk:",
|
|
34
|
+
"@milaboratories/ts-builder": "sdk:",
|
|
35
|
+
"@milaboratories/ts-configs": "sdk:",
|
|
36
|
+
vitest: "catalog:",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function testPackageJsonRules(): void {
|
|
42
|
+
ensureField("type", "module");
|
|
43
|
+
|
|
44
|
+
// Type-only check (no oxlint/oxfmt — the test scope ships no lint/fmt
|
|
45
|
+
// config); slots into the turbo `check` task.
|
|
46
|
+
ensureScript("check", "ts-builder type-check --target block-test");
|
|
47
|
+
ensureScript("test", "vitest run --passWithNoTests");
|
|
48
|
+
|
|
49
|
+
// @platforma-sdk/test is a test-time dep → devDependencies (matches prod).
|
|
50
|
+
ensureDevDeps({
|
|
51
|
+
"@platforma-sdk/test": "sdk:",
|
|
52
|
+
"@milaboratories/ts-builder": "sdk:",
|
|
53
|
+
"@milaboratories/ts-configs": "sdk:",
|
|
54
|
+
vitest: "catalog:",
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// The test tsconfig (@milaboratories/ts-configs/block/test) supplies the
|
|
58
|
+
// ambient types; only the `typescript` peer is needed. Drop any stray
|
|
59
|
+
// `@types/node` peer a legacy block declares.
|
|
60
|
+
ensurePeerDeps({
|
|
61
|
+
typescript: "*",
|
|
62
|
+
});
|
|
63
|
+
removeDep("@types/node");
|
|
64
|
+
|
|
65
|
+
enforceAlphabeticalOrder("dependencies");
|
|
66
|
+
enforceAlphabeticalOrder("devDependencies");
|
|
67
|
+
enforceAlphabeticalOrder("peerDependencies");
|
|
68
|
+
enforceAlphabeticalOrder("optionalDependencies");
|
|
69
|
+
enforceFieldOrder([...canonicalPackageJsonOrder]);
|
|
70
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Test-scope rules.
|
|
2
|
+
|
|
3
|
+
import { scope, fixed, managed, scaffold, seed, file, text, generate } from "../engine/api";
|
|
4
|
+
import { getActiveRunContext } from "../engine/builders";
|
|
5
|
+
import { testPackageJsonInitial, testPackageJsonRules } from "./test-package-json";
|
|
6
|
+
|
|
7
|
+
export function testRules(): void {
|
|
8
|
+
scope("test", () => {
|
|
9
|
+
// tsconfig carries `files: []` alongside `include: ["src/**/*"]`: tsc
|
|
10
|
+
// errors TS18003 when an `include` matches nothing, so an empty `files`
|
|
11
|
+
// lets the check pass on a test-less block while `include` still
|
|
12
|
+
// type-checks real tests once present.
|
|
13
|
+
fixed("tsconfig.json", file("test/tsconfig.json"));
|
|
14
|
+
// scaffold (not fixed): integration tests legitimately tune timeout /
|
|
15
|
+
// retry per block. Write the canonical default if absent; never
|
|
16
|
+
// overwrite an author's config.
|
|
17
|
+
scaffold("vitest.config.mts", file("test/vitest.config.mts"));
|
|
18
|
+
|
|
19
|
+
// A trivial, backend-free demo test so a freshly-init'd block ships a
|
|
20
|
+
// runnable suite (`pnpm test` green out of the box) rather than an empty
|
|
21
|
+
// scope. Author-owned seed: written once at init, untouched on refresh.
|
|
22
|
+
seed(
|
|
23
|
+
"src/demo.test.ts",
|
|
24
|
+
text(
|
|
25
|
+
`import { expect, test } from "vitest";\n\n` +
|
|
26
|
+
`test("scaffolded block sanity check", () => {\n` +
|
|
27
|
+
` expect(true).toBe(true);\n` +
|
|
28
|
+
`});\n`,
|
|
29
|
+
),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
managed(
|
|
33
|
+
"package.json",
|
|
34
|
+
generate(() => testPackageJsonInitial(getActiveRunContext())),
|
|
35
|
+
() => {
|
|
36
|
+
testPackageJsonRules();
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
}
|