@platforma-sdk/block-tools 2.16.17 → 2.17.1
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 +849 -875
- package/dist/cli.mjs.map +1 -1
- package/dist/{config-Dx45aFJ_.mjs → config-C07cYptA.mjs} +606 -591
- package/dist/config-C07cYptA.mjs.map +1 -0
- package/dist/config-on5N57rI.js +3 -0
- package/dist/config-on5N57rI.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -5
- package/dist/index.mjs.map +1 -1
- package/dist/structure/engine/api.d.ts +1 -1
- package/dist/structure/engine/content-rules.d.ts +12 -0
- package/dist/structure/rules/root-pnpm-workspace.d.ts +1 -1
- package/dist/structure/rules/shared/key-order.d.ts +1 -1
- package/dist/structure/rules/shared/toolchain.d.ts +18 -0
- package/package.json +25 -25
- package/src/structure/__tests__/root-catalog-bump.test.ts +1 -1
- package/src/structure/__tests__/root-ci-workflows.test.ts +4 -3
- package/src/structure/__tests__/toolchain.test.ts +156 -0
- package/src/structure/engine/__tests__/content-rules/ensure-catalog-at-least.test.ts +28 -0
- package/src/structure/engine/api.ts +4 -0
- package/src/structure/engine/content-rules.ts +60 -0
- package/src/structure/rules/root-ci.ts +3 -0
- package/src/structure/rules/root-package-json.ts +17 -2
- package/src/structure/rules/root-pnpm-workspace.ts +23 -5
- package/src/structure/rules/shared/key-order.ts +2 -1
- package/src/structure/rules/shared/toolchain.ts +35 -0
- package/src/structure/templates/text/workflows/build.tpl.yaml +1 -1
- package/src/structure/templates/text/workflows/mark-stable.tpl.yaml +1 -1
- package/dist/config-CtXMWNgm.js +0 -3
- package/dist/config-CtXMWNgm.js.map +0 -1
- package/dist/config-Dx45aFJ_.mjs.map +0 -1
- package/src/structure/templates/static/root/.gitignore +0 -13
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config-on5N57rI.js");var t=e.Xt({GlobalOverviewPath:()=>e.r,MetaFile:()=>e.i,PlPackageConfigData:()=>e.c,PlPackageJsonConfigFile:()=>e.l,PlPackageYamlConfigFile:()=>e.u,PlRegCommonConfigData:()=>e.d,PlRegFullPackageConfigData:()=>e.f,PlRegPackageConfig:()=>e.t,PlRegPackageConfigDataShard:()=>e.p,packageContentPrefix:()=>e.a,packageOverviewPath:()=>e.o,payloadFilePath:()=>e.s});exports.BlockDescriptionPackageJsonField=e.ht,exports.BlockPackFolderName=e.gt,exports.BlockRegistryV2=e.w,exports.ChannelNameRegexp=e.T,exports.ChannelsFolder=e.E,exports.FSStorage=e.h,exports.GlobalOverviewFileName=e.D,exports.GlobalOverviewGzFileName=e.O,exports.GlobalOverviewGzPath=e.k,exports.GlobalOverviewPath=e.A,exports.KindImplementer=e.nt,exports.KindManifest=e.rt,exports.KindManifestFile=e.St,exports.KindManifestFileInfo=e.it,exports.KindManifestFileName=e.at,exports.KindManifestIdentity=e.ot,exports.KindOverview=e.st,exports.KindOverviewFileName=e.ct,exports.KindOverviewPathPattern=e.lt,exports.KindResolutionError=e.b,exports.KindVersionMismatchError=e.Z,exports.KindVersionOverview=e.ut,exports.KindsPrefix=e.dt,exports.MainPrefix=e.j,exports.ManifestFileName=e.M,exports.ManifestSuffix=e.N,exports.PackageManifestPattern=e.P,exports.PackageOverview=e.F,exports.PackageOverviewFileName=e.I,exports.PackageOverviewVersionEntry=e.L,exports.PublishedCoordsFileName=e.K,Object.defineProperty(exports,"RegistryV1",{enumerable:!0,get:function(){return t}}),exports.RegistryV2Reader=e.v,exports.S3Storage=e.g,exports.absoluteToBase64=e.Rt,exports.absoluteToBytes=e.zt,exports.absoluteToString=e.Bt,exports.addRelativePathPrefix=e.Tt,exports.blockComponentsManifestToAbsoluteUrl=e.Ot,exports.buildBlockPackDist=e.wt,exports.buildKindDist=e.Ct,exports.buildPublishedCoords=e.q,exports.checkKindVersionMatch=e.Q,exports.consolidateBlockComponents=e.kt,exports.consolidateBlockPackDescription=e.Et,exports.consolidateBlockPackMeta=e.Mt,exports.cpAbsoluteToRelative=e.Vt,exports.embedBlockPackMetaAbsoluteBase64=e.Nt,exports.embedBlockPackMetaAbsoluteBytes=e.Pt,exports.embedBlockPackMetaBytes=e.Ft,exports.folderReaderByUrl=e.m,exports.inferUpdateSuggestions=e.y,exports.kindContentPrefix=e.ft,exports.kindOverviewPath=e.pt,exports.loadPackDescription=e._t,exports.loadPackDescriptionFromManifest=e.vt,exports.loadPackDescriptionRaw=e.yt,exports.mapLocalToAbsolute=e.Ht,exports.npmNameToKindPath=e.mt,exports.packFolderToRelativeTgz=e.Ut,exports.packageChannelPrefix=e.R,exports.packageChannelPrefixInsideV2=e.z,exports.packageContentPrefix=e.B,exports.packageContentPrefixInsideV2=e.V,exports.packageOverviewPath=e.H,exports.packageOverviewPathInsideV2=e.U,exports.parseGlobalOverviewReg=e.W,exports.parsePackageName=e.bt,exports.parseSelector=e.x,exports.publishBlock=e.X,exports.readFacadeKindDependency=e.$,exports.readModelCompiledKindRef=e.et,exports.relativeToContentString=e.Wt,exports.relativeToExplicitBinary64=e.Gt,exports.relativeToExplicitBytes=e.Kt,exports.relativeToExplicitString=e.qt,exports.resolveBlockComponents=e.At,exports.resolveBlockPackDescription=e.Dt,exports.resolveBlockPackMeta=e.It,exports.resolveFacadeKind=e.tt,exports.resolveKind=e.S,exports.resolveManifestBlockComponents=e.jt,exports.resolveManifestBlockPackMeta=e.Lt,exports.resolveModuleFile=e.Jt,exports.resolveModuleFolder=e.Yt,exports.resolveToRegistry=e.J,exports.selectorToRange=e.C,exports.storageByUrl=e._,exports.tryLoadPackDescription=e.xt,exports.writePublishedCoords=e.Y;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/registry_v1/index.ts"],"sourcesContent":["export * from \"./v1_repo_schema\";\nexport * from \"./config_schema\";\nexport { PlRegPackageConfig } from \"./config\";\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.js","names":["require_config","registry_v1_exports"],"sources":["../src/registry_v1/index.ts"],"sourcesContent":["export * from \"./v1_repo_schema\";\nexport * from \"./config_schema\";\nexport { PlRegPackageConfig } from \"./config\";\n"],"mappings":""}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { $ as e, A as t, At as n, B as r, Bt as i, C as a, Ct as o, D as s, Dt as c, E as l, Et as u, F as d, Ft as f,
|
|
2
|
-
|
|
3
|
-
var Je = /* @__PURE__ */
|
|
1
|
+
import { $ as e, A as t, At as n, B as r, Bt as i, C as a, Ct as o, D as s, Dt as c, E as l, Et as u, F as d, Ft as f, Gt as p, H as m, Ht as h, I as g, It as _, J as v, Jt as y, K as b, Kt as x, L as S, Lt as C, M as w, Mt as T, N as E, Nt as D, O, Ot as k, P as A, Pt as j, Q as M, R as N, Rt as P, S as F, St as I, T as L, Tt as R, U as z, Ut as B, V, Vt as H, W as U, Wt as W, X as G, Xt as K, Y as q, Yt as J, Z as Y, _ as X, _t as Z, a as Q, at as $, b as ee, bt as te, c as ne, ct as re, d as ie, dt as ae, et as oe, f as se, ft as ce, g as le, gt as ue, h as de, ht as fe, i as pe, it as me, j as he, jt as ge, k as _e, kt as ve, l as ye, lt as be, m as xe, mt as Se, nt as Ce, o as we, ot as Te, p as Ee, pt as De, q as Oe, qt as ke, r as Ae, rt as je, s as Me, st as Ne, t as Pe, tt as Fe, u as Ie, ut as Le, v as Re, vt as ze, w as Be, wt as Ve, x as He, xt as Ue, y as We, yt as Ge, z as Ke, zt as qe } from "./config-C07cYptA.mjs";
|
|
2
|
+
// src/registry_v1/index.ts
|
|
3
|
+
var Je = /* @__PURE__ */ K({
|
|
4
4
|
GlobalOverviewPath: () => Ae,
|
|
5
5
|
MetaFile: () => pe,
|
|
6
6
|
PlPackageConfigData: () => ne,
|
|
@@ -14,7 +14,6 @@ var Je = /* @__PURE__ */ J({
|
|
|
14
14
|
packageOverviewPath: () => we,
|
|
15
15
|
payloadFilePath: () => Me
|
|
16
16
|
});
|
|
17
|
-
|
|
18
|
-
export { Se as BlockDescriptionPackageJsonField, fe as BlockPackFolderName, Be as BlockRegistryV2, R as ChannelNameRegexp, l as ChannelsFolder, de as FSStorage, s as GlobalOverviewFileName, k as GlobalOverviewGzFileName, _e as GlobalOverviewGzPath, t as GlobalOverviewPath, Fe as KindImplementer, Ce as KindManifest, Ue as KindManifestFile, je as KindManifestFileInfo, me as KindManifestFileName, $ as KindManifestIdentity, Te as KindOverview, Ne as KindOverviewFileName, re as KindOverviewPathPattern, ee as KindResolutionError, K as KindVersionMismatchError, be as KindVersionOverview, Le as KindsPrefix, he as MainPrefix, T as ManifestFileName, D as ManifestSuffix, j as PackageManifestPattern, d as PackageOverview, _ as PackageOverviewFileName, C as PackageOverviewVersionEntry, p as PublishedCoordsFileName, Je as RegistryV1, Re as RegistryV2Reader, le as S3Storage, w as absoluteToBase64, F as absoluteToBytes, qe as absoluteToString, Ve as addRelativePathPrefix, c as blockComponentsManifestToAbsoluteUrl, o as buildBlockPackDist, L as buildKindDist, x as buildPublishedCoords, Y as checkKindVersionMatch, A as consolidateBlockComponents, z as consolidateBlockPackDescription, ge as consolidateBlockPackMeta, i as cpAbsoluteToRelative, E as embedBlockPackMetaAbsoluteBase64, O as embedBlockPackMetaAbsoluteBytes, M as embedBlockPackMetaBytes, xe as folderReaderByUrl, We as inferUpdateSuggestions, ae as kindContentPrefix, ce as kindOverviewPath, ue as loadPackDescription, Z as loadPackDescriptionFromManifest, ze as loadPackDescriptionRaw, U as mapLocalToAbsolute, De as npmNameToKindPath, g as packFolderToRelativeTgz, P as packageChannelPrefix, Ke as packageChannelPrefixInsideV2, r as packageContentPrefix, H as packageContentPrefixInsideV2, h as packageOverviewPath, B as packageOverviewPathInsideV2, W as parseGlobalOverviewReg, Ge as parsePackageName, He as parseSelector, q as publishBlock, N as readFacadeKindDependency, e as readModelCompiledKindRef, V as relativeToContentString, G as relativeToExplicitBinary64, m as relativeToExplicitBytes, S as relativeToExplicitString, ve as resolveBlockComponents, u as resolveBlockPackDescription, f as resolveBlockPackMeta, oe as resolveFacadeKind, I as resolveKind, n as resolveManifestBlockComponents, v as resolveManifestBlockPackMeta, ke as resolveModuleFile, b as resolveModuleFolder, Oe as resolveToRegistry, a as selectorToRange, X as storageByUrl, te as tryLoadPackDescription, y as writePublishedCoords };
|
|
17
|
+
export { fe as BlockDescriptionPackageJsonField, ue as BlockPackFolderName, Be as BlockRegistryV2, L as ChannelNameRegexp, l as ChannelsFolder, de as FSStorage, s as GlobalOverviewFileName, O as GlobalOverviewGzFileName, _e as GlobalOverviewGzPath, t as GlobalOverviewPath, Ce as KindImplementer, je as KindManifest, I as KindManifestFile, me as KindManifestFileInfo, $ as KindManifestFileName, Te as KindManifestIdentity, Ne as KindOverview, re as KindOverviewFileName, be as KindOverviewPathPattern, ee as KindResolutionError, Y as KindVersionMismatchError, Le as KindVersionOverview, ae as KindsPrefix, he as MainPrefix, w as ManifestFileName, E as ManifestSuffix, A as PackageManifestPattern, d as PackageOverview, g as PackageOverviewFileName, S as PackageOverviewVersionEntry, b as PublishedCoordsFileName, Je as RegistryV1, Re as RegistryV2Reader, le as S3Storage, P as absoluteToBase64, qe as absoluteToBytes, i as absoluteToString, R as addRelativePathPrefix, k as blockComponentsManifestToAbsoluteUrl, Ve as buildBlockPackDist, o as buildKindDist, Oe as buildPublishedCoords, M as checkKindVersionMatch, ve as consolidateBlockComponents, u as consolidateBlockPackDescription, T as consolidateBlockPackMeta, H as cpAbsoluteToRelative, D as embedBlockPackMetaAbsoluteBase64, j as embedBlockPackMetaAbsoluteBytes, f as embedBlockPackMetaBytes, xe as folderReaderByUrl, We as inferUpdateSuggestions, ce as kindContentPrefix, De as kindOverviewPath, Z as loadPackDescription, ze as loadPackDescriptionFromManifest, Ge as loadPackDescriptionRaw, h as mapLocalToAbsolute, Se as npmNameToKindPath, B as packFolderToRelativeTgz, N as packageChannelPrefix, Ke as packageChannelPrefixInsideV2, r as packageContentPrefix, V as packageContentPrefixInsideV2, m as packageOverviewPath, z as packageOverviewPathInsideV2, U as parseGlobalOverviewReg, te as parsePackageName, He as parseSelector, G as publishBlock, e as readFacadeKindDependency, oe as readModelCompiledKindRef, W as relativeToContentString, p as relativeToExplicitBinary64, x as relativeToExplicitBytes, ke as relativeToExplicitString, n as resolveBlockComponents, c as resolveBlockPackDescription, _ as resolveBlockPackMeta, Fe as resolveFacadeKind, F as resolveKind, ge as resolveManifestBlockComponents, C as resolveManifestBlockPackMeta, y as resolveModuleFile, J as resolveModuleFolder, v as resolveToRegistry, a as selectorToRange, X as storageByUrl, Ue as tryLoadPackDescription, q as writePublishedCoords };
|
|
19
18
|
|
|
20
19
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/registry_v1/index.ts"],"sourcesContent":["export * from \"./v1_repo_schema\";\nexport * from \"./config_schema\";\nexport { PlRegPackageConfig } from \"./config\";\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["readFacadeKindDependency","GlobalOverviewPath","resolveBlockComponents","packageContentPrefix","absoluteToString","selectorToRange","buildKindDist","GlobalOverviewFileName","resolveBlockPackDescription","ChannelsFolder","consolidateBlockPackDescription","PackageOverview","embedBlockPackMetaBytes","relativeToExplicitBinary64","packageOverviewPath","mapLocalToAbsolute","PackageOverviewFileName","resolveBlockPackMeta","resolveToRegistry","resolveModuleFile","PublishedCoordsFileName","relativeToExplicitBytes","PackageOverviewVersionEntry","resolveManifestBlockPackMeta","ManifestFileName","consolidateBlockPackMeta","ManifestSuffix","embedBlockPackMetaAbsoluteBase64","blockComponentsManifestToAbsoluteUrl","PackageManifestPattern","embedBlockPackMetaAbsoluteBytes","checkKindVersionMatch","packageChannelPrefix","absoluteToBase64","resolveKind","KindManifestFile","ChannelNameRegexp","addRelativePathPrefix","packageOverviewPathInsideV2","packFolderToRelativeTgz","cpAbsoluteToRelative","parseGlobalOverviewReg","relativeToContentString","publishBlock","__exportAll","writePublishedCoords","resolveModuleFolder","KindVersionMismatchError","storageByUrl","loadPackDescription","packageContentPrefix$1","KindManifestFileName","KindResolutionError","parsePackageName","PlPackageConfigData","KindOverviewFileName","PlRegCommonConfigData","KindsPrefix","readModelCompiledKindRef","PlRegFullPackageConfigData","kindContentPrefix","S3Storage","BlockPackFolderName","FSStorage","BlockDescriptionPackageJsonField","MetaFile","KindManifestFileInfo","MainPrefix","resolveManifestBlockComponents","GlobalOverviewGzPath","consolidateBlockComponents","PlPackageJsonConfigFile","KindOverviewPathPattern","folderReaderByUrl","npmNameToKindPath","KindImplementer","packageOverviewPath$1","KindManifestIdentity","PlRegPackageConfigDataShard","kindOverviewPath","buildPublishedCoords","relativeToExplicitString","GlobalOverviewPath$1","KindManifest","payloadFilePath","KindOverview","PlRegPackageConfig","resolveFacadeKind","PlPackageYamlConfigFile","KindVersionOverview","RegistryV2Reader","loadPackDescriptionFromManifest","BlockRegistryV2","buildBlockPackDist","parseSelector","tryLoadPackDescription","inferUpdateSuggestions","loadPackDescriptionRaw","packageChannelPrefixInsideV2","absoluteToBytes","registry_v1_exports","GlobalOverviewGzFileName","packageContentPrefixInsideV2"],"sources":["../src/registry_v1/index.ts"],"sourcesContent":["export * from \"./v1_repo_schema\";\nexport * from \"./config_schema\";\nexport { PlRegPackageConfig } from \"./config\";\n"],"mappings":""}
|
|
@@ -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, pinCatalogToDependencyOf, ensureCatalogLatest, ensureCatalogAbsent, ensureGitignoreEntries, removeGitignoreEntries, withManagedBody, withManagedYaml, withManagedLines, } from './content-rules';
|
|
54
|
+
export { ensureField, removeField, requireField, forbidField, 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, ensureCatalogAtLeast, ensureWorkspaceMapEntries, ensureWorkspaceListItems, ensureGitignoreEntries, removeGitignoreEntries, withManagedBody, withManagedYaml, withManagedLines, } from './content-rules';
|
|
55
55
|
export type { DepVersion } from './content-rules';
|
|
@@ -52,6 +52,8 @@ export declare function ensureField(jsonPath: string, value: unknown): void;
|
|
|
52
52
|
export declare function removeField(jsonPath: string, predicate?: (currentValue: unknown) => boolean): void;
|
|
53
53
|
/** Assert a field exists; throw if absent. No mutation. */
|
|
54
54
|
export declare function requireField(jsonPath: string, message?: string): void;
|
|
55
|
+
/** Throw `message` when the field at `jsonPath` exists. No mutation. */
|
|
56
|
+
export declare function forbidField(jsonPath: string, message: string): void;
|
|
55
57
|
/** Merge `entries` into the object at `jsonPath`. Auto-creates the
|
|
56
58
|
* object if missing. Existing other entries preserved. */
|
|
57
59
|
export declare function ensureFieldEntries(jsonPath: string, entries: Record<string, unknown>): void;
|
|
@@ -157,8 +159,18 @@ export declare function pinCatalogToDependencyOf(catalogEntry: string, _opts: {
|
|
|
157
159
|
of: string;
|
|
158
160
|
ofVersion?: string;
|
|
159
161
|
}): void;
|
|
162
|
+
/** Raise `catalog.<name>` to `range` when its lowest version is lower; add it when absent.
|
|
163
|
+
* An entry that is not a semver range stays. */
|
|
164
|
+
export declare function ensureCatalogAtLeast(name: string, range: string): void;
|
|
160
165
|
/** Remove `catalog.<name>` if present; no-op when absent. */
|
|
161
166
|
export declare function ensureCatalogAbsent(name: string): void;
|
|
167
|
+
/** Set each `entries` key under the top-level map `key`; other keys stay.
|
|
168
|
+
* With `keepExisting`, a key the map already has keeps its value. */
|
|
169
|
+
export declare function ensureWorkspaceMapEntries(key: string, entries: Record<string, unknown>, { keepExisting }?: {
|
|
170
|
+
keepExisting?: boolean | undefined;
|
|
171
|
+
}): void;
|
|
172
|
+
/** Append each missing `items` entry to the top-level list `key`. */
|
|
173
|
+
export declare function ensureWorkspaceListItems(key: string, items: readonly string[]): void;
|
|
162
174
|
/** Append each `entry` if not already present (comment-aware equality). */
|
|
163
175
|
export declare function ensureGitignoreEntries(entries: string[]): void;
|
|
164
176
|
/** Drop any line whose normalised form matches any of `patterns`. */
|
|
@@ -5,7 +5,7 @@ import { DerivedCatalogPin } from '../engine/registry-client';
|
|
|
5
5
|
* them. */
|
|
6
6
|
export declare const SDK_CATALOG_PACKAGES: readonly string[];
|
|
7
7
|
/** Infra / tooling — a `~`-floored curated set. Not exact-pinned on refresh
|
|
8
|
-
* and not bumped by update-deps. */
|
|
8
|
+
* (refresh only raises turbo to `TURBO_VERSION`) and not bumped by update-deps. */
|
|
9
9
|
export declare const INFRA_CATALOG_FLOOR: Record<string, string>;
|
|
10
10
|
/** Catalog entries whose exact version is DERIVED from the version another
|
|
11
11
|
* package declares for them (see `pinCatalogToDependencyOf`). Resolved on
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const canonicalPackageJsonOrder: readonly ["name", "version", "private", "description", "keywords", "files", "type", "main", "module", "types", "exports", "scripts", "dependencies", "devDependencies", "peerDependencies", "optionalDependencies", "
|
|
1
|
+
export declare const canonicalPackageJsonOrder: readonly ["name", "version", "private", "description", "keywords", "files", "type", "main", "module", "types", "exports", "scripts", "dependencies", "devDependencies", "peerDependencies", "optionalDependencies", "devEngines", "engines", "packageManager", "block", "block-software"];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Node version for the block CI workflows. */
|
|
2
|
+
export declare const NODE_VERSION = "24.22.1";
|
|
3
|
+
/** Root `devEngines.runtime` of a block: pnpm runs the block scripts on this Node. */
|
|
4
|
+
export declare const NODE_RUNTIME: {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
onFail: string;
|
|
8
|
+
};
|
|
9
|
+
/** Root `packageManager` of a block. The shared CI workflow installs this pnpm. */
|
|
10
|
+
export declare const PACKAGE_MANAGER = "pnpm@12.16.1+sha512.091d1dee7927575661b25dab3c2ae31cafc1c54d6b71ed6a6600cf0c1cb10434a447eae14015f1b23e2e6bedeed79df94a932e2164d2832280dce3fb32f656d1";
|
|
11
|
+
/** turbo before 2.11 cannot parse a pnpm 12 lockfile. */
|
|
12
|
+
export declare const TURBO_VERSION = "~2.11.10";
|
|
13
|
+
/** Our scopes skip `minimumReleaseAge`, so `upgrade-sdk` gets a fresh SDK release. */
|
|
14
|
+
export declare const MINIMUM_RELEASE_AGE_EXCLUDE: readonly string[];
|
|
15
|
+
/** pnpm 11+ fails an install on an unlisted install script. This one downloads the native addon. */
|
|
16
|
+
export declare const REQUIRED_BUILDS: Record<string, boolean>;
|
|
17
|
+
/** Install scripts in the SDK tree that only clean up, print, or build optional native code. */
|
|
18
|
+
export declare const SKIPPED_BUILDS: Record<string, boolean>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/block-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.1",
|
|
4
4
|
"description": "Utility to manipulate Platforma Blocks and Block Registry",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"bin": {
|
|
@@ -23,42 +23,42 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@aws-sdk/client-ecr-public": "3.
|
|
27
|
-
"@aws-sdk/client-s3": "3.
|
|
26
|
+
"@aws-sdk/client-ecr-public": "3.1157.0",
|
|
27
|
+
"@aws-sdk/client-s3": "3.1157.0",
|
|
28
28
|
"@inquirer/prompts": "^7.0.1",
|
|
29
|
+
"@milaboratories/pl-http": "1.2.5",
|
|
30
|
+
"@milaboratories/pl-model-backend": "1.4.40",
|
|
31
|
+
"@milaboratories/pl-model-common": "1.54.2",
|
|
32
|
+
"@milaboratories/pl-model-middle-layer": "1.34.6",
|
|
33
|
+
"@milaboratories/resolve-helper": "1.1.3",
|
|
34
|
+
"@milaboratories/ts-helpers": "1.9.0",
|
|
35
|
+
"@platforma-sdk/blocks-deps-updater": "2.2.1",
|
|
36
|
+
"@platforma-sdk/package-builder-lib": "1.4.2",
|
|
29
37
|
"canonicalize": "~2.1.0",
|
|
30
38
|
"commander": "^15.0.0",
|
|
31
|
-
"lru-cache": "^11.
|
|
39
|
+
"lru-cache": "^11.5.3",
|
|
32
40
|
"mime-types": "^2.1.35",
|
|
33
|
-
"tar": "^7.
|
|
34
|
-
"undici": "~7.
|
|
35
|
-
"yaml": "^2.
|
|
36
|
-
"zod": "~3.25.76"
|
|
37
|
-
"@milaboratories/pl-http": "1.2.4",
|
|
38
|
-
"@milaboratories/pl-model-middle-layer": "1.34.4",
|
|
39
|
-
"@milaboratories/pl-model-backend": "1.4.38",
|
|
40
|
-
"@milaboratories/resolve-helper": "1.1.3",
|
|
41
|
-
"@platforma-sdk/blocks-deps-updater": "2.2.0",
|
|
42
|
-
"@milaboratories/pl-model-common": "1.54.0",
|
|
43
|
-
"@milaboratories/ts-helpers": "1.8.6",
|
|
44
|
-
"@platforma-sdk/package-builder-lib": "1.4.1"
|
|
41
|
+
"tar": "^7.5.22",
|
|
42
|
+
"undici": "~7.30.1",
|
|
43
|
+
"yaml": "^2.9.1",
|
|
44
|
+
"zod": "~3.25.76"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
+
"@milaboratories/build-configs": "2.0.2",
|
|
48
|
+
"@milaboratories/ts-builder": "1.7.3",
|
|
49
|
+
"@milaboratories/ts-configs": "1.4.0",
|
|
47
50
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
48
51
|
"@types/mime-types": "^2.1.4",
|
|
49
|
-
"@types/node": "~24.
|
|
52
|
+
"@types/node": "~24.19.2",
|
|
50
53
|
"@types/semver": "^7.7.0",
|
|
51
|
-
"@vitest/coverage-istanbul": "^4.1.
|
|
52
|
-
"oxfmt": "0.
|
|
54
|
+
"@vitest/coverage-istanbul": "^4.1.12",
|
|
55
|
+
"oxfmt": "0.75.0",
|
|
53
56
|
"rollup-plugin-node-externals": "^8.0.0",
|
|
54
57
|
"semver": "^7.7.2",
|
|
55
58
|
"typescript": "7.0.2",
|
|
56
|
-
"vite": "^8.
|
|
57
|
-
"vite-plugin-dts": "^5.
|
|
58
|
-
"vitest": "^4.1.
|
|
59
|
-
"@milaboratories/build-configs": "2.0.2",
|
|
60
|
-
"@milaboratories/ts-configs": "1.4.0",
|
|
61
|
-
"@milaboratories/ts-builder": "1.7.2"
|
|
59
|
+
"vite": "^8.3.5",
|
|
60
|
+
"vite-plugin-dts": "^5.1.2",
|
|
61
|
+
"vitest": "^4.1.12"
|
|
62
62
|
},
|
|
63
63
|
"repository": {
|
|
64
64
|
"type": "git",
|
|
@@ -86,7 +86,7 @@ describe("rootCatalogBumpRules mode split", () => {
|
|
|
86
86
|
// standard infra-floor keys ABSENT from the on-disk catalog are
|
|
87
87
|
// SEEDED add-if-absent (no manual seed step needed).
|
|
88
88
|
expect(cat["shx"]).toBe("~0.4.0");
|
|
89
|
-
expect(cat["turbo"]).toBe("~2.
|
|
89
|
+
expect(cat["turbo"]).toBe("~2.11.10");
|
|
90
90
|
expect(cat["vitest"]).toBe("~4.0.18");
|
|
91
91
|
// Non-matching dep left alone.
|
|
92
92
|
expect(cat["lodash"]).toBe("1.0.0");
|
|
@@ -12,6 +12,7 @@ import type { BlockVars, RunContext } from "../engine/api";
|
|
|
12
12
|
import { STRUCTURE } from "../structure-definition";
|
|
13
13
|
import { run as engineRun } from "../engine/runner";
|
|
14
14
|
import { defaultTemplateProvider, simulateInit } from "../engine/testing";
|
|
15
|
+
import { NODE_VERSION } from "../rules/shared/toolchain";
|
|
15
16
|
|
|
16
17
|
const TEMPLATES = defaultTemplateProvider();
|
|
17
18
|
|
|
@@ -37,9 +38,9 @@ describe("root CI workflows (fixed, generated)", () => {
|
|
|
37
38
|
// Shared constants.
|
|
38
39
|
expect(build).toContain("team-id: 'ciplopen'");
|
|
39
40
|
expect(build).toContain("test: true");
|
|
40
|
-
// Both workflows
|
|
41
|
-
expect(build).toContain(
|
|
42
|
-
expect(fs.read(MARK_STABLE)).toContain(
|
|
41
|
+
// Both workflows run the SDK's Node.
|
|
42
|
+
expect(build).toContain(`node-version: '${NODE_VERSION}'`);
|
|
43
|
+
expect(fs.read(MARK_STABLE)).toContain(`node-version: '${NODE_VERSION}'`);
|
|
43
44
|
// Opt-in gate: the published `block` package must be bumped on PRs.
|
|
44
45
|
expect(build).toContain("require-package-path-bump: true");
|
|
45
46
|
// No bare `build` script exists (root-package-json removes it), so both
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// A block must run on the SDK's Node and pnpm: `upgrade-sdk` aligns it.
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { satisfies } from "semver";
|
|
5
|
+
import { describe, expect, test } from "vitest";
|
|
6
|
+
import { parse as parseYaml, parseDocument } from "yaml";
|
|
7
|
+
import type { BlockVars } from "../engine/api";
|
|
8
|
+
import type { MemoryFileSystem } from "../engine/fs/memory";
|
|
9
|
+
import { discoverRunContext } from "../engine/discovery-fs";
|
|
10
|
+
import { run as engineRun } from "../engine/runner";
|
|
11
|
+
import { defaultTemplateProvider, simulateInit } from "../engine/testing";
|
|
12
|
+
import {
|
|
13
|
+
MINIMUM_RELEASE_AGE_EXCLUDE,
|
|
14
|
+
NODE_RUNTIME,
|
|
15
|
+
NODE_VERSION,
|
|
16
|
+
PACKAGE_MANAGER,
|
|
17
|
+
REQUIRED_BUILDS,
|
|
18
|
+
SKIPPED_BUILDS,
|
|
19
|
+
TURBO_VERSION,
|
|
20
|
+
} from "../rules/shared/toolchain";
|
|
21
|
+
import { STRUCTURE } from "../structure-definition";
|
|
22
|
+
|
|
23
|
+
const VARS: BlockVars = {
|
|
24
|
+
facadeName: "@platforma-open/test-org.demo",
|
|
25
|
+
baseName: "test-org.demo",
|
|
26
|
+
npmOrg: "@platforma-open",
|
|
27
|
+
orgScope: "test-org",
|
|
28
|
+
shortName: "demo",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const readMonorepoFile = (relativePath: string) =>
|
|
32
|
+
readFileSync(new URL(`../../../../../${relativePath}`, import.meta.url), "utf-8");
|
|
33
|
+
|
|
34
|
+
function refresh(fs: MemoryFileSystem) {
|
|
35
|
+
return engineRun(STRUCTURE, fs, discoverRunContext({ fs, isSdkInternal: false }), {
|
|
36
|
+
templates: defaultTemplateProvider(),
|
|
37
|
+
rediscover: () => discoverRunContext({ fs, isSdkInternal: false, dryRun: true }),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function editJson(fs: MemoryFileSystem, edit: (json: Record<string, unknown>) => void) {
|
|
42
|
+
const json = JSON.parse(fs.read("package.json"));
|
|
43
|
+
edit(json);
|
|
44
|
+
fs.write("package.json", JSON.stringify(json, null, 2) + "\n");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function editWorkspace(
|
|
48
|
+
fs: MemoryFileSystem,
|
|
49
|
+
edit: (doc: ReturnType<typeof parseDocument>) => void,
|
|
50
|
+
) {
|
|
51
|
+
const doc = parseDocument(fs.read("pnpm-workspace.yaml"));
|
|
52
|
+
edit(doc);
|
|
53
|
+
fs.write("pnpm-workspace.yaml", doc.toString());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const readWorkspace = (fs: MemoryFileSystem) => parseYaml(fs.read("pnpm-workspace.yaml"));
|
|
57
|
+
|
|
58
|
+
describe("block toolchain", () => {
|
|
59
|
+
test("matches the SDK monorepo", () => {
|
|
60
|
+
const root = JSON.parse(readMonorepoFile("package.json"));
|
|
61
|
+
expect(PACKAGE_MANAGER).toBe(root.packageManager);
|
|
62
|
+
const setup = parseYaml(readMonorepoFile(".github/actions/setup/action.yml"));
|
|
63
|
+
expect(NODE_VERSION).toBe(setup.inputs["node-version"].default);
|
|
64
|
+
const workspace = parseYaml(readMonorepoFile("pnpm-workspace.yaml"));
|
|
65
|
+
expect(MINIMUM_RELEASE_AGE_EXCLUDE).toEqual(workspace.minimumReleaseAgeExclude);
|
|
66
|
+
expect(satisfies(workspace.catalog.turbo, TURBO_VERSION)).toBe(true);
|
|
67
|
+
expect(workspace.allowBuilds).toMatchObject({ ...REQUIRED_BUILDS, ...SKIPPED_BUILDS });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("refresh moves an old block to the SDK pnpm and Node", () => {
|
|
71
|
+
const { fs } = simulateInit({ vars: VARS });
|
|
72
|
+
editJson(fs, (json) => {
|
|
73
|
+
json.packageManager = "pnpm@9.12.0";
|
|
74
|
+
delete json.devEngines;
|
|
75
|
+
json.pnpm = { overrides: {} };
|
|
76
|
+
});
|
|
77
|
+
editWorkspace(fs, (doc) => {
|
|
78
|
+
doc.delete("minimumReleaseAgeExclude");
|
|
79
|
+
doc.delete("allowBuilds");
|
|
80
|
+
doc.setIn(["catalog", "turbo"], "~2.8.11");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
refresh(fs);
|
|
84
|
+
|
|
85
|
+
const pkg = JSON.parse(fs.read("package.json"));
|
|
86
|
+
expect(pkg.packageManager).toBe(PACKAGE_MANAGER);
|
|
87
|
+
expect(pkg.devEngines).toEqual({ runtime: NODE_RUNTIME });
|
|
88
|
+
expect(pkg.pnpm).toBeUndefined();
|
|
89
|
+
const workspace = readWorkspace(fs);
|
|
90
|
+
expect(workspace.minimumReleaseAgeExclude).toEqual(MINIMUM_RELEASE_AGE_EXCLUDE);
|
|
91
|
+
expect(workspace.allowBuilds).toEqual({ ...SKIPPED_BUILDS, ...REQUIRED_BUILDS });
|
|
92
|
+
expect(workspace.catalog.turbo).toBe(TURBO_VERSION);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("refresh replaces only the runtime among the author's engines", () => {
|
|
96
|
+
const { fs } = simulateInit({ vars: VARS });
|
|
97
|
+
const packageManager = { name: "pnpm", version: "12.16.1" };
|
|
98
|
+
editJson(fs, (json) => {
|
|
99
|
+
json.engines = { node: ">=20" };
|
|
100
|
+
json.devEngines = { packageManager, runtime: { name: "node", version: "22" } };
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
refresh(fs);
|
|
104
|
+
|
|
105
|
+
const pkg = JSON.parse(fs.read("package.json"));
|
|
106
|
+
expect(pkg.devEngines).toEqual({ packageManager, runtime: NODE_RUNTIME });
|
|
107
|
+
expect(pkg.engines).toEqual({ node: ">=20" });
|
|
108
|
+
const toolchainKeys = ["devEngines", "engines", "packageManager"];
|
|
109
|
+
expect(Object.keys(pkg).filter((key) => toolchainKeys.includes(key))).toEqual(toolchainKeys);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("refresh keeps the author's workspace settings", () => {
|
|
113
|
+
const { fs } = simulateInit({ vars: VARS });
|
|
114
|
+
editWorkspace(fs, (doc) => {
|
|
115
|
+
doc.set("overrides", { zod: "~3.25.76" });
|
|
116
|
+
doc.setIn(["allowBuilds", "sharp"], true);
|
|
117
|
+
doc.setIn(["allowBuilds", "esbuild"], true);
|
|
118
|
+
doc.setIn(["allowBuilds", "@milaboratories/pframes-rs-node"], false);
|
|
119
|
+
doc.setIn(["catalog", "turbo"], "~2.12.3");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
refresh(fs);
|
|
123
|
+
|
|
124
|
+
const workspace = readWorkspace(fs);
|
|
125
|
+
expect(workspace.overrides).toEqual({ zod: "~3.25.76" });
|
|
126
|
+
expect(workspace.allowBuilds).toEqual({
|
|
127
|
+
...SKIPPED_BUILDS,
|
|
128
|
+
...REQUIRED_BUILDS,
|
|
129
|
+
sharp: true,
|
|
130
|
+
esbuild: true,
|
|
131
|
+
});
|
|
132
|
+
expect(workspace.catalog.turbo).toBe("~2.12.3");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("refresh fills empty workspace settings", () => {
|
|
136
|
+
const { fs } = simulateInit({ vars: VARS });
|
|
137
|
+
editWorkspace(fs, (doc) => {
|
|
138
|
+
doc.set("minimumReleaseAgeExclude", null);
|
|
139
|
+
doc.set("allowBuilds", null);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
refresh(fs);
|
|
143
|
+
|
|
144
|
+
const workspace = readWorkspace(fs);
|
|
145
|
+
expect(workspace.minimumReleaseAgeExclude).toEqual(MINIMUM_RELEASE_AGE_EXCLUDE);
|
|
146
|
+
expect(workspace.allowBuilds).toEqual({ ...SKIPPED_BUILDS, ...REQUIRED_BUILDS });
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("refresh refuses a package.json pnpm field with settings", () => {
|
|
150
|
+
const { fs } = simulateInit({ vars: VARS });
|
|
151
|
+
editJson(fs, (json) => {
|
|
152
|
+
json.pnpm = { overrides: { zod: "~3.25.76" } };
|
|
153
|
+
});
|
|
154
|
+
expect(() => refresh(fs)).toThrow(/pnpm-workspace\.yaml/);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { ensureCatalogAtLeast, withManagedYaml } from "../../content-rules";
|
|
3
|
+
import { parseYaml } from "../../parsers/yaml";
|
|
4
|
+
|
|
5
|
+
function turboAfter(catalog: string): unknown {
|
|
6
|
+
const doc = parseYaml(`catalog:\n${catalog}`);
|
|
7
|
+
withManagedYaml(doc, () => ensureCatalogAtLeast("turbo", "~2.11.10"));
|
|
8
|
+
return doc.getIn(["catalog", "turbo"]);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe("ensureCatalogAtLeast", () => {
|
|
12
|
+
test("raises a lower range", () => {
|
|
13
|
+
expect(turboAfter(" turbo: ~2.8.11\n")).toBe("~2.11.10");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("keeps an equal or higher range", () => {
|
|
17
|
+
expect(turboAfter(" turbo: ^2.11.10\n")).toBe("^2.11.10");
|
|
18
|
+
expect(turboAfter(" turbo: 2.12.0\n")).toBe("2.12.0");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("adds an absent entry", () => {
|
|
22
|
+
expect(turboAfter(" shx: ~0.4.0\n")).toBe("~2.11.10");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("keeps an entry that is not a semver range", () => {
|
|
26
|
+
expect(turboAfter(" turbo: latest\n")).toBe("latest");
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -92,6 +92,7 @@ export {
|
|
|
92
92
|
ensureField,
|
|
93
93
|
removeField,
|
|
94
94
|
requireField,
|
|
95
|
+
forbidField,
|
|
95
96
|
ensureFieldEntries,
|
|
96
97
|
ensureScript,
|
|
97
98
|
removeScript,
|
|
@@ -120,6 +121,9 @@ export {
|
|
|
120
121
|
pinCatalogToDependencyOf,
|
|
121
122
|
ensureCatalogLatest,
|
|
122
123
|
ensureCatalogAbsent,
|
|
124
|
+
ensureCatalogAtLeast,
|
|
125
|
+
ensureWorkspaceMapEntries,
|
|
126
|
+
ensureWorkspaceListItems,
|
|
123
127
|
// Lines managed builders
|
|
124
128
|
ensureGitignoreEntries,
|
|
125
129
|
removeGitignoreEntries,
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
// ensure*/remove*/require*/prune/enforce*/transform; YAML catalog
|
|
12
12
|
// management + workspace module paths; gitignore line management.
|
|
13
13
|
|
|
14
|
+
import { gte, minVersion, validRange } from "semver";
|
|
15
|
+
import { isMap, isSeq } from "yaml";
|
|
14
16
|
import { registerInnerWhenHandler, tryGetActiveRunContext } from "./builders";
|
|
15
17
|
import type { RunContext, Scope } from "./api";
|
|
16
18
|
import type { ManagedBody, TriggerContext, TriggerFn } from "./ir";
|
|
@@ -286,6 +288,13 @@ export function requireField(jsonPath: string, message?: string): void {
|
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
290
|
|
|
291
|
+
/** Throw `message` when the field at `jsonPath` exists. No mutation. */
|
|
292
|
+
export function forbidField(jsonPath: string, message: string): void {
|
|
293
|
+
if (hasAtPath(requireJson("forbidField").obj, jsonPath)) {
|
|
294
|
+
throw new Error(message);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
289
298
|
/** Merge `entries` into the object at `jsonPath`. Auto-creates the
|
|
290
299
|
* object if missing. Existing other entries preserved. */
|
|
291
300
|
export function ensureFieldEntries(jsonPath: string, entries: Record<string, unknown>): void {
|
|
@@ -608,6 +617,20 @@ export function pinCatalogToDependencyOf(
|
|
|
608
617
|
state.doc.setIn(["catalog", catalogEntry], version);
|
|
609
618
|
}
|
|
610
619
|
|
|
620
|
+
/** Raise `catalog.<name>` to `range` when its lowest version is lower; add it when absent.
|
|
621
|
+
* An entry that is not a semver range stays. */
|
|
622
|
+
export function ensureCatalogAtLeast(name: string, range: string): void {
|
|
623
|
+
const state = requireYaml("ensureCatalogAtLeast");
|
|
624
|
+
const current = readCatalogString(state, name);
|
|
625
|
+
const floor = minVersion(range);
|
|
626
|
+
const currentMin =
|
|
627
|
+
current !== undefined && validRange(current) !== null ? minVersion(current) : null;
|
|
628
|
+
if (current !== undefined && (floor === null || currentMin === null || gte(currentMin, floor))) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
state.doc.setIn(["catalog", name], range);
|
|
632
|
+
}
|
|
633
|
+
|
|
611
634
|
/** Remove `catalog.<name>` if present; no-op when absent. */
|
|
612
635
|
export function ensureCatalogAbsent(name: string): void {
|
|
613
636
|
const state = requireYaml("ensureCatalogAbsent");
|
|
@@ -615,6 +638,43 @@ export function ensureCatalogAbsent(name: string): void {
|
|
|
615
638
|
state.doc.deleteIn(["catalog", name]);
|
|
616
639
|
}
|
|
617
640
|
|
|
641
|
+
/** Set each `entries` key under the top-level map `key`; other keys stay.
|
|
642
|
+
* With `keepExisting`, a key the map already has keeps its value. */
|
|
643
|
+
export function ensureWorkspaceMapEntries(
|
|
644
|
+
key: string,
|
|
645
|
+
entries: Record<string, unknown>,
|
|
646
|
+
{ keepExisting = false } = {},
|
|
647
|
+
): void {
|
|
648
|
+
const state = requireYaml("ensureWorkspaceMapEntries");
|
|
649
|
+
if (!isMap(state.doc.get(key))) {
|
|
650
|
+
state.doc.delete(key);
|
|
651
|
+
}
|
|
652
|
+
const changed = Object.entries(entries).filter(([name, value]) =>
|
|
653
|
+
keepExisting ? !state.doc.hasIn([key, name]) : state.doc.getIn([key, name]) !== value,
|
|
654
|
+
);
|
|
655
|
+
for (const [name, value] of changed) {
|
|
656
|
+
state.doc.setIn([key, name], value);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/** Append each missing `items` entry to the top-level list `key`. */
|
|
661
|
+
export function ensureWorkspaceListItems(key: string, items: readonly string[]): void {
|
|
662
|
+
const state = requireYaml("ensureWorkspaceListItems");
|
|
663
|
+
const current = state.doc.toJSON()?.[key];
|
|
664
|
+
const present = new Set(Array.isArray(current) ? current : []);
|
|
665
|
+
const missing = items.filter((item) => !present.has(item));
|
|
666
|
+
if (missing.length === 0) {
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (!isSeq(state.doc.get(key))) {
|
|
670
|
+
state.doc.set(key, missing);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
for (const item of missing) {
|
|
674
|
+
state.doc.addIn([key], item);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
618
678
|
// ============================================================
|
|
619
679
|
// Lines builders — `.gitignore`
|
|
620
680
|
// ============================================================
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
// `when(!isSdkInternal)` guard, matching the rest of the root scope.
|
|
16
16
|
|
|
17
17
|
import { scope, when, fixed, tpl } from "../engine/api";
|
|
18
|
+
import { NODE_VERSION } from "./shared/toolchain";
|
|
18
19
|
|
|
19
20
|
/** Readable default CI label from a short name (`mixcr-clonotyping-2` →
|
|
20
21
|
* `Mixcr Clonotyping 2`). Dash/underscore words, title-cased. Human-curated
|
|
@@ -40,6 +41,7 @@ export function rootCiRules(): void {
|
|
|
40
41
|
return {
|
|
41
42
|
appName: `Block: ${humanizeShortName(shortName)}`,
|
|
42
43
|
appNameSlug: `block-${shortName}`,
|
|
44
|
+
nodeVersion: NODE_VERSION,
|
|
43
45
|
};
|
|
44
46
|
}),
|
|
45
47
|
);
|
|
@@ -47,6 +49,7 @@ export function rootCiRules(): void {
|
|
|
47
49
|
".github/workflows/mark-stable.yaml",
|
|
48
50
|
tpl("workflows/mark-stable.tpl.yaml", (ctx) => ({
|
|
49
51
|
appName: `Block: ${humanizeShortName(ctx.blockVars.shortName)} - Mark Stable`,
|
|
52
|
+
nodeVersion: NODE_VERSION,
|
|
50
53
|
})),
|
|
51
54
|
);
|
|
52
55
|
},
|
|
@@ -13,9 +13,11 @@ import {
|
|
|
13
13
|
pruneKeysMatching,
|
|
14
14
|
enforceAlphabeticalOrder,
|
|
15
15
|
enforceFieldOrder,
|
|
16
|
+
forbidField,
|
|
16
17
|
} from "../engine/api";
|
|
17
18
|
import { canonicalPackageJsonOrder } from "./shared/key-order";
|
|
18
19
|
import { INITIAL_MODULE_VERSION } from "./shared/initial-version";
|
|
20
|
+
import { NODE_RUNTIME, PACKAGE_MANAGER } from "./shared/toolchain";
|
|
19
21
|
|
|
20
22
|
// `variant=all` builds every variant the software declares — docker-vs-binary is not a per-script
|
|
21
23
|
// choice. `no-software` builds placeholder software for validators.
|
|
@@ -71,12 +73,25 @@ export function rootPackageJsonInitial(): Record<string, unknown> {
|
|
|
71
73
|
shx: "catalog:",
|
|
72
74
|
turbo: "catalog:",
|
|
73
75
|
},
|
|
74
|
-
packageManager: "pnpm@9.12.0",
|
|
75
76
|
};
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export function rootPackageJsonRules(): void {
|
|
79
|
-
ensureField("packageManager",
|
|
80
|
+
ensureField("packageManager", PACKAGE_MANAGER);
|
|
81
|
+
ensureField("devEngines.runtime", NODE_RUNTIME);
|
|
82
|
+
removeField(
|
|
83
|
+
"pnpm",
|
|
84
|
+
(settings) =>
|
|
85
|
+
settings === null ||
|
|
86
|
+
(typeof settings === "object" &&
|
|
87
|
+
Object.values(settings).every(
|
|
88
|
+
(value) => typeof value === "object" && value !== null && Object.keys(value).length === 0,
|
|
89
|
+
)),
|
|
90
|
+
);
|
|
91
|
+
forbidField(
|
|
92
|
+
"pnpm",
|
|
93
|
+
'pnpm 11+ ignores the "pnpm" field in package.json. Move its settings to pnpm-workspace.yaml: overrides as is, onlyBuiltDependencies as allowBuilds true, neverBuiltDependencies as allowBuilds false.',
|
|
94
|
+
);
|
|
80
95
|
|
|
81
96
|
// Root is never published — it carries no `name`; delete any stray one.
|
|
82
97
|
removeField("name");
|