@keystrokehq/cli 0.1.171 → 0.1.172

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/index.mjs CHANGED
@@ -40,7 +40,7 @@ process.emitWarning = ((warning, ...args) => {
40
40
  if ((type === "ExperimentalWarning" || /ExperimentalWarning/i.test(type)) && /SQLite/i.test(message)) return;
41
41
  return Reflect.apply(originalEmitWarning, process, [warning, ...args]);
42
42
  });
43
- const { runCli } = await import("./program-Ckl_ELbL.mjs");
43
+ const { runCli } = await import("./program-BfapxNQ4.mjs");
44
44
  await runCli(process.argv);
45
45
  //#endregion
46
46
  export {};
@@ -9061,15 +9061,18 @@ function registerBuildCommand(program) {
9061
9061
  //#endregion
9062
9062
  //#region src/deploy/assert-portable-dependencies.ts
9063
9063
  const LINK_SPEC = /^link:/i;
9064
+ const WORKSPACE_SPEC = /^workspace:/i;
9065
+ const FILE_SPEC = /^file:(?:\.\.?(?:\/|$)|\/|[A-Za-z]:\\|~)/i;
9064
9066
  const NONPORTABLE_SPEC = /^(?:link:|workspace:|file:(?:\.\.?(?:\/|$)|\/|[A-Za-z]:\\|~))/i;
9065
9067
  /**
9066
9068
  * Reject tracked dependency specs that cannot resolve in disposable/server
9067
9069
  * checkouts (absolute/local link:, external file:, unresolved workspace:).
9068
9070
  *
9069
9071
  * `KEYSTROKE_ALLOW_NONPORTABLE_DEPS=1` (local packs / soak deploys) permits
9070
- * `link:` only `file:` and unresolved `workspace:` still fail the gate.
9072
+ * `link:` only. Explicit options allow `workspace:`, `link:`, and local `file:`
9073
+ * specs when deploy deliberately builds from the current checkout.
9071
9074
  */
9072
- async function assertPortableProjectDependencies(projectRoot) {
9075
+ async function assertPortableProjectDependencies(projectRoot, options = {}) {
9073
9076
  const allowLinkDeps = process.env.KEYSTROKE_ALLOW_NONPORTABLE_DEPS === "1";
9074
9077
  const packageJsonPath = join(projectRoot, "package.json");
9075
9078
  let raw;
@@ -9099,7 +9102,7 @@ async function assertPortableProjectDependencies(projectRoot) {
9099
9102
  for (const [name, spec] of Object.entries(deps)) {
9100
9103
  if (typeof spec !== "string") continue;
9101
9104
  const trimmed = spec.trim();
9102
- if (allowLinkDeps && LINK_SPEC.test(trimmed)) continue;
9105
+ if ((allowLinkDeps || options.allowLink) && LINK_SPEC.test(trimmed) || options.allowWorkspace && WORKSPACE_SPEC.test(trimmed) || options.allowFile && FILE_SPEC.test(trimmed)) continue;
9103
9106
  if (NONPORTABLE_SPEC.test(trimmed)) offenders.push(`${name}@${spec}`);
9104
9107
  }
9105
9108
  }
@@ -11019,6 +11022,25 @@ async function buildExactCandidate(input) {
11019
11022
  const depsRoot = input.depsRoot ?? input.cwd;
11020
11023
  const cleanEnv = worktreeGitEnv();
11021
11024
  const skipVerify = input.skipVerify === true;
11025
+ if (input.buildFromWorkspace) {
11026
+ await rm(join(input.cwd, "dist"), {
11027
+ recursive: true,
11028
+ force: true
11029
+ });
11030
+ await buildInRoot({
11031
+ buildRoot: input.cwd,
11032
+ env: cleanEnv,
11033
+ skipVerify,
11034
+ manager: await detectPackageManager(input.cwd),
11035
+ needInstall: false
11036
+ });
11037
+ const modules = collectArtifactModules(input.cwd);
11038
+ return {
11039
+ modules,
11040
+ index: artifactIndexFromModules(modules),
11041
+ blobs: moduleBlobRefsFromModules(modules)
11042
+ };
11043
+ }
11022
11044
  if (input.allowInPlace) {
11023
11045
  const head = await runGit(["rev-parse", "HEAD"], {
11024
11046
  cwd: input.cwd,
@@ -11515,7 +11537,13 @@ async function pollProjectActive(client, projectId, options = {}) {
11515
11537
  async function runManagedDeploy(client, config, options) {
11516
11538
  const deployStarted = Date.now();
11517
11539
  const root = resolveProjectRoot(options.dir);
11518
- await assertPortableProjectDependencies(root);
11540
+ if (options.buildFromWorkspace && process.env["KEYSTROKE_DEPLOY_GIT_MODE"] === "checkout") throw new ExpectedCliError("--build-from-workspace is only available from a local monorepo checkout");
11541
+ await assertPortableProjectDependencies(root, {
11542
+ allowWorkspace: options.buildFromWorkspace === true,
11543
+ allowFile: options.buildFromWorkspace === true,
11544
+ allowLink: options.buildFromWorkspace === true
11545
+ });
11546
+ if (options.buildFromWorkspace) process.stderr.write("Warning: --build-from-workspace builds with local workspace dependencies that are not captured in Keystroke's managed source. Use published dependencies for reproducible deploys.\n");
11519
11547
  const verbose = options.verbose === true;
11520
11548
  const phase = (label, started) => {
11521
11549
  if (!verbose) return;
@@ -11563,6 +11591,10 @@ async function runManagedDeploy(client, config, options) {
11563
11591
  env: gitContext.env,
11564
11592
  ...filter ? { filter } : {}
11565
11593
  });
11594
+ if (options.buildFromWorkspace && plan.mode === "no_op") plan = {
11595
+ ...plan,
11596
+ mode: "full"
11597
+ };
11566
11598
  phase("plan", planStarted);
11567
11599
  writePlan(plan);
11568
11600
  if (plan.mode === "no_op") {
@@ -11707,7 +11739,8 @@ async function runManagedDeploy(client, config, options) {
11707
11739
  candidateSha: composed.candidateSha,
11708
11740
  depsRoot: root,
11709
11741
  skipVerify: verifyOutside,
11710
- allowInPlace: hostedCheckout && prepared.mode === "full"
11742
+ allowInPlace: hostedCheckout && prepared.mode === "full",
11743
+ buildFromWorkspace: options.buildFromWorkspace === true
11711
11744
  });
11712
11745
  buildMs = Date.now() - buildStarted;
11713
11746
  return result;
@@ -11744,7 +11777,8 @@ async function runManagedDeploy(client, config, options) {
11744
11777
  candidateSha: publishedCandidateSha,
11745
11778
  depsRoot: root,
11746
11779
  skipVerify: verifyOutside,
11747
- allowInPlace: false
11780
+ allowInPlace: false,
11781
+ buildFromWorkspace: options.buildFromWorkspace === true
11748
11782
  });
11749
11783
  buildMs += Date.now() - rebuildStarted;
11750
11784
  }
@@ -11817,6 +11851,10 @@ async function runManagedDeploy(client, config, options) {
11817
11851
  env: gitContext.env,
11818
11852
  ...filter ? { filter } : {}
11819
11853
  });
11854
+ if (options.buildFromWorkspace && plan.mode === "no_op") plan = {
11855
+ ...plan,
11856
+ mode: "full"
11857
+ };
11820
11858
  writePlan(plan);
11821
11859
  if (plan.mode === "no_op") {
11822
11860
  process.stdout.write("Nothing to deploy — draft matches main.\n");
@@ -11870,6 +11908,7 @@ async function resolveTrustedDeployGitEnv(input) {
11870
11908
  }
11871
11909
  async function runDeploy(options) {
11872
11910
  if (options.acceptImpact && !options.filter?.length) throw new ExpectedCliError("--accept-impact requires at least one --filter");
11911
+ if (options.buildFromWorkspace && options.filter?.length) throw new ExpectedCliError("--build-from-workspace cannot be combined with --filter");
11873
11912
  const root = resolveProjectRoot(options.dir);
11874
11913
  await ensureSdkCurrent(root);
11875
11914
  const config = createCliConfig();
@@ -11879,7 +11918,7 @@ async function runDeploy(options) {
11879
11918
  await runManagedDeploy(client, config, options);
11880
11919
  }
11881
11920
  function registerDeployCommand(program) {
11882
- program.command("deploy").description("Deploy the project via managed Git (draft sync, local analyze/build, cutover)").option("--dir <path>", "Project directory", process.cwd()).option("--filter <entry>", "Deploy only matching workflow/agent keys (repeatable; e.g. workflows/ping)", (value, previous) => [...previous, value], []).option("--accept-impact", "Accept the current filtered deploy impact (required for non-TTY expansion)").option("--verbose", "Show phase timings, pin SHAs, and deploy detail").action(async (options) => {
11921
+ program.command("deploy").description("Deploy the project via managed Git (draft sync, local analyze/build, cutover)").option("--dir <path>", "Project directory", process.cwd()).option("--filter <entry>", "Deploy only matching workflow/agent keys (repeatable; e.g. workflows/ping)", (value, previous) => [...previous, value], []).option("--accept-impact", "Accept the current filtered deploy impact (required for non-TTY expansion)").option("--build-from-workspace", "Build from the current monorepo checkout (full deploys only; non-reproducible)").option("--verbose", "Show phase timings, pin SHAs, and deploy detail").action(async (options) => {
11883
11922
  let config;
11884
11923
  try {
11885
11924
  config = createCliConfig();
@@ -11891,6 +11930,7 @@ function registerDeployCommand(program) {
11891
11930
  projectId,
11892
11931
  filter: options.filter.length > 0 ? options.filter : void 0,
11893
11932
  acceptImpact: options.acceptImpact === true,
11933
+ buildFromWorkspace: options.buildFromWorkspace === true,
11894
11934
  verbose: options.verbose === true
11895
11935
  });
11896
11936
  await trackCliEvent("cli:deploy", { projectId });
@@ -14341,4 +14381,4 @@ async function runCli(argv) {
14341
14381
  //#endregion
14342
14382
  export { runCli };
14343
14383
 
14344
- //# sourceMappingURL=program-Ckl_ELbL.mjs.map
14384
+ //# sourceMappingURL=program-BfapxNQ4.mjs.map