@pmate/cli 0.21.5 → 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
@@ -15002,15 +15002,18 @@ var INTRO_MIN_LENGTHS = Object.freeze({
15002
15002
  var FIELD_RULES = Object.freeze({
15003
15003
  teachingArticle: Object.freeze({
15004
15004
  label: "teachingArticle\uFF08\u6559\u5B66\u77ED\u6587\uFF09",
15005
+ legacyLabel: "knowledgeSummary\uFF08\u77E5\u8BC6\u8BB2\u89E3\uFF09",
15005
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",
15006
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"
15007
15008
  }),
15008
15009
  teachingTip: Object.freeze({
15009
15010
  label: "teachingTip\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
15011
+ legacyLabel: "knowledgeNote\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
15010
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"
15011
15013
  }),
15012
15014
  explanation: Object.freeze({
15013
15015
  label: "explanation\uFF08\u89E3\u6790\uFF09",
15016
+ legacyLabel: "explanation\uFF08\u89E3\u6790\uFF09",
15014
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",
15015
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"
15016
15019
  })
@@ -15025,14 +15028,47 @@ function formatStepLabel(step, index) {
15025
15028
  const stepId = String(step?.stepId || `step-${index + 1}`);
15026
15029
  return `\u7B2C ${index + 1} \u9898\uFF08${stepId}\uFF09`;
15027
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
+ }
15028
15065
  function assertMinLength(step, index, field, minLength, hint) {
15029
- const currentLength = countMeaningfulChars(step?.[field]);
15066
+ const currentLength = countMeaningfulChars(getFieldValue(step, field));
15030
15067
  if (currentLength >= minLength) {
15031
15068
  return;
15032
15069
  }
15033
- const fieldRule = FIELD_RULES[field];
15034
15070
  throw new Error(
15035
- `${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}`
15036
15072
  );
15037
15073
  }
15038
15074
  function validateQuizPaperPayload(payload) {
@@ -15114,8 +15150,10 @@ async function publishQuizPaper({
15114
15150
  }) {
15115
15151
  const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
15116
15152
  const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
15117
- const { steps = [], ...metadata } = payload ?? {};
15118
- validateQuizPaperPayload(payload);
15153
+ const rawPayload = payload ?? {};
15154
+ const normalizedPayload = normalizeQuizPaperPayloadDocument(rawPayload);
15155
+ const { steps = [], ...metadata } = normalizedPayload;
15156
+ validateQuizPaperPayload(rawPayload);
15119
15157
  await requestJson(
15120
15158
  fetchImpl,
15121
15159
  `${trimmedApiBaseUrl}/api/quiz/papers`,
@@ -15292,6 +15330,7 @@ async function appendQuizPaperStep({
15292
15330
  const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
15293
15331
  const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
15294
15332
  const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
15333
+ const normalizedStep = normalizeQuizStep(step);
15295
15334
  const data = await requestJson(
15296
15335
  fetchImpl,
15297
15336
  `${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps`,
@@ -15301,7 +15340,7 @@ async function appendQuizPaperStep({
15301
15340
  Authorization: `Bearer ${token}`,
15302
15341
  "Content-Type": "application/json"
15303
15342
  },
15304
- body: JSON.stringify(step)
15343
+ body: JSON.stringify(normalizedStep)
15305
15344
  },
15306
15345
  `\u8FFD\u52A0\u9898\u76EE\uFF08${String(step?.stepId ?? "unknown-step")}\uFF09`
15307
15346
  );
@@ -15324,6 +15363,7 @@ async function updateQuizPaperStep({
15324
15363
  const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
15325
15364
  const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
15326
15365
  const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
15366
+ const normalizedStep = normalizeQuizStep(step);
15327
15367
  const data = await requestJson(
15328
15368
  fetchImpl,
15329
15369
  `${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps/${encodeURIComponent(stepId)}`,
@@ -15333,7 +15373,7 @@ async function updateQuizPaperStep({
15333
15373
  Authorization: `Bearer ${token}`,
15334
15374
  "Content-Type": "application/json"
15335
15375
  },
15336
- body: JSON.stringify(step)
15376
+ body: JSON.stringify(normalizedStep)
15337
15377
  },
15338
15378
  `\u66F4\u65B0\u9898\u76EE\uFF08${stepId}\uFF09`
15339
15379
  );
@@ -17303,7 +17343,9 @@ function readNamespaceFromPayload(payload) {
17303
17343
 
17304
17344
  // src/commands/ServiceCommandHandler.ts
17305
17345
  var import_node_fs18 = require("fs");
17346
+ var import_promises5 = require("fs/promises");
17306
17347
  var import_node_path23 = __toESM(require("path"));
17348
+ var import_promises6 = require("readline/promises");
17307
17349
 
17308
17350
  // src/services/ServiceRuntimeRunner.ts
17309
17351
  var import_node_fs17 = require("fs");
@@ -18398,6 +18440,107 @@ var ServiceCommandHandler = class {
18398
18440
  });
18399
18441
  return;
18400
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
+ }
18401
18544
  }
18402
18545
  }
18403
18546
  resolveBaseUrl(baseUrl) {
@@ -18437,6 +18580,44 @@ var ServiceCommandHandler = class {
18437
18580
  }
18438
18581
  return payload.data;
18439
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
+ }
18440
18621
  async requireNamespace(payload, baseUrl) {
18441
18622
  if (!payload || typeof payload !== "object") {
18442
18623
  throw new Error("Service payload must be a JSON object.");
@@ -19883,6 +20064,10 @@ init_namespacedRef();
19883
20064
  function parseServiceArgs(tokens) {
19884
20065
  const rest = [...tokens];
19885
20066
  const rawAction = rest.shift();
20067
+ if (rawAction && looksLikeNamespacedRef(rawAction) && rest[0] === "env") {
20068
+ rest.shift();
20069
+ return parseServiceEnvArgs(rawAction, rest);
20070
+ }
19886
20071
  const action = rawAction === "view" ? "view" : rawAction;
19887
20072
  if (!action) {
19888
20073
  throw new Error("Missing service action. Use: service list|get|view|create|update|rename|delete");
@@ -20159,6 +20344,245 @@ function parseBareRenameId3(value, entityName) {
20159
20344
  }
20160
20345
  return normalized;
20161
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
+ }
20162
20586
 
20163
20587
  // src/roleCommandParser.ts
20164
20588
  function parseRoleArgs(tokens) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/cli",
3
- "version": "0.21.5",
3
+ "version": "0.21.6",
4
4
  "description": "CLI utilities for the pMate project",
5
5
  "license": "MIT",
6
6
  "bin": {