@platforma-sdk/block-tools 2.10.17 → 2.10.19
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 +13 -13
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +674 -615
- package/dist/cli.mjs.map +1 -1
- package/dist/structure/engine/api.d.ts +1 -1
- package/dist/structure/engine/content-rules.d.ts +17 -0
- package/dist/structure/engine/registry-client.d.ts +30 -2
- package/dist/structure/engine/runner.d.ts +6 -0
- package/dist/structure/rules/root-pnpm-workspace.d.ts +13 -0
- package/dist/structure/rules/shared/retired-deps.d.ts +7 -0
- package/dist/v2/registry/schema_public.d.ts +6177 -6177
- package/package.json +8 -8
- package/src/structure/CLAUDE.md +28 -0
- package/src/structure/__tests__/model-package-json.snapshot.test.ts +1 -2
- package/src/structure/cli/run-structure.ts +12 -2
- package/src/structure/engine/__tests__/content-rules/pin-catalog-to-dependency-of.test.ts +65 -0
- package/src/structure/engine/__tests__/derived-pin-lookup.test.ts +54 -0
- package/src/structure/engine/api.ts +1 -0
- package/src/structure/engine/content-rules.ts +29 -0
- package/src/structure/engine/registry-client.ts +116 -2
- package/src/structure/engine/runner.ts +18 -2
- package/src/structure/init-block-constructor.ts +16 -3
- package/src/structure/rules/migrations.ts +15 -16
- package/src/structure/rules/model-package-json.ts +34 -16
- package/src/structure/rules/root-catalog-bump.ts +12 -1
- package/src/structure/rules/root-package-json.ts +15 -11
- package/src/structure/rules/root-pnpm-workspace.ts +21 -8
- package/src/structure/rules/root.ts +0 -1
- package/src/structure/rules/shared/retired-deps.ts +42 -0
- package/src/structure/rules/test-package-json.ts +12 -9
- package/src/structure/rules/test.ts +4 -0
- package/src/structure/rules/ui-package-json.ts +33 -25
- package/src/structure/rules/workflow-package-json.ts +32 -14
- package/src/structure/rules/workflow.ts +32 -8
- package/src/structure/templates/static/test/.oxfmtrc.json +4 -0
- package/src/structure/templates/static/test/.oxlintrc.json +3 -0
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
ensureDep,
|
|
16
16
|
ensureDevDep,
|
|
17
17
|
ensureDevDeps,
|
|
18
|
+
removeDep,
|
|
19
|
+
removeScript,
|
|
20
|
+
removeField,
|
|
18
21
|
ensurePeerDeps,
|
|
19
22
|
enforceAlphabeticalOrder,
|
|
20
23
|
enforceFieldOrder,
|
|
@@ -24,6 +27,7 @@ import {
|
|
|
24
27
|
} from "../engine/api";
|
|
25
28
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
26
29
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
30
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
27
31
|
|
|
28
32
|
export function modelPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
29
33
|
const v = ctx.blockVars;
|
|
@@ -49,8 +53,6 @@ export function modelPackageJsonInitial(ctx: RunContext): Record<string, unknown
|
|
|
49
53
|
watch: "ts-builder build --target block-model --watch",
|
|
50
54
|
build: "ts-builder build --target block-model && block-tools build-model",
|
|
51
55
|
check: "ts-builder check --target block-model",
|
|
52
|
-
// No `test`: the vitest `test` script is wired by the body rule ONLY
|
|
53
|
-
// when co-located test files exist (a freshly-init'd model has none).
|
|
54
56
|
},
|
|
55
57
|
dependencies: {
|
|
56
58
|
"@platforma-sdk/model": "sdk:",
|
|
@@ -59,7 +61,6 @@ export function modelPackageJsonInitial(ctx: RunContext): Record<string, unknown
|
|
|
59
61
|
"@milaboratories/ts-builder": "sdk:",
|
|
60
62
|
"@milaboratories/ts-configs": "sdk:",
|
|
61
63
|
"@platforma-sdk/block-tools": "sdk:",
|
|
62
|
-
vitest: "catalog:",
|
|
63
64
|
},
|
|
64
65
|
peerDependencies: {
|
|
65
66
|
"@types/node": "*",
|
|
@@ -94,7 +95,6 @@ export function modelPackageJsonRules(): void {
|
|
|
94
95
|
"@milaboratories/ts-builder": "sdk:",
|
|
95
96
|
"@milaboratories/ts-configs": "sdk:",
|
|
96
97
|
"@platforma-sdk/block-tools": "sdk:",
|
|
97
|
-
vitest: "catalog:",
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
ensurePeerDeps({
|
|
@@ -102,18 +102,36 @@ export function modelPackageJsonRules(): void {
|
|
|
102
102
|
typescript: "*",
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
// The vitest `test` script
|
|
106
|
-
// model carries co-located unit tests (`src/**/*.test.ts`).
|
|
107
|
-
// model gets
|
|
108
|
-
// scope stays a refresh fixpoint. When tests ARE present, `@types/node`
|
|
109
|
-
// is promoted from peer to a devDep (the single-section invariant drops
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
105
|
+
// The vitest `test` script, the `vitest` devDep, and node ambient types are
|
|
106
|
+
// wired ONLY when the model carries co-located unit tests (`src/**/*.test.ts`).
|
|
107
|
+
// A test-less model gets none — turbo simply has no `test` task for it, and
|
|
108
|
+
// the scope stays a refresh fixpoint. When tests ARE present, `@types/node`
|
|
109
|
+
// is promoted from peer to a devDep (the single-section invariant drops the
|
|
110
|
+
// peer) so the tests' `node:*` imports resolve under the `types: ["node"]`
|
|
111
|
+
// that model/tsconfig adds under the same predicate. Runs AFTER ensurePeerDeps
|
|
112
|
+
// so the promotion is not reverted.
|
|
113
|
+
//
|
|
114
|
+
// Skipped entirely for sdk-internal (in-monorepo) blocks: those live inside
|
|
115
|
+
// the platforma monorepo's own test infrastructure (build-configs, shared
|
|
116
|
+
// catalog, coverage providers) and own their test wiring — the structurer
|
|
117
|
+
// must not impose or strip standalone-block test conventions on them.
|
|
118
|
+
when(
|
|
119
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
120
|
+
() =>
|
|
121
|
+
when(
|
|
122
|
+
whenFilesExist(COLOCATED_TEST_GLOB),
|
|
123
|
+
() => {
|
|
124
|
+
ensureScript("test", "vitest run --passWithNoTests");
|
|
125
|
+
ensureDevDep("vitest", "catalog:");
|
|
126
|
+
ensureDevDep("@types/node", "*");
|
|
127
|
+
},
|
|
128
|
+
() => removeDep("vitest"),
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
removeRetiredToolchainDeps();
|
|
133
|
+
removeField("tsup");
|
|
134
|
+
removeScript("lint");
|
|
117
135
|
|
|
118
136
|
enforceAlphabeticalOrder("dependencies");
|
|
119
137
|
enforceAlphabeticalOrder("devDependencies");
|
|
@@ -26,12 +26,14 @@ import {
|
|
|
26
26
|
generate,
|
|
27
27
|
ensureCatalogLatest,
|
|
28
28
|
ensureCatalogVersion,
|
|
29
|
+
pinCatalogToDependencyOf,
|
|
29
30
|
} from "../engine/api";
|
|
30
31
|
import { getActiveRunContext } from "../engine/builders";
|
|
31
32
|
import {
|
|
32
33
|
rootPnpmWorkspaceInitial,
|
|
33
34
|
SDK_CATALOG_PACKAGES,
|
|
34
35
|
INFRA_CATALOG_FLOOR,
|
|
36
|
+
DERIVED_CATALOG_PINS,
|
|
35
37
|
RUNENV_PYTHON,
|
|
36
38
|
RUNENV_PYTHON_VERSION,
|
|
37
39
|
} from "./root-pnpm-workspace";
|
|
@@ -57,8 +59,17 @@ export function rootCatalogBumpRules(): void {
|
|
|
57
59
|
// block's missing standard keys + overwrites the init
|
|
58
60
|
// placeholder).
|
|
59
61
|
for (const name of SDK_CATALOG_PACKAGES) ensureCatalogLatest(name);
|
|
62
|
+
// Derived catalog pins → the EXACT version their source package
|
|
63
|
+
// declares (e.g. `vue` from `@platforma-sdk/ui-vue`). OVERWRITES
|
|
64
|
+
// (seeds when absent, tightens a loose on-disk entry). Resolved
|
|
65
|
+
// by the prefetched `derivedPinLookup`; a no-op when absent
|
|
66
|
+
// (default refresh passes none). Must run AFTER ensureCatalogLatest
|
|
67
|
+
// — the source package's own version is bumped there first.
|
|
68
|
+
for (const pin of DERIVED_CATALOG_PINS) {
|
|
69
|
+
pinCatalogToDependencyOf(pin.entry, { of: pin.of, ofVersion: pin.ofVersion });
|
|
70
|
+
}
|
|
60
71
|
// Curated infra floor → fixed version, ADD-IF-ABSENT (seeds
|
|
61
|
-
// shx/turbo/vitest/
|
|
72
|
+
// shx/turbo/vitest/changesets when missing; never touches a
|
|
62
73
|
// version the block already pins).
|
|
63
74
|
for (const [name, version] of Object.entries(INFRA_CATALOG_FLOOR)) {
|
|
64
75
|
ensureCatalogVersion(name, version);
|
|
@@ -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,11 +35,10 @@ 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
|
-
|
|
41
|
-
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm fmt",
|
|
40
|
+
"upgrade-sdk":
|
|
41
|
+
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt",
|
|
42
42
|
},
|
|
43
43
|
peerDependencies: {
|
|
44
44
|
oxlint: "*",
|
|
@@ -76,15 +76,19 @@ 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
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
82
|
+
removeScript("update");
|
|
83
|
+
// Full SDK-upgrade flow: bump catalog (deps-only) → install → re-apply
|
|
84
|
+
// structure against the freshly-pulled deps → install AGAIN (the structural
|
|
85
|
+
// pass can add new devDeps — e.g. ts-builder/oxlint/oxfmt on a first
|
|
86
|
+
// migration — that `pnpm fmt` then needs on PATH) → format. Wrapped as one
|
|
87
|
+
// script. `pnpm fmt` (turbo run fmt) leaves the tree oxfmt-clean after the
|
|
88
|
+
// structural rewrite so a follow-up `pnpm check` passes.
|
|
85
89
|
ensureScript(
|
|
86
|
-
"
|
|
87
|
-
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm fmt",
|
|
90
|
+
"upgrade-sdk",
|
|
91
|
+
"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt",
|
|
88
92
|
);
|
|
89
93
|
|
|
90
94
|
ensureDevDeps({
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
// npm-latest for the SDK families) lives in the separate `onInitOrUpdate`
|
|
19
19
|
// frame (`rootCatalogBumpRules`), which fires on init + update-deps only.
|
|
20
20
|
|
|
21
|
-
import { ensureWorkspaceModulePaths, type RunContext } from "../engine/api";
|
|
22
|
-
import { matchesBumpPattern } from "../engine/registry-client";
|
|
21
|
+
import { ensureWorkspaceModulePaths, ensureCatalogAbsent, type RunContext } from "../engine/api";
|
|
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
|
|
@@ -62,14 +63,23 @@ export const INFRA_CATALOG_FLOOR: Record<string, string> = {
|
|
|
62
63
|
shx: "~0.4.0",
|
|
63
64
|
"@changesets/cli": "~2.29.8",
|
|
64
65
|
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
66
|
};
|
|
72
67
|
|
|
68
|
+
/** Catalog entries whose exact version is DERIVED from the version another
|
|
69
|
+
* package declares for them (see `pinCatalogToDependencyOf`). Resolved on
|
|
70
|
+
* init + update-deps and OVERWRITES the on-disk entry.
|
|
71
|
+
*
|
|
72
|
+
* `vue`: the seeded ui depends on `vue` (catalog:). `@platforma-sdk/ui-vue`
|
|
73
|
+
* pins vue as an EXACT regular dependency (not a peer), so the block must
|
|
74
|
+
* pin the SAME exact version — a floated `~` lets the ui resolve a newer
|
|
75
|
+
* 3.5.x than ui-vue's, yielding two vue instances and a SdkPluginV3-vs-Plugin
|
|
76
|
+
* type clash in `main.ts`. Deriving the pin from ui-vue's declared dep keeps
|
|
77
|
+
* the block in lockstep with whatever vue ui-vue's npm-latest pins, with no
|
|
78
|
+
* hand-maintained version here. */
|
|
79
|
+
export const DERIVED_CATALOG_PINS: readonly DerivedCatalogPin[] = [
|
|
80
|
+
{ entry: "vue", of: "@platforma-sdk/ui-vue" },
|
|
81
|
+
];
|
|
82
|
+
|
|
73
83
|
/** Catalog name of the python runenv. Added to a block's catalog only when
|
|
74
84
|
* the block carries a software module. Pinned to an EXACT version — updating
|
|
75
85
|
* the python runenv is an explicit author decision, never automatic. */
|
|
@@ -100,4 +110,7 @@ export function rootPnpmWorkspaceInitial(ctx: RunContext): Record<string, unknow
|
|
|
100
110
|
|
|
101
111
|
export function rootPnpmWorkspaceRules(): void {
|
|
102
112
|
ensureWorkspaceModulePaths();
|
|
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);
|
|
103
116
|
}
|
|
@@ -14,7 +14,6 @@ export function rootRules(): void {
|
|
|
14
14
|
when(
|
|
15
15
|
({ ctx }) => !ctx.isSdkInternal,
|
|
16
16
|
() => {
|
|
17
|
-
// see templates/static/root/turbo.json — verbatim canonical content.
|
|
18
17
|
fixed("turbo.json", file("root/turbo.json"));
|
|
19
18
|
fixed(".vscode/settings.json", file("root/.vscode/settings.json"));
|
|
20
19
|
|
|
@@ -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
|
+
}
|
|
@@ -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");
|
|
@@ -11,6 +11,10 @@ export function testRules(): void {
|
|
|
11
11
|
// lets the check pass on a test-less block while `include` still
|
|
12
12
|
// type-checks real tests once present.
|
|
13
13
|
fixed("tsconfig.json", file("test/tsconfig.json"));
|
|
14
|
+
// Block-local oxlint/oxfmt config — test sources are lint + fmt-checked
|
|
15
|
+
// (the `check` script runs `ts-builder check --target block-test`).
|
|
16
|
+
fixed(".oxlintrc.json", file("test/.oxlintrc.json"));
|
|
17
|
+
fixed(".oxfmtrc.json", file("test/.oxfmtrc.json"));
|
|
14
18
|
// scaffold (not fixed): integration tests legitimately tune timeout /
|
|
15
19
|
// retry per block. Write the canonical default if absent; never
|
|
16
20
|
// overwrite an author's config.
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ensurePeerDeps,
|
|
17
17
|
ensureWorkspaceScopeDeps,
|
|
18
18
|
removeDep,
|
|
19
|
+
removeScript,
|
|
19
20
|
enforceAlphabeticalOrder,
|
|
20
21
|
enforceFieldOrder,
|
|
21
22
|
when,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
import { scopeDepMap } from "../engine/ctx";
|
|
26
27
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
27
28
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
29
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
28
30
|
|
|
29
31
|
export function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
30
32
|
const v = ctx.blockVars;
|
|
@@ -38,8 +40,6 @@ export function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
|
38
40
|
watch: "ts-builder build --target block-ui --watch",
|
|
39
41
|
build: "ts-builder build --target block-ui",
|
|
40
42
|
check: "ts-builder check --target block-ui",
|
|
41
|
-
// No `test`: the vitest `test` script is wired by the body rule ONLY
|
|
42
|
-
// when co-located test files exist (a freshly-init'd ui has none).
|
|
43
43
|
},
|
|
44
44
|
dependencies: {
|
|
45
45
|
"@platforma-sdk/ui-vue": "sdk:",
|
|
@@ -51,9 +51,9 @@ export function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
|
51
51
|
devDependencies: {
|
|
52
52
|
"@milaboratories/ts-builder": "sdk:",
|
|
53
53
|
"@milaboratories/ts-configs": "sdk:",
|
|
54
|
-
vitest: "catalog:",
|
|
55
54
|
},
|
|
56
55
|
peerDependencies: {
|
|
56
|
+
"@types/node": "*",
|
|
57
57
|
typescript: "*",
|
|
58
58
|
},
|
|
59
59
|
};
|
|
@@ -77,35 +77,43 @@ export function uiPackageJsonRules(): void {
|
|
|
77
77
|
ensureDevDeps({
|
|
78
78
|
"@milaboratories/ts-builder": "sdk:",
|
|
79
79
|
"@milaboratories/ts-configs": "sdk:",
|
|
80
|
-
vitest: "catalog:",
|
|
81
80
|
});
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// independently of the version ts-builder pins, which is how a block ended
|
|
87
|
-
// up type-checking under a different vue-tsc than the toolchain intends.
|
|
88
|
-
removeDep("vue-tsc");
|
|
82
|
+
removeRetiredToolchainDeps();
|
|
83
|
+
removeScript("preview");
|
|
84
|
+
removeScript("lint");
|
|
89
85
|
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
//
|
|
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`.
|
|
94
90
|
ensurePeerDeps({
|
|
91
|
+
"@types/node": "*",
|
|
95
92
|
typescript: "*",
|
|
96
93
|
});
|
|
97
|
-
removeDep("@types/node");
|
|
98
94
|
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
// the
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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.
|
|
101
|
+
//
|
|
102
|
+
// Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test
|
|
103
|
+
// wiring under the monorepo's shared infrastructure — see model-package-json.
|
|
104
|
+
when(
|
|
105
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
106
|
+
() =>
|
|
107
|
+
when(
|
|
108
|
+
whenFilesExist(COLOCATED_TEST_GLOB),
|
|
109
|
+
() => {
|
|
110
|
+
ensureScript("test", "vitest run --passWithNoTests");
|
|
111
|
+
ensureDevDep("vitest", "catalog:");
|
|
112
|
+
ensureDevDep("@types/node", "*");
|
|
113
|
+
},
|
|
114
|
+
() => removeDep("vitest"),
|
|
115
|
+
),
|
|
116
|
+
);
|
|
109
117
|
|
|
110
118
|
enforceAlphabeticalOrder("dependencies");
|
|
111
119
|
enforceAlphabeticalOrder("devDependencies");
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ensureScript,
|
|
9
9
|
ensureDep,
|
|
10
10
|
ensureDevDeps,
|
|
11
|
+
removeDep,
|
|
11
12
|
ensureWorkspaceScopeDeps,
|
|
12
13
|
enforceAlphabeticalOrder,
|
|
13
14
|
enforceFieldOrder,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
import { scopeDepMaps } from "../engine/ctx";
|
|
19
20
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
20
21
|
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
22
|
+
import { removeRetiredToolchainDeps } from "./shared/retired-deps";
|
|
21
23
|
|
|
22
24
|
export function workflowPackageJsonInitial(ctx: RunContext): Record<string, unknown> {
|
|
23
25
|
const v = ctx.blockVars;
|
|
@@ -44,7 +46,8 @@ export function workflowPackageJsonInitial(ctx: RunContext): Record<string, unkn
|
|
|
44
46
|
devDependencies: {
|
|
45
47
|
"@platforma-sdk/tengo-builder": "sdk:",
|
|
46
48
|
"@platforma-sdk/test": "sdk:",
|
|
47
|
-
vitest
|
|
49
|
+
// `vitest` is NOT seeded here — it's wired by the body rule only when the
|
|
50
|
+
// workflow carries co-located tests (a freshly-init'd workflow has none).
|
|
48
51
|
shx: "catalog:",
|
|
49
52
|
},
|
|
50
53
|
};
|
|
@@ -53,21 +56,33 @@ export function workflowPackageJsonInitial(ctx: RunContext): Record<string, unkn
|
|
|
53
56
|
export function workflowPackageJsonRules(): void {
|
|
54
57
|
ensureField("type", "module");
|
|
55
58
|
|
|
56
|
-
// No `fmt
|
|
57
|
-
// 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).
|
|
58
61
|
ensureScript("build", "shx rm -rf dist && pl-tengo build");
|
|
59
62
|
ensureScript("check", "pl-tengo check");
|
|
60
|
-
// Tengo source formatter (emacs batch); no-op notice when emacs is absent.
|
|
61
63
|
ensureScript("format", "/usr/bin/env emacs --script ./format.el || echo 'No emacs.'");
|
|
62
|
-
// The vitest `test` script
|
|
63
|
-
// co-located integration tests (`src/**/*.test.ts`, incl.
|
|
64
|
-
// A test-less workflow gets no `test` task
|
|
65
|
-
// (Workflow tests type-check via
|
|
66
|
-
// `types: []` — they pull their types
|
|
67
|
-
// node-types wiring is needed here,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
// The vitest `test` script AND the `vitest` devDep are wired ONLY when the
|
|
65
|
+
// workflow carries co-located integration tests (`src/**/*.test.ts`, incl.
|
|
66
|
+
// `src/test/`). A test-less workflow gets neither — no `test` task, no
|
|
67
|
+
// vitest dep — and stays a refresh fixpoint. (Workflow tests type-check via
|
|
68
|
+
// the standalone workflow/tsconfig with `types: []` — they pull their types
|
|
69
|
+
// from `@platforma-sdk/test` — so no node-types wiring is needed here,
|
|
70
|
+
// unlike model/ui.)
|
|
71
|
+
//
|
|
72
|
+
// Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test
|
|
73
|
+
// wiring under the monorepo's shared infrastructure — see model-package-json.
|
|
74
|
+
when(
|
|
75
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
76
|
+
() =>
|
|
77
|
+
when(
|
|
78
|
+
whenFilesExist(COLOCATED_TEST_GLOB),
|
|
79
|
+
() => {
|
|
80
|
+
ensureScript("test", "vitest run --passWithNoTests");
|
|
81
|
+
ensureDevDeps({ vitest: "catalog:" });
|
|
82
|
+
},
|
|
83
|
+
() => removeDep("vitest"),
|
|
84
|
+
),
|
|
85
|
+
);
|
|
71
86
|
|
|
72
87
|
ensureDep("@platforma-sdk/workflow-tengo", "sdk:");
|
|
73
88
|
|
|
@@ -80,10 +95,13 @@ export function workflowPackageJsonRules(): void {
|
|
|
80
95
|
ensureDevDeps({
|
|
81
96
|
"@platforma-sdk/tengo-builder": "sdk:",
|
|
82
97
|
"@platforma-sdk/test": "sdk:",
|
|
83
|
-
vitest: "catalog:",
|
|
84
98
|
shx: "catalog:",
|
|
85
99
|
});
|
|
86
100
|
|
|
101
|
+
// No-op for a canonical Tengo workflow; called uniformly across every scope
|
|
102
|
+
// for safety.
|
|
103
|
+
removeRetiredToolchainDeps();
|
|
104
|
+
|
|
87
105
|
enforceAlphabeticalOrder("dependencies");
|
|
88
106
|
enforceAlphabeticalOrder("devDependencies");
|
|
89
107
|
enforceAlphabeticalOrder("peerDependencies");
|
|
@@ -11,25 +11,49 @@ import {
|
|
|
11
11
|
tpl,
|
|
12
12
|
generate,
|
|
13
13
|
remove,
|
|
14
|
+
when,
|
|
15
|
+
whenFilesExist,
|
|
14
16
|
blockVars,
|
|
15
17
|
} from "../engine/api";
|
|
16
18
|
import { getActiveRunContext } from "../engine/builders";
|
|
17
19
|
import { workflowPackageJsonInitial, workflowPackageJsonRules } from "./workflow-package-json";
|
|
20
|
+
import { COLOCATED_TEST_GLOB } from "./shared/colocated-tests";
|
|
18
21
|
|
|
19
22
|
export function workflowRules(): void {
|
|
20
23
|
scope("workflow", () => {
|
|
21
|
-
// tsconfig for the TypeScript vitest integration tests under src/test
|
|
22
|
-
// (e.g. mixcr's workflow/src/test/columns.test.ts). types:[] keeps the
|
|
23
|
-
// isomorphic workflow free of ambient Node/DOM types.
|
|
24
|
-
fixed("tsconfig.json", file("workflow/tsconfig.json"));
|
|
25
24
|
// Tengo source formatter (emacs batch); the `format` script invokes it.
|
|
26
25
|
fixed("format.el", file("workflow/format.el"));
|
|
27
|
-
//
|
|
28
|
-
|
|
26
|
+
// The TS-test tsconfig + vitest config exist ONLY when the workflow carries
|
|
27
|
+
// co-located tests (`src/**/*.test.ts`, incl. `src/test/` — e.g. mixcr's
|
|
28
|
+
// workflow/src/test/columns.test.ts). They pair with the conditional
|
|
29
|
+
// `vitest` devDep + `test` script in workflow-package-json. tsconfig is
|
|
30
|
+
// `fixed` (structural: types:[] keeps the isomorphic workflow free of
|
|
31
|
+
// ambient Node/DOM types); vitest.config is `scaffold` (author-tunable once
|
|
32
|
+
// present). A test-less workflow gets neither and stays a refresh fixpoint.
|
|
33
|
+
//
|
|
34
|
+
// Skipped entirely for sdk-internal (in-monorepo) blocks: they own their
|
|
35
|
+
// test config under the monorepo's shared infrastructure (e.g. a bespoke
|
|
36
|
+
// `vitest run --coverage` + `createVitestConfig`), which the structurer
|
|
37
|
+
// must neither scaffold nor remove. See workflow-package-json.
|
|
38
|
+
when(
|
|
39
|
+
({ ctx }) => !ctx.isSdkInternal,
|
|
40
|
+
() =>
|
|
41
|
+
when(
|
|
42
|
+
whenFilesExist(COLOCATED_TEST_GLOB),
|
|
43
|
+
() => {
|
|
44
|
+
fixed("tsconfig.json", file("workflow/tsconfig.json"));
|
|
45
|
+
scaffold("vitest.config.mts", file("workflow/vitest.config.mts"));
|
|
46
|
+
},
|
|
47
|
+
() => {
|
|
48
|
+
remove("tsconfig.json");
|
|
49
|
+
remove("vitest.config.mts");
|
|
50
|
+
},
|
|
51
|
+
),
|
|
52
|
+
);
|
|
29
53
|
// No workflow facade (index.js / index.d.ts): the block loader resolves the
|
|
30
54
|
// workflow via the `block:` components dist path (workflow/dist/.../main.plj.gz),
|
|
31
|
-
// never the JS facade.
|
|
32
|
-
//
|
|
55
|
+
// never the JS facade. Removed so blocks that carry one get cleaned
|
|
56
|
+
// (idempotent on absence).
|
|
33
57
|
remove("index.js");
|
|
34
58
|
remove("index.d.ts");
|
|
35
59
|
|