@platforma-sdk/block-tools 2.10.14 → 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 +9 -7
- 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,124 @@
|
|
|
1
|
+
import { Scope, RunContext } from './api';
|
|
2
|
+
/** The three leaf-firing modes. `check` and `refresh` share the
|
|
3
|
+
* `"default"` mode — they run the same leaves, the `dryRun` flag (carried
|
|
4
|
+
* separately on `RunContext`) only decides whether writes happen.
|
|
5
|
+
* `"updateDeps"` is `--update-deps-only`; `"init"` is the init
|
|
6
|
+
* constructor. A leaf declares which modes it fires in via its enclosing
|
|
7
|
+
* mode frame (see `ModeFrame`); the runner derives the current mode from
|
|
8
|
+
* the run context and keeps only the leaves whose membership includes it. */
|
|
9
|
+
export type RunMode = "default" | "updateDeps" | "init";
|
|
10
|
+
/** Predicate evaluated against derived trigger context. */
|
|
11
|
+
export type TriggerContext = {
|
|
12
|
+
ctx: RunContext;
|
|
13
|
+
version: number;
|
|
14
|
+
/** Block-relative path queries against the post-structural FS snapshot. */
|
|
15
|
+
pathExists(path: string): boolean;
|
|
16
|
+
pathMissing(path: string): boolean;
|
|
17
|
+
/** True if any file in the snapshot matches `glob`, resolved
|
|
18
|
+
* MODULE-RELATIVE to the leaf's bound module: a co-located-test glob
|
|
19
|
+
* inside `scope("model")` is checked under the `model/` dir. At the
|
|
20
|
+
* block root the glob is block-relative. Unlike `pathExists`/`pathMissing`
|
|
21
|
+
* (block-relative), `filesMatch` is the module-aware predicate used by
|
|
22
|
+
* `whenFilesExist`. */
|
|
23
|
+
filesMatch(glob: string): boolean;
|
|
24
|
+
};
|
|
25
|
+
export type TriggerFn = (tctx: TriggerContext) => boolean;
|
|
26
|
+
/** Content forms — what to write into a file when creating it.
|
|
27
|
+
* `tpl.vars` may be a record or a thunk returning a record; the latter
|
|
28
|
+
* lets rule authors call `blockVars()` lazily at resolve time. */
|
|
29
|
+
export type TplVarsLike = Record<string, string> | (() => Record<string, string>);
|
|
30
|
+
export type ContentForm = {
|
|
31
|
+
kind: "file";
|
|
32
|
+
path: string;
|
|
33
|
+
} | {
|
|
34
|
+
kind: "text";
|
|
35
|
+
value: string;
|
|
36
|
+
} | {
|
|
37
|
+
kind: "tpl";
|
|
38
|
+
path: string;
|
|
39
|
+
vars: TplVarsLike;
|
|
40
|
+
} | {
|
|
41
|
+
kind: "generate";
|
|
42
|
+
fn: () => unknown;
|
|
43
|
+
} | {
|
|
44
|
+
kind: "binary";
|
|
45
|
+
path: string;
|
|
46
|
+
};
|
|
47
|
+
/** Builder-body for a `managed` file (the content-rules lambda). */
|
|
48
|
+
export type ManagedBody = () => void;
|
|
49
|
+
export type FixedItem = {
|
|
50
|
+
kind: "fixed";
|
|
51
|
+
path: string;
|
|
52
|
+
content: ContentForm;
|
|
53
|
+
};
|
|
54
|
+
export type ManagedItem = {
|
|
55
|
+
kind: "managed";
|
|
56
|
+
path: string;
|
|
57
|
+
initial: ContentForm;
|
|
58
|
+
body: ManagedBody;
|
|
59
|
+
};
|
|
60
|
+
export type ScaffoldItem = {
|
|
61
|
+
kind: "scaffold";
|
|
62
|
+
path: string;
|
|
63
|
+
initial: ContentForm;
|
|
64
|
+
};
|
|
65
|
+
export type SeedItem = {
|
|
66
|
+
kind: "seed";
|
|
67
|
+
path: string;
|
|
68
|
+
initial: ContentForm;
|
|
69
|
+
};
|
|
70
|
+
export type RemoveItem = {
|
|
71
|
+
kind: "remove";
|
|
72
|
+
path: string;
|
|
73
|
+
};
|
|
74
|
+
export type RenameItem = {
|
|
75
|
+
kind: "rename";
|
|
76
|
+
from: string;
|
|
77
|
+
to: string;
|
|
78
|
+
};
|
|
79
|
+
export type LeafItem = FixedItem | ManagedItem | ScaffoldItem | SeedItem | RemoveItem | RenameItem;
|
|
80
|
+
export type ScopeFrame = {
|
|
81
|
+
kind: "scope";
|
|
82
|
+
scope: Scope;
|
|
83
|
+
children: TreeNode[];
|
|
84
|
+
};
|
|
85
|
+
export type WhenFrame = {
|
|
86
|
+
kind: "when";
|
|
87
|
+
trigger: TriggerFn;
|
|
88
|
+
children: TreeNode[];
|
|
89
|
+
};
|
|
90
|
+
/** Top-level mode frame: contained leaves fire only in the listed run
|
|
91
|
+
* modes. Leaves outside any mode frame fire in `["default", "init"]`
|
|
92
|
+
* (refresh/check + init). `onUpdateDeps()` produces `["updateDeps"]`;
|
|
93
|
+
* `onInitOrUpdate()` produces `["init", "updateDeps"]`. */
|
|
94
|
+
export type ModeFrame = {
|
|
95
|
+
kind: "mode";
|
|
96
|
+
modes: RunMode[];
|
|
97
|
+
children: TreeNode[];
|
|
98
|
+
};
|
|
99
|
+
export type TreeNode = LeafItem | ScopeFrame | WhenFrame | ModeFrame;
|
|
100
|
+
/** Structure object returned by `defineStructure`. */
|
|
101
|
+
export type Structure = {
|
|
102
|
+
/** Top-level children — may contain leaves, scope frames, when
|
|
103
|
+
* frames, and mode frames. */
|
|
104
|
+
children: TreeNode[];
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* After fan-out: one entry per (leaf × matching module). `scope` is
|
|
108
|
+
* always set; `modulePath` is the workspace path the leaf is bound to
|
|
109
|
+
* (empty string for the workspace root). `triggers` is the AND of all
|
|
110
|
+
* enclosing `when` predicates. `modes` is the set of run modes the leaf
|
|
111
|
+
* fires in — `["default", "init"]` outside any mode frame, otherwise the
|
|
112
|
+
* enclosing mode frame's `modes`.
|
|
113
|
+
*/
|
|
114
|
+
export type FlatItem = {
|
|
115
|
+
leaf: LeafItem;
|
|
116
|
+
scope: Scope;
|
|
117
|
+
modulePath: string;
|
|
118
|
+
/** Block-relative resolved path(s). */
|
|
119
|
+
resolvedPath: string;
|
|
120
|
+
/** For rename, the resolved destination. */
|
|
121
|
+
resolvedTo?: string;
|
|
122
|
+
triggers: TriggerFn[];
|
|
123
|
+
modes: RunMode[];
|
|
124
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
2
|
+
[k: string]: JsonValue;
|
|
3
|
+
};
|
|
4
|
+
export type JsonObject = {
|
|
5
|
+
[k: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
/** Parse JSON; throws on invalid input. */
|
|
8
|
+
export declare function parseJson(raw: string): unknown;
|
|
9
|
+
/** Canonical serialiser: 2-space indent, trailing newline.
|
|
10
|
+
* Default — every container expanded (the package.json shape, byte-identical
|
|
11
|
+
* to `JSON.stringify(…, 2)`).
|
|
12
|
+
* `{ collapse: true }` — oxfmt's generic-.json shape: containers that fit
|
|
13
|
+
* `PRINT_WIDTH` collapse onto one line. Used for tsconfig.json and any other
|
|
14
|
+
* non-package.json the engine emits, so `oxfmt --check` passes without a
|
|
15
|
+
* prior format pass. */
|
|
16
|
+
export declare function stringifyJson(value: unknown, opts?: {
|
|
17
|
+
collapse?: boolean;
|
|
18
|
+
}): string;
|
|
19
|
+
/** Get the value at `jsonPath`. Returns `undefined` if any segment is
|
|
20
|
+
* missing or not an object. */
|
|
21
|
+
export declare function getAtPath(obj: JsonObject, jsonPath: string): unknown;
|
|
22
|
+
/** True if `jsonPath` resolves to a defined value (including `null`). */
|
|
23
|
+
export declare function hasAtPath(obj: JsonObject, jsonPath: string): boolean;
|
|
24
|
+
/** Set `value` at `jsonPath`. Auto-creates intermediate objects. Throws
|
|
25
|
+
* if a non-object value is on the path (would be silently overwritten
|
|
26
|
+
* otherwise — caller bug). */
|
|
27
|
+
export declare function setAtPath(obj: JsonObject, jsonPath: string, value: unknown): void;
|
|
28
|
+
/** Delete the value at `jsonPath`. No-op if any segment is missing. */
|
|
29
|
+
export declare function deleteAtPath(obj: JsonObject, jsonPath: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Reorder top-level keys of `obj`:
|
|
32
|
+
* - Known keys (those listed in `order`) appear in declared order.
|
|
33
|
+
* - Unknown keys (not in `order`) stay adjacent to the preceding known
|
|
34
|
+
* key they followed in the source. Unknown keys appearing before any
|
|
35
|
+
* known key go first, in source order.
|
|
36
|
+
*/
|
|
37
|
+
export declare function reorderTopLevel(obj: JsonObject, order: readonly string[]): JsonObject;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function parseLines(raw: string): string[];
|
|
2
|
+
export declare function serializeLines(lines: readonly string[]): string;
|
|
3
|
+
/** Strip leading/trailing whitespace and trailing inline `# ...` comments.
|
|
4
|
+
* Returns empty string for blank / comment-only lines. */
|
|
5
|
+
export declare function normaliseLine(line: string): string;
|
|
6
|
+
/** True if `line` (after normalisation) equals `entry` (after trim). */
|
|
7
|
+
export declare function lineEqualsEntry(line: string, entry: string): boolean;
|
|
8
|
+
/** True if any line in `lines` normalises to `entry`. */
|
|
9
|
+
export declare function containsEntry(lines: readonly string[], entry: string): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Document, isMap, isPair, isSeq, YAMLMap, YAMLSeq, Scalar, Node } from 'yaml';
|
|
2
|
+
export type YamlDocument = Document.Parsed;
|
|
3
|
+
/** Parse YAML into a CST-preserving Document. */
|
|
4
|
+
export declare function parseYaml(raw: string): YamlDocument;
|
|
5
|
+
/** Serialise back to string. Preserves comments + ordering of unchanged
|
|
6
|
+
* nodes per the `yaml` library's contract. */
|
|
7
|
+
export declare function stringifyYaml(doc: YamlDocument): string;
|
|
8
|
+
/** Get the JS value at the given jsonPath in the document. */
|
|
9
|
+
export declare function yamlGet(doc: YamlDocument, jsonPath: string): unknown;
|
|
10
|
+
export declare function yamlHas(doc: YamlDocument, jsonPath: string): boolean;
|
|
11
|
+
/** Set a value at jsonPath. Auto-creates intermediate maps. Existing
|
|
12
|
+
* comments on parent map entries are preserved by the yaml library. */
|
|
13
|
+
export declare function yamlSet(doc: YamlDocument, jsonPath: string, value: unknown): void;
|
|
14
|
+
/** Delete a value at jsonPath. No-op if missing. */
|
|
15
|
+
export declare function yamlDelete(doc: YamlDocument, jsonPath: string): void;
|
|
16
|
+
/** Re-export selected `yaml` lib types for downstream content-rule builders. */
|
|
17
|
+
export { isMap, isPair, isSeq, YAMLMap, YAMLSeq, Scalar };
|
|
18
|
+
export type { Node };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface RegistryClient {
|
|
2
|
+
getLatestVersion(packageName: string): Promise<string>;
|
|
3
|
+
}
|
|
4
|
+
/** Parse the HTTP Retry-After header (RFC 9110): either a delay in
|
|
5
|
+
* seconds or an absolute HTTP-date. Returns the delay in ms, or null
|
|
6
|
+
* if the header is missing / unparseable. */
|
|
7
|
+
export declare function parseRetryAfter(header: string | null): number | null;
|
|
8
|
+
/** Live npm registry client. Hits the network on each call. */
|
|
9
|
+
export declare function createRealRegistryClient(): RegistryClient;
|
|
10
|
+
/** In-memory client backed by a fixed `name → version` map. */
|
|
11
|
+
export declare function createMockRegistryClient(versions: Record<string, string>): RegistryClient;
|
|
12
|
+
/** Resolve a batch of `name → latest` entries in parallel. */
|
|
13
|
+
export declare function prefetchLatestVersions(client: RegistryClient, packageNames: readonly string[]): Promise<Map<string, string>>;
|
|
14
|
+
/** Build a sync lookup function (the shape `withManagedYaml` consumes)
|
|
15
|
+
* from a prefetched map. Returns undefined for unknown names. */
|
|
16
|
+
export declare function makeSyncLookup(resolved: Map<string, string>): (packageName: string) => string | undefined;
|
|
17
|
+
/** Catalog package-name patterns the version-resolution rules
|
|
18
|
+
* (`ensureCatalogLatest`) match against — the `@platforma-sdk/*` and
|
|
19
|
+
* `@milaboratories/*` SDK families. Infra/runtime entries (turbo, shx,
|
|
20
|
+
* …) are deliberately NOT here: they stay a curated floor, not auto-latest.
|
|
21
|
+
* Shared so `init` (names from the SDK pin map) and `refresh
|
|
22
|
+
* --update-deps-only` (names from the on-disk catalog) select the same
|
|
23
|
+
* set. */
|
|
24
|
+
export declare const CATALOG_BUMP_PATTERNS: readonly RegExp[];
|
|
25
|
+
/** True if `name` is a version-resolved SDK package (matches any bump
|
|
26
|
+
* pattern). */
|
|
27
|
+
export declare function matchesBumpPattern(name: string): boolean;
|
|
28
|
+
/** Prefetch npm "latest" for `names` and return the sync lookup the
|
|
29
|
+
* runner passes to the catalog ensure-family (`ensureCatalogLatest`).
|
|
30
|
+
* Empty list → a lookup that
|
|
31
|
+
* resolves nothing (no network). A network/registry failure REJECTS
|
|
32
|
+
* (callers that require the network — `init` — let it propagate).
|
|
33
|
+
* `client` defaults to the live npm client; tests inject a mock. */
|
|
34
|
+
export declare function buildRegistryLookupForNames(names: readonly string[], client?: RegistryClient): Promise<(packageName: string) => string | undefined>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Structure } from './ir';
|
|
2
|
+
import { RunContext, Scope } from './api';
|
|
3
|
+
import { FileSystem } from './fs/api';
|
|
4
|
+
import { TemplateProvider } from './templates';
|
|
5
|
+
export type ChangeAction = "create" | "update" | "delete" | "rename" | "noop";
|
|
6
|
+
export type Change = {
|
|
7
|
+
scope: Scope;
|
|
8
|
+
/** Resolved (block-relative) path. For rename, the source path. */
|
|
9
|
+
path: string;
|
|
10
|
+
/** "fixed" | "managed" | "scaffold" | "seed" | "remove" | "rename" */
|
|
11
|
+
primitive: string;
|
|
12
|
+
action: ChangeAction;
|
|
13
|
+
};
|
|
14
|
+
export type RunResult = {
|
|
15
|
+
changes: Change[];
|
|
16
|
+
};
|
|
17
|
+
export type RunOptions = {
|
|
18
|
+
/** Called before the post-run recheck to obtain a fresh RunContext
|
|
19
|
+
* reflecting the just-written FS state (re-reads `pnpm-workspace.yaml`).
|
|
20
|
+
* If absent, recheck reuses the original ctx with `dryRun: true`. */
|
|
21
|
+
rediscover?: (fs: FileSystem) => RunContext;
|
|
22
|
+
/** Template provider used by `file(...)` and `tpl(...)` content forms.
|
|
23
|
+
* Required whenever the structure references such forms. */
|
|
24
|
+
templates?: TemplateProvider;
|
|
25
|
+
/** Init mode: write seed leaves (only-if-missing semantics) and skip
|
|
26
|
+
* the post-run recheck. The caller is expected to follow with an
|
|
27
|
+
* explicit dry-run check (Layer-2 invariant). */
|
|
28
|
+
initMode?: boolean;
|
|
29
|
+
/** Sync accessor for prefetched npm "latest" versions, consumed by
|
|
30
|
+
* `ensureCatalogLatest` inside `onUpdateDeps` managed bodies. The CLI
|
|
31
|
+
* prefetches the catalog's package versions before the run (network)
|
|
32
|
+
* and passes the resulting sync map here; unit tests pass a mock.
|
|
33
|
+
* Absent → `ensureCatalogLatest` is a no-op (default refresh). */
|
|
34
|
+
registryLookup?: (packageName: string) => string | undefined;
|
|
35
|
+
};
|
|
36
|
+
export declare class RecheckError extends Error {
|
|
37
|
+
readonly failing: Change;
|
|
38
|
+
constructor(failing: Change);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Run the structurer engine end-to-end. See module header for mode
|
|
42
|
+
* semantics. Throws `RecheckError` if the post-run dry-run finds any
|
|
43
|
+
* leftover diff after a successful refresh.
|
|
44
|
+
*/
|
|
45
|
+
export declare function run(structure: Structure, fs: FileSystem, ctx: RunContext, opts?: RunOptions): RunResult;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface TemplateProvider {
|
|
2
|
+
/** Read a static template file (under `<root>/static/`). */
|
|
3
|
+
staticRead(p: string): string;
|
|
4
|
+
/** Read a static template file as raw bytes (under `<root>/static/`).
|
|
5
|
+
* For binary assets (logos, images) that must not be utf-8 decoded. */
|
|
6
|
+
staticReadBinary(p: string): Uint8Array;
|
|
7
|
+
/** Read a text template file (under `<root>/text/`). */
|
|
8
|
+
textRead(p: string): string;
|
|
9
|
+
}
|
|
10
|
+
/** Provider backed by an on-disk template tree. Reads are synchronous
|
|
11
|
+
* so the runner can stay sync inside content-form resolution. */
|
|
12
|
+
export declare class NodeTemplateProvider implements TemplateProvider {
|
|
13
|
+
private root;
|
|
14
|
+
constructor(root: string);
|
|
15
|
+
staticRead(p: string): string;
|
|
16
|
+
staticReadBinary(p: string): Uint8Array;
|
|
17
|
+
textRead(p: string): string;
|
|
18
|
+
}
|
|
19
|
+
/** In-memory provider for tests. Keyed by the same `static/...` /
|
|
20
|
+
* `text/...` shape as on disk. */
|
|
21
|
+
export declare class MemoryTemplateProvider implements TemplateProvider {
|
|
22
|
+
private files;
|
|
23
|
+
constructor(files: Record<string, string>);
|
|
24
|
+
staticRead(p: string): string;
|
|
25
|
+
staticReadBinary(p: string): Uint8Array;
|
|
26
|
+
textRead(p: string): string;
|
|
27
|
+
}
|
|
28
|
+
/** Shell-style `${name}` substitution. Unknown names left as-is so
|
|
29
|
+
* template authors notice. Backslash escape is not supported. */
|
|
30
|
+
export declare function substituteVars(text: string, vars: Record<string, string>): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BlockVars, Module, RunContext, Structure } from './api';
|
|
2
|
+
import { JsonObject } from './content-rules';
|
|
3
|
+
import { MemoryFileSystem } from './fs/memory';
|
|
4
|
+
import { TemplateProvider } from './templates';
|
|
5
|
+
/** Layer-1 helper. */
|
|
6
|
+
export declare function runRulesAgainst(input: JsonObject, body: () => void): JsonObject;
|
|
7
|
+
export type SimulateInitInput = {
|
|
8
|
+
vars: BlockVars;
|
|
9
|
+
/** Override the discovered module set. Defaults to `defaultModulesFor`. */
|
|
10
|
+
modules?: Module[];
|
|
11
|
+
/** Override the structure under test (defaults to the canonical one). */
|
|
12
|
+
structure?: Structure;
|
|
13
|
+
/** Override the template provider (defaults to NodeTemplateProvider
|
|
14
|
+
* pointing at the bundled `templates/` directory). */
|
|
15
|
+
templates?: TemplateProvider;
|
|
16
|
+
/** SDK-internal flag. Default `false` (standalone block). */
|
|
17
|
+
isSdkInternal?: boolean;
|
|
18
|
+
/** Sync npm-latest lookup for the `onInitOrUpdate` catalog resolution.
|
|
19
|
+
* Absent → the SDK catalog keeps its seed versions (no bump), matching
|
|
20
|
+
* an offline scaffold; tests that assert init writes latest pass a mock. */
|
|
21
|
+
registryLookup?: (packageName: string) => string | undefined;
|
|
22
|
+
};
|
|
23
|
+
export type SimulatedInit = {
|
|
24
|
+
fs: MemoryFileSystem;
|
|
25
|
+
ctx: RunContext;
|
|
26
|
+
};
|
|
27
|
+
/** Module set produced by `init` for a given BlockVars. Delegates to the
|
|
28
|
+
* shared `modulesForInit` so the test helper and the real `init`
|
|
29
|
+
* constructor never drift. */
|
|
30
|
+
export declare function defaultModulesFor(vars: BlockVars): Module[];
|
|
31
|
+
/** Default template provider — reads from the bundled templates tree
|
|
32
|
+
* next to this file. */
|
|
33
|
+
export declare function defaultTemplateProvider(): TemplateProvider;
|
|
34
|
+
export declare function simulateInit(input: SimulateInitInput): SimulatedInit;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FileSystem } from './fs/api';
|
|
2
|
+
export declare const STRUCTURE_VERSION = 1;
|
|
3
|
+
export declare const STRUCTURE_MIN_SUPPORTED = 0;
|
|
4
|
+
/** Block-relative path of the structurer metadata file. */
|
|
5
|
+
export declare const STRUCTURE_META_FILE = ".structure";
|
|
6
|
+
export type StructureMeta = {
|
|
7
|
+
version: number;
|
|
8
|
+
};
|
|
9
|
+
/** Read `.structure`. Missing file or invalid payload → 0. */
|
|
10
|
+
export declare function readStructureVersion(fs: FileSystem): number;
|
|
11
|
+
/** Throw if version is below floor. */
|
|
12
|
+
export declare function assertVersionAboveFloor(version: number, floor?: number): void;
|
|
13
|
+
export declare class StructureVersionFloorError extends Error {
|
|
14
|
+
readonly version: number;
|
|
15
|
+
readonly floor: number;
|
|
16
|
+
constructor(version: number, floor: number);
|
|
17
|
+
}
|
|
18
|
+
export declare function writeStructureVersion(fs: FileSystem, version?: number): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BlockVars } from './engine/api';
|
|
2
|
+
/** Platform choices `init` can scaffold a software module for. Python is
|
|
3
|
+
* the only platform with a real, buildable scaffold at v1; any other
|
|
4
|
+
* value is rejected rather than scaffolded as a non-buildable placeholder,
|
|
5
|
+
* which would defeat the "init must produce a working block" intent.
|
|
6
|
+
* `softwarePlatform` stays in BlockVars for when another platform gets a
|
|
7
|
+
* real scaffold. (Note: Tengo is the workflow language, not a software
|
|
8
|
+
* platform.) */
|
|
9
|
+
export declare const SUPPORTED_PLATFORMS: readonly ["python"];
|
|
10
|
+
export type InitFlagValues = {
|
|
11
|
+
npmOrg?: string;
|
|
12
|
+
orgScope?: string;
|
|
13
|
+
shortName?: string;
|
|
14
|
+
/** Tri-state: true (--with-software), false (--no-software),
|
|
15
|
+
* undefined (unspecified → prompt or, non-interactive, default off). */
|
|
16
|
+
withSoftware?: boolean;
|
|
17
|
+
platform?: string;
|
|
18
|
+
nonInteractive: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type InitInput = {
|
|
21
|
+
/** Resolved BlockVars (from `resolveBlockVars`). */
|
|
22
|
+
vars: BlockVars;
|
|
23
|
+
/** Resolved absolute target directory. */
|
|
24
|
+
blockPath: string;
|
|
25
|
+
/** `<block-tools>/src/structure/templates`. */
|
|
26
|
+
templatesRoot: string;
|
|
27
|
+
log: (msg: string) => void;
|
|
28
|
+
};
|
|
29
|
+
/** Resolve the full BlockVars (incl. softwarePlatform) from flags +
|
|
30
|
+
* prompts. */
|
|
31
|
+
export declare function resolveBlockVars(flags: InitFlagValues): Promise<BlockVars>;
|
|
32
|
+
export declare function runInit(init: InitInput): Promise<BlockVars>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RunContext } from '../engine/api';
|
|
2
|
+
/** The facade's `block.components` map: the dist artifact each module build
|
|
3
|
+
* emits, keyed by role. Fully determined by the discovered modules — the
|
|
4
|
+
* body rule re-asserts this exact value, so it is engine-managed (NOT an
|
|
5
|
+
* author seed). Mirrors the artifact paths produced by each scope's build:
|
|
6
|
+
* workflow → pl-tengo, model → build-model, ui → ts-builder. */
|
|
7
|
+
export declare function blockComponents(ctx: RunContext): Record<string, string>;
|
|
8
|
+
export declare function blockPackageJsonInitial(ctx: RunContext): Record<string, unknown>;
|
|
9
|
+
export declare function blockPackageJsonRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function blockRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function modelRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rootCatalogBumpRules(): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RunContext } from '../engine/api';
|
|
2
|
+
/** SDK packages that live in the catalog (membership only — no versions).
|
|
3
|
+
* Init fetches npm latest for each; refresh leaves them as the lockfile has
|
|
4
|
+
* them. */
|
|
5
|
+
export declare const SDK_CATALOG_PACKAGES: readonly string[];
|
|
6
|
+
/** Infra / tooling — a `~`-floored curated set. Not exact-pinned on refresh
|
|
7
|
+
* and not bumped by update-deps. */
|
|
8
|
+
export declare const INFRA_CATALOG_FLOOR: Record<string, string>;
|
|
9
|
+
/** Catalog name of the python runenv. Added to a block's catalog only when
|
|
10
|
+
* the block carries a software module. Pinned to an EXACT version — updating
|
|
11
|
+
* the python runenv is an explicit author decision, never automatic. */
|
|
12
|
+
export declare const RUNENV_PYTHON = "@platforma-open/milaboratories.runenv-python-3";
|
|
13
|
+
export declare const RUNENV_PYTHON_VERSION = "1.8.2";
|
|
14
|
+
export declare function rootPnpmWorkspaceInitial(ctx: RunContext): Record<string, unknown>;
|
|
15
|
+
export declare function rootPnpmWorkspaceRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rootRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const canonicalPackageJsonOrder: readonly ["name", "version", "private", "description", "keywords", "files", "type", "main", "module", "types", "exports", "scripts", "dependencies", "devDependencies", "peerDependencies", "optionalDependencies", "packageManager", "pnpm", "block", "block-software"];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function softwareRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function testRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function uiRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function workflowRules(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const STRUCTURE: import('./engine/ir').Structure;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/block-tools",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.15",
|
|
4
4
|
"description": "Utility to manipulate Platforma Blocks and Block Registry",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@aws-sdk/client-s3": "3.859.0",
|
|
27
|
+
"@inquirer/prompts": "^7.0.1",
|
|
27
28
|
"@oclif/core": "^4.0.37",
|
|
28
29
|
"canonicalize": "~2.1.0",
|
|
29
30
|
"lru-cache": "^11.2.2",
|
|
@@ -33,13 +34,13 @@
|
|
|
33
34
|
"yaml": "^2.8.0",
|
|
34
35
|
"zod": "~3.25.76",
|
|
35
36
|
"@milaboratories/pl-http": "1.2.4",
|
|
36
|
-
"@milaboratories/pl-model-backend": "1.4.7",
|
|
37
37
|
"@milaboratories/pl-model-common": "1.46.1",
|
|
38
|
+
"@milaboratories/pl-model-backend": "1.4.7",
|
|
38
39
|
"@milaboratories/pl-model-middle-layer": "1.30.5",
|
|
39
40
|
"@milaboratories/ts-helpers": "1.8.3",
|
|
40
|
-
"@
|
|
41
|
+
"@milaboratories/resolve-helper": "1.1.3",
|
|
41
42
|
"@milaboratories/ts-helpers-oclif": "1.1.42",
|
|
42
|
-
"@
|
|
43
|
+
"@platforma-sdk/blocks-deps-updater": "2.2.0"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
@@ -48,16 +49,17 @@
|
|
|
48
49
|
"@types/semver": "^7.7.0",
|
|
49
50
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
50
51
|
"oclif": "^4.16.2",
|
|
52
|
+
"oxfmt": "0.35.0",
|
|
51
53
|
"rollup-plugin-node-externals": "^8.0.0",
|
|
52
54
|
"semver": "^7.7.2",
|
|
53
55
|
"typescript": "~5.9.3",
|
|
54
56
|
"vite": "^8.0.6",
|
|
55
57
|
"vite-plugin-dts": "^4.5.3",
|
|
56
58
|
"vitest": "^4.1.3",
|
|
57
|
-
"@milaboratories/build-configs": "2.0.0",
|
|
58
59
|
"@milaboratories/oclif-index": "1.1.1",
|
|
59
|
-
"@milaboratories/ts-
|
|
60
|
-
"@milaboratories/
|
|
60
|
+
"@milaboratories/ts-configs": "1.2.3",
|
|
61
|
+
"@milaboratories/build-configs": "2.0.0",
|
|
62
|
+
"@milaboratories/ts-builder": "1.5.0"
|
|
61
63
|
},
|
|
62
64
|
"oclif": {
|
|
63
65
|
"bin": "block-tools",
|
package/src/cmd/index.ts
CHANGED
|
@@ -8,8 +8,11 @@ import Cmd5 from "./pack";
|
|
|
8
8
|
import Cmd6 from "./publish";
|
|
9
9
|
import Cmd7 from "./refresh-registry";
|
|
10
10
|
import Cmd8 from "./restore-overview-from-snapshot";
|
|
11
|
-
import Cmd9 from "./
|
|
12
|
-
import Cmd10 from "./
|
|
11
|
+
import Cmd9 from "./update-deps";
|
|
12
|
+
import Cmd10 from "./upload-package-v1";
|
|
13
|
+
import Cmd11 from "./structure/check";
|
|
14
|
+
import Cmd12 from "./structure/init";
|
|
15
|
+
import Cmd13 from "./structure/refresh";
|
|
13
16
|
|
|
14
17
|
export const COMMANDS = {
|
|
15
18
|
"build-meta": Cmd0,
|
|
@@ -20,6 +23,9 @@ export const COMMANDS = {
|
|
|
20
23
|
publish: Cmd6,
|
|
21
24
|
"refresh-registry": Cmd7,
|
|
22
25
|
"restore-overview-from-snapshot": Cmd8,
|
|
23
|
-
"
|
|
24
|
-
"
|
|
26
|
+
"update-deps": Cmd9,
|
|
27
|
+
"upload-package-v1": Cmd10,
|
|
28
|
+
"structure:check": Cmd11,
|
|
29
|
+
"structure:init": Cmd12,
|
|
30
|
+
"structure:refresh": Cmd13,
|
|
25
31
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Command, Flags } from "@oclif/core";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { runStructureForPath, formatChanges } from "../../structure/cli/run-structure";
|
|
4
|
+
|
|
5
|
+
export default class StructureCheck extends Command {
|
|
6
|
+
static override description =
|
|
7
|
+
"Check block(s) against the canonical structure (read-only). Exits non-zero if any diff would land — used as the CI gate.";
|
|
8
|
+
|
|
9
|
+
static override examples = [
|
|
10
|
+
"<%= config.bin %> <%= command.id %> ./my-block",
|
|
11
|
+
"<%= config.bin %> <%= command.id %> --sdk-internal etc/blocks/*",
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
// Variadic positional block paths (shell-expanded globs).
|
|
15
|
+
static override strict = false;
|
|
16
|
+
|
|
17
|
+
static override flags = {
|
|
18
|
+
"sdk-internal": Flags.boolean({
|
|
19
|
+
description: "block(s) live inside the SDK monorepo; skip root-scope rules",
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
public async run(): Promise<void> {
|
|
24
|
+
const { argv, flags } = await this.parse(StructureCheck);
|
|
25
|
+
const paths = (argv as string[]).length > 0 ? (argv as string[]) : ["."];
|
|
26
|
+
const templatesRoot = path.join(this.config.root, "src", "structure", "templates");
|
|
27
|
+
|
|
28
|
+
let anyChanged = false;
|
|
29
|
+
for (const p of paths) {
|
|
30
|
+
const res = await runStructureForPath({
|
|
31
|
+
blockPath: p,
|
|
32
|
+
isSdkInternal: flags["sdk-internal"],
|
|
33
|
+
updateDepsOnly: false,
|
|
34
|
+
mode: "check",
|
|
35
|
+
templatesRoot,
|
|
36
|
+
log: (m) => this.log(m),
|
|
37
|
+
});
|
|
38
|
+
this.log(formatChanges(p, res.changes));
|
|
39
|
+
if (res.changes.length > 0) anyChanged = true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (anyChanged) {
|
|
43
|
+
this.error(
|
|
44
|
+
"Structure check failed: one or more blocks are out of date. Run `structure refresh`.",
|
|
45
|
+
{
|
|
46
|
+
exit: 1,
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|