@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.
Files changed (36) hide show
  1. package/dist/cli.js +13 -13
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cli.mjs +674 -615
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/structure/engine/api.d.ts +1 -1
  6. package/dist/structure/engine/content-rules.d.ts +17 -0
  7. package/dist/structure/engine/registry-client.d.ts +30 -2
  8. package/dist/structure/engine/runner.d.ts +6 -0
  9. package/dist/structure/rules/root-pnpm-workspace.d.ts +13 -0
  10. package/dist/structure/rules/shared/retired-deps.d.ts +7 -0
  11. package/dist/v2/registry/schema_public.d.ts +6177 -6177
  12. package/package.json +8 -8
  13. package/src/structure/CLAUDE.md +28 -0
  14. package/src/structure/__tests__/model-package-json.snapshot.test.ts +1 -2
  15. package/src/structure/cli/run-structure.ts +12 -2
  16. package/src/structure/engine/__tests__/content-rules/pin-catalog-to-dependency-of.test.ts +65 -0
  17. package/src/structure/engine/__tests__/derived-pin-lookup.test.ts +54 -0
  18. package/src/structure/engine/api.ts +1 -0
  19. package/src/structure/engine/content-rules.ts +29 -0
  20. package/src/structure/engine/registry-client.ts +116 -2
  21. package/src/structure/engine/runner.ts +18 -2
  22. package/src/structure/init-block-constructor.ts +16 -3
  23. package/src/structure/rules/migrations.ts +15 -16
  24. package/src/structure/rules/model-package-json.ts +34 -16
  25. package/src/structure/rules/root-catalog-bump.ts +12 -1
  26. package/src/structure/rules/root-package-json.ts +15 -11
  27. package/src/structure/rules/root-pnpm-workspace.ts +21 -8
  28. package/src/structure/rules/root.ts +0 -1
  29. package/src/structure/rules/shared/retired-deps.ts +42 -0
  30. package/src/structure/rules/test-package-json.ts +12 -9
  31. package/src/structure/rules/test.ts +4 -0
  32. package/src/structure/rules/ui-package-json.ts +33 -25
  33. package/src/structure/rules/workflow-package-json.ts +32 -14
  34. package/src/structure/rules/workflow.ts +32 -8
  35. package/src/structure/templates/static/test/.oxfmtrc.json +4 -0
  36. package/src/structure/templates/static/test/.oxlintrc.json +3 -0
@@ -51,5 +51,5 @@ export type RunContext = {
51
51
  };
52
52
  export type { ContentForm, ManagedBody, RunMode, Structure, TriggerFn };
53
53
  export { defineStructure, scope, when, whenFilesExist, onUpdateDeps, onInitOrUpdate, fixed, managed, scaffold, seed, remove, rename, file, binaryFile, text, tpl, generate, blockVars, } from './builders';
54
- export { ensureField, removeField, requireField, ensureFieldEntries, ensureScript, removeScript, ensureDep, ensureDevDep, ensurePeerDep, ensureOptionalDep, removeDep, ensureDeps, ensureDevDeps, ensurePeerDeps, ensureOptionalDeps, ensureWorkspaceScopeDeps, ensureWorkspaceScopeDevDeps, ensureWorkspaceScopePeerDeps, pruneKeysMatching, pruneKeysMatchingAt, enforceFieldOrder, enforceFieldOrderAt, enforceAlphabeticalOrder, transformAt, ensureWorkspaceModulePaths, ensureCatalogVersion, pinCatalogTo, ensureCatalogLatest, ensureCatalogAbsent, ensureGitignoreEntries, removeGitignoreEntries, withManagedBody, withManagedYaml, withManagedLines, } from './content-rules';
54
+ export { ensureField, removeField, requireField, ensureFieldEntries, ensureScript, removeScript, ensureDep, ensureDevDep, ensurePeerDep, ensureOptionalDep, removeDep, ensureDeps, ensureDevDeps, ensurePeerDeps, ensureOptionalDeps, ensureWorkspaceScopeDeps, ensureWorkspaceScopeDevDeps, ensureWorkspaceScopePeerDeps, pruneKeysMatching, pruneKeysMatchingAt, enforceFieldOrder, enforceFieldOrderAt, enforceAlphabeticalOrder, transformAt, ensureWorkspaceModulePaths, ensureCatalogVersion, pinCatalogTo, pinCatalogToDependencyOf, ensureCatalogLatest, ensureCatalogAbsent, ensureGitignoreEntries, removeGitignoreEntries, withManagedBody, withManagedYaml, withManagedLines, } from './content-rules';
55
55
  export type { DepVersion } from './content-rules';
@@ -35,6 +35,9 @@ export type WithManagedYamlOpts = WithManagedOpts & {
35
35
  /** Sync accessor for prefetched latest versions. Required for
36
36
  * `ensureCatalogLatest` to take effect. */
37
37
  getLatestVersion?: (packageName: string) => string | undefined;
38
+ /** Sync accessor for prefetched derived catalog pins. Required for
39
+ * `pinCatalogToDependencyOf` to take effect. */
40
+ getDerivedDependencyPin?: (catalogEntry: string) => string | undefined;
38
41
  };
39
42
  /** Engine-internal: run `body` with `doc` as the active YAML state (for
40
43
  * `pnpm-workspace.yaml`); returns the mutated document. Exported for tests. */
@@ -140,6 +143,20 @@ export declare function pinCatalogTo(name: string, version: string): void;
140
143
  * and refreshes a present one, and on `init` it overwrites the
141
144
  * placeholder with the real latest. */
142
145
  export declare function ensureCatalogLatest(name: string): void;
146
+ /** Pin `catalog.<catalogEntry>` to the EXACT version that package `opts.of`
147
+ * declares for `catalogEntry` in its own manifest (read at npm latest, or at
148
+ * `opts.ofVersion` if given). The value is resolved by the runner's
149
+ * prefetched `getDerivedDependencyPin` accessor (the caller pre-resolves and
150
+ * validates — exact-version-only — at prefetch time; no network here).
151
+ * OVERWRITES like `pinCatalogTo` (not add-if-absent): a pre-existing loose
152
+ * entry (`vue: ^3.5.24`) is tightened to the exact derived version. No-op
153
+ * when no derived-pin lookup is available — default refresh/check pass none,
154
+ * leaving the entry exactly as the lockfile has it; the resolution leaves
155
+ * live in the `onInitOrUpdate` frame. */
156
+ export declare function pinCatalogToDependencyOf(catalogEntry: string, _opts: {
157
+ of: string;
158
+ ofVersion?: string;
159
+ }): void;
143
160
  /** Remove `catalog.<name>` if present; no-op when absent. */
144
161
  export declare function ensureCatalogAbsent(name: string): void;
145
162
  /** Append each `entry` if not already present (comment-aware equality). */
@@ -1,5 +1,10 @@
1
1
  export interface RegistryClient {
2
2
  getLatestVersion(packageName: string): Promise<string>;
3
+ /** Read the version `packageName@version` declares for `depName` in its
4
+ * published manifest. `version` may be "latest" (resolved via the
5
+ * dist-tags). Looks in `dependencies` first, then `peerDependencies`.
6
+ * Returns `undefined` when the dep is declared in neither section. */
7
+ getDeclaredDependency(packageName: string, version: string, depName: string): Promise<string | undefined>;
3
8
  }
4
9
  /** Parse the HTTP Retry-After header (RFC 9110): either a delay in
5
10
  * seconds or an absolute HTTP-date. Returns the delay in ms, or null
@@ -7,8 +12,10 @@ export interface RegistryClient {
7
12
  export declare function parseRetryAfter(header: string | null): number | null;
8
13
  /** Live npm registry client. Hits the network on each call. */
9
14
  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;
15
+ /** In-memory client backed by a fixed `name → version` map. The optional
16
+ * `manifests` map (`pkg@version` → declared deps) backs
17
+ * `getDeclaredDependency`; "latest" keys resolve via the `versions` map. */
18
+ export declare function createMockRegistryClient(versions: Record<string, string>, manifests?: Record<string, Record<string, string>>): RegistryClient;
12
19
  /** Resolve a batch of `name → latest` entries in parallel. */
13
20
  export declare function prefetchLatestVersions(client: RegistryClient, packageNames: readonly string[]): Promise<Map<string, string>>;
14
21
  /** Build a sync lookup function (the shape `withManagedYaml` consumes)
@@ -32,3 +39,24 @@ export declare function matchesBumpPattern(name: string): boolean;
32
39
  * (callers that require the network — `init` — let it propagate).
33
40
  * `client` defaults to the live npm client; tests inject a mock. */
34
41
  export declare function buildRegistryLookupForNames(names: readonly string[], client?: RegistryClient): Promise<(packageName: string) => string | undefined>;
42
+ /** A catalog entry whose version is DERIVED from the version another
43
+ * package declares for it. `entry` is the catalog key (== the dep name in
44
+ * the source manifest); `of` is the package whose manifest is read; the
45
+ * optional `ofVersion` pins which release of `of` to read (default: npm
46
+ * latest, the same release the catalog bump pins `of` to). Consumed by
47
+ * `pinCatalogToDependencyOf`. */
48
+ export type DerivedCatalogPin = {
49
+ entry: string;
50
+ of: string;
51
+ ofVersion?: string;
52
+ };
53
+ /** Prefetch every derived pin and build the sync lookup the runner passes
54
+ * to `pinCatalogToDependencyOf` (`entry → exact version`). Reads
55
+ * `pin.of`'s manifest (at `pin.ofVersion`, default npm latest) and the
56
+ * version it declares for `pin.entry`. Policy (b): THROWS at prefetch time
57
+ * if the source declares the dep as a non-exact (ranged) version or does
58
+ * not declare it at all — a derived pin must resolve to an exact version
59
+ * or it is a configuration error. Empty list → a lookup that resolves
60
+ * nothing (no network). A registry failure REJECTS. `client` defaults to
61
+ * the live npm client; tests inject a mock. */
62
+ export declare function buildDerivedPinLookupForPins(pins: readonly DerivedCatalogPin[], client?: RegistryClient): Promise<(entry: string) => string | undefined>;
@@ -32,6 +32,12 @@ export type RunOptions = {
32
32
  * and passes the resulting sync map here; unit tests pass a mock.
33
33
  * Absent → `ensureCatalogLatest` is a no-op (default refresh). */
34
34
  registryLookup?: (packageName: string) => string | undefined;
35
+ /** Sync accessor for prefetched derived catalog pins
36
+ * (`catalogEntry → exact version`), consumed by `pinCatalogToDependencyOf`
37
+ * inside `onInitOrUpdate` managed bodies. The CLI / init constructor
38
+ * prefetches + validates these before the run (network). Absent →
39
+ * `pinCatalogToDependencyOf` is a no-op (default refresh). */
40
+ derivedPinLookup?: (catalogEntry: string) => string | undefined;
35
41
  };
36
42
  export declare class RecheckError extends Error {
37
43
  readonly failing: Change;
@@ -1,4 +1,5 @@
1
1
  import { RunContext } from '../engine/api';
2
+ import { DerivedCatalogPin } from '../engine/registry-client';
2
3
  /** SDK packages that live in the catalog (membership only — no versions).
3
4
  * Init fetches npm latest for each; refresh leaves them as the lockfile has
4
5
  * them. */
@@ -6,6 +7,18 @@ export declare const SDK_CATALOG_PACKAGES: readonly string[];
6
7
  /** Infra / tooling — a `~`-floored curated set. Not exact-pinned on refresh
7
8
  * and not bumped by update-deps. */
8
9
  export declare const INFRA_CATALOG_FLOOR: Record<string, string>;
10
+ /** Catalog entries whose exact version is DERIVED from the version another
11
+ * package declares for them (see `pinCatalogToDependencyOf`). Resolved on
12
+ * init + update-deps and OVERWRITES the on-disk entry.
13
+ *
14
+ * `vue`: the seeded ui depends on `vue` (catalog:). `@platforma-sdk/ui-vue`
15
+ * pins vue as an EXACT regular dependency (not a peer), so the block must
16
+ * pin the SAME exact version — a floated `~` lets the ui resolve a newer
17
+ * 3.5.x than ui-vue's, yielding two vue instances and a SdkPluginV3-vs-Plugin
18
+ * type clash in `main.ts`. Deriving the pin from ui-vue's declared dep keeps
19
+ * the block in lockstep with whatever vue ui-vue's npm-latest pins, with no
20
+ * hand-maintained version here. */
21
+ export declare const DERIVED_CATALOG_PINS: readonly DerivedCatalogPin[];
9
22
  /** Catalog name of the python runenv. Added to a block's catalog only when
10
23
  * the block carries a software module. Pinned to an EXACT version — updating
11
24
  * the python runenv is an explicit author decision, never automatic. */
@@ -0,0 +1,7 @@
1
+ export declare const RETIRED_TOOLCHAIN_DEPS: readonly string[];
2
+ /** Drop every retired toolchain dep from the current package.json scope.
3
+ * Idempotent (a `removeDep` on an absent key is a no-op), so it is safe to
4
+ * call uniformly from every package.json rules body regardless of which deps
5
+ * a given scope ever carried. Pairs with the catalog-side removal in
6
+ * `rootPnpmWorkspaceRules`. */
7
+ export declare function removeRetiredToolchainDeps(): void;