@platforma-sdk/block-tools 2.10.18 → 2.11.0
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 +12 -12
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +391 -355
- package/dist/cli.mjs.map +1 -1
- package/dist/structure/engine/builders.d.ts +7 -6
- package/dist/structure/engine/content-rules.d.ts +4 -4
- package/dist/structure/engine/ir.d.ts +11 -6
- package/dist/structure/rules/block-package-json.d.ts +1 -1
- package/dist/structure/rules/root-ci.d.ts +1 -0
- package/dist/structure/rules/shared/retired-deps.d.ts +7 -0
- package/package.json +7 -7
- package/src/structure/CLAUDE.md +30 -0
- package/src/structure/__tests__/discovery-shortname.test.ts +50 -0
- package/src/structure/__tests__/root-ci-workflows.test.ts +68 -0
- package/src/structure/engine/builders.ts +7 -6
- package/src/structure/engine/content-rules.ts +7 -7
- package/src/structure/engine/discovery-fs.ts +9 -1
- package/src/structure/engine/ir.ts +11 -6
- package/src/structure/engine/runner.ts +14 -14
- package/src/structure/rules/block-package-json.ts +2 -3
- package/src/structure/rules/block.ts +3 -4
- package/src/structure/rules/migrations.ts +16 -18
- package/src/structure/rules/model-package-json.ts +4 -5
- package/src/structure/rules/model.ts +1 -2
- package/src/structure/rules/root-catalog-bump.ts +3 -4
- package/src/structure/rules/root-ci.ts +55 -0
- package/src/structure/rules/root-package-json.ts +8 -6
- package/src/structure/rules/root-pnpm-workspace.ts +4 -7
- package/src/structure/rules/root.ts +2 -4
- package/src/structure/rules/shared/retired-deps.ts +42 -0
- package/src/structure/rules/software.ts +1 -2
- package/src/structure/rules/test-package-json.ts +12 -9
- package/src/structure/rules/test.ts +5 -2
- package/src/structure/rules/ui-package-json.ts +15 -21
- package/src/structure/rules/ui.ts +3 -5
- package/src/structure/rules/workflow-package-json.ts +7 -3
- package/src/structure/rules/workflow.ts +20 -17
- package/src/structure/structure-definition.ts +2 -0
- package/src/structure/templates/static/test/.oxfmtrc.json +4 -0
- package/src/structure/templates/static/test/.oxlintrc.json +3 -0
- package/src/structure/templates/text/workflows/build.tpl.yaml +67 -0
- package/src/structure/templates/text/workflows/mark-stable.tpl.yaml +34 -0
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
// keys/paths). Each line is a one-way decision: every block converges.
|
|
13
13
|
|
|
14
14
|
import { scope, remove, managed, generate, removeScript, removeDep } from "../engine/api";
|
|
15
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
16
15
|
import { rootPackageJsonInitial } from "./root-package-json";
|
|
17
16
|
|
|
18
17
|
export function testFrameworkMigration(): void {
|
|
@@ -23,40 +22,39 @@ export function testFrameworkMigration(): void {
|
|
|
23
22
|
// Unconditional legacy-cleanup rules. Each is a no-op on an
|
|
24
23
|
// already-canonical block (remove on an absent path, removeScript /
|
|
25
24
|
// removeDep on an absent key) and idempotent, so they sit at top level
|
|
26
|
-
// with no `when` gate.
|
|
27
|
-
// block(s) that carry the artefact being cleaned.
|
|
25
|
+
// with no `when` gate.
|
|
28
26
|
//
|
|
29
27
|
// Root-scope cleanup is skipped for `--sdk-internal` blocks (no root
|
|
30
28
|
// module in that mode), so it never touches in-monorepo blocks.
|
|
31
29
|
export function legacyCleanup(): void {
|
|
32
|
-
//
|
|
33
|
-
//
|
|
30
|
+
// Retired per-scope config files: flat eslint configs and vite-era build /
|
|
31
|
+
// split-tsconfig files, replaced by the oxlint/oxfmt + ts-builder layout.
|
|
34
32
|
scope("model", () => {
|
|
35
|
-
remove("eslint.config.mjs");
|
|
36
|
-
remove("vite.config.mts");
|
|
33
|
+
remove("eslint.config.mjs");
|
|
34
|
+
remove("vite.config.mts");
|
|
37
35
|
});
|
|
38
36
|
scope("ui", () => {
|
|
39
|
-
remove("eslint.config.mjs");
|
|
40
|
-
remove("vite.config.ts");
|
|
41
|
-
remove("tsconfig.app.json");
|
|
42
|
-
remove("tsconfig.node.json");
|
|
37
|
+
remove("eslint.config.mjs");
|
|
38
|
+
remove("vite.config.ts");
|
|
39
|
+
remove("tsconfig.app.json");
|
|
40
|
+
remove("tsconfig.node.json");
|
|
43
41
|
});
|
|
44
42
|
scope("test", () => {
|
|
45
|
-
remove("eslint.config.mjs");
|
|
43
|
+
remove("eslint.config.mjs");
|
|
46
44
|
});
|
|
47
45
|
|
|
48
46
|
// Root-scope cleanup. The second `managed("package.json")` body composes
|
|
49
47
|
// after rootRules.
|
|
50
48
|
scope("root", () => {
|
|
51
|
-
remove(".prettierrc");
|
|
49
|
+
remove(".prettierrc");
|
|
52
50
|
managed(
|
|
53
51
|
"package.json",
|
|
54
|
-
generate(() => rootPackageJsonInitial(
|
|
52
|
+
generate((ctx) => rootPackageJsonInitial(ctx)),
|
|
55
53
|
() => {
|
|
56
|
-
// `pretty` (prettier) is superseded by
|
|
57
|
-
//
|
|
58
|
-
removeScript("pretty");
|
|
59
|
-
removeDep("@platforma-sdk/blocks-deps-updater");
|
|
54
|
+
// `pretty` (prettier) is superseded by `fmt` (oxfmt); the standalone
|
|
55
|
+
// deps-updater is now part of block-tools.
|
|
56
|
+
removeScript("pretty");
|
|
57
|
+
removeDep("@platforma-sdk/blocks-deps-updater");
|
|
60
58
|
},
|
|
61
59
|
);
|
|
62
60
|
});
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ensureDevDep,
|
|
17
17
|
ensureDevDeps,
|
|
18
18
|
removeDep,
|
|
19
|
+
removeScript,
|
|
19
20
|
removeField,
|
|
20
21
|
ensurePeerDeps,
|
|
21
22
|
enforceAlphabeticalOrder,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
} from "../engine/api";
|
|
27
28
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
28
29
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
30
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
29
31
|
|
|
30
32
|
export function modelPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
31
33
|
const v = ctx.blockVars;
|
|
@@ -127,12 +129,9 @@ export function modelPackageJsonRules(): void {
|
|
|
127
129
|
),
|
|
128
130
|
);
|
|
129
131
|
|
|
130
|
-
|
|
131
|
-
// legacy `tsup`/`vite` devDeps and the top-level `tsup` bundler config block
|
|
132
|
-
// are dropped.
|
|
133
|
-
removeDep("tsup");
|
|
134
|
-
removeDep("vite");
|
|
132
|
+
removeRetiredToolchainDeps();
|
|
135
133
|
removeField("tsup");
|
|
134
|
+
removeScript("lint");
|
|
136
135
|
|
|
137
136
|
enforceAlphabeticalOrder("dependencies");
|
|
138
137
|
enforceAlphabeticalOrder("devDependencies");
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// (block author owns it).
|
|
4
4
|
|
|
5
5
|
import { scope, fixed, managed, seed, file, generate, when, whenFilesExist } from "../engine/api";
|
|
6
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
7
6
|
import { modelPackageJsonInitial, modelPackageJsonRules } from "./model-package-json";
|
|
8
7
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
9
8
|
|
|
@@ -32,7 +31,7 @@ export function modelRules(): void {
|
|
|
32
31
|
|
|
33
32
|
managed(
|
|
34
33
|
"package.json",
|
|
35
|
-
generate(() => modelPackageJsonInitial(
|
|
34
|
+
generate((ctx) => modelPackageJsonInitial(ctx)),
|
|
36
35
|
() => {
|
|
37
36
|
modelPackageJsonRules();
|
|
38
37
|
},
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
ensureCatalogVersion,
|
|
29
29
|
pinCatalogToDependencyOf,
|
|
30
30
|
} from "../engine/api";
|
|
31
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
32
31
|
import {
|
|
33
32
|
rootPnpmWorkspaceInitial,
|
|
34
33
|
SDK_CATALOG_PACKAGES,
|
|
@@ -53,8 +52,8 @@ export function rootCatalogBumpRules(): void {
|
|
|
53
52
|
// generator.
|
|
54
53
|
managed(
|
|
55
54
|
"pnpm-workspace.yaml",
|
|
56
|
-
generate(() => rootPnpmWorkspaceInitial(
|
|
57
|
-
() => {
|
|
55
|
+
generate((ctx) => rootPnpmWorkspaceInitial(ctx)),
|
|
56
|
+
(ctx) => {
|
|
58
57
|
// SDK families → npm latest, ADD-IF-ABSENT (seeds a migrated
|
|
59
58
|
// block's missing standard keys + overwrites the init
|
|
60
59
|
// placeholder).
|
|
@@ -76,7 +75,7 @@ export function rootCatalogBumpRules(): void {
|
|
|
76
75
|
}
|
|
77
76
|
// The python runenv pin is relevant only to software-bearing
|
|
78
77
|
// blocks; seed it add-if-absent when one is present.
|
|
79
|
-
if (
|
|
78
|
+
if (ctx.modules.some((m) => m.scope === "software")) {
|
|
80
79
|
ensureCatalogVersion(RUNENV_PYTHON, RUNENV_PYTHON_VERSION);
|
|
81
80
|
}
|
|
82
81
|
},
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Root-scope CI workflows — the block's GitHub Actions `build.yaml` and
|
|
2
|
+
// `mark-stable.yaml`. Engine-OWNED (`fixed`): rewritten verbatim on every
|
|
3
|
+
// refresh, generated from the block's identity (short name); everything else
|
|
4
|
+
// is a constant baked into the templates.
|
|
5
|
+
//
|
|
6
|
+
// Why fixed, not managed: previously each block carried a hand-copied
|
|
7
|
+
// workflow pinning the shared reusable workflow at `@v4` (a moving branch),
|
|
8
|
+
// so a breaking shared-CI change was absorbed silently and per-block edits
|
|
9
|
+
// drifted. Engine-owning the file makes the pin + job wiring centrally
|
|
10
|
+
// refreshable; the only per-block bits are derived (app-name, slug), so
|
|
11
|
+
// nothing author-tunable is clobbered.
|
|
12
|
+
//
|
|
13
|
+
// Standalone blocks only — `--sdk-internal` blocks (`etc/blocks/*`) carry no
|
|
14
|
+
// per-block workflow (the monorepo owns their CI), hence the
|
|
15
|
+
// `when(!isSdkInternal)` guard, matching the rest of the root scope.
|
|
16
|
+
|
|
17
|
+
import { scope, when, fixed, tpl } from "../engine/api";
|
|
18
|
+
|
|
19
|
+
/** Readable default CI label from a short name (`mixcr-clonotyping-2` →
|
|
20
|
+
* `Mixcr Clonotyping 2`). Dash/underscore words, title-cased. Human-curated
|
|
21
|
+
* casing (e.g. `MiXCR`) is not recoverable from the slug — this is a
|
|
22
|
+
* generated label, not the marketing name. */
|
|
23
|
+
function humanizeShortName(shortName: string): string {
|
|
24
|
+
return shortName
|
|
25
|
+
.split(/[-_]+/)
|
|
26
|
+
.filter((w) => w.length > 0)
|
|
27
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
28
|
+
.join(" ");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function rootCiRules(): void {
|
|
32
|
+
scope("root", () => {
|
|
33
|
+
when(
|
|
34
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
35
|
+
() => {
|
|
36
|
+
fixed(
|
|
37
|
+
".github/workflows/build.yaml",
|
|
38
|
+
tpl("workflows/build.tpl.yaml", (ctx) => {
|
|
39
|
+
const shortName = ctx.blockVars.shortName;
|
|
40
|
+
return {
|
|
41
|
+
appName: `Block: ${humanizeShortName(shortName)}`,
|
|
42
|
+
appNameSlug: `block-${shortName}`,
|
|
43
|
+
};
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
fixed(
|
|
47
|
+
".github/workflows/mark-stable.yaml",
|
|
48
|
+
tpl("workflows/mark-stable.tpl.yaml", (ctx) => ({
|
|
49
|
+
appName: `Block: ${humanizeShortName(ctx.blockVars.shortName)} - Mark Stable`,
|
|
50
|
+
})),
|
|
51
|
+
);
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ensureScript,
|
|
9
9
|
ensureDevDeps,
|
|
10
10
|
ensurePeerDeps,
|
|
11
|
+
removeScript,
|
|
11
12
|
removeField,
|
|
12
13
|
pruneKeysMatching,
|
|
13
14
|
enforceAlphabeticalOrder,
|
|
@@ -34,10 +35,9 @@ export function rootPackageJsonInitial(_ctx: RunContext): Record<string, unknown
|
|
|
34
35
|
watch: "turbo watch build",
|
|
35
36
|
changeset: "changeset",
|
|
36
37
|
"version-packages": "changeset version",
|
|
37
|
-
// Deprecated
|
|
38
|
-
// refresh → format flow); kept for compatibility.
|
|
38
|
+
// Deprecated alias of `upgrade-sdk`; kept for compatibility.
|
|
39
39
|
"update-sdk": "block-tools structure refresh --update-deps-only",
|
|
40
|
-
|
|
40
|
+
"upgrade-sdk":
|
|
41
41
|
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt",
|
|
42
42
|
},
|
|
43
43
|
peerDependencies: {
|
|
@@ -76,16 +76,18 @@ export function rootPackageJsonRules(): void {
|
|
|
76
76
|
ensureScript("watch", "turbo watch build");
|
|
77
77
|
ensureScript("changeset", "changeset");
|
|
78
78
|
ensureScript("version-packages", "changeset version");
|
|
79
|
-
//
|
|
79
|
+
// `update-sdk` is a deprecated alias of `upgrade-sdk`, kept for compatibility;
|
|
80
|
+
// `update` is the pre-rename name — drop it so refreshed blocks converge.
|
|
80
81
|
ensureScript("update-sdk", "block-tools structure refresh --update-deps-only");
|
|
81
|
-
|
|
82
|
+
removeScript("update");
|
|
83
|
+
// Full SDK-upgrade flow: bump catalog (deps-only) → install → re-apply
|
|
82
84
|
// structure against the freshly-pulled deps → install AGAIN (the structural
|
|
83
85
|
// pass can add new devDeps — e.g. ts-builder/oxlint/oxfmt on a first
|
|
84
86
|
// migration — that `pnpm fmt` then needs on PATH) → format. Wrapped as one
|
|
85
87
|
// script. `pnpm fmt` (turbo run fmt) leaves the tree oxfmt-clean after the
|
|
86
88
|
// structural rewrite so a follow-up `pnpm check` passes.
|
|
87
89
|
ensureScript(
|
|
88
|
-
"
|
|
90
|
+
"upgrade-sdk",
|
|
89
91
|
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt",
|
|
90
92
|
);
|
|
91
93
|
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { ensureWorkspaceModulePaths, ensureCatalogAbsent, type RunContext } from "../engine/api";
|
|
22
22
|
import { matchesBumpPattern, type DerivedCatalogPin } from "../engine/registry-client";
|
|
23
|
+
import { RETIRED_TOOLCHAIN_DEPS } from "./shared/retired-deps";
|
|
23
24
|
|
|
24
25
|
/** SDK packages that live in the catalog (membership only — no versions).
|
|
25
26
|
* Init fetches npm latest for each; refresh leaves them as the lockfile has
|
|
@@ -109,11 +110,7 @@ export function rootPnpmWorkspaceInitial(ctx: RunContext): Record<string, unknow
|
|
|
109
110
|
|
|
110
111
|
export function rootPnpmWorkspaceRules(): void {
|
|
111
112
|
ensureWorkspaceModulePaths();
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
// so a migrated block sheds both the dep and its catalog entry.
|
|
116
|
-
ensureCatalogAbsent("vite");
|
|
117
|
-
ensureCatalogAbsent("tsup");
|
|
118
|
-
ensureCatalogAbsent("vue-tsc");
|
|
113
|
+
// Catalog side of the retired-dep cleanup — the per-package side sheds the
|
|
114
|
+
// matching `catalog:` references.
|
|
115
|
+
for (const name of RETIRED_TOOLCHAIN_DEPS) ensureCatalogAbsent(name);
|
|
119
116
|
}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
// `when(({ ctx }) => !ctx.isSdkInternal, ...)` wrapper.
|
|
5
5
|
|
|
6
6
|
import { scope, when, fixed, managed, file, generate } from "../engine/api";
|
|
7
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
8
7
|
import { rootPackageJsonInitial, rootPackageJsonRules } from "./root-package-json";
|
|
9
8
|
import { rootPnpmWorkspaceInitial, rootPnpmWorkspaceRules } from "./root-pnpm-workspace";
|
|
10
9
|
import { rootGitignoreRules } from "./root-gitignore";
|
|
@@ -14,13 +13,12 @@ export function rootRules(): void {
|
|
|
14
13
|
when(
|
|
15
14
|
({ ctx }) => !ctx.isSdkInternal,
|
|
16
15
|
() => {
|
|
17
|
-
// see templates/static/root/turbo.json — verbatim canonical content.
|
|
18
16
|
fixed("turbo.json", file("root/turbo.json"));
|
|
19
17
|
fixed(".vscode/settings.json", file("root/.vscode/settings.json"));
|
|
20
18
|
|
|
21
19
|
managed(
|
|
22
20
|
"package.json",
|
|
23
|
-
generate(() => rootPackageJsonInitial(
|
|
21
|
+
generate((ctx) => rootPackageJsonInitial(ctx)),
|
|
24
22
|
() => {
|
|
25
23
|
rootPackageJsonRules();
|
|
26
24
|
},
|
|
@@ -28,7 +26,7 @@ export function rootRules(): void {
|
|
|
28
26
|
|
|
29
27
|
managed(
|
|
30
28
|
"pnpm-workspace.yaml",
|
|
31
|
-
generate(() => rootPnpmWorkspaceInitial(
|
|
29
|
+
generate((ctx) => rootPnpmWorkspaceInitial(ctx)),
|
|
32
30
|
() => {
|
|
33
31
|
rootPnpmWorkspaceRules();
|
|
34
32
|
},
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Retired toolchain dependencies — a SINGLE source of truth.
|
|
2
|
+
//
|
|
3
|
+
// These packages are superseded by the canonical toolchain (ts-builder owns
|
|
4
|
+
// the build, vue-tsc, and the vite plugins; oxlint/oxfmt replace eslint) and
|
|
5
|
+
// must be shed from a migrated block in BOTH places at once:
|
|
6
|
+
// - the root catalog → `ensureCatalogAbsent` (root-pnpm-workspace)
|
|
7
|
+
// - every package.json scope → `removeDep` (via removeRetiredToolchainDeps)
|
|
8
|
+
//
|
|
9
|
+
// Removing from only one side is a latent bug: a catalog entry dropped while a
|
|
10
|
+
// package still references `<dep>: "catalog:"` leaves a dangling reference that
|
|
11
|
+
// breaks `pnpm install`. Driving both from this one list makes that impossible
|
|
12
|
+
// — add (or un-retire) a dependency HERE, once.
|
|
13
|
+
//
|
|
14
|
+
// Per-entry rationale:
|
|
15
|
+
// vite / tsup — bundling now goes through ts-builder + rolldown.
|
|
16
|
+
// vue-tsc — ts-builder runs vue-tsc internally for `block-ui`; a
|
|
17
|
+
// direct dep resolves a different version than the
|
|
18
|
+
// toolchain pins, causing type clashes in main.ts.
|
|
19
|
+
// @vitejs/plugin-vue — bundled by ts-builder's internal vite config.
|
|
20
|
+
// vite-plugin-dts — .d.ts emit is handled by ts-builder.
|
|
21
|
+
// @platforma-sdk/eslint-config — eslint is retired; linting runs via oxlint
|
|
22
|
+
// inside `ts-builder check`.
|
|
23
|
+
|
|
24
|
+
import { removeDep } from "../../engine/api";
|
|
25
|
+
|
|
26
|
+
export const RETIRED_TOOLCHAIN_DEPS: readonly string[] = [
|
|
27
|
+
"vite",
|
|
28
|
+
"tsup",
|
|
29
|
+
"vue-tsc",
|
|
30
|
+
"@vitejs/plugin-vue",
|
|
31
|
+
"vite-plugin-dts",
|
|
32
|
+
"@platforma-sdk/eslint-config",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/** Drop every retired toolchain dep from the current package.json scope.
|
|
36
|
+
* Idempotent (a `removeDep` on an absent key is a no-op), so it is safe to
|
|
37
|
+
* call uniformly from every package.json rules body regardless of which deps
|
|
38
|
+
* a given scope ever carried. Pairs with the catalog-side removal in
|
|
39
|
+
* `rootPnpmWorkspaceRules`. */
|
|
40
|
+
export function removeRetiredToolchainDeps(): void {
|
|
41
|
+
for (const name of RETIRED_TOOLCHAIN_DEPS) removeDep(name);
|
|
42
|
+
}
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
// `init` and never touched again — the block author owns them.
|
|
7
7
|
|
|
8
8
|
import { scope, managed, seed, generate, text } from "../engine/api";
|
|
9
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
10
9
|
import { softwarePackageJsonInitial, softwarePackageJsonRules } from "./software-package-json";
|
|
11
10
|
|
|
12
11
|
const MAIN_PY_SEED = `import sys
|
|
@@ -24,7 +23,7 @@ export function softwareRules(): void {
|
|
|
24
23
|
|
|
25
24
|
managed(
|
|
26
25
|
"package.json",
|
|
27
|
-
generate(() => softwarePackageJsonInitial(
|
|
26
|
+
generate((ctx) => softwarePackageJsonInitial(ctx)),
|
|
28
27
|
() => {
|
|
29
28
|
softwarePackageJsonRules();
|
|
30
29
|
},
|
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
ensureDevDeps,
|
|
8
8
|
ensurePeerDeps,
|
|
9
9
|
removeDep,
|
|
10
|
+
removeScript,
|
|
10
11
|
enforceAlphabeticalOrder,
|
|
11
12
|
enforceFieldOrder,
|
|
12
13
|
type RunContext,
|
|
13
14
|
} from "../engine/api";
|
|
14
15
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
16
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
15
17
|
|
|
16
18
|
export function testPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
17
19
|
const v = ctx.blockVars;
|
|
@@ -21,9 +23,9 @@ export function testPackageJsonInitial(ctx: RunContext): Record<string, unknown>
|
|
|
21
23
|
private: true,
|
|
22
24
|
type: "module",
|
|
23
25
|
scripts: {
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
check: "ts-builder
|
|
26
|
+
fmt: "ts-builder format",
|
|
27
|
+
// `ts-builder check` runs type-check + lint (oxlint) + fmt-check (oxfmt).
|
|
28
|
+
check: "ts-builder check --target block-test",
|
|
27
29
|
test: "vitest run --passWithNoTests",
|
|
28
30
|
},
|
|
29
31
|
peerDependencies: {
|
|
@@ -41,12 +43,13 @@ export function testPackageJsonInitial(ctx: RunContext): Record<string, unknown>
|
|
|
41
43
|
export function testPackageJsonRules(): void {
|
|
42
44
|
ensureField("type", "module");
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
ensureScript("check", "ts-builder
|
|
46
|
+
ensureScript("fmt", "ts-builder format");
|
|
47
|
+
// `ts-builder check` runs type-check + lint (oxlint) + fmt-check (oxfmt).
|
|
48
|
+
ensureScript("check", "ts-builder check --target block-test");
|
|
47
49
|
ensureScript("test", "vitest run --passWithNoTests");
|
|
50
|
+
// Linting runs inside `ts-builder check` — no separate `lint` script.
|
|
51
|
+
removeScript("lint");
|
|
48
52
|
|
|
49
|
-
// @platforma-sdk/test is a test-time dep → devDependencies (matches prod).
|
|
50
53
|
ensureDevDeps({
|
|
51
54
|
"@platforma-sdk/test": "sdk:",
|
|
52
55
|
"@milaboratories/ts-builder": "sdk:",
|
|
@@ -55,12 +58,12 @@ export function testPackageJsonRules(): void {
|
|
|
55
58
|
});
|
|
56
59
|
|
|
57
60
|
// The test tsconfig (@milaboratories/ts-configs/block/test) supplies the
|
|
58
|
-
// ambient types
|
|
59
|
-
// `@types/node` peer a legacy block declares.
|
|
61
|
+
// ambient types, so only the `typescript` peer is needed — no `@types/node`.
|
|
60
62
|
ensurePeerDeps({
|
|
61
63
|
typescript: "*",
|
|
62
64
|
});
|
|
63
65
|
removeDep("@types/node");
|
|
66
|
+
removeRetiredToolchainDeps();
|
|
64
67
|
|
|
65
68
|
enforceAlphabeticalOrder("dependencies");
|
|
66
69
|
enforceAlphabeticalOrder("devDependencies");
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Test-scope rules.
|
|
2
2
|
|
|
3
3
|
import { scope, fixed, managed, scaffold, seed, file, text, generate } from "../engine/api";
|
|
4
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
5
4
|
import { testPackageJsonInitial, testPackageJsonRules } from "./test-package-json";
|
|
6
5
|
|
|
7
6
|
export function testRules(): void {
|
|
@@ -11,6 +10,10 @@ export function testRules(): void {
|
|
|
11
10
|
// lets the check pass on a test-less block while `include` still
|
|
12
11
|
// type-checks real tests once present.
|
|
13
12
|
fixed("tsconfig.json", file("test/tsconfig.json"));
|
|
13
|
+
// Block-local oxlint/oxfmt config — test sources are lint + fmt-checked
|
|
14
|
+
// (the `check` script runs `ts-builder check --target block-test`).
|
|
15
|
+
fixed(".oxlintrc.json", file("test/.oxlintrc.json"));
|
|
16
|
+
fixed(".oxfmtrc.json", file("test/.oxfmtrc.json"));
|
|
14
17
|
// scaffold (not fixed): integration tests legitimately tune timeout /
|
|
15
18
|
// retry per block. Write the canonical default if absent; never
|
|
16
19
|
// overwrite an author's config.
|
|
@@ -31,7 +34,7 @@ export function testRules(): void {
|
|
|
31
34
|
|
|
32
35
|
managed(
|
|
33
36
|
"package.json",
|
|
34
|
-
generate(() => testPackageJsonInitial(
|
|
37
|
+
generate((ctx) => testPackageJsonInitial(ctx)),
|
|
35
38
|
() => {
|
|
36
39
|
testPackageJsonRules();
|
|
37
40
|
},
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { scopeDepMap } from "../engine/ctx";
|
|
27
27
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
28
28
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
29
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
29
30
|
|
|
30
31
|
export function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
31
32
|
const v = ctx.blockVars;
|
|
@@ -52,6 +53,7 @@ export function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
|
52
53
|
"@milaboratories/ts-configs": "sdk:",
|
|
53
54
|
},
|
|
54
55
|
peerDependencies: {
|
|
56
|
+
"@types/node": "*",
|
|
55
57
|
typescript: "*",
|
|
56
58
|
},
|
|
57
59
|
};
|
|
@@ -77,33 +79,25 @@ export function uiPackageJsonRules(): void {
|
|
|
77
79
|
"@milaboratories/ts-configs": "sdk:",
|
|
78
80
|
});
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
// `--target block-ui`), so the ui must NOT declare its own. A direct
|
|
82
|
-
// `vue-tsc` dep is the vestigial vite/vue-tsc-era artefact: it resolves
|
|
83
|
-
// independently of the version ts-builder pins, which is how a block ended
|
|
84
|
-
// up type-checking under a different vue-tsc than the toolchain intends.
|
|
85
|
-
removeDep("vue-tsc");
|
|
86
|
-
|
|
87
|
-
// vite-era artefacts: the canonical ui builds + dev-serves via ts-builder,
|
|
88
|
-
// so a legacy `vite` dep and the `preview` (vite preview) script are dropped.
|
|
89
|
-
removeDep("vite");
|
|
82
|
+
removeRetiredToolchainDeps();
|
|
90
83
|
removeScript("preview");
|
|
84
|
+
removeScript("lint");
|
|
91
85
|
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
86
|
+
// `@types/node` is declared as a peer by default — mirrors the model scope
|
|
87
|
+
// (the block author resolves it from the workspace root). The ui builds with
|
|
88
|
+
// `--target block-ui` (types: []), so it pulls no node ambient types into the
|
|
89
|
+
// build; the peer only satisfies IDE / type resolution, alongside `typescript`.
|
|
96
90
|
ensurePeerDeps({
|
|
91
|
+
"@types/node": "*",
|
|
97
92
|
typescript: "*",
|
|
98
93
|
});
|
|
99
|
-
removeDep("@types/node");
|
|
100
94
|
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
95
|
+
// A ui WITH co-located unit tests (`src/**/*.test.ts`) needs the vitest
|
|
96
|
+
// `test` script, the `vitest` devDep, AND node ambient types promoted from
|
|
97
|
+
// peer to a devDep (the single-section invariant drops the peer) so that
|
|
98
|
+
// `types: ["node"]` in ui/tsconfig — wired under the same predicate —
|
|
99
|
+
// resolves the tests' `node:*` imports. A test-less ui keeps `@types/node`
|
|
100
|
+
// as a peer and carries no vitest, staying a refresh fixpoint.
|
|
107
101
|
//
|
|
108
102
|
// Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test
|
|
109
103
|
// wiring under the monorepo's shared infrastructure — see model-package-json.
|
|
@@ -10,11 +10,9 @@ import {
|
|
|
10
10
|
file,
|
|
11
11
|
tpl,
|
|
12
12
|
generate,
|
|
13
|
-
blockVars,
|
|
14
13
|
when,
|
|
15
14
|
whenFilesExist,
|
|
16
15
|
} from "../engine/api";
|
|
17
|
-
import { getActiveRunContext } from "../engine/builders";
|
|
18
16
|
import { uiPackageJsonInitial, uiPackageJsonRules } from "./ui-package-json";
|
|
19
17
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
20
18
|
|
|
@@ -45,16 +43,16 @@ export function uiRules(): void {
|
|
|
45
43
|
seed("src/main.ts", file("ui/src/main.ts"));
|
|
46
44
|
seed(
|
|
47
45
|
"src/app.ts",
|
|
48
|
-
tpl("ui/src/app.tpl.ts", () => ({ modelPkg: `${blockVars
|
|
46
|
+
tpl("ui/src/app.tpl.ts", (ctx) => ({ modelPkg: `${ctx.blockVars.facadeName}.model` })),
|
|
49
47
|
);
|
|
50
48
|
seed(
|
|
51
49
|
"src/MainPage.vue",
|
|
52
|
-
tpl("ui/src/MainPage.tpl.vue", () => ({ shortName: blockVars
|
|
50
|
+
tpl("ui/src/MainPage.tpl.vue", (ctx) => ({ shortName: ctx.blockVars.shortName })),
|
|
53
51
|
);
|
|
54
52
|
|
|
55
53
|
managed(
|
|
56
54
|
"package.json",
|
|
57
|
-
generate(() => uiPackageJsonInitial(
|
|
55
|
+
generate((ctx) => uiPackageJsonInitial(ctx)),
|
|
58
56
|
() => {
|
|
59
57
|
uiPackageJsonRules();
|
|
60
58
|
},
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { scopeDepMaps } from "../engine/ctx";
|
|
20
20
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
21
21
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
22
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
22
23
|
|
|
23
24
|
export function workflowPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
24
25
|
const v = ctx.blockVars;
|
|
@@ -55,11 +56,10 @@ export function workflowPackageJsonInitial(ctx: RunContext): Record<string, unkn
|
|
|
55
56
|
export function workflowPackageJsonRules(): void {
|
|
56
57
|
ensureField("type", "module");
|
|
57
58
|
|
|
58
|
-
// No `fmt
|
|
59
|
-
// pl-tengo
|
|
59
|
+
// No `fmt` script: the workflow is Tengo, not TS — build + check run via
|
|
60
|
+
// pl-tengo; `format` runs the emacs-batch Tengo formatter (no-op when absent).
|
|
60
61
|
ensureScript("build", "shx rm -rf dist && pl-tengo build");
|
|
61
62
|
ensureScript("check", "pl-tengo check");
|
|
62
|
-
// Tengo source formatter (emacs batch); no-op notice when emacs is absent.
|
|
63
63
|
ensureScript("format", "/usr/bin/env emacs --script ./format.el || echo 'No emacs.'");
|
|
64
64
|
// The vitest `test` script AND the `vitest` devDep are wired ONLY when the
|
|
65
65
|
// workflow carries co-located integration tests (`src/**/*.test.ts`, incl.
|
|
@@ -98,6 +98,10 @@ export function workflowPackageJsonRules(): void {
|
|
|
98
98
|
shx: "catalog:",
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
+
// No-op for a canonical Tengo workflow; called uniformly across every scope
|
|
102
|
+
// for safety.
|
|
103
|
+
removeRetiredToolchainDeps();
|
|
104
|
+
|
|
101
105
|
enforceAlphabeticalOrder("dependencies");
|
|
102
106
|
enforceAlphabeticalOrder("devDependencies");
|
|
103
107
|
enforceAlphabeticalOrder("peerDependencies");
|