@pmate/cli 0.21.4 → 0.21.6

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.d.ts CHANGED
@@ -693,6 +693,72 @@ type ServiceCommandArgs = {
693
693
  history: boolean;
694
694
  search?: string;
695
695
  follow: boolean;
696
+ } | {
697
+ type: Command.Service;
698
+ action: "env-list";
699
+ appId: string;
700
+ scope?: string;
701
+ includeSecretMeta: boolean;
702
+ includeSecretValue: boolean;
703
+ baseUrl?: string;
704
+ json: boolean;
705
+ } | {
706
+ type: Command.Service;
707
+ action: "env-get";
708
+ appId: string;
709
+ key: string;
710
+ scope: string;
711
+ includeSecretValue: boolean;
712
+ baseUrl?: string;
713
+ json: boolean;
714
+ } | {
715
+ type: Command.Service;
716
+ action: "env-set";
717
+ appId: string;
718
+ key: string;
719
+ value?: string;
720
+ scope: string;
721
+ secret: boolean;
722
+ prompt: boolean;
723
+ baseUrl?: string;
724
+ json: boolean;
725
+ } | {
726
+ type: Command.Service;
727
+ action: "env-unset";
728
+ appId: string;
729
+ key: string;
730
+ scope: string;
731
+ baseUrl?: string;
732
+ json: boolean;
733
+ } | {
734
+ type: Command.Service;
735
+ action: "env-resolve";
736
+ appId: string;
737
+ stage: "dev" | "preview" | "prod";
738
+ branch?: string;
739
+ includeSecretValue: boolean;
740
+ baseUrl?: string;
741
+ json: boolean;
742
+ } | {
743
+ type: Command.Service;
744
+ action: "env-pull";
745
+ appId: string;
746
+ stage: "dev" | "preview" | "prod";
747
+ branch?: string;
748
+ output: string;
749
+ baseUrl?: string;
750
+ json: boolean;
751
+ } | {
752
+ type: Command.Service;
753
+ action: "env-copy-from";
754
+ targetAppId: string;
755
+ sourceAppId: string;
756
+ scope?: string;
757
+ includeSecret: boolean;
758
+ overwrite: boolean;
759
+ onlyKeys?: string[];
760
+ baseUrl?: string;
761
+ json: boolean;
696
762
  };
697
763
  type VercelProjectsCommandArgs = {
698
764
  type: Command.Vercel;
package/dist/index.js CHANGED
@@ -11835,8 +11835,9 @@ var PrepareDevCommandHandler = class {
11835
11835
  return;
11836
11836
  }
11837
11837
  ui.success(
11838
- `Prepared ${result.repo}-${result.envIndex}${result.created ? " (cloned)" : ""}`,
11838
+ `${result.repo} env ready: ${result.envPath}${result.created ? " (cloned)" : ""}`,
11839
11839
  {
11840
+ env: `${result.repo}-${result.envIndex}`,
11840
11841
  path: result.envPath,
11841
11842
  origin: result.origin,
11842
11843
  lock: result.lockPath
@@ -15001,15 +15002,18 @@ var INTRO_MIN_LENGTHS = Object.freeze({
15001
15002
  var FIELD_RULES = Object.freeze({
15002
15003
  teachingArticle: Object.freeze({
15003
15004
  label: "teachingArticle\uFF08\u6559\u5B66\u77ED\u6587\uFF09",
15005
+ legacyLabel: "knowledgeSummary\uFF08\u77E5\u8BC6\u8BB2\u89E3\uFF09",
15004
15006
  defaultHint: "\u77E5\u8BC6\u8BB2\u89E3\u81F3\u5C11\u8981\u5148\u628A\u9898\u76EE\u524D\u63D0\u8BF4\u6E05\u695A\uFF0C\u518D\u8BA9\u7528\u6237\u53BB\u9009\u7B54\u6848\u3002",
15005
15007
  introHint: "\u5F00\u573A\u9898\u81F3\u5C11\u8981\u8BB2\u6E05\u5B83\u662F\u4EC0\u4E48\u3001\u89E3\u51B3\u4EC0\u4E48\u95EE\u9898\uFF0C\u4EE5\u53CA\u8BFB\u8005\u63A5\u4E0B\u6765\u8BE5\u5E26\u7740\u4EC0\u4E48\u7406\u89E3\u8DEF\u5F84\u7EE7\u7EED\u5F80\u4E0B\u770B\u3002"
15006
15008
  }),
15007
15009
  teachingTip: Object.freeze({
15008
15010
  label: "teachingTip\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
15011
+ legacyLabel: "knowledgeNote\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
15009
15012
  introHint: "\u5F00\u573A\u9898\u8981\u8865\u5145\u4E3A\u4EC0\u4E48\u5BB9\u6613\u8BEF\u89E3\uFF0C\u6216\u8005\u7B2C\u4E00\u6B21\u8BFB\u8FD9\u5757\u5185\u5BB9\u65F6\u5E94\u8BE5\u5148\u770B\u54EA\u91CC\u3002"
15010
15013
  }),
15011
15014
  explanation: Object.freeze({
15012
15015
  label: "explanation\uFF08\u89E3\u6790\uFF09",
15016
+ legacyLabel: "explanation\uFF08\u89E3\u6790\uFF09",
15013
15017
  defaultHint: "\u89E3\u6790\u81F3\u5C11\u8981\u6309 3W+1H \u8BB2\u6E05 What\u3001Why\u3001Where\u3001How\uFF0C\u5E76\u8986\u76D6\u6B63\u786E\u539F\u56E0\u548C\u4E00\u4E2A\u5E38\u89C1\u8BEF\u533A\u3002",
15014
15018
  introHint: "\u89E3\u6790\u81F3\u5C11\u8981\u6309 3W+1H \u8BB2\u6E05 What\u3001Why\u3001Where\u3001How\uFF0C\u5E76\u8865\u4E0A\u6B63\u786E\u539F\u56E0\u3001\u4E00\u4E2A\u5E38\u89C1\u8BEF\u533A\uFF0C\u4EE5\u53CA\u5B83\u548C\u5F53\u524D\u4E0A\u4E0B\u6587\u7684\u5177\u4F53\u5173\u7CFB\u3002"
15015
15019
  })
@@ -15024,14 +15028,47 @@ function formatStepLabel(step, index) {
15024
15028
  const stepId = String(step?.stepId || `step-${index + 1}`);
15025
15029
  return `\u7B2C ${index + 1} \u9898\uFF08${stepId}\uFF09`;
15026
15030
  }
15031
+ function getFieldValue(step, field) {
15032
+ if (field === "teachingArticle") {
15033
+ return step.teachingArticle ?? step.knowledgeSummary;
15034
+ }
15035
+ if (field === "teachingTip") {
15036
+ return step.teachingTip ?? step.knowledgeNote;
15037
+ }
15038
+ return step[field];
15039
+ }
15040
+ function getFieldLabel(step, field) {
15041
+ const fieldRule = FIELD_RULES[field];
15042
+ if (field === "teachingArticle" && step.teachingArticle == null && step.knowledgeSummary != null) {
15043
+ return fieldRule.legacyLabel ?? "teachingArticle\uFF08\u6559\u5B66\u77ED\u6587\uFF09";
15044
+ }
15045
+ if (field === "teachingTip" && step.teachingTip == null && step.knowledgeNote != null) {
15046
+ return fieldRule.legacyLabel ?? "teachingTip\uFF08\u8865\u5145\u8BF4\u660E\uFF09";
15047
+ }
15048
+ return fieldRule.label;
15049
+ }
15050
+ function normalizeQuizStep(rawStep) {
15051
+ return {
15052
+ ...rawStep,
15053
+ conceptTitle: rawStep.conceptTitle ?? rawStep.knowledgeTitle,
15054
+ teachingArticle: rawStep.teachingArticle ?? rawStep.knowledgeSummary,
15055
+ teachingTip: rawStep.teachingTip ?? rawStep.knowledgeNote
15056
+ };
15057
+ }
15058
+ function normalizeQuizPaperPayloadDocument(payload) {
15059
+ const rawSteps = Array.isArray(payload.steps) ? payload.steps : [];
15060
+ return {
15061
+ ...payload,
15062
+ steps: rawSteps.map((step) => normalizeQuizStep(step ?? {}))
15063
+ };
15064
+ }
15027
15065
  function assertMinLength(step, index, field, minLength, hint) {
15028
- const currentLength = countMeaningfulChars(step?.[field]);
15066
+ const currentLength = countMeaningfulChars(getFieldValue(step, field));
15029
15067
  if (currentLength >= minLength) {
15030
15068
  return;
15031
15069
  }
15032
- const fieldRule = FIELD_RULES[field];
15033
15070
  throw new Error(
15034
- `${formatStepLabel(step, index)}\u7684${fieldRule.label}\u592A\u77ED\uFF0C\u81F3\u5C11\u9700\u8981${minLength}\u4E2A\u975E\u7A7A\u767D\u5B57\u7B26\uFF0C\u5F53\u524D\u53EA\u6709${currentLength}\u4E2A\u3002${hint}`
15071
+ `${formatStepLabel(step, index)}\u7684${getFieldLabel(step, field)}\u592A\u77ED\uFF0C\u81F3\u5C11\u9700\u8981${minLength}\u4E2A\u975E\u7A7A\u767D\u5B57\u7B26\uFF0C\u5F53\u524D\u53EA\u6709${currentLength}\u4E2A\u3002${hint}`
15035
15072
  );
15036
15073
  }
15037
15074
  function validateQuizPaperPayload(payload) {
@@ -15113,8 +15150,10 @@ async function publishQuizPaper({
15113
15150
  }) {
15114
15151
  const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
15115
15152
  const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
15116
- const { steps = [], ...metadata } = payload ?? {};
15117
- validateQuizPaperPayload(payload);
15153
+ const rawPayload = payload ?? {};
15154
+ const normalizedPayload = normalizeQuizPaperPayloadDocument(rawPayload);
15155
+ const { steps = [], ...metadata } = normalizedPayload;
15156
+ validateQuizPaperPayload(rawPayload);
15118
15157
  await requestJson(
15119
15158
  fetchImpl,
15120
15159
  `${trimmedApiBaseUrl}/api/quiz/papers`,
@@ -15291,6 +15330,7 @@ async function appendQuizPaperStep({
15291
15330
  const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
15292
15331
  const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
15293
15332
  const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
15333
+ const normalizedStep = normalizeQuizStep(step);
15294
15334
  const data = await requestJson(
15295
15335
  fetchImpl,
15296
15336
  `${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps`,
@@ -15300,7 +15340,7 @@ async function appendQuizPaperStep({
15300
15340
  Authorization: `Bearer ${token}`,
15301
15341
  "Content-Type": "application/json"
15302
15342
  },
15303
- body: JSON.stringify(step)
15343
+ body: JSON.stringify(normalizedStep)
15304
15344
  },
15305
15345
  `\u8FFD\u52A0\u9898\u76EE\uFF08${String(step?.stepId ?? "unknown-step")}\uFF09`
15306
15346
  );
@@ -15323,6 +15363,7 @@ async function updateQuizPaperStep({
15323
15363
  const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
15324
15364
  const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
15325
15365
  const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
15366
+ const normalizedStep = normalizeQuizStep(step);
15326
15367
  const data = await requestJson(
15327
15368
  fetchImpl,
15328
15369
  `${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps/${encodeURIComponent(stepId)}`,
@@ -15332,7 +15373,7 @@ async function updateQuizPaperStep({
15332
15373
  Authorization: `Bearer ${token}`,
15333
15374
  "Content-Type": "application/json"
15334
15375
  },
15335
- body: JSON.stringify(step)
15376
+ body: JSON.stringify(normalizedStep)
15336
15377
  },
15337
15378
  `\u66F4\u65B0\u9898\u76EE\uFF08${stepId}\uFF09`
15338
15379
  );
@@ -17302,7 +17343,9 @@ function readNamespaceFromPayload(payload) {
17302
17343
 
17303
17344
  // src/commands/ServiceCommandHandler.ts
17304
17345
  var import_node_fs18 = require("fs");
17346
+ var import_promises5 = require("fs/promises");
17305
17347
  var import_node_path23 = __toESM(require("path"));
17348
+ var import_promises6 = require("readline/promises");
17306
17349
 
17307
17350
  // src/services/ServiceRuntimeRunner.ts
17308
17351
  var import_node_fs17 = require("fs");
@@ -18397,6 +18440,107 @@ var ServiceCommandHandler = class {
18397
18440
  });
18398
18441
  return;
18399
18442
  }
18443
+ case "env-list": {
18444
+ const payload = await this.request(
18445
+ baseUrl,
18446
+ "GET",
18447
+ this.buildEnvPath(args.appId, {
18448
+ scope: args.scope,
18449
+ includeSecretMeta: args.includeSecretMeta,
18450
+ includeSecretValue: args.includeSecretValue
18451
+ })
18452
+ );
18453
+ this.renderJson(payload, true);
18454
+ return;
18455
+ }
18456
+ case "env-get": {
18457
+ const payload = await this.request(
18458
+ baseUrl,
18459
+ "GET",
18460
+ `${this.buildEnvBasePath(args.appId)}/${encodeURIComponent(args.key)}?${new URLSearchParams({
18461
+ scope: args.scope,
18462
+ ...args.includeSecretValue ? { includeSecretValue: "true" } : {}
18463
+ }).toString()}`
18464
+ );
18465
+ this.renderJson(payload, true);
18466
+ return;
18467
+ }
18468
+ case "env-set": {
18469
+ const value = await this.resolveEnvValue(args);
18470
+ const payload = await this.request(
18471
+ baseUrl,
18472
+ "PUT",
18473
+ `${this.buildEnvBasePath(args.appId)}/${encodeURIComponent(args.key)}`,
18474
+ {
18475
+ value,
18476
+ scope: args.scope,
18477
+ kind: args.secret ? "secret" : "plain"
18478
+ }
18479
+ );
18480
+ ui.success(`Updated env ${args.key} for ${args.appId}`);
18481
+ this.renderJson(payload, args.json);
18482
+ return;
18483
+ }
18484
+ case "env-unset": {
18485
+ const payload = await this.request(
18486
+ baseUrl,
18487
+ "DELETE",
18488
+ `${this.buildEnvBasePath(args.appId)}/${encodeURIComponent(args.key)}?${new URLSearchParams({
18489
+ scope: args.scope
18490
+ }).toString()}`
18491
+ );
18492
+ ui.success(`Deleted env ${payload.key} (${payload.scope}) from ${args.appId}`);
18493
+ this.renderJson(payload, args.json);
18494
+ return;
18495
+ }
18496
+ case "env-resolve": {
18497
+ const payload = await this.request(
18498
+ baseUrl,
18499
+ "POST",
18500
+ `${this.buildEnvBasePath(args.appId)}/resolve`,
18501
+ {
18502
+ stage: args.stage,
18503
+ ...args.branch ? { branch: args.branch } : {},
18504
+ ...args.includeSecretValue ? { includeSecretValue: true } : {}
18505
+ }
18506
+ );
18507
+ this.renderJson(payload, true);
18508
+ return;
18509
+ }
18510
+ case "env-pull": {
18511
+ const payload = await this.request(
18512
+ baseUrl,
18513
+ "POST",
18514
+ `${this.buildEnvBasePath(args.appId)}/pull`,
18515
+ {
18516
+ stage: args.stage,
18517
+ ...args.branch ? { branch: args.branch } : {},
18518
+ format: "dotenv"
18519
+ }
18520
+ );
18521
+ const outputPath = import_node_path23.default.resolve(process.cwd(), args.output);
18522
+ await (0, import_promises5.writeFile)(outputPath, payload.content, "utf8");
18523
+ ui.success(`Wrote env file for ${args.appId} to ${outputPath}`);
18524
+ this.renderJson({ ...payload, output: outputPath }, args.json);
18525
+ return;
18526
+ }
18527
+ case "env-copy-from": {
18528
+ const payload = await this.request(
18529
+ baseUrl,
18530
+ "POST",
18531
+ `${this.buildEnvBasePath(args.targetAppId)}/copy-from`,
18532
+ {
18533
+ sourceAppId: args.sourceAppId,
18534
+ ...args.scope ? { scope: args.scope } : {},
18535
+ ...args.includeSecret ? { includeSecret: true } : {},
18536
+ ...args.overwrite ? { overwrite: true } : {},
18537
+ ...args.onlyKeys?.length ? { onlyKeys: args.onlyKeys } : {}
18538
+ }
18539
+ );
18540
+ ui.success(`Copied env items from ${args.sourceAppId} to ${args.targetAppId}`);
18541
+ this.renderJson(payload, args.json);
18542
+ return;
18543
+ }
18400
18544
  }
18401
18545
  }
18402
18546
  resolveBaseUrl(baseUrl) {
@@ -18436,6 +18580,44 @@ var ServiceCommandHandler = class {
18436
18580
  }
18437
18581
  return payload.data;
18438
18582
  }
18583
+ buildEnvBasePath(appId) {
18584
+ return `/apps/by-id/${encodeURIComponent(appId)}/env`;
18585
+ }
18586
+ buildEnvPath(appId, query) {
18587
+ const params = new URLSearchParams();
18588
+ if (query.scope) {
18589
+ params.set("scope", query.scope);
18590
+ }
18591
+ if (query.includeSecretMeta) {
18592
+ params.set("includeSecretMeta", "true");
18593
+ }
18594
+ if (query.includeSecretValue) {
18595
+ params.set("includeSecretValue", "true");
18596
+ }
18597
+ const qs = params.toString();
18598
+ return `${this.buildEnvBasePath(appId)}${qs ? `?${qs}` : ""}`;
18599
+ }
18600
+ async resolveEnvValue(args) {
18601
+ if (args.value !== void 0) {
18602
+ return args.value;
18603
+ }
18604
+ if (!args.prompt && !args.secret) {
18605
+ throw new Error("Missing env value. Pass a value or use --prompt.");
18606
+ }
18607
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
18608
+ throw new Error("Prompt input requires an interactive terminal.");
18609
+ }
18610
+ const rl = (0, import_promises6.createInterface)({
18611
+ input: process.stdin,
18612
+ output: process.stdout
18613
+ });
18614
+ try {
18615
+ const prompt = args.secret ? `Enter secret value for ${args.key}: ` : `Enter value for ${args.key}: `;
18616
+ return await rl.question(prompt);
18617
+ } finally {
18618
+ rl.close();
18619
+ }
18620
+ }
18439
18621
  async requireNamespace(payload, baseUrl) {
18440
18622
  if (!payload || typeof payload !== "object") {
18441
18623
  throw new Error("Service payload must be a JSON object.");
@@ -19882,6 +20064,10 @@ init_namespacedRef();
19882
20064
  function parseServiceArgs(tokens) {
19883
20065
  const rest = [...tokens];
19884
20066
  const rawAction = rest.shift();
20067
+ if (rawAction && looksLikeNamespacedRef(rawAction) && rest[0] === "env") {
20068
+ rest.shift();
20069
+ return parseServiceEnvArgs(rawAction, rest);
20070
+ }
19885
20071
  const action = rawAction === "view" ? "view" : rawAction;
19886
20072
  if (!action) {
19887
20073
  throw new Error("Missing service action. Use: service list|get|view|create|update|rename|delete");
@@ -20158,6 +20344,245 @@ function parseBareRenameId3(value, entityName) {
20158
20344
  }
20159
20345
  return normalized;
20160
20346
  }
20347
+ function looksLikeNamespacedRef(value) {
20348
+ return value.includes(":") && !value.startsWith("-");
20349
+ }
20350
+ function parseServiceEnvArgs(appId, tokens) {
20351
+ const rest = [...tokens];
20352
+ const action = rest.shift();
20353
+ if (!action) {
20354
+ throw new Error("Usage: service <ns:app> env list|get|set|unset|resolve|pull|copy-from");
20355
+ }
20356
+ let baseUrl;
20357
+ let json = false;
20358
+ if (action === "list") {
20359
+ let scope;
20360
+ let includeSecretMeta = false;
20361
+ let includeSecretValue = false;
20362
+ while (rest.length > 0) {
20363
+ const token = rest.shift();
20364
+ switch (token) {
20365
+ case "--scope":
20366
+ scope = requireValue6(rest, token);
20367
+ break;
20368
+ case "--include-secret-meta":
20369
+ includeSecretMeta = true;
20370
+ break;
20371
+ case "--include-secret-value":
20372
+ includeSecretValue = true;
20373
+ break;
20374
+ case "--base-url":
20375
+ baseUrl = requireValue6(rest, token);
20376
+ break;
20377
+ case "--json":
20378
+ json = true;
20379
+ break;
20380
+ default:
20381
+ throw new Error(`Unknown service env list option: ${token}`);
20382
+ }
20383
+ }
20384
+ return { type: "service" /* Service */, action: "env-list", appId, scope, includeSecretMeta, includeSecretValue, baseUrl, json };
20385
+ }
20386
+ if (action === "get") {
20387
+ const key = rest.shift();
20388
+ if (!key || key.startsWith("-")) {
20389
+ throw new Error("Usage: service <ns:app> env get <key> --scope <scope> [--include-secret-value]");
20390
+ }
20391
+ let scope;
20392
+ let includeSecretValue = false;
20393
+ while (rest.length > 0) {
20394
+ const token = rest.shift();
20395
+ switch (token) {
20396
+ case "--scope":
20397
+ scope = requireValue6(rest, token);
20398
+ break;
20399
+ case "--include-secret-value":
20400
+ includeSecretValue = true;
20401
+ break;
20402
+ case "--base-url":
20403
+ baseUrl = requireValue6(rest, token);
20404
+ break;
20405
+ case "--json":
20406
+ json = true;
20407
+ break;
20408
+ default:
20409
+ throw new Error(`Unknown service env get option: ${token}`);
20410
+ }
20411
+ }
20412
+ if (!scope) {
20413
+ throw new Error("Usage: service <ns:app> env get <key> --scope <scope> [--include-secret-value]");
20414
+ }
20415
+ return { type: "service" /* Service */, action: "env-get", appId, key, scope, includeSecretValue, baseUrl, json };
20416
+ }
20417
+ if (action === "set") {
20418
+ const key = rest.shift();
20419
+ if (!key || key.startsWith("-")) {
20420
+ throw new Error("Usage: service <ns:app> env set <key> [value] --scope <scope> [--secret] [--prompt]");
20421
+ }
20422
+ let value;
20423
+ if (rest[0] && !rest[0].startsWith("-")) {
20424
+ value = rest.shift();
20425
+ }
20426
+ let scope;
20427
+ let secret = false;
20428
+ let prompt = false;
20429
+ while (rest.length > 0) {
20430
+ const token = rest.shift();
20431
+ switch (token) {
20432
+ case "--scope":
20433
+ scope = requireValue6(rest, token);
20434
+ break;
20435
+ case "--secret":
20436
+ secret = true;
20437
+ break;
20438
+ case "--prompt":
20439
+ prompt = true;
20440
+ break;
20441
+ case "--base-url":
20442
+ baseUrl = requireValue6(rest, token);
20443
+ break;
20444
+ case "--json":
20445
+ json = true;
20446
+ break;
20447
+ default:
20448
+ throw new Error(`Unknown service env set option: ${token}`);
20449
+ }
20450
+ }
20451
+ if (!scope) {
20452
+ throw new Error("Usage: service <ns:app> env set <key> [value] --scope <scope> [--secret] [--prompt]");
20453
+ }
20454
+ if (!value && !secret && !prompt) {
20455
+ throw new Error("Missing env value. Pass a value or use --prompt.");
20456
+ }
20457
+ return { type: "service" /* Service */, action: "env-set", appId, key, value, scope, secret, prompt, baseUrl, json };
20458
+ }
20459
+ if (action === "unset") {
20460
+ const key = rest.shift();
20461
+ if (!key || key.startsWith("-")) {
20462
+ throw new Error("Usage: service <ns:app> env unset <key> --scope <scope>");
20463
+ }
20464
+ let scope;
20465
+ while (rest.length > 0) {
20466
+ const token = rest.shift();
20467
+ switch (token) {
20468
+ case "--scope":
20469
+ scope = requireValue6(rest, token);
20470
+ break;
20471
+ case "--base-url":
20472
+ baseUrl = requireValue6(rest, token);
20473
+ break;
20474
+ case "--json":
20475
+ json = true;
20476
+ break;
20477
+ default:
20478
+ throw new Error(`Unknown service env unset option: ${token}`);
20479
+ }
20480
+ }
20481
+ if (!scope) {
20482
+ throw new Error("Usage: service <ns:app> env unset <key> --scope <scope>");
20483
+ }
20484
+ return { type: "service" /* Service */, action: "env-unset", appId, key, scope, baseUrl, json };
20485
+ }
20486
+ if (action === "resolve") {
20487
+ let stage;
20488
+ let branch;
20489
+ let includeSecretValue = false;
20490
+ while (rest.length > 0) {
20491
+ const token = rest.shift();
20492
+ switch (token) {
20493
+ case "--stage":
20494
+ stage = requireValue6(rest, token);
20495
+ break;
20496
+ case "--branch":
20497
+ branch = requireValue6(rest, token);
20498
+ break;
20499
+ case "--include-secret-value":
20500
+ includeSecretValue = true;
20501
+ break;
20502
+ case "--base-url":
20503
+ baseUrl = requireValue6(rest, token);
20504
+ break;
20505
+ case "--json":
20506
+ json = true;
20507
+ break;
20508
+ default:
20509
+ throw new Error(`Unknown service env resolve option: ${token}`);
20510
+ }
20511
+ }
20512
+ if (!stage) {
20513
+ throw new Error("Usage: service <ns:app> env resolve --stage <dev|preview|prod> [--branch <name>]");
20514
+ }
20515
+ return { type: "service" /* Service */, action: "env-resolve", appId, stage, branch, includeSecretValue, baseUrl, json };
20516
+ }
20517
+ if (action === "pull") {
20518
+ let stage;
20519
+ let branch;
20520
+ let output = ".env.local";
20521
+ while (rest.length > 0) {
20522
+ const token = rest.shift();
20523
+ switch (token) {
20524
+ case "--stage":
20525
+ stage = requireValue6(rest, token);
20526
+ break;
20527
+ case "--branch":
20528
+ branch = requireValue6(rest, token);
20529
+ break;
20530
+ case "--output":
20531
+ output = requireValue6(rest, token);
20532
+ break;
20533
+ case "--base-url":
20534
+ baseUrl = requireValue6(rest, token);
20535
+ break;
20536
+ case "--json":
20537
+ json = true;
20538
+ break;
20539
+ default:
20540
+ throw new Error(`Unknown service env pull option: ${token}`);
20541
+ }
20542
+ }
20543
+ if (!stage) {
20544
+ throw new Error("Usage: service <ns:app> env pull --stage <dev|preview|prod> [--branch <name>] [--output <path>]");
20545
+ }
20546
+ return { type: "service" /* Service */, action: "env-pull", appId, stage, branch, output, baseUrl, json };
20547
+ }
20548
+ if (action === "copy-from") {
20549
+ const sourceAppId = rest.shift();
20550
+ if (!sourceAppId || sourceAppId.startsWith("-")) {
20551
+ throw new Error("Usage: service <ns:app> env copy-from <source-ns:app> [--scope <scope>] [--include-secret] [--overwrite]");
20552
+ }
20553
+ let scope;
20554
+ let includeSecret = false;
20555
+ let overwrite = false;
20556
+ let onlyKeys;
20557
+ while (rest.length > 0) {
20558
+ const token = rest.shift();
20559
+ switch (token) {
20560
+ case "--scope":
20561
+ scope = requireValue6(rest, token);
20562
+ break;
20563
+ case "--include-secret":
20564
+ includeSecret = true;
20565
+ break;
20566
+ case "--overwrite":
20567
+ overwrite = true;
20568
+ break;
20569
+ case "--only":
20570
+ onlyKeys = requireValue6(rest, token).split(",").map((item) => item.trim()).filter(Boolean);
20571
+ break;
20572
+ case "--base-url":
20573
+ baseUrl = requireValue6(rest, token);
20574
+ break;
20575
+ case "--json":
20576
+ json = true;
20577
+ break;
20578
+ default:
20579
+ throw new Error(`Unknown service env copy-from option: ${token}`);
20580
+ }
20581
+ }
20582
+ return { type: "service" /* Service */, action: "env-copy-from", targetAppId: appId, sourceAppId, scope, includeSecret, overwrite, onlyKeys, baseUrl, json };
20583
+ }
20584
+ throw new Error(`Unknown service env action: ${action}`);
20585
+ }
20161
20586
 
20162
20587
  // src/roleCommandParser.ts
20163
20588
  function parseRoleArgs(tokens) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/cli",
3
- "version": "0.21.4",
3
+ "version": "0.21.6",
4
4
  "description": "CLI utilities for the pMate project",
5
5
  "license": "MIT",
6
6
  "bin": {