@platforma-sdk/block-tools 2.12.12 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -20,5 +20,5 @@ print("Hello from Python, " + sys.argv[1] + "!")
20
20
  `,vr=`# No dependencies specified for this script
21
21
  `;function yr(){_(`software`,()=>{C(`src/main.py`,je(_r)),C(`src/requirements.txt`,je(vr)),x(`package.json`,D(e=>hr(e)),()=>{gr()})})}function br(){_(`model`,()=>{w(`eslint.config.mjs`),w(`vite.config.mts`)}),_(`ui`,()=>{w(`eslint.config.mjs`),w(`vite.config.ts`),w(`tsconfig.app.json`),w(`tsconfig.node.json`)}),_(`test`,()=>{w(`eslint.config.mjs`)}),_(`root`,()=>{w(`.prettierrc`),x(`package.json`,D(()=>cn()),()=>{L(`pretty`),V(`@platforma-sdk/blocks-deps-updater`)})})}function xr(){ke(()=>{_(`root`,()=>{v(({ctx:e})=>!e.isSdkInternal,()=>{x(`pnpm-workspace.yaml`,D(e=>Pn(e)),e=>{for(let e of Z)_t(e);for(let e of jn)vt(e.entry,{of:e.of,ofVersion:e.ofVersion});for(let[e,t]of Object.entries(An))gt(e,t);e.modules.some(e=>e.scope===`software`)&&gt(Mn,Nn)})})})})}var Sr=Se(()=>{Rn(),Bn(),$n(),nr(),ar(),cr(),dr(),yr(),br(),xr()});async function Cr(){return Tn(Z.filter(wn))}async function wr(e){let t=n.default.resolve(e.blockPath),r=e.mode===`check`,i=new se(t),a=new ce(e.templatesRoot),o=Vt(Sr,i,an({fs:i,isSdkInternal:e.isSdkInternal,updateDepsOnly:e.updateDepsOnly,dryRun:r}),{templates:a,registryLookup:e.updateDepsOnly?await Cr():void 0,derivedPinLookup:e.updateDepsOnly?await Dn(jn):void 0,rediscover:()=>an({fs:i,isSdkInternal:e.isSdkInternal,updateDepsOnly:!1,dryRun:!0})});return{blockPath:e.blockPath,changes:o.changes}}function Tr(e,t){if(t.length===0)return` ${e}: up to date (0 changes)`;let n=t.map(e=>` ${e.action.padEnd(6)} ${e.primitive.padEnd(8)} ${e.path} [${e.scope}]`);return` ${e}: ${t.length} change(s)\n${n.join(`
22
22
  `)}`}async function Er(e){for(let t of e.paths){let n=await wr({blockPath:t,isSdkInternal:e.isSdkInternal,updateDepsOnly:e.updateDepsOnly,mode:`refresh`,templatesRoot:e.templatesRoot,log:t=>e.logger.info(t)});e.logger.info(Tr(t,n.changes))}}function Dr(e){let r=new t.Command(`refresh`).description(`Bring block(s) up to date with the canonical structure. Applies rules, writes files, bumps .structure version. Default mode is offline; --update-deps-only fires only catalog-bump rules (network).`);return r.argument(`[paths...]`,`block path(s); defaults to the current directory`),r.option(`--sdk-internal`,`block(s) live inside the SDK monorepo; skip root-scope rules`),r.option(`--update-deps-only`,"fire ONLY catalog-bump rules (npm network). Follow with `pnpm install` then a plain refresh."),r.action(async(t,r)=>{let i=t.length>0?t:[`.`],o=n.default.join(e,`src`,`structure`,`templates`);await Er({paths:i,isSdkInternal:!!r.sdkInternal,updateDepsOnly:!!r.updateDepsOnly,templatesRoot:o,logger:new a.ConsoleLoggerAdapter})}),r}function Or(e){let r=new t.Command(`update-deps`).description("[DEPRECATED] Use `block-tools structure refresh --update-deps-only`. This alias delegates to it.");return r.action(async()=>{let t=new a.ConsoleLoggerAdapter;t.warn("`block-tools update-deps` is deprecated and will be removed in a future release. Use `block-tools structure refresh --update-deps-only` instead. Delegating now."),await Er({paths:[`.`],isSdkInternal:!1,updateDepsOnly:!0,templatesRoot:n.default.join(e,`src`,`structure`,`templates`),logger:t})}),r}function kr(){let n=new t.Command(`list-overview-snapshots`).description(`List all available global overview snapshots in the registry`);return n.addOption(new t.Option(`-r, --registry <address>`,`full address of the registry`).env(`PL_REGISTRY`).makeOptionMandatory()),n.option(`--json`,`output in JSON format`,!1),n.action(async t=>{let n=new a.ConsoleLoggerAdapter,r=await new e.b(e._(t.registry),n).listGlobalOverviewSnapshots();if(t.json)n.info(JSON.stringify(r,null,2));else if(r.length===0)n.info(`No snapshots found.`);else{n.info(`Found ${r.length} snapshot(s):\n`);for(let e of r)n.info(` ${e.timestamp}`),n.info(` Path: ${e.path}`),n.info(``)}}),n}function Ar(){let n=new t.Command(`restore-overview-from-snapshot`).description(`Restore global overview from a snapshot`);return n.addOption(new t.Option(`-r, --registry <address>`,`full address of the registry`).env(`PL_REGISTRY`).makeOptionMandatory()),n.requiredOption(`-s, --snapshot <timestamp>`,`snapshot timestamp ID to restore from`),n.option(`--skip-confirmation`,`skip confirmation prompt (use with caution)`,!1),n.action(async t=>{let n=new a.ConsoleLoggerAdapter,r=new e.b(e._(t.registry),n),i=await r.listGlobalOverviewSnapshots();if(!i.find(e=>e.timestamp===t.snapshot))throw Error(`Snapshot '${t.snapshot}' not found. Available snapshots:\n${i.map(e=>` - ${e.timestamp}`).join(`
23
- `)||` (none)`}`);if(!t.skipConfirmation){let e=(await import(`node:readline`)).createInterface({input:process.stdin,output:process.stdout}),r=await new Promise(n=>{e.question(`⚠️ This will overwrite the current global overview with snapshot '${t.snapshot}'.\nAre you sure you want to continue? (y/N): `,n)});if(e.close(),r.toLowerCase()!==`y`&&r.toLowerCase()!==`yes`){n.info(`Restore cancelled.`);return}}try{await r.restoreGlobalOverviewFromSnapshot(t.snapshot),n.info(`✅ Successfully restored global overview from snapshot '${t.snapshot}'`)}catch(e){throw Error(`Failed to restore from snapshot: ${String(e)}`)}}),n}function jr(e){let t=e.match(/(?<destName>[^/\\]+)=(?<src>.*)/);if(t){let{src:e,destName:n}=t.groups;return{src:e,destName:n}}else return{src:e,destName:n.default.basename(e)}}function Mr(e,n){return new t.Option(e,n).argParser((e,t)=>[...t??[],jr(e)]).default([])}var Nr=[`registry`,`organization`,`package`,`version`];function Pr(){let n=new t.Command(`upload-package-v1`).description(`Uploads V1 package and refreshes the registry`);return n.addOption(new t.Option(`-r, --registry <address|alias>`,`full address of the registry or alias from .pl.reg`).env(`PL_REGISTRY`)),n.addOption(new t.Option(`-o, --organization <organization>`,`target organisation`).env(`PL_PACKAGE_ORGANIZATION`)),n.addOption(new t.Option(`-p, --package <package>`,`target package`).env(`PL_PACKAGE_NAME`)),n.addOption(new t.Option(`-v, --version <version>`,`target version`).env(`PL_PACKAGE_VERSION`)),n.option(`-m, --meta <path>`,`json file containing meta information to associate with tha package`),n.addOption(Mr(`-f, --file <file>`,`package files`)),n.addOption(new t.Option(`--refresh`,`refresh repository after adding the package`).default(!0).env(`PL_REGISTRY_REFRESH`)),n.option(`--no-refresh`,`do not refresh repository after adding the package`),n.action(async t=>{let n=new a.ConsoleLoggerAdapter,i=e.p.parse({});for(let e of Nr)t[e]&&(i[e]=t[e]);t.meta&&(t.meta.endsWith(`.json`)?i.meta=JSON.parse(await r.default.promises.readFile(t.meta,{encoding:`utf-8`})):t.meta.endsWith(`.yaml`)&&(i.meta=o.default.parse(await r.default.promises.readFile(t.meta,{encoding:`utf-8`}))));for(let e of t.file)i.files[e.destName]=e.src;let s=await e.n(i);n.info(o.default.stringify(s.conf));let c=s.createRegistry(n),l=s.fullPackageName,u=c.constructNewPackage(l);for(let[e,t]of Object.entries(s.conf.files)){n.info(`Uploading ${t} -> ${e} ...`);let i=await r.default.promises.readFile(t);await u.addFile(e,i)}n.info(`Uploading meta information...`),await u.writeMeta(s.conf.meta),await u.finish(),t.refresh&&await c.updateIfNeeded()}),n}function Fr(e){let r=new t.Command(`check`).description(`Check block(s) against the canonical structure (read-only). Exits non-zero if any diff would land — used as the CI gate.`);return r.argument(`[paths...]`,`block path(s); defaults to the current directory`),r.option(`--sdk-internal`,`block(s) live inside the SDK monorepo; skip root-scope rules`),r.action(async(t,r)=>{let i=new a.ConsoleLoggerAdapter,o=t.length>0?t:[`.`],s=n.default.join(e,`src`,`structure`,`templates`),c=!1;for(let e of o){let t=await wr({blockPath:e,isSdkInternal:!!r.sdkInternal,updateDepsOnly:!1,mode:`check`,templatesRoot:s,log:e=>i.info(e)});i.info(Tr(e,t.changes)),t.changes.length>0&&(c=!0)}if(c)throw Error("Structure check failed: one or more blocks are out of date. Run `structure refresh`.")}),r}var $=[`python`],Ir=class extends Error{constructor(e){super(`Missing required flag --${e} in --non-interactive mode. Supply every BlockVars flag, or drop --non-interactive to be prompted.`),this.name=`InitFlagError`}};async function Lr(e,t,n,r){if(e!==void 0&&e!==``)return e;if(n)throw new Ir(t);return r()}async function Rr(e){let t=await Lr(e.npmOrg,`npm-org`,e.nonInteractive,()=>(0,l.input)({message:`npm org (e.g. @platforma-open):`,default:`@platforma-open`})),n=await Lr(e.orgScope,`org-scope`,e.nonInteractive,()=>(0,l.input)({message:`org scope (e.g. my-org):`})),r=await Lr(e.shortName,`short-name`,e.nonInteractive,()=>(0,l.input)({message:`block short name (e.g. mixcr-clonotyping):`})),i;i=e.withSoftware===void 0?e.nonInteractive?!1:await(0,l.confirm)({message:`Include a software module?`,default:!1}):e.withSoftware;let a;if(i){if(a=await Lr(e.platform,`platform`,e.nonInteractive,()=>(0,l.select)({message:`Software platform:`,choices:$.map(e=>({name:e,value:e}))})),!$.includes(a))throw Error(`Unsupported --platform '${a}'. Only ${$.join(`, `)} ${$.length===1?`is`:`are`} supported at v1.`)}else if(e.platform)throw Error(`--platform was given but software is disabled (--no-software).`);return{facadeName:`${t}/${n}.${r}`,baseName:`${n}.${r}`,npmOrg:t,orgScope:n,shortName:r,softwarePlatform:a}}async function zr(e){let t=e.vars,n=Xt(t),r=new se(e.blockPath),i=new ce(e.templatesRoot),a=Zt({blockVars:t,modules:n,isSdkInternal:!1,version:2,dryRun:!1}),o=Z.filter(wn),s,c;try{s=await Tn(o),c=await Dn(jn)}catch(e){throw Error(`init requires network access to resolve SDK catalog versions from npm, but the registry lookup failed: ${e instanceof Error?e.message:String(e)}`)}return Vt(Sr,r,a,{templates:i,initMode:!0,registryLookup:s,derivedPinLookup:c}),e.log(`Initialised block '${t.facadeName}'${t.softwarePlatform?` (software: ${t.softwarePlatform})`:` (no software)`} at ${e.blockPath}`),t}function Br(e){let r=new t.Command(`init`).description(`Scaffold a fresh Platforma block from the canonical structure. Missing flags are prompted unless --non-interactive.`);return r.argument(`[path]`,`target directory (default: <short-name> under the current directory)`),r.option(`--npm-org <org>`,`npm org, e.g. @platforma-open`),r.option(`--org-scope <scope>`,`org scope, e.g. my-org`),r.option(`--short-name <name>`,`block short name, e.g. mixcr-clonotyping`),r.option(`--with-software`,`include a software module`),r.option(`--no-software`,`omit the software module`),r.addOption(new t.Option(`--platform <platform>`,`software platform (single-valued)`).choices([...$])),r.option(`--non-interactive`,`error on any missing flag instead of prompting`),r.action(async(t,r)=>{let i=new a.ConsoleLoggerAdapter,o=r.withSoftware===!0,s=r.software===!1;if(o&&s)throw Error(`--with-software and --no-software are mutually exclusive.`);let c=o?!0:s?!1:void 0,l=await Rr({npmOrg:r.npmOrg,orgScope:r.orgScope,shortName:r.shortName,withSoftware:c,platform:r.platform,nonInteractive:r.nonInteractive});await zr({vars:l,blockPath:t?n.default.resolve(t):n.default.resolve(process.cwd(),l.shortName),templatesRoot:n.default.join(e,`src`,`structure`,`templates`),log:e=>i.info(e)})}),r}var Vr=[`dev`,`release`],Hr=[`docker`,`binary`,`all`,`none`],Ur=[`local`,`remote`];function Wr(e){if(e.usePublished){if(e.variant===`docker`||e.variant===`all`)throw u.util.CLIError(`--use-published is binary-only and cannot be combined with --variant ${e.variant}`);return{kind:`binary-existing`}}return e.variant===`none`?{kind:`no-software`}:e.location===void 0?{kind:`bare`}:{kind:`target`,channel:e.channel??`release`,variant:e.variant??`all`,location:e.location}}var Gr=`public.ecr.aws`,Kr=`us-east-1`;function qr(e){if(process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)return;let t=process.env.PL_AWS_PROFILE??u.defaults.AWS_DEV_PROFILE;process.env.AWS_PROFILE=t,e?.debug(`Using AWS profile '${t}' for dev push credentials`)}function Jr(e){return new URL(`https://${e}`).hostname}function Yr(){return` aws sso login --profile ${process.env.AWS_PROFILE??process.env.PL_AWS_PROFILE??u.defaults.AWS_DEV_PROFILE}`}async function Xr(e,t){let n=Jr(e);if(n!==Gr)throw u.util.CLIError(`automatic docker login is only supported for '${Gr}', not '${n}'.\nLog in manually, or drop the ecr:// scheme from the push target to opt out.`);t?.info(`Logging in to ECR registry '${n}'...`);let r,i;try{let e=(await new f.ECRPUBLICClient({region:Kr}).send(new f.GetAuthorizationTokenCommand({}))).authorizationData?.authorizationToken;if(!e)throw Error(`empty authorization token`);let t=Buffer.from(e,`base64`).toString(`utf8`),n=t.indexOf(`:`);if(n<0)throw Error(`malformed authorization token (no ':' separator)`);r=t.slice(0,n),i=t.slice(n+1)}catch(e){throw u.util.CLIError(`failed to obtain an ECR login token for '${n}': ${e instanceof Error?e.message:String(e)}\nYour AWS/SSO session is likely expired or absent — log in and retry:\n`+Yr())}let a=(0,d.spawnSync)(`docker`,[`login`,`--username`,r,`--password-stdin`,n],{input:i,stdio:[`pipe`,`inherit`,`inherit`],env:{...process.env,HOME:process.env.HOME||c.homedir()}});if(a.error||a.status!==0)throw u.util.CLIError(`'docker login ${n}' failed`)}async function Zr(e){let{core:t,scenario:n,options:r={},logger:i}=e,a=r.ids;t.buildMode=Qr(n);let o=()=>t.buildSoftwareArchives({ids:a,forceBuild:!!r.force,contentRoot:r.contentRoot,skipIfEmpty:!a,condaBuild:r.condaBuild});switch(n.kind){case`binary-existing`:t.writePublishedArtifactInfo({ids:a});break;case`no-software`:break;case`bare`:r.buildDocker&&t.buildDockerImages({ids:a,registry:r.dockerRegistry,strictPlatformMatching:u.envs.isCI()}),await o(),r.pushDocker&&t.publishDockerImages({ids:a,pushTo:r.dockerPushTo,strictPlatformMatching:u.envs.isCI()});break;case`target`:{let{channel:e,variant:s,location:c}=n,l=s!==`binary`,d=s!==`docker`,f=c===`remote`,p=ti(e,r);l&&t.buildDockerImages({ids:a,registry:p.pull,strictPlatformMatching:u.envs.isCI()}),d&&await o(),f&&e===`dev`&&(l||d)&&qr(i),l&&f&&(p.autoLogin&&p.push&&await Xr(p.push,i),t.publishDockerImages({ids:a,pushTo:p.push,strictPlatformMatching:u.envs.isCI()})),d&&f&&await t.publishPackages({ids:a,storageURL:r.storageUrl});break}default:u.util.assertNever(n)}t.buildSwJsonFiles({packageIds:a,noSoftware:n.kind===`no-software`})}function Qr(e){return e.kind!==`target`||e.channel===`release`?`release`:e.variant!==`docker`&&e.location===`remote`?`dev-remote`:`dev-local`}function $r(e){if(!e.includes(`://`))return e;let t=new URL(e);return t.host+t.pathname}function ei(e){return{registry:$r(e),autoLogin:e.startsWith(`ecr://`)}}function ti(e,t){let n=e===`dev`,r=process.env[n?u.envs.PL_DEV_DOCKER_PUSH_URL:u.envs.PL_RELEASE_DOCKER_PUSH_URL],i=process.env[n?u.envs.PL_DEV_DOCKER_PULL_URL:u.envs.PL_RELEASE_DOCKER_PULL_URL],a=t.dockerPushTo??r??(n?u.defaults.DEV_DOCKER_PUSH_TARGET:void 0),o=a?ei(a):{registry:void 0,autoLogin:!1},s=t.dockerRegistry??i??(n?a:u.defaults.DOCKER_REGISTRY);return{pull:s?$r(s):void 0,push:o.registry,autoLogin:o.autoLogin}}var ni=`PL_BUILD_CHANNEL`,ri=`PL_BUILD_VARIANT`,ii=`PL_BUILD_LOCATION`,ai=`PL_BUILD_USE_PUBLISHED`;u.envs.PL_DOCKER_REGISTRY_PUSH_TO,u.envs.PL_DEV_DOCKER_PUSH_URL,u.envs.PL_DEV_DOCKER_PULL_URL,u.envs.PL_DEV_BINARY_UPLOAD_URL,u.envs.PL_RELEASE_DOCKER_PUSH_URL,u.envs.PL_RELEASE_DOCKER_PULL_URL,u.envs.PL_RELEASE_BINARY_UPLOAD_URL;function oi(){let e=new t.Command(`build`).description(`Build a software module for a target and write its .sw.json descriptor (build + push in one pass)`);return e.addOption(new t.Option(`--channel <channel>`,`registry channel to build for`).choices([...Vr]).env(ni)),e.addOption(new t.Option(`--variant <variant>`,`artifact kind to build (default: all declared)`).choices([...Hr]).env(ri)),e.addOption(new t.Option(`--location <location>`,`where the artifact lands (local = no push)`).choices([...Ur]).env(ii)),e.addOption(new t.Option(`--use-published`,`do not build or push; emit a descriptor pointing at the already-published release artifact`).env(ai)),e.addOption(new t.Option(`--log-level <level>`,`logging level`).choices([`error`,`warn`,`info`,`debug`]).default(`info`)),e.addOption(new t.Option(`--package-root <path>`,`path to directory with package.json file`)),e.addOption(new t.Option(`--force`,`force action, ignoring automatic safety checks`).default(!1)),e.addOption(new t.Option(`--version <value>`,`override package version (ignore package.json)`)),e.addOption(new t.Option(`--platform <os-arch>`,`{os}-{arch} pair; no effect on cross-platform packages`).choices([...u.util.AllPlatforms]).env(u.envs.PL_PKG_OS)),e.addOption(new t.Option(`--all-platforms`,`build for all supported platforms`).default(!1)),e.addOption(new t.Option(`--full-dir-hash`,`hash file contents (not metadata) for the dev content hash`).env(u.envs.PL_PKG_FULL_HASH).default(!1)),e.addOption(new t.Option(`--package-id <id...>`,`act only on selected packages`)),e.addOption(new t.Option(`--content-root <path>`,`override software content root`).env(u.envs.PL_PKG_CONTENT_ROOT)),e.addOption(new t.Option(`--storage-url <url>`,`override binary upload registry URL`).env(u.envs.PL_PKG_STORAGE_URL)),e.addOption(new t.Option(`--docker-registry <registry>`,`docker pull registry embedded in the descriptor`).env(u.envs.PL_DOCKER_REGISTRY)),e.addOption(new t.Option(`--docker-push-to <registry>`,`alternative registry for docker push`).env(u.envs.PL_DOCKER_REGISTRY_PUSH_TO)),e.addOption(new t.Option(`--docker-build`,`build docker images`).env(u.envs.PL_DOCKER_BUILD).default(!1)),e.addOption(new t.Option(`--docker-no-build`,`do not build docker images`).env(u.envs.PL_DOCKER_NO_BUILD).default(!1)),e.addOption(new t.Option(`--docker-autopush`,`push docker images after build`).env(u.envs.PL_DOCKER_AUTOPUSH).default(!1)),e.addOption(new t.Option(`--docker-no-autopush`,`do not push docker images`).env(u.envs.PL_DOCKER_NO_AUTOPUSH).default(!1)),e.addOption(new t.Option(`--conda-build`,`build conda environment before packing`).env(u.envs.PL_CONDA_BUILD).default(!1)),e.addOption(new t.Option(`--conda-no-build`,`do not build conda environment`).env(u.envs.PL_CONDA_NO_BUILD).default(!1)),e.action(async e=>{let t=u.util.createLogger(e.logLevel);try{let n=Wr({channel:e.channel,variant:e.variant,location:e.location,usePublished:!!e.usePublished}),r=(0,u.createBuilder)(t,{packageRoot:e.packageRoot});r.version=e.version,r.targetPlatform=e.platform,r.allPlatforms=!!e.allPlatforms,r.fullDirHash=!!e.fullDirHash;let i=u.util.shouldDoAction({default:u.envs.isCI(),enable:e.dockerBuild,disable:e.dockerNoBuild}),a=i&&u.util.shouldDoAction({default:u.envs.isCI()&&!r.isPrivate,enable:e.dockerAutopush,disable:e.dockerNoAutopush});await Zr({core:r,scenario:n,logger:t,options:{ids:e.packageId,force:e.force,contentRoot:e.contentRoot,storageUrl:e.storageUrl,dockerRegistry:e.dockerRegistry,dockerPushTo:e.dockerPushTo,buildDocker:i,pushDocker:a,condaBuild:u.util.shouldDoAction({default:!0,enable:e.condaBuild,disable:e.condaNoBuild})}})}catch(e){throw t.debug(e),e instanceof Error&&t.debug(e.stack),e}}),e}function si(){let e=new t.Command(`software`).description(`Build and publish a block's software modules`);return e.addCommand(oi()),e}function ci(e=process.cwd()){let n=new t.Command;n.name(`block-tools`).description(`Utility to manipulate Platforma Blocks and Block Registry`),n.addCommand(p()),n.addCommand(te()),n.addCommand(ne()),n.addCommand(ie()),n.addCommand(ae()),n.addCommand(oe()),n.addCommand(Or(e)),n.addCommand(kr()),n.addCommand(Ar()),n.addCommand(Pr()),n.addCommand(si());let r=new t.Command(`structure`).description(`Manage block scaffolding against the canonical structure (check / init / refresh)`);return r.addCommand(Fr(e)),r.addCommand(Br(e)),r.addCommand(Dr(e)),n.addCommand(r),n}async function li(e,t){await ci(t).parseAsync(e)}exports.buildProgram=ci,exports.run=li;
23
+ `)||` (none)`}`);if(!t.skipConfirmation){let e=(await import(`node:readline`)).createInterface({input:process.stdin,output:process.stdout}),r=await new Promise(n=>{e.question(`⚠️ This will overwrite the current global overview with snapshot '${t.snapshot}'.\nAre you sure you want to continue? (y/N): `,n)});if(e.close(),r.toLowerCase()!==`y`&&r.toLowerCase()!==`yes`){n.info(`Restore cancelled.`);return}}try{await r.restoreGlobalOverviewFromSnapshot(t.snapshot),n.info(`✅ Successfully restored global overview from snapshot '${t.snapshot}'`)}catch(e){throw Error(`Failed to restore from snapshot: ${String(e)}`)}}),n}function jr(e){let t=e.match(/(?<destName>[^/\\]+)=(?<src>.*)/);if(t){let{src:e,destName:n}=t.groups;return{src:e,destName:n}}else return{src:e,destName:n.default.basename(e)}}function Mr(e,n){return new t.Option(e,n).argParser((e,t)=>[...t??[],jr(e)]).default([])}var Nr=[`registry`,`organization`,`package`,`version`];function Pr(){let n=new t.Command(`upload-package-v1`).description(`Uploads V1 package and refreshes the registry`);return n.addOption(new t.Option(`-r, --registry <address|alias>`,`full address of the registry or alias from .pl.reg`).env(`PL_REGISTRY`)),n.addOption(new t.Option(`-o, --organization <organization>`,`target organisation`).env(`PL_PACKAGE_ORGANIZATION`)),n.addOption(new t.Option(`-p, --package <package>`,`target package`).env(`PL_PACKAGE_NAME`)),n.addOption(new t.Option(`-v, --version <version>`,`target version`).env(`PL_PACKAGE_VERSION`)),n.option(`-m, --meta <path>`,`json file containing meta information to associate with tha package`),n.addOption(Mr(`-f, --file <file>`,`package files`)),n.addOption(new t.Option(`--refresh`,`refresh repository after adding the package`).default(!0).env(`PL_REGISTRY_REFRESH`)),n.option(`--no-refresh`,`do not refresh repository after adding the package`),n.action(async t=>{let n=new a.ConsoleLoggerAdapter,i=e.p.parse({});for(let e of Nr)t[e]&&(i[e]=t[e]);t.meta&&(t.meta.endsWith(`.json`)?i.meta=JSON.parse(await r.default.promises.readFile(t.meta,{encoding:`utf-8`})):t.meta.endsWith(`.yaml`)&&(i.meta=o.default.parse(await r.default.promises.readFile(t.meta,{encoding:`utf-8`}))));for(let e of t.file)i.files[e.destName]=e.src;let s=await e.n(i);n.info(o.default.stringify(s.conf));let c=s.createRegistry(n),l=s.fullPackageName,u=c.constructNewPackage(l);for(let[e,t]of Object.entries(s.conf.files)){n.info(`Uploading ${t} -> ${e} ...`);let i=await r.default.promises.readFile(t);await u.addFile(e,i)}n.info(`Uploading meta information...`),await u.writeMeta(s.conf.meta),await u.finish(),t.refresh&&await c.updateIfNeeded()}),n}function Fr(e){let r=new t.Command(`check`).description(`Check block(s) against the canonical structure (read-only). Exits non-zero if any diff would land — used as the CI gate.`);return r.argument(`[paths...]`,`block path(s); defaults to the current directory`),r.option(`--sdk-internal`,`block(s) live inside the SDK monorepo; skip root-scope rules`),r.action(async(t,r)=>{let i=new a.ConsoleLoggerAdapter,o=t.length>0?t:[`.`],s=n.default.join(e,`src`,`structure`,`templates`),c=!1;for(let e of o){let t=await wr({blockPath:e,isSdkInternal:!!r.sdkInternal,updateDepsOnly:!1,mode:`check`,templatesRoot:s,log:e=>i.info(e)});i.info(Tr(e,t.changes)),t.changes.length>0&&(c=!0)}if(c)throw Error("Structure check failed: one or more blocks are out of date. Run `structure refresh`.")}),r}var $=[`python`],Ir=class extends Error{constructor(e){super(`Missing required flag --${e} in --non-interactive mode. Supply every BlockVars flag, or drop --non-interactive to be prompted.`),this.name=`InitFlagError`}};async function Lr(e,t,n,r){if(e!==void 0&&e!==``)return e;if(n)throw new Ir(t);return r()}async function Rr(e){let t=await Lr(e.npmOrg,`npm-org`,e.nonInteractive,()=>(0,l.input)({message:`npm org (e.g. @platforma-open):`,default:`@platforma-open`})),n=await Lr(e.orgScope,`org-scope`,e.nonInteractive,()=>(0,l.input)({message:`org scope (e.g. my-org):`})),r=await Lr(e.shortName,`short-name`,e.nonInteractive,()=>(0,l.input)({message:`block short name (e.g. mixcr-clonotyping):`})),i;i=e.withSoftware===void 0?e.nonInteractive?!1:await(0,l.confirm)({message:`Include a software module?`,default:!1}):e.withSoftware;let a;if(i){if(a=await Lr(e.platform,`platform`,e.nonInteractive,()=>(0,l.select)({message:`Software platform:`,choices:$.map(e=>({name:e,value:e}))})),!$.includes(a))throw Error(`Unsupported --platform '${a}'. Only ${$.join(`, `)} ${$.length===1?`is`:`are`} supported at v1.`)}else if(e.platform)throw Error(`--platform was given but software is disabled (--no-software).`);return{facadeName:`${t}/${n}.${r}`,baseName:`${n}.${r}`,npmOrg:t,orgScope:n,shortName:r,softwarePlatform:a}}async function zr(e){let t=e.vars,n=Xt(t),r=new se(e.blockPath),i=new ce(e.templatesRoot),a=Zt({blockVars:t,modules:n,isSdkInternal:!1,version:2,dryRun:!1}),o=Z.filter(wn),s,c;try{s=await Tn(o),c=await Dn(jn)}catch(e){throw Error(`init requires network access to resolve SDK catalog versions from npm, but the registry lookup failed: ${e instanceof Error?e.message:String(e)}`)}return Vt(Sr,r,a,{templates:i,initMode:!0,registryLookup:s,derivedPinLookup:c}),e.log(`Initialised block '${t.facadeName}'${t.softwarePlatform?` (software: ${t.softwarePlatform})`:` (no software)`} at ${e.blockPath}`),t}function Br(e){let r=new t.Command(`init`).description(`Scaffold a fresh Platforma block from the canonical structure. Missing flags are prompted unless --non-interactive.`);return r.argument(`[path]`,`target directory (default: <short-name> under the current directory)`),r.option(`--npm-org <org>`,`npm org, e.g. @platforma-open`),r.option(`--org-scope <scope>`,`org scope, e.g. my-org`),r.option(`--short-name <name>`,`block short name, e.g. mixcr-clonotyping`),r.option(`--with-software`,`include a software module`),r.option(`--no-software`,`omit the software module`),r.addOption(new t.Option(`--platform <platform>`,`software platform (single-valued)`).choices([...$])),r.option(`--non-interactive`,`error on any missing flag instead of prompting`),r.action(async(t,r)=>{let i=new a.ConsoleLoggerAdapter,o=r.withSoftware===!0,s=r.software===!1;if(o&&s)throw Error(`--with-software and --no-software are mutually exclusive.`);let c=o?!0:s?!1:void 0,l=await Rr({npmOrg:r.npmOrg,orgScope:r.orgScope,shortName:r.shortName,withSoftware:c,platform:r.platform,nonInteractive:r.nonInteractive});await zr({vars:l,blockPath:t?n.default.resolve(t):n.default.resolve(process.cwd(),l.shortName),templatesRoot:n.default.join(e,`src`,`structure`,`templates`),log:e=>i.info(e)})}),r}var Vr=[`dev`,`release`],Hr=[`docker`,`binary`,`all`,`none`],Ur=[`local`,`remote`];function Wr(e){if(e.usePublished){if(e.variant===`docker`||e.variant===`all`)throw u.util.CLIError(`--use-published is binary-only and cannot be combined with --variant ${e.variant}`);return{kind:`binary-existing`}}return e.variant===`none`?{kind:`no-software`}:e.location===void 0?{kind:`bare`}:{kind:`target`,channel:e.channel??`release`,variant:e.variant??`all`,location:e.location}}var Gr=`public.ecr.aws`,Kr=`us-east-1`;function qr(e){if(process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)return;let t=process.env.PL_AWS_PROFILE??u.defaults.AWS_DEV_PROFILE;process.env.AWS_PROFILE=t,e?.debug(`Using AWS profile '${t}' for dev push credentials`)}function Jr(e){return new URL(`https://${e}`).hostname}function Yr(){return` aws sso login --profile ${process.env.AWS_PROFILE??process.env.PL_AWS_PROFILE??u.defaults.AWS_DEV_PROFILE}`}async function Xr(e,t){let n=Jr(e);if(n!==Gr)throw u.util.CLIError(`automatic docker login is only supported for '${Gr}', not '${n}'.\nLog in manually, or drop the ecr:// scheme from the push target to opt out.`);t?.info(`Logging in to ECR registry '${n}'...`);let r,i;try{let e=(await new f.ECRPUBLICClient({region:Kr}).send(new f.GetAuthorizationTokenCommand({}))).authorizationData?.authorizationToken;if(!e)throw Error(`empty authorization token`);let t=Buffer.from(e,`base64`).toString(`utf8`),n=t.indexOf(`:`);if(n<0)throw Error(`malformed authorization token (no ':' separator)`);r=t.slice(0,n),i=t.slice(n+1)}catch(e){throw u.util.CLIError(`failed to obtain an ECR login token for '${n}': ${e instanceof Error?e.message:String(e)}\nYour AWS/SSO session is likely expired or absent — log in and retry:\n`+Yr())}let a=(0,d.spawnSync)(`docker`,[`login`,`--username`,r,`--password-stdin`,n],{input:i,stdio:[`pipe`,`inherit`,`inherit`],env:{...process.env,HOME:process.env.HOME||c.homedir()}});if(a.error||a.status!==0)throw u.util.CLIError(`'docker login ${n}' failed`)}async function Zr(e){let{core:t,scenario:n,options:r={},logger:i}=e,a=r.ids;t.buildMode=Qr(n);let o=()=>t.buildSoftwareArchives({ids:a,forceBuild:!!r.force,contentRoot:r.contentRoot,skipIfEmpty:!a,condaBuild:r.condaBuild});switch(n.kind){case`binary-existing`:t.writePublishedArtifactInfo({ids:a});break;case`no-software`:break;case`bare`:r.buildDocker&&t.buildDockerImages({ids:a,registry:r.dockerRegistry,strictPlatformMatching:u.envs.isCI()}),await o(),r.pushDocker&&t.publishDockerImages({ids:a,pushTo:r.dockerPushTo,strictPlatformMatching:u.envs.isCI()});break;case`target`:{let{channel:e,variant:s,location:c}=n,l=s!==`binary`,d=s!==`docker`,f=c===`remote`,p=ti(e,r);l&&t.buildDockerImages({ids:a,registry:p.pull,strictPlatformMatching:u.envs.isCI()}),d&&await o(),f&&e===`dev`&&(l||d)&&qr(i),l&&f&&(p.autoLogin&&p.push&&await Xr(p.push,i),t.publishDockerImages({ids:a,pushTo:p.push,strictPlatformMatching:u.envs.isCI()})),d&&f&&await t.publishPackages({ids:a,storageURL:r.storageUrl});break}default:u.util.assertNever(n)}t.buildSwJsonFiles({packageIds:a,noSoftware:n.kind===`no-software`})}function Qr(e){return e.kind!==`target`||e.channel===`release`?`release`:e.variant!==`docker`&&e.location===`remote`?`dev-remote`:`dev-local`}function $r(e){if(!e.includes(`://`))return e;let t=new URL(e);return t.host+t.pathname}function ei(e){return{registry:$r(e),autoLogin:e.startsWith(`ecr://`)}}function ti(e,t){let n=e===`dev`,r=process.env[n?u.envs.PL_DEV_DOCKER_PUSH_URL:u.envs.PL_RELEASE_DOCKER_PUSH_URL],i=process.env[n?u.envs.PL_DEV_DOCKER_PULL_URL:u.envs.PL_RELEASE_DOCKER_PULL_URL],a=t.dockerPushTo??r??(n?u.defaults.DEV_DOCKER_PUSH_TARGET:void 0),o=a?ei(a):{registry:void 0,autoLogin:!1},s=t.dockerRegistry??i??(n?a:u.defaults.DOCKER_REGISTRY);return{pull:s?$r(s):void 0,push:o.registry,autoLogin:o.autoLogin}}var ni=`PL_BUILD_CHANNEL`,ri=`PL_BUILD_VARIANT`,ii=`PL_BUILD_LOCATION`,ai=`PL_BUILD_USE_PUBLISHED`;u.envs.PL_DOCKER_REGISTRY_PUSH_TO,u.envs.PL_DEV_DOCKER_PUSH_URL,u.envs.PL_DEV_DOCKER_PULL_URL,u.envs.PL_DEV_BINARY_UPLOAD_URL,u.envs.PL_RELEASE_DOCKER_PUSH_URL,u.envs.PL_RELEASE_DOCKER_PULL_URL,u.envs.PL_RELEASE_BINARY_UPLOAD_URL;function oi(){let e=new t.Command(`build`).description(`Build a software module for a target and write its .sw.json descriptor (build + push in one pass)`);return e.addOption(new t.Option(`--channel <channel>`,`registry channel to build for`).choices([...Vr]).env(ni)),e.addOption(new t.Option(`--variant <variant>`,`artifact kind to build (default: all declared)`).choices([...Hr]).env(ri)),e.addOption(new t.Option(`--location <location>`,`where the artifact lands (local = no push)`).choices([...Ur]).env(ii)),e.addOption(new t.Option(`--use-published`,`do not build or push; emit a descriptor pointing at the already-published release artifact`).env(ai)),e.addOption(new t.Option(`--log-level <level>`,`logging level`).choices([`error`,`warn`,`info`,`debug`]).default(`info`)),e.addOption(new t.Option(`--package-root <path>`,`path to directory with package.json file`)),e.addOption(new t.Option(`--force`,`force action, ignoring automatic safety checks`).default(!1)),e.addOption(new t.Option(`--version <value>`,`override package version (ignore package.json)`)),e.addOption(new t.Option(`--platform <os-arch>`,`{os}-{arch} pair; no effect on cross-platform packages`).choices([...u.util.AllPlatforms]).env(u.envs.PL_PKG_OS)),e.addOption(new t.Option(`--all-platforms`,`build for all supported platforms`).default(!1)),e.addOption(new t.Option(`--full-dir-hash`,`hash file contents (not metadata) for the dev content hash`).env(u.envs.PL_PKG_FULL_HASH).default(!1)),e.addOption(new t.Option(`--package-id <id...>`,`act only on selected packages`)),e.addOption(new t.Option(`--content-root <path>`,`override software content root`).env(u.envs.PL_PKG_CONTENT_ROOT)),e.addOption(new t.Option(`--storage-url <url>`,`override binary upload registry URL`).env(u.envs.PL_PKG_STORAGE_URL)),e.addOption(new t.Option(`--docker-registry <registry>`,`docker pull registry embedded in the descriptor`).env(u.envs.PL_DOCKER_REGISTRY)),e.addOption(new t.Option(`--docker-push-to <registry>`,`alternative registry for docker push`).env(u.envs.PL_DOCKER_REGISTRY_PUSH_TO)),e.addOption(new t.Option(`--docker-build`,`build docker images`).env(u.envs.PL_DOCKER_BUILD).default(!1)),e.addOption(new t.Option(`--docker-no-build`,`do not build docker images`).env(u.envs.PL_DOCKER_NO_BUILD).default(!1)),e.addOption(new t.Option(`--docker-autopush`,`push docker images after build`).env(u.envs.PL_DOCKER_AUTOPUSH).default(!1)),e.addOption(new t.Option(`--docker-no-autopush`,`do not push docker images`).env(u.envs.PL_DOCKER_NO_AUTOPUSH).default(!1)),e.addOption(new t.Option(`--conda-build`,`build conda environment before packing`).env(u.envs.PL_CONDA_BUILD).default(!1)),e.addOption(new t.Option(`--conda-no-build`,`do not build conda environment`).env(u.envs.PL_CONDA_NO_BUILD).default(!1)),e.action(async e=>{let t=u.util.createLogger(e.logLevel);try{let n=Wr({channel:e.channel,variant:e.variant,location:e.location,usePublished:!!e.usePublished}),r=(0,u.createBuilder)(t,{packageRoot:e.packageRoot});r.version=e.version,r.targetPlatform=e.platform,r.allPlatforms=!!e.allPlatforms,r.fullDirHash=!!e.fullDirHash;let i=u.util.shouldDoAction({default:u.envs.isCI(),enable:e.dockerBuild,disable:e.dockerNoBuild}),a=i&&u.util.shouldDoAction({default:u.envs.isCI()&&!r.isPrivate,enable:e.dockerAutopush,disable:e.dockerNoAutopush});n.kind===`bare`&&(0,u.assertDockerPushIntent)({buildDocker:i,pushDocker:a,pushDisabledExplicitly:!!e.dockerNoAutopush,dockerPackageCount:r.selectedDockerPackages(e.packageId).length}),await Zr({core:r,scenario:n,logger:t,options:{ids:e.packageId,force:e.force,contentRoot:e.contentRoot,storageUrl:e.storageUrl,dockerRegistry:e.dockerRegistry,dockerPushTo:e.dockerPushTo,buildDocker:i,pushDocker:a,condaBuild:u.util.shouldDoAction({default:!0,enable:e.condaBuild,disable:e.condaNoBuild})}})}catch(e){throw t.debug(e),e instanceof Error&&t.debug(e.stack),e}}),e}function si(){let e=new t.Command(`software`).description(`Build and publish a block's software modules`);return e.addCommand(oi()),e}function ci(e=process.cwd()){let n=new t.Command;n.name(`block-tools`).description(`Utility to manipulate Platforma Blocks and Block Registry`),n.addCommand(p()),n.addCommand(te()),n.addCommand(ne()),n.addCommand(ie()),n.addCommand(ae()),n.addCommand(oe()),n.addCommand(Or(e)),n.addCommand(kr()),n.addCommand(Ar()),n.addCommand(Pr()),n.addCommand(si());let r=new t.Command(`structure`).description(`Manage block scaffolding against the canonical structure (check / init / refresh)`);return r.addCommand(Fr(e)),r.addCommand(Br(e)),r.addCommand(Dr(e)),n.addCommand(r),n}async function li(e,t){await ci(t).parseAsync(e)}exports.buildProgram=ci,exports.run=li;
24
24
  //# sourceMappingURL=cli.js.map