@pmate/cli 0.21.5 → 0.21.7
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 +66 -0
- package/dist/index.js +468 -11
- package/package.json +1 -1
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
|
@@ -11660,7 +11660,7 @@ var PrepareDevCommandHandler = class {
|
|
|
11660
11660
|
this.renderOpen(result2, args.json);
|
|
11661
11661
|
return result2;
|
|
11662
11662
|
}
|
|
11663
|
-
const result = await this.closeEnvironment(args.repo, args.envIndex, envRoot);
|
|
11663
|
+
const result = await this.closeEnvironment(args.repo, args.envIndex, envRoot, baseRoot);
|
|
11664
11664
|
this.renderClose(result, args.json);
|
|
11665
11665
|
return result;
|
|
11666
11666
|
}
|
|
@@ -11732,9 +11732,10 @@ var PrepareDevCommandHandler = class {
|
|
|
11732
11732
|
}
|
|
11733
11733
|
throw new Error(`No available dev environment found for ${repo} under ${envRoot}`);
|
|
11734
11734
|
}
|
|
11735
|
-
async closeEnvironment(repo, envIndex, envRoot) {
|
|
11735
|
+
async closeEnvironment(repo, envIndex, envRoot, baseRoot) {
|
|
11736
11736
|
const envPath = import_node_path10.default.join(envRoot, `${repo}-${envIndex}`);
|
|
11737
11737
|
const lockPath = import_node_path10.default.join(envPath, LOCK_FILE_NAME);
|
|
11738
|
+
const baseRepoPath = import_node_path10.default.join(baseRoot, repo);
|
|
11738
11739
|
if (!await this.pathExists(envPath) || !await this.pathExists(import_node_path10.default.join(envPath, ".git"))) {
|
|
11739
11740
|
throw new Error(`Dev environment not found: ${envPath}`);
|
|
11740
11741
|
}
|
|
@@ -11744,6 +11745,7 @@ var PrepareDevCommandHandler = class {
|
|
|
11744
11745
|
`Cannot close ${repo}-${envIndex}: local changes detected. Commit or clean the worktree first.`
|
|
11745
11746
|
);
|
|
11746
11747
|
}
|
|
11748
|
+
const baseRepoSync = await this.syncBaseRepo(baseRepoPath);
|
|
11747
11749
|
const removedLock = await this.removeLock(lockPath);
|
|
11748
11750
|
return {
|
|
11749
11751
|
action: "close",
|
|
@@ -11751,7 +11753,9 @@ var PrepareDevCommandHandler = class {
|
|
|
11751
11753
|
envIndex,
|
|
11752
11754
|
envPath,
|
|
11753
11755
|
lockPath,
|
|
11754
|
-
removedLock
|
|
11756
|
+
removedLock,
|
|
11757
|
+
baseRepoPath,
|
|
11758
|
+
baseRepoSync
|
|
11755
11759
|
};
|
|
11756
11760
|
}
|
|
11757
11761
|
resolveRoot(input, fallbackSegments) {
|
|
@@ -11766,6 +11770,33 @@ var PrepareDevCommandHandler = class {
|
|
|
11766
11770
|
throw new Error(`Expected ${cwd} to be on main, got ${branch || "(detached)"}`);
|
|
11767
11771
|
}
|
|
11768
11772
|
}
|
|
11773
|
+
async syncBaseRepo(baseRepoPath) {
|
|
11774
|
+
if (!await this.pathExists(baseRepoPath) || !await this.pathExists(import_node_path10.default.join(baseRepoPath, ".git"))) {
|
|
11775
|
+
throw new Error(`Cannot close dev environment: base repo not found: ${baseRepoPath}`);
|
|
11776
|
+
}
|
|
11777
|
+
const origin = await this.safeGitOutput(baseRepoPath, ["remote", "get-url", "origin"]);
|
|
11778
|
+
if (!origin || this.isLocalOrigin(origin)) {
|
|
11779
|
+
throw new Error(
|
|
11780
|
+
`Cannot close dev environment: base repo has invalid origin: ${baseRepoPath}`
|
|
11781
|
+
);
|
|
11782
|
+
}
|
|
11783
|
+
const branch = await this.safeGitOutput(baseRepoPath, ["branch", "--show-current"]);
|
|
11784
|
+
if (branch !== "main") {
|
|
11785
|
+
throw new Error(
|
|
11786
|
+
`Cannot close dev environment: base repo must be on main before sync, got ${branch || "(detached)"}.`
|
|
11787
|
+
);
|
|
11788
|
+
}
|
|
11789
|
+
if (await this.hasUncommittedChanges(baseRepoPath)) {
|
|
11790
|
+
throw new Error(
|
|
11791
|
+
`Cannot close dev environment: base repo has local changes: ${baseRepoPath}`
|
|
11792
|
+
);
|
|
11793
|
+
}
|
|
11794
|
+
await this.runGit(["pull", "--ff-only"], baseRepoPath);
|
|
11795
|
+
return {
|
|
11796
|
+
attempted: true,
|
|
11797
|
+
updated: true
|
|
11798
|
+
};
|
|
11799
|
+
}
|
|
11769
11800
|
async hasUncommittedChanges(cwd) {
|
|
11770
11801
|
const status = await this.getGitOutput(cwd, ["status", "--porcelain"]);
|
|
11771
11802
|
if (!status) {
|
|
@@ -11851,7 +11882,9 @@ var PrepareDevCommandHandler = class {
|
|
|
11851
11882
|
}
|
|
11852
11883
|
ui.success(`Closed ${result.repo}-${result.envIndex}`, {
|
|
11853
11884
|
path: result.envPath,
|
|
11854
|
-
lockRemoved: result.removedLock
|
|
11885
|
+
lockRemoved: result.removedLock,
|
|
11886
|
+
baseRepo: result.baseRepoPath,
|
|
11887
|
+
baseRepoSynced: result.baseRepoSync.updated
|
|
11855
11888
|
});
|
|
11856
11889
|
}
|
|
11857
11890
|
};
|
|
@@ -15002,15 +15035,18 @@ var INTRO_MIN_LENGTHS = Object.freeze({
|
|
|
15002
15035
|
var FIELD_RULES = Object.freeze({
|
|
15003
15036
|
teachingArticle: Object.freeze({
|
|
15004
15037
|
label: "teachingArticle\uFF08\u6559\u5B66\u77ED\u6587\uFF09",
|
|
15038
|
+
legacyLabel: "knowledgeSummary\uFF08\u77E5\u8BC6\u8BB2\u89E3\uFF09",
|
|
15005
15039
|
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
15040
|
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
15041
|
}),
|
|
15008
15042
|
teachingTip: Object.freeze({
|
|
15009
15043
|
label: "teachingTip\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
|
|
15044
|
+
legacyLabel: "knowledgeNote\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
|
|
15010
15045
|
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
15046
|
}),
|
|
15012
15047
|
explanation: Object.freeze({
|
|
15013
15048
|
label: "explanation\uFF08\u89E3\u6790\uFF09",
|
|
15049
|
+
legacyLabel: "explanation\uFF08\u89E3\u6790\uFF09",
|
|
15014
15050
|
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
15051
|
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
15052
|
})
|
|
@@ -15025,14 +15061,47 @@ function formatStepLabel(step, index) {
|
|
|
15025
15061
|
const stepId = String(step?.stepId || `step-${index + 1}`);
|
|
15026
15062
|
return `\u7B2C ${index + 1} \u9898\uFF08${stepId}\uFF09`;
|
|
15027
15063
|
}
|
|
15064
|
+
function getFieldValue(step, field) {
|
|
15065
|
+
if (field === "teachingArticle") {
|
|
15066
|
+
return step.teachingArticle ?? step.knowledgeSummary;
|
|
15067
|
+
}
|
|
15068
|
+
if (field === "teachingTip") {
|
|
15069
|
+
return step.teachingTip ?? step.knowledgeNote;
|
|
15070
|
+
}
|
|
15071
|
+
return step[field];
|
|
15072
|
+
}
|
|
15073
|
+
function getFieldLabel(step, field) {
|
|
15074
|
+
const fieldRule = FIELD_RULES[field];
|
|
15075
|
+
if (field === "teachingArticle" && step.teachingArticle == null && step.knowledgeSummary != null) {
|
|
15076
|
+
return fieldRule.legacyLabel ?? "teachingArticle\uFF08\u6559\u5B66\u77ED\u6587\uFF09";
|
|
15077
|
+
}
|
|
15078
|
+
if (field === "teachingTip" && step.teachingTip == null && step.knowledgeNote != null) {
|
|
15079
|
+
return fieldRule.legacyLabel ?? "teachingTip\uFF08\u8865\u5145\u8BF4\u660E\uFF09";
|
|
15080
|
+
}
|
|
15081
|
+
return fieldRule.label;
|
|
15082
|
+
}
|
|
15083
|
+
function normalizeQuizStep(rawStep) {
|
|
15084
|
+
return {
|
|
15085
|
+
...rawStep,
|
|
15086
|
+
conceptTitle: rawStep.conceptTitle ?? rawStep.knowledgeTitle,
|
|
15087
|
+
teachingArticle: rawStep.teachingArticle ?? rawStep.knowledgeSummary,
|
|
15088
|
+
teachingTip: rawStep.teachingTip ?? rawStep.knowledgeNote
|
|
15089
|
+
};
|
|
15090
|
+
}
|
|
15091
|
+
function normalizeQuizPaperPayloadDocument(payload) {
|
|
15092
|
+
const rawSteps = Array.isArray(payload.steps) ? payload.steps : [];
|
|
15093
|
+
return {
|
|
15094
|
+
...payload,
|
|
15095
|
+
steps: rawSteps.map((step) => normalizeQuizStep(step ?? {}))
|
|
15096
|
+
};
|
|
15097
|
+
}
|
|
15028
15098
|
function assertMinLength(step, index, field, minLength, hint) {
|
|
15029
|
-
const currentLength = countMeaningfulChars(step
|
|
15099
|
+
const currentLength = countMeaningfulChars(getFieldValue(step, field));
|
|
15030
15100
|
if (currentLength >= minLength) {
|
|
15031
15101
|
return;
|
|
15032
15102
|
}
|
|
15033
|
-
const fieldRule = FIELD_RULES[field];
|
|
15034
15103
|
throw new Error(
|
|
15035
|
-
`${formatStepLabel(step, index)}\u7684${
|
|
15104
|
+
`${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
15105
|
);
|
|
15037
15106
|
}
|
|
15038
15107
|
function validateQuizPaperPayload(payload) {
|
|
@@ -15114,8 +15183,10 @@ async function publishQuizPaper({
|
|
|
15114
15183
|
}) {
|
|
15115
15184
|
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
15116
15185
|
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
15117
|
-
const
|
|
15118
|
-
|
|
15186
|
+
const rawPayload = payload ?? {};
|
|
15187
|
+
const normalizedPayload = normalizeQuizPaperPayloadDocument(rawPayload);
|
|
15188
|
+
const { steps = [], ...metadata } = normalizedPayload;
|
|
15189
|
+
validateQuizPaperPayload(rawPayload);
|
|
15119
15190
|
await requestJson(
|
|
15120
15191
|
fetchImpl,
|
|
15121
15192
|
`${trimmedApiBaseUrl}/api/quiz/papers`,
|
|
@@ -15292,6 +15363,7 @@ async function appendQuizPaperStep({
|
|
|
15292
15363
|
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
15293
15364
|
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
15294
15365
|
const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
|
|
15366
|
+
const normalizedStep = normalizeQuizStep(step);
|
|
15295
15367
|
const data = await requestJson(
|
|
15296
15368
|
fetchImpl,
|
|
15297
15369
|
`${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps`,
|
|
@@ -15301,7 +15373,7 @@ async function appendQuizPaperStep({
|
|
|
15301
15373
|
Authorization: `Bearer ${token}`,
|
|
15302
15374
|
"Content-Type": "application/json"
|
|
15303
15375
|
},
|
|
15304
|
-
body: JSON.stringify(
|
|
15376
|
+
body: JSON.stringify(normalizedStep)
|
|
15305
15377
|
},
|
|
15306
15378
|
`\u8FFD\u52A0\u9898\u76EE\uFF08${String(step?.stepId ?? "unknown-step")}\uFF09`
|
|
15307
15379
|
);
|
|
@@ -15324,6 +15396,7 @@ async function updateQuizPaperStep({
|
|
|
15324
15396
|
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
15325
15397
|
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
15326
15398
|
const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
|
|
15399
|
+
const normalizedStep = normalizeQuizStep(step);
|
|
15327
15400
|
const data = await requestJson(
|
|
15328
15401
|
fetchImpl,
|
|
15329
15402
|
`${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps/${encodeURIComponent(stepId)}`,
|
|
@@ -15333,7 +15406,7 @@ async function updateQuizPaperStep({
|
|
|
15333
15406
|
Authorization: `Bearer ${token}`,
|
|
15334
15407
|
"Content-Type": "application/json"
|
|
15335
15408
|
},
|
|
15336
|
-
body: JSON.stringify(
|
|
15409
|
+
body: JSON.stringify(normalizedStep)
|
|
15337
15410
|
},
|
|
15338
15411
|
`\u66F4\u65B0\u9898\u76EE\uFF08${stepId}\uFF09`
|
|
15339
15412
|
);
|
|
@@ -17303,7 +17376,9 @@ function readNamespaceFromPayload(payload) {
|
|
|
17303
17376
|
|
|
17304
17377
|
// src/commands/ServiceCommandHandler.ts
|
|
17305
17378
|
var import_node_fs18 = require("fs");
|
|
17379
|
+
var import_promises5 = require("fs/promises");
|
|
17306
17380
|
var import_node_path23 = __toESM(require("path"));
|
|
17381
|
+
var import_promises6 = require("readline/promises");
|
|
17307
17382
|
|
|
17308
17383
|
// src/services/ServiceRuntimeRunner.ts
|
|
17309
17384
|
var import_node_fs17 = require("fs");
|
|
@@ -18398,6 +18473,107 @@ var ServiceCommandHandler = class {
|
|
|
18398
18473
|
});
|
|
18399
18474
|
return;
|
|
18400
18475
|
}
|
|
18476
|
+
case "env-list": {
|
|
18477
|
+
const payload = await this.request(
|
|
18478
|
+
baseUrl,
|
|
18479
|
+
"GET",
|
|
18480
|
+
this.buildEnvPath(args.appId, {
|
|
18481
|
+
scope: args.scope,
|
|
18482
|
+
includeSecretMeta: args.includeSecretMeta,
|
|
18483
|
+
includeSecretValue: args.includeSecretValue
|
|
18484
|
+
})
|
|
18485
|
+
);
|
|
18486
|
+
this.renderJson(payload, true);
|
|
18487
|
+
return;
|
|
18488
|
+
}
|
|
18489
|
+
case "env-get": {
|
|
18490
|
+
const payload = await this.request(
|
|
18491
|
+
baseUrl,
|
|
18492
|
+
"GET",
|
|
18493
|
+
`${this.buildEnvBasePath(args.appId)}/${encodeURIComponent(args.key)}?${new URLSearchParams({
|
|
18494
|
+
scope: args.scope,
|
|
18495
|
+
...args.includeSecretValue ? { includeSecretValue: "true" } : {}
|
|
18496
|
+
}).toString()}`
|
|
18497
|
+
);
|
|
18498
|
+
this.renderJson(payload, true);
|
|
18499
|
+
return;
|
|
18500
|
+
}
|
|
18501
|
+
case "env-set": {
|
|
18502
|
+
const value = await this.resolveEnvValue(args);
|
|
18503
|
+
const payload = await this.request(
|
|
18504
|
+
baseUrl,
|
|
18505
|
+
"PUT",
|
|
18506
|
+
`${this.buildEnvBasePath(args.appId)}/${encodeURIComponent(args.key)}`,
|
|
18507
|
+
{
|
|
18508
|
+
value,
|
|
18509
|
+
scope: args.scope,
|
|
18510
|
+
kind: args.secret ? "secret" : "plain"
|
|
18511
|
+
}
|
|
18512
|
+
);
|
|
18513
|
+
ui.success(`Updated env ${args.key} for ${args.appId}`);
|
|
18514
|
+
this.renderJson(payload, args.json);
|
|
18515
|
+
return;
|
|
18516
|
+
}
|
|
18517
|
+
case "env-unset": {
|
|
18518
|
+
const payload = await this.request(
|
|
18519
|
+
baseUrl,
|
|
18520
|
+
"DELETE",
|
|
18521
|
+
`${this.buildEnvBasePath(args.appId)}/${encodeURIComponent(args.key)}?${new URLSearchParams({
|
|
18522
|
+
scope: args.scope
|
|
18523
|
+
}).toString()}`
|
|
18524
|
+
);
|
|
18525
|
+
ui.success(`Deleted env ${payload.key} (${payload.scope}) from ${args.appId}`);
|
|
18526
|
+
this.renderJson(payload, args.json);
|
|
18527
|
+
return;
|
|
18528
|
+
}
|
|
18529
|
+
case "env-resolve": {
|
|
18530
|
+
const payload = await this.request(
|
|
18531
|
+
baseUrl,
|
|
18532
|
+
"POST",
|
|
18533
|
+
`${this.buildEnvBasePath(args.appId)}/resolve`,
|
|
18534
|
+
{
|
|
18535
|
+
stage: args.stage,
|
|
18536
|
+
...args.branch ? { branch: args.branch } : {},
|
|
18537
|
+
...args.includeSecretValue ? { includeSecretValue: true } : {}
|
|
18538
|
+
}
|
|
18539
|
+
);
|
|
18540
|
+
this.renderJson(payload, true);
|
|
18541
|
+
return;
|
|
18542
|
+
}
|
|
18543
|
+
case "env-pull": {
|
|
18544
|
+
const payload = await this.request(
|
|
18545
|
+
baseUrl,
|
|
18546
|
+
"POST",
|
|
18547
|
+
`${this.buildEnvBasePath(args.appId)}/pull`,
|
|
18548
|
+
{
|
|
18549
|
+
stage: args.stage,
|
|
18550
|
+
...args.branch ? { branch: args.branch } : {},
|
|
18551
|
+
format: "dotenv"
|
|
18552
|
+
}
|
|
18553
|
+
);
|
|
18554
|
+
const outputPath = import_node_path23.default.resolve(process.cwd(), args.output);
|
|
18555
|
+
await (0, import_promises5.writeFile)(outputPath, payload.content, "utf8");
|
|
18556
|
+
ui.success(`Wrote env file for ${args.appId} to ${outputPath}`);
|
|
18557
|
+
this.renderJson({ ...payload, output: outputPath }, args.json);
|
|
18558
|
+
return;
|
|
18559
|
+
}
|
|
18560
|
+
case "env-copy-from": {
|
|
18561
|
+
const payload = await this.request(
|
|
18562
|
+
baseUrl,
|
|
18563
|
+
"POST",
|
|
18564
|
+
`${this.buildEnvBasePath(args.targetAppId)}/copy-from`,
|
|
18565
|
+
{
|
|
18566
|
+
sourceAppId: args.sourceAppId,
|
|
18567
|
+
...args.scope ? { scope: args.scope } : {},
|
|
18568
|
+
...args.includeSecret ? { includeSecret: true } : {},
|
|
18569
|
+
...args.overwrite ? { overwrite: true } : {},
|
|
18570
|
+
...args.onlyKeys?.length ? { onlyKeys: args.onlyKeys } : {}
|
|
18571
|
+
}
|
|
18572
|
+
);
|
|
18573
|
+
ui.success(`Copied env items from ${args.sourceAppId} to ${args.targetAppId}`);
|
|
18574
|
+
this.renderJson(payload, args.json);
|
|
18575
|
+
return;
|
|
18576
|
+
}
|
|
18401
18577
|
}
|
|
18402
18578
|
}
|
|
18403
18579
|
resolveBaseUrl(baseUrl) {
|
|
@@ -18437,6 +18613,44 @@ var ServiceCommandHandler = class {
|
|
|
18437
18613
|
}
|
|
18438
18614
|
return payload.data;
|
|
18439
18615
|
}
|
|
18616
|
+
buildEnvBasePath(appId) {
|
|
18617
|
+
return `/apps/by-id/${encodeURIComponent(appId)}/env`;
|
|
18618
|
+
}
|
|
18619
|
+
buildEnvPath(appId, query) {
|
|
18620
|
+
const params = new URLSearchParams();
|
|
18621
|
+
if (query.scope) {
|
|
18622
|
+
params.set("scope", query.scope);
|
|
18623
|
+
}
|
|
18624
|
+
if (query.includeSecretMeta) {
|
|
18625
|
+
params.set("includeSecretMeta", "true");
|
|
18626
|
+
}
|
|
18627
|
+
if (query.includeSecretValue) {
|
|
18628
|
+
params.set("includeSecretValue", "true");
|
|
18629
|
+
}
|
|
18630
|
+
const qs = params.toString();
|
|
18631
|
+
return `${this.buildEnvBasePath(appId)}${qs ? `?${qs}` : ""}`;
|
|
18632
|
+
}
|
|
18633
|
+
async resolveEnvValue(args) {
|
|
18634
|
+
if (args.value !== void 0) {
|
|
18635
|
+
return args.value;
|
|
18636
|
+
}
|
|
18637
|
+
if (!args.prompt && !args.secret) {
|
|
18638
|
+
throw new Error("Missing env value. Pass a value or use --prompt.");
|
|
18639
|
+
}
|
|
18640
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
18641
|
+
throw new Error("Prompt input requires an interactive terminal.");
|
|
18642
|
+
}
|
|
18643
|
+
const rl = (0, import_promises6.createInterface)({
|
|
18644
|
+
input: process.stdin,
|
|
18645
|
+
output: process.stdout
|
|
18646
|
+
});
|
|
18647
|
+
try {
|
|
18648
|
+
const prompt = args.secret ? `Enter secret value for ${args.key}: ` : `Enter value for ${args.key}: `;
|
|
18649
|
+
return await rl.question(prompt);
|
|
18650
|
+
} finally {
|
|
18651
|
+
rl.close();
|
|
18652
|
+
}
|
|
18653
|
+
}
|
|
18440
18654
|
async requireNamespace(payload, baseUrl) {
|
|
18441
18655
|
if (!payload || typeof payload !== "object") {
|
|
18442
18656
|
throw new Error("Service payload must be a JSON object.");
|
|
@@ -19883,6 +20097,10 @@ init_namespacedRef();
|
|
|
19883
20097
|
function parseServiceArgs(tokens) {
|
|
19884
20098
|
const rest = [...tokens];
|
|
19885
20099
|
const rawAction = rest.shift();
|
|
20100
|
+
if (rawAction && looksLikeNamespacedRef(rawAction) && rest[0] === "env") {
|
|
20101
|
+
rest.shift();
|
|
20102
|
+
return parseServiceEnvArgs(rawAction, rest);
|
|
20103
|
+
}
|
|
19886
20104
|
const action = rawAction === "view" ? "view" : rawAction;
|
|
19887
20105
|
if (!action) {
|
|
19888
20106
|
throw new Error("Missing service action. Use: service list|get|view|create|update|rename|delete");
|
|
@@ -20159,6 +20377,245 @@ function parseBareRenameId3(value, entityName) {
|
|
|
20159
20377
|
}
|
|
20160
20378
|
return normalized;
|
|
20161
20379
|
}
|
|
20380
|
+
function looksLikeNamespacedRef(value) {
|
|
20381
|
+
return value.includes(":") && !value.startsWith("-");
|
|
20382
|
+
}
|
|
20383
|
+
function parseServiceEnvArgs(appId, tokens) {
|
|
20384
|
+
const rest = [...tokens];
|
|
20385
|
+
const action = rest.shift();
|
|
20386
|
+
if (!action) {
|
|
20387
|
+
throw new Error("Usage: service <ns:app> env list|get|set|unset|resolve|pull|copy-from");
|
|
20388
|
+
}
|
|
20389
|
+
let baseUrl;
|
|
20390
|
+
let json = false;
|
|
20391
|
+
if (action === "list") {
|
|
20392
|
+
let scope;
|
|
20393
|
+
let includeSecretMeta = false;
|
|
20394
|
+
let includeSecretValue = false;
|
|
20395
|
+
while (rest.length > 0) {
|
|
20396
|
+
const token = rest.shift();
|
|
20397
|
+
switch (token) {
|
|
20398
|
+
case "--scope":
|
|
20399
|
+
scope = requireValue6(rest, token);
|
|
20400
|
+
break;
|
|
20401
|
+
case "--include-secret-meta":
|
|
20402
|
+
includeSecretMeta = true;
|
|
20403
|
+
break;
|
|
20404
|
+
case "--include-secret-value":
|
|
20405
|
+
includeSecretValue = true;
|
|
20406
|
+
break;
|
|
20407
|
+
case "--base-url":
|
|
20408
|
+
baseUrl = requireValue6(rest, token);
|
|
20409
|
+
break;
|
|
20410
|
+
case "--json":
|
|
20411
|
+
json = true;
|
|
20412
|
+
break;
|
|
20413
|
+
default:
|
|
20414
|
+
throw new Error(`Unknown service env list option: ${token}`);
|
|
20415
|
+
}
|
|
20416
|
+
}
|
|
20417
|
+
return { type: "service" /* Service */, action: "env-list", appId, scope, includeSecretMeta, includeSecretValue, baseUrl, json };
|
|
20418
|
+
}
|
|
20419
|
+
if (action === "get") {
|
|
20420
|
+
const key = rest.shift();
|
|
20421
|
+
if (!key || key.startsWith("-")) {
|
|
20422
|
+
throw new Error("Usage: service <ns:app> env get <key> --scope <scope> [--include-secret-value]");
|
|
20423
|
+
}
|
|
20424
|
+
let scope;
|
|
20425
|
+
let includeSecretValue = false;
|
|
20426
|
+
while (rest.length > 0) {
|
|
20427
|
+
const token = rest.shift();
|
|
20428
|
+
switch (token) {
|
|
20429
|
+
case "--scope":
|
|
20430
|
+
scope = requireValue6(rest, token);
|
|
20431
|
+
break;
|
|
20432
|
+
case "--include-secret-value":
|
|
20433
|
+
includeSecretValue = true;
|
|
20434
|
+
break;
|
|
20435
|
+
case "--base-url":
|
|
20436
|
+
baseUrl = requireValue6(rest, token);
|
|
20437
|
+
break;
|
|
20438
|
+
case "--json":
|
|
20439
|
+
json = true;
|
|
20440
|
+
break;
|
|
20441
|
+
default:
|
|
20442
|
+
throw new Error(`Unknown service env get option: ${token}`);
|
|
20443
|
+
}
|
|
20444
|
+
}
|
|
20445
|
+
if (!scope) {
|
|
20446
|
+
throw new Error("Usage: service <ns:app> env get <key> --scope <scope> [--include-secret-value]");
|
|
20447
|
+
}
|
|
20448
|
+
return { type: "service" /* Service */, action: "env-get", appId, key, scope, includeSecretValue, baseUrl, json };
|
|
20449
|
+
}
|
|
20450
|
+
if (action === "set") {
|
|
20451
|
+
const key = rest.shift();
|
|
20452
|
+
if (!key || key.startsWith("-")) {
|
|
20453
|
+
throw new Error("Usage: service <ns:app> env set <key> [value] --scope <scope> [--secret] [--prompt]");
|
|
20454
|
+
}
|
|
20455
|
+
let value;
|
|
20456
|
+
if (rest[0] && !rest[0].startsWith("-")) {
|
|
20457
|
+
value = rest.shift();
|
|
20458
|
+
}
|
|
20459
|
+
let scope;
|
|
20460
|
+
let secret = false;
|
|
20461
|
+
let prompt = false;
|
|
20462
|
+
while (rest.length > 0) {
|
|
20463
|
+
const token = rest.shift();
|
|
20464
|
+
switch (token) {
|
|
20465
|
+
case "--scope":
|
|
20466
|
+
scope = requireValue6(rest, token);
|
|
20467
|
+
break;
|
|
20468
|
+
case "--secret":
|
|
20469
|
+
secret = true;
|
|
20470
|
+
break;
|
|
20471
|
+
case "--prompt":
|
|
20472
|
+
prompt = true;
|
|
20473
|
+
break;
|
|
20474
|
+
case "--base-url":
|
|
20475
|
+
baseUrl = requireValue6(rest, token);
|
|
20476
|
+
break;
|
|
20477
|
+
case "--json":
|
|
20478
|
+
json = true;
|
|
20479
|
+
break;
|
|
20480
|
+
default:
|
|
20481
|
+
throw new Error(`Unknown service env set option: ${token}`);
|
|
20482
|
+
}
|
|
20483
|
+
}
|
|
20484
|
+
if (!scope) {
|
|
20485
|
+
throw new Error("Usage: service <ns:app> env set <key> [value] --scope <scope> [--secret] [--prompt]");
|
|
20486
|
+
}
|
|
20487
|
+
if (!value && !secret && !prompt) {
|
|
20488
|
+
throw new Error("Missing env value. Pass a value or use --prompt.");
|
|
20489
|
+
}
|
|
20490
|
+
return { type: "service" /* Service */, action: "env-set", appId, key, value, scope, secret, prompt, baseUrl, json };
|
|
20491
|
+
}
|
|
20492
|
+
if (action === "unset") {
|
|
20493
|
+
const key = rest.shift();
|
|
20494
|
+
if (!key || key.startsWith("-")) {
|
|
20495
|
+
throw new Error("Usage: service <ns:app> env unset <key> --scope <scope>");
|
|
20496
|
+
}
|
|
20497
|
+
let scope;
|
|
20498
|
+
while (rest.length > 0) {
|
|
20499
|
+
const token = rest.shift();
|
|
20500
|
+
switch (token) {
|
|
20501
|
+
case "--scope":
|
|
20502
|
+
scope = requireValue6(rest, token);
|
|
20503
|
+
break;
|
|
20504
|
+
case "--base-url":
|
|
20505
|
+
baseUrl = requireValue6(rest, token);
|
|
20506
|
+
break;
|
|
20507
|
+
case "--json":
|
|
20508
|
+
json = true;
|
|
20509
|
+
break;
|
|
20510
|
+
default:
|
|
20511
|
+
throw new Error(`Unknown service env unset option: ${token}`);
|
|
20512
|
+
}
|
|
20513
|
+
}
|
|
20514
|
+
if (!scope) {
|
|
20515
|
+
throw new Error("Usage: service <ns:app> env unset <key> --scope <scope>");
|
|
20516
|
+
}
|
|
20517
|
+
return { type: "service" /* Service */, action: "env-unset", appId, key, scope, baseUrl, json };
|
|
20518
|
+
}
|
|
20519
|
+
if (action === "resolve") {
|
|
20520
|
+
let stage;
|
|
20521
|
+
let branch;
|
|
20522
|
+
let includeSecretValue = false;
|
|
20523
|
+
while (rest.length > 0) {
|
|
20524
|
+
const token = rest.shift();
|
|
20525
|
+
switch (token) {
|
|
20526
|
+
case "--stage":
|
|
20527
|
+
stage = requireValue6(rest, token);
|
|
20528
|
+
break;
|
|
20529
|
+
case "--branch":
|
|
20530
|
+
branch = requireValue6(rest, token);
|
|
20531
|
+
break;
|
|
20532
|
+
case "--include-secret-value":
|
|
20533
|
+
includeSecretValue = true;
|
|
20534
|
+
break;
|
|
20535
|
+
case "--base-url":
|
|
20536
|
+
baseUrl = requireValue6(rest, token);
|
|
20537
|
+
break;
|
|
20538
|
+
case "--json":
|
|
20539
|
+
json = true;
|
|
20540
|
+
break;
|
|
20541
|
+
default:
|
|
20542
|
+
throw new Error(`Unknown service env resolve option: ${token}`);
|
|
20543
|
+
}
|
|
20544
|
+
}
|
|
20545
|
+
if (!stage) {
|
|
20546
|
+
throw new Error("Usage: service <ns:app> env resolve --stage <dev|preview|prod> [--branch <name>]");
|
|
20547
|
+
}
|
|
20548
|
+
return { type: "service" /* Service */, action: "env-resolve", appId, stage, branch, includeSecretValue, baseUrl, json };
|
|
20549
|
+
}
|
|
20550
|
+
if (action === "pull") {
|
|
20551
|
+
let stage;
|
|
20552
|
+
let branch;
|
|
20553
|
+
let output = ".env.local";
|
|
20554
|
+
while (rest.length > 0) {
|
|
20555
|
+
const token = rest.shift();
|
|
20556
|
+
switch (token) {
|
|
20557
|
+
case "--stage":
|
|
20558
|
+
stage = requireValue6(rest, token);
|
|
20559
|
+
break;
|
|
20560
|
+
case "--branch":
|
|
20561
|
+
branch = requireValue6(rest, token);
|
|
20562
|
+
break;
|
|
20563
|
+
case "--output":
|
|
20564
|
+
output = requireValue6(rest, token);
|
|
20565
|
+
break;
|
|
20566
|
+
case "--base-url":
|
|
20567
|
+
baseUrl = requireValue6(rest, token);
|
|
20568
|
+
break;
|
|
20569
|
+
case "--json":
|
|
20570
|
+
json = true;
|
|
20571
|
+
break;
|
|
20572
|
+
default:
|
|
20573
|
+
throw new Error(`Unknown service env pull option: ${token}`);
|
|
20574
|
+
}
|
|
20575
|
+
}
|
|
20576
|
+
if (!stage) {
|
|
20577
|
+
throw new Error("Usage: service <ns:app> env pull --stage <dev|preview|prod> [--branch <name>] [--output <path>]");
|
|
20578
|
+
}
|
|
20579
|
+
return { type: "service" /* Service */, action: "env-pull", appId, stage, branch, output, baseUrl, json };
|
|
20580
|
+
}
|
|
20581
|
+
if (action === "copy-from") {
|
|
20582
|
+
const sourceAppId = rest.shift();
|
|
20583
|
+
if (!sourceAppId || sourceAppId.startsWith("-")) {
|
|
20584
|
+
throw new Error("Usage: service <ns:app> env copy-from <source-ns:app> [--scope <scope>] [--include-secret] [--overwrite]");
|
|
20585
|
+
}
|
|
20586
|
+
let scope;
|
|
20587
|
+
let includeSecret = false;
|
|
20588
|
+
let overwrite = false;
|
|
20589
|
+
let onlyKeys;
|
|
20590
|
+
while (rest.length > 0) {
|
|
20591
|
+
const token = rest.shift();
|
|
20592
|
+
switch (token) {
|
|
20593
|
+
case "--scope":
|
|
20594
|
+
scope = requireValue6(rest, token);
|
|
20595
|
+
break;
|
|
20596
|
+
case "--include-secret":
|
|
20597
|
+
includeSecret = true;
|
|
20598
|
+
break;
|
|
20599
|
+
case "--overwrite":
|
|
20600
|
+
overwrite = true;
|
|
20601
|
+
break;
|
|
20602
|
+
case "--only":
|
|
20603
|
+
onlyKeys = requireValue6(rest, token).split(",").map((item) => item.trim()).filter(Boolean);
|
|
20604
|
+
break;
|
|
20605
|
+
case "--base-url":
|
|
20606
|
+
baseUrl = requireValue6(rest, token);
|
|
20607
|
+
break;
|
|
20608
|
+
case "--json":
|
|
20609
|
+
json = true;
|
|
20610
|
+
break;
|
|
20611
|
+
default:
|
|
20612
|
+
throw new Error(`Unknown service env copy-from option: ${token}`);
|
|
20613
|
+
}
|
|
20614
|
+
}
|
|
20615
|
+
return { type: "service" /* Service */, action: "env-copy-from", targetAppId: appId, sourceAppId, scope, includeSecret, overwrite, onlyKeys, baseUrl, json };
|
|
20616
|
+
}
|
|
20617
|
+
throw new Error(`Unknown service env action: ${action}`);
|
|
20618
|
+
}
|
|
20162
20619
|
|
|
20163
20620
|
// src/roleCommandParser.ts
|
|
20164
20621
|
function parseRoleArgs(tokens) {
|