@pmate/cli 0.24.25 → 0.24.27
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 +42 -0
- package/dist/index.js +678 -31
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -913,6 +913,7 @@ type ServiceCommandArgs = {
|
|
|
913
913
|
action: "deploy" | "stop";
|
|
914
914
|
namespace: string;
|
|
915
915
|
name: string;
|
|
916
|
+
env?: string;
|
|
916
917
|
baseUrl?: string;
|
|
917
918
|
json: boolean;
|
|
918
919
|
} | {
|
|
@@ -920,6 +921,7 @@ type ServiceCommandArgs = {
|
|
|
920
921
|
action: "init";
|
|
921
922
|
namespace: string;
|
|
922
923
|
name: string;
|
|
924
|
+
env: string;
|
|
923
925
|
cwd?: string;
|
|
924
926
|
baseUrl?: string;
|
|
925
927
|
json: boolean;
|
|
@@ -943,6 +945,36 @@ type ServiceCommandArgs = {
|
|
|
943
945
|
includeSecretValue: boolean;
|
|
944
946
|
baseUrl?: string;
|
|
945
947
|
json: boolean;
|
|
948
|
+
} | {
|
|
949
|
+
type: Command.Service;
|
|
950
|
+
action: "service-env-list";
|
|
951
|
+
appId: string;
|
|
952
|
+
baseUrl?: string;
|
|
953
|
+
json: boolean;
|
|
954
|
+
} | {
|
|
955
|
+
type: Command.Service;
|
|
956
|
+
action: "service-env-get";
|
|
957
|
+
appId: string;
|
|
958
|
+
envName: string;
|
|
959
|
+
baseUrl?: string;
|
|
960
|
+
json: boolean;
|
|
961
|
+
} | {
|
|
962
|
+
type: Command.Service;
|
|
963
|
+
action: "service-env-add";
|
|
964
|
+
appId: string;
|
|
965
|
+
envName: string;
|
|
966
|
+
baseUrl?: string;
|
|
967
|
+
json: boolean;
|
|
968
|
+
} | {
|
|
969
|
+
type: Command.Service;
|
|
970
|
+
action: "service-env-expose";
|
|
971
|
+
appId: string;
|
|
972
|
+
envName: string;
|
|
973
|
+
exposeType?: "https" | "websocket";
|
|
974
|
+
off: boolean;
|
|
975
|
+
domain?: string;
|
|
976
|
+
baseUrl?: string;
|
|
977
|
+
json: boolean;
|
|
946
978
|
} | {
|
|
947
979
|
type: Command.Service;
|
|
948
980
|
action: "env-get";
|
|
@@ -1000,6 +1032,16 @@ type ServiceCommandArgs = {
|
|
|
1000
1032
|
onlyKeys?: string[];
|
|
1001
1033
|
baseUrl?: string;
|
|
1002
1034
|
json: boolean;
|
|
1035
|
+
} | {
|
|
1036
|
+
type: Command.Service;
|
|
1037
|
+
action: "env-update-scope";
|
|
1038
|
+
appId: string;
|
|
1039
|
+
fromScope: string;
|
|
1040
|
+
toScope: string;
|
|
1041
|
+
overwrite: boolean;
|
|
1042
|
+
onlyKeys?: string[];
|
|
1043
|
+
baseUrl?: string;
|
|
1044
|
+
json: boolean;
|
|
1003
1045
|
};
|
|
1004
1046
|
type VercelProjectsCommandArgs = {
|
|
1005
1047
|
type: Command.Vercel;
|
package/dist/index.js
CHANGED
|
@@ -10050,6 +10050,19 @@ var AliyunService = class {
|
|
|
10050
10050
|
);
|
|
10051
10051
|
ui.success(`Created FC custom domain: ${input.domainName}`);
|
|
10052
10052
|
}
|
|
10053
|
+
static async deleteFcCustomDomain(domainName, region) {
|
|
10054
|
+
const client = await this.createFcClient(region);
|
|
10055
|
+
try {
|
|
10056
|
+
await client.deleteCustomDomain(domainName);
|
|
10057
|
+
ui.success(`Deleted FC custom domain: ${domainName}`);
|
|
10058
|
+
} catch (error) {
|
|
10059
|
+
if (this.isNotFoundError(error)) {
|
|
10060
|
+
ui.warn(`FC custom domain not found: ${domainName}`);
|
|
10061
|
+
return;
|
|
10062
|
+
}
|
|
10063
|
+
throw error;
|
|
10064
|
+
}
|
|
10065
|
+
}
|
|
10053
10066
|
/** Add a DNS record via Aliyun DNS. */
|
|
10054
10067
|
static async addRecord(input) {
|
|
10055
10068
|
const userConfig = loadPmateConfig();
|
|
@@ -18110,6 +18123,7 @@ function readNamespaceFromPayload(payload) {
|
|
|
18110
18123
|
var import_node_fs20 = require("fs");
|
|
18111
18124
|
var import_promises6 = require("fs/promises");
|
|
18112
18125
|
var import_node_path24 = __toESM(require("path"));
|
|
18126
|
+
var import_node_child_process11 = require("child_process");
|
|
18113
18127
|
var import_promises7 = require("readline/promises");
|
|
18114
18128
|
|
|
18115
18129
|
// src/services/ServiceRuntimeRunner.ts
|
|
@@ -18198,6 +18212,20 @@ var ServiceRegistryClient = class {
|
|
|
18198
18212
|
}
|
|
18199
18213
|
);
|
|
18200
18214
|
}
|
|
18215
|
+
async getServiceEnv(serviceId, envName) {
|
|
18216
|
+
const payload = await this.request(
|
|
18217
|
+
"GET",
|
|
18218
|
+
`/services/by-id/${encodeURIComponent(serviceId)}/envs/${encodeURIComponent(envName)}`
|
|
18219
|
+
);
|
|
18220
|
+
return payload.item;
|
|
18221
|
+
}
|
|
18222
|
+
async appendDeployHistory(serviceId, input) {
|
|
18223
|
+
return this.requestWithBody(
|
|
18224
|
+
"POST",
|
|
18225
|
+
`/services/by-id/${encodeURIComponent(serviceId)}/deploy-history`,
|
|
18226
|
+
input
|
|
18227
|
+
);
|
|
18228
|
+
}
|
|
18201
18229
|
async pullEnv(serviceId, options) {
|
|
18202
18230
|
const pathname = `/services/by-id/${encodeURIComponent(serviceId)}/env/pull`;
|
|
18203
18231
|
const response = await fetch(`${this.resolveBaseUrl()}${pathname}`, {
|
|
@@ -18313,6 +18341,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18313
18341
|
}
|
|
18314
18342
|
async deploy(service, options = {}) {
|
|
18315
18343
|
switch (this.getType(service)) {
|
|
18344
|
+
case "node-api":
|
|
18345
|
+
await this.deployNode(service, options);
|
|
18346
|
+
return;
|
|
18347
|
+
case "node-job":
|
|
18348
|
+
await this.deployScriptManaged(service);
|
|
18349
|
+
return;
|
|
18316
18350
|
case "vite":
|
|
18317
18351
|
await this.deployVite(service, options);
|
|
18318
18352
|
return;
|
|
@@ -18320,14 +18354,14 @@ var ServiceRuntimeRunner = class {
|
|
|
18320
18354
|
await this.deployStatic(service, options);
|
|
18321
18355
|
return;
|
|
18322
18356
|
case "node":
|
|
18323
|
-
await this.deployNode(service);
|
|
18357
|
+
await this.deployNode(service, options);
|
|
18324
18358
|
return;
|
|
18325
18359
|
case "rust":
|
|
18326
18360
|
case "python":
|
|
18327
18361
|
await this.deployScriptManaged(service);
|
|
18328
18362
|
return;
|
|
18329
18363
|
case "fc":
|
|
18330
|
-
await this.deployFc(service);
|
|
18364
|
+
await this.deployFc(service, options);
|
|
18331
18365
|
return;
|
|
18332
18366
|
case "ios":
|
|
18333
18367
|
case "android":
|
|
@@ -18340,6 +18374,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18340
18374
|
}
|
|
18341
18375
|
async stop(service) {
|
|
18342
18376
|
switch (this.getType(service)) {
|
|
18377
|
+
case "node-job":
|
|
18343
18378
|
case "rust":
|
|
18344
18379
|
case "python":
|
|
18345
18380
|
await this.stopScriptManaged(service);
|
|
@@ -18362,6 +18397,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18362
18397
|
case "static":
|
|
18363
18398
|
await this.initStaticLike(service);
|
|
18364
18399
|
return;
|
|
18400
|
+
case "node-api":
|
|
18401
|
+
await this.initServerApp(service, options, { ensurePackageJson: true });
|
|
18402
|
+
return;
|
|
18403
|
+
case "node-job":
|
|
18404
|
+
await this.initServerApp(service, options, { ensurePackageJson: false });
|
|
18405
|
+
return;
|
|
18365
18406
|
case "node":
|
|
18366
18407
|
await this.initServerApp(service, options, { ensurePackageJson: true });
|
|
18367
18408
|
return;
|
|
@@ -18574,7 +18615,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18574
18615
|
}
|
|
18575
18616
|
await AliyunService.uploadDirectory(srcDir, bucketName);
|
|
18576
18617
|
}
|
|
18577
|
-
async deployFc(service) {
|
|
18618
|
+
async deployFc(service, options = {}) {
|
|
18578
18619
|
const fc = this.getFc(service);
|
|
18579
18620
|
this.validateFcConfig(service, fc);
|
|
18580
18621
|
const repoRoot = this.resolveRepoRoot(service);
|
|
@@ -18592,7 +18633,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18592
18633
|
await this.runCommand("pnpm", ["--filter", pkgName, "build"], repoRoot);
|
|
18593
18634
|
const registry = new ServiceRegistryClient();
|
|
18594
18635
|
const appId = `${service.namespace}:${service.name}`;
|
|
18595
|
-
const stage = fc.deployStage ?? "prod";
|
|
18636
|
+
const stage = this.envNameToStage(options.envName ?? fc.deployStage ?? "prod");
|
|
18596
18637
|
const requiredEnv = await this.syncFcRequiredEnv(service, registry, stage);
|
|
18597
18638
|
const resolved = await registry.resolveEnv(appId, {
|
|
18598
18639
|
stage,
|
|
@@ -18690,7 +18731,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18690
18731
|
url: this.buildFcUrl(fc)
|
|
18691
18732
|
});
|
|
18692
18733
|
}
|
|
18693
|
-
async deployNode(service) {
|
|
18734
|
+
async deployNode(service, options = {}) {
|
|
18694
18735
|
const network = this.getNetwork(service);
|
|
18695
18736
|
const server = network.server?.trim();
|
|
18696
18737
|
const repository = network.repository?.trim();
|
|
@@ -18717,7 +18758,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18717
18758
|
`pkg="${appDir}/package.json"`,
|
|
18718
18759
|
`if [ -f "$pkg" ] && node -e 'const fs=require("node:fs"); const p=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); process.exit(p?.scripts?.build ? 0 : 1);' "$pkg"; then (cd "${appDir}" && pnpm run build); fi`
|
|
18719
18760
|
].join("; ");
|
|
18720
|
-
const envSyncCommand = await this.buildNodeEnvSyncCommand(service.id, appDir);
|
|
18761
|
+
const envSyncCommand = await this.buildNodeEnvSyncCommand(service.id, appDir, options.envName);
|
|
18721
18762
|
const command = [
|
|
18722
18763
|
`cd "$HOME"`,
|
|
18723
18764
|
`[ -d "${repoDir}/.git" ] || git clone "${gitUrl}" "${repoDir}"`,
|
|
@@ -18735,13 +18776,13 @@ var ServiceRuntimeRunner = class {
|
|
|
18735
18776
|
].join(" && ");
|
|
18736
18777
|
await this.runRemoteCommand(server, command);
|
|
18737
18778
|
}
|
|
18738
|
-
async buildNodeEnvSyncCommand(serviceId, appDir) {
|
|
18779
|
+
async buildNodeEnvSyncCommand(serviceId, appDir, envName = "prod") {
|
|
18739
18780
|
if (!this.envProvider) {
|
|
18740
18781
|
return void 0;
|
|
18741
18782
|
}
|
|
18742
18783
|
let pulled;
|
|
18743
18784
|
try {
|
|
18744
|
-
pulled = await this.envProvider(serviceId, { stage:
|
|
18785
|
+
pulled = await this.envProvider(serviceId, { stage: this.envNameToStage(envName), format: "dotenv" });
|
|
18745
18786
|
} catch (error) {
|
|
18746
18787
|
if (error instanceof ServiceEnvNotFoundError) {
|
|
18747
18788
|
ui.warn(`No env found for ${serviceId}; skipping .env.local sync.`);
|
|
@@ -18963,6 +19004,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18963
19004
|
}
|
|
18964
19005
|
return payload.data;
|
|
18965
19006
|
}
|
|
19007
|
+
envNameToStage(envName) {
|
|
19008
|
+
if (envName === "dev" || envName === "preview" || envName === "prod") {
|
|
19009
|
+
return envName;
|
|
19010
|
+
}
|
|
19011
|
+
return "preview";
|
|
19012
|
+
}
|
|
18966
19013
|
renderPage(page, options = {}) {
|
|
18967
19014
|
ui.info("Page", {
|
|
18968
19015
|
page: page.page,
|
|
@@ -19443,10 +19490,15 @@ var ServiceRuntimeRunner = class {
|
|
|
19443
19490
|
return [];
|
|
19444
19491
|
}
|
|
19445
19492
|
const appId = `${service.namespace}:${service.name}`;
|
|
19446
|
-
const
|
|
19493
|
+
const scopedItems = await registry.listEnvItems(appId, {
|
|
19447
19494
|
scope: stage,
|
|
19448
19495
|
includeSecretMeta: true
|
|
19449
19496
|
});
|
|
19497
|
+
const allItems = await registry.listEnvItems(appId, {
|
|
19498
|
+
scope: "all",
|
|
19499
|
+
includeSecretMeta: true
|
|
19500
|
+
});
|
|
19501
|
+
const items = [...allItems, ...scopedItems];
|
|
19450
19502
|
const requiredEnv = Array.from(
|
|
19451
19503
|
new Set(
|
|
19452
19504
|
items.map((item) => item.key ?? item.name).filter((key) => typeof key === "string" && key.trim().length > 0).map((key) => key.trim())
|
|
@@ -19693,6 +19745,8 @@ var ServiceCommandHandler = class {
|
|
|
19693
19745
|
return;
|
|
19694
19746
|
}
|
|
19695
19747
|
case "delete": {
|
|
19748
|
+
const service = await registry.getService(args.namespace, args.name);
|
|
19749
|
+
await this.deleteServiceResources(service);
|
|
19696
19750
|
const record = await this.request(
|
|
19697
19751
|
baseUrl,
|
|
19698
19752
|
"DELETE",
|
|
@@ -19737,17 +19791,32 @@ var ServiceCommandHandler = class {
|
|
|
19737
19791
|
}
|
|
19738
19792
|
case "deploy": {
|
|
19739
19793
|
const record = await registry.getService(args.namespace, args.name);
|
|
19740
|
-
await
|
|
19794
|
+
const service = await this.materializeServiceEnv(registry, record, args.env);
|
|
19795
|
+
try {
|
|
19796
|
+
await runtime.deploy(service, { envName: args.env });
|
|
19797
|
+
await this.appendDeployHistory(registry, record.id, args.env, "success");
|
|
19798
|
+
} catch (error) {
|
|
19799
|
+
await this.appendDeployHistory(
|
|
19800
|
+
registry,
|
|
19801
|
+
record.id,
|
|
19802
|
+
args.env,
|
|
19803
|
+
"failed",
|
|
19804
|
+
error instanceof Error ? error.message : String(error)
|
|
19805
|
+
);
|
|
19806
|
+
throw error;
|
|
19807
|
+
}
|
|
19741
19808
|
return;
|
|
19742
19809
|
}
|
|
19743
19810
|
case "stop": {
|
|
19744
19811
|
const record = await registry.getService(args.namespace, args.name);
|
|
19745
|
-
await
|
|
19812
|
+
const service = args.env ? await this.materializeServiceEnv(registry, record, args.env) : record;
|
|
19813
|
+
await runtime.stop(service);
|
|
19746
19814
|
return;
|
|
19747
19815
|
}
|
|
19748
19816
|
case "init": {
|
|
19749
19817
|
const record = await registry.getService(args.namespace, args.name);
|
|
19750
|
-
await
|
|
19818
|
+
const service = await this.materializeServiceEnv(registry, record, args.env);
|
|
19819
|
+
await runtime.init(service, { cwd: args.cwd });
|
|
19751
19820
|
return;
|
|
19752
19821
|
}
|
|
19753
19822
|
case "log": {
|
|
@@ -19863,6 +19932,188 @@ var ServiceCommandHandler = class {
|
|
|
19863
19932
|
this.renderJson(payload, args.json);
|
|
19864
19933
|
return;
|
|
19865
19934
|
}
|
|
19935
|
+
case "env-update-scope": {
|
|
19936
|
+
const payload = await this.request(
|
|
19937
|
+
baseUrl,
|
|
19938
|
+
"POST",
|
|
19939
|
+
`${this.buildEnvBasePath(args.appId)}/update-scope`,
|
|
19940
|
+
{
|
|
19941
|
+
fromScope: args.fromScope,
|
|
19942
|
+
toScope: args.toScope,
|
|
19943
|
+
...args.overwrite ? { overwrite: true } : {},
|
|
19944
|
+
...args.onlyKeys?.length ? { onlyKeys: args.onlyKeys } : {}
|
|
19945
|
+
}
|
|
19946
|
+
);
|
|
19947
|
+
ui.success(`Updated env scope for ${args.appId}: ${args.fromScope} -> ${args.toScope}`);
|
|
19948
|
+
await this.syncFcRequiredEnvFromServiceEnv(registry, args.appId, args.toScope);
|
|
19949
|
+
this.renderJson(payload, args.json);
|
|
19950
|
+
return;
|
|
19951
|
+
}
|
|
19952
|
+
case "service-env-list": {
|
|
19953
|
+
const payload = await this.request(
|
|
19954
|
+
baseUrl,
|
|
19955
|
+
"GET",
|
|
19956
|
+
this.buildServiceEnvBasePath(args.appId)
|
|
19957
|
+
);
|
|
19958
|
+
this.renderJson(payload, true);
|
|
19959
|
+
return;
|
|
19960
|
+
}
|
|
19961
|
+
case "service-env-get": {
|
|
19962
|
+
const payload = await this.request(
|
|
19963
|
+
baseUrl,
|
|
19964
|
+
"GET",
|
|
19965
|
+
`${this.buildServiceEnvBasePath(args.appId)}/${encodeURIComponent(args.envName)}`
|
|
19966
|
+
);
|
|
19967
|
+
this.renderJson(payload, true);
|
|
19968
|
+
return;
|
|
19969
|
+
}
|
|
19970
|
+
case "service-env-add": {
|
|
19971
|
+
const payload = await this.request(
|
|
19972
|
+
baseUrl,
|
|
19973
|
+
"PUT",
|
|
19974
|
+
`${this.buildServiceEnvBasePath(args.appId)}/${encodeURIComponent(args.envName)}`,
|
|
19975
|
+
{
|
|
19976
|
+
name: args.envName
|
|
19977
|
+
}
|
|
19978
|
+
);
|
|
19979
|
+
ui.success(`Updated service env ${args.envName} for ${args.appId}`);
|
|
19980
|
+
this.renderJson(payload, args.json);
|
|
19981
|
+
return;
|
|
19982
|
+
}
|
|
19983
|
+
case "service-env-expose": {
|
|
19984
|
+
const payload = await this.request(
|
|
19985
|
+
baseUrl,
|
|
19986
|
+
"POST",
|
|
19987
|
+
`${this.buildServiceEnvBasePath(args.appId)}/${encodeURIComponent(args.envName)}/expose`,
|
|
19988
|
+
{
|
|
19989
|
+
...args.exposeType ? { type: args.exposeType } : {},
|
|
19990
|
+
...args.domain ? { domain: args.domain } : {},
|
|
19991
|
+
...args.off ? { off: true } : {}
|
|
19992
|
+
}
|
|
19993
|
+
);
|
|
19994
|
+
ui.success(
|
|
19995
|
+
args.off ? `Disabled network for ${args.appId} ${args.envName}` : `Updated network for ${args.appId} ${args.envName}`
|
|
19996
|
+
);
|
|
19997
|
+
this.renderJson(payload, args.json);
|
|
19998
|
+
return;
|
|
19999
|
+
}
|
|
20000
|
+
}
|
|
20001
|
+
}
|
|
20002
|
+
async materializeServiceEnv(registry, service, envName) {
|
|
20003
|
+
if (!envName || !this.isDefinitionStyleService(service)) {
|
|
20004
|
+
return service;
|
|
20005
|
+
}
|
|
20006
|
+
const env = await registry.getServiceEnv(service.id, envName);
|
|
20007
|
+
return this.buildRuntimeServiceRecord(service, env);
|
|
20008
|
+
}
|
|
20009
|
+
isDefinitionStyleService(service) {
|
|
20010
|
+
return "repository" in service || "type" in service && (service.type === "node-api" || service.type === "node-job") || !("site" in service) && !("network" in service) && !("fc" in service) && !("runtimeType" in service);
|
|
20011
|
+
}
|
|
20012
|
+
buildRuntimeServiceRecord(service, env) {
|
|
20013
|
+
if (!("type" in service)) {
|
|
20014
|
+
return service;
|
|
20015
|
+
}
|
|
20016
|
+
const repository = service.repository?.trim();
|
|
20017
|
+
const dir = service.dir?.trim();
|
|
20018
|
+
const runtime = env.runtime;
|
|
20019
|
+
if (!runtime) {
|
|
20020
|
+
throw new Error(`Missing runtime for ${service.id} env ${env.name}`);
|
|
20021
|
+
}
|
|
20022
|
+
if (!repository) {
|
|
20023
|
+
throw new Error(`Missing service.repository for ${service.id}`);
|
|
20024
|
+
}
|
|
20025
|
+
if (!dir) {
|
|
20026
|
+
throw new Error(`Missing service.dir for ${service.id}`);
|
|
20027
|
+
}
|
|
20028
|
+
if (runtime.type === "ali-oss") {
|
|
20029
|
+
const domainParts = splitPrimaryDomain(env.network?.domain);
|
|
20030
|
+
return {
|
|
20031
|
+
id: service.id,
|
|
20032
|
+
namespace: service.namespace,
|
|
20033
|
+
name: service.name,
|
|
20034
|
+
type: service.type === "static" ? "static" : "vite",
|
|
20035
|
+
site: {
|
|
20036
|
+
exposeType: "static-site",
|
|
20037
|
+
repository,
|
|
20038
|
+
dir,
|
|
20039
|
+
bucket: requireString(runtime.bucket, `runtime.bucket for ${service.id} ${env.name}`),
|
|
20040
|
+
domain: domainParts.domain,
|
|
20041
|
+
...domainParts.subdomain ? { subdomain: domainParts.subdomain } : {}
|
|
20042
|
+
}
|
|
20043
|
+
};
|
|
20044
|
+
}
|
|
20045
|
+
if (runtime.type === "ssh-pm2") {
|
|
20046
|
+
return {
|
|
20047
|
+
id: service.id,
|
|
20048
|
+
namespace: service.namespace,
|
|
20049
|
+
name: runtime.appName?.trim() || service.name,
|
|
20050
|
+
type: service.type === "node-api" ? "node-api" : "node",
|
|
20051
|
+
network: {
|
|
20052
|
+
exposeType: env.network?.type === "websocket" ? "websocket" : env.network ? "rest" : "internal",
|
|
20053
|
+
repository,
|
|
20054
|
+
dir,
|
|
20055
|
+
server: requireString(runtime.server, `runtime.server for ${service.id} ${env.name}`),
|
|
20056
|
+
...runtime.port !== void 0 ? { port: runtime.port } : {},
|
|
20057
|
+
...splitPrimaryDomain(env.network?.domain)
|
|
20058
|
+
}
|
|
20059
|
+
};
|
|
20060
|
+
}
|
|
20061
|
+
if (runtime.type === "ssh-script") {
|
|
20062
|
+
return {
|
|
20063
|
+
id: service.id,
|
|
20064
|
+
namespace: service.namespace,
|
|
20065
|
+
name: service.name,
|
|
20066
|
+
type: service.type === "node-job" ? "node-job" : service.type === "rust" ? "rust" : "python",
|
|
20067
|
+
network: {
|
|
20068
|
+
exposeType: env.network?.type === "websocket" ? "websocket" : env.network ? "rest" : "internal",
|
|
20069
|
+
repository,
|
|
20070
|
+
dir: runtime.cwd?.trim() || dir,
|
|
20071
|
+
server: requireString(runtime.server, `runtime.server for ${service.id} ${env.name}`),
|
|
20072
|
+
...runtime.port !== void 0 ? { port: runtime.port } : {},
|
|
20073
|
+
...splitPrimaryDomain(env.network?.domain)
|
|
20074
|
+
},
|
|
20075
|
+
runner: {
|
|
20076
|
+
script: requireString(runtime.command, `runtime.command for ${service.id} ${env.name}`)
|
|
20077
|
+
}
|
|
20078
|
+
};
|
|
20079
|
+
}
|
|
20080
|
+
if (runtime.type === "fc") {
|
|
20081
|
+
const domainParts = splitPrimaryDomain(env.network?.domain);
|
|
20082
|
+
return {
|
|
20083
|
+
id: service.id,
|
|
20084
|
+
namespace: service.namespace,
|
|
20085
|
+
name: service.name,
|
|
20086
|
+
type: "fc",
|
|
20087
|
+
fc: {
|
|
20088
|
+
provider: runtime.provider ?? "aliyun",
|
|
20089
|
+
region: requireString(runtime.region, `runtime.region for ${service.id} ${env.name}`),
|
|
20090
|
+
repository,
|
|
20091
|
+
dir,
|
|
20092
|
+
functionName: requireString(runtime.functionName, `runtime.functionName for ${service.id} ${env.name}`),
|
|
20093
|
+
...runtime.configFile ? { configFile: runtime.configFile } : {},
|
|
20094
|
+
...runtime.qualifier ? { qualifier: runtime.qualifier } : {},
|
|
20095
|
+
...domainParts.domain ? { domain: domainParts.domain } : {},
|
|
20096
|
+
...domainParts.subdomain ? { subdomain: domainParts.subdomain } : {},
|
|
20097
|
+
deployStage: env.name === "prod" || env.name === "preview" || env.name === "dev" ? env.name : "preview"
|
|
20098
|
+
}
|
|
20099
|
+
};
|
|
20100
|
+
}
|
|
20101
|
+
throw new Error(`Unsupported runtime ${runtime.type} for ${service.id} env ${env.name}`);
|
|
20102
|
+
}
|
|
20103
|
+
async appendDeployHistory(registry, serviceId, environment, status, message) {
|
|
20104
|
+
try {
|
|
20105
|
+
await registry.appendDeployHistory(serviceId, {
|
|
20106
|
+
environment,
|
|
20107
|
+
status,
|
|
20108
|
+
...message ? { message } : {}
|
|
20109
|
+
});
|
|
20110
|
+
} catch (error) {
|
|
20111
|
+
ui.warn("Failed to append deploy history", {
|
|
20112
|
+
serviceId,
|
|
20113
|
+
environment,
|
|
20114
|
+
status,
|
|
20115
|
+
message: error instanceof Error ? error.message : String(error)
|
|
20116
|
+
});
|
|
19866
20117
|
}
|
|
19867
20118
|
}
|
|
19868
20119
|
resolveBaseUrl(baseUrl) {
|
|
@@ -19905,6 +20156,9 @@ var ServiceCommandHandler = class {
|
|
|
19905
20156
|
buildEnvBasePath(appId) {
|
|
19906
20157
|
return `/services/by-id/${encodeURIComponent(appId)}/env`;
|
|
19907
20158
|
}
|
|
20159
|
+
buildServiceEnvBasePath(appId) {
|
|
20160
|
+
return `/services/by-id/${encodeURIComponent(appId)}/envs`;
|
|
20161
|
+
}
|
|
19908
20162
|
buildEnvPath(appId, query) {
|
|
19909
20163
|
const params = new URLSearchParams();
|
|
19910
20164
|
if (query.scope) {
|
|
@@ -20014,10 +20268,7 @@ var ServiceCommandHandler = class {
|
|
|
20014
20268
|
if (!("type" in service) || service.type !== "fc" || !service.fc) {
|
|
20015
20269
|
return;
|
|
20016
20270
|
}
|
|
20017
|
-
const items = await
|
|
20018
|
-
scope,
|
|
20019
|
-
includeSecretMeta: true
|
|
20020
|
-
});
|
|
20271
|
+
const items = await this.listEffectiveEnvItems(registry, appId, scope);
|
|
20021
20272
|
const requiredEnv = Array.from(
|
|
20022
20273
|
new Set(
|
|
20023
20274
|
items.map((item) => item.key ?? item.name).filter((key) => typeof key === "string" && key.trim().length > 0).map((key) => key.trim())
|
|
@@ -20039,6 +20290,20 @@ var ServiceCommandHandler = class {
|
|
|
20039
20290
|
const normalizedRight = [...right].sort();
|
|
20040
20291
|
return normalizedLeft.every((value, index) => value === normalizedRight[index]);
|
|
20041
20292
|
}
|
|
20293
|
+
async listEffectiveEnvItems(registry, appId, scope) {
|
|
20294
|
+
const scopedItems = await registry.listEnvItems(appId, {
|
|
20295
|
+
scope,
|
|
20296
|
+
includeSecretMeta: true
|
|
20297
|
+
});
|
|
20298
|
+
if (scope === "all") {
|
|
20299
|
+
return scopedItems;
|
|
20300
|
+
}
|
|
20301
|
+
const allItems = await registry.listEnvItems(appId, {
|
|
20302
|
+
scope: "all",
|
|
20303
|
+
includeSecretMeta: true
|
|
20304
|
+
});
|
|
20305
|
+
return [...allItems, ...scopedItems];
|
|
20306
|
+
}
|
|
20042
20307
|
renderList(items, asJson) {
|
|
20043
20308
|
if (asJson) {
|
|
20044
20309
|
ui.plain(JSON.stringify(items, null, 2));
|
|
@@ -20052,6 +20317,206 @@ var ServiceCommandHandler = class {
|
|
|
20052
20317
|
ui.info(formatNamespacedDisplayId(item.namespace, item.name), item);
|
|
20053
20318
|
}
|
|
20054
20319
|
}
|
|
20320
|
+
async deleteServiceResources(service) {
|
|
20321
|
+
switch (this.getServiceType(service)) {
|
|
20322
|
+
case "vite":
|
|
20323
|
+
case "static":
|
|
20324
|
+
await this.deleteStaticResources(service);
|
|
20325
|
+
return;
|
|
20326
|
+
case "node":
|
|
20327
|
+
case "rust":
|
|
20328
|
+
case "python":
|
|
20329
|
+
await this.deleteServerResources(service);
|
|
20330
|
+
return;
|
|
20331
|
+
case "fc":
|
|
20332
|
+
await this.deleteFcResources(service);
|
|
20333
|
+
return;
|
|
20334
|
+
case "ios":
|
|
20335
|
+
case "android":
|
|
20336
|
+
ui.warn(`Service type "${this.getServiceType(service)}" has no runtime resources to delete`);
|
|
20337
|
+
return;
|
|
20338
|
+
default:
|
|
20339
|
+
throw new Error(`Unsupported service type for delete: ${this.getServiceType(service)}`);
|
|
20340
|
+
}
|
|
20341
|
+
}
|
|
20342
|
+
async deleteStaticResources(service) {
|
|
20343
|
+
const site = this.getStaticSiteConfig(service);
|
|
20344
|
+
const bucketName = site.bucket?.trim();
|
|
20345
|
+
const domainName = site.domain?.trim();
|
|
20346
|
+
if (!bucketName) {
|
|
20347
|
+
throw new Error(`Missing site.bucket for ${service.id}`);
|
|
20348
|
+
}
|
|
20349
|
+
if (!domainName) {
|
|
20350
|
+
throw new Error(`Missing site.domain for ${service.id}`);
|
|
20351
|
+
}
|
|
20352
|
+
const subdomain = site.subdomain?.trim();
|
|
20353
|
+
const rr = subdomain || "@";
|
|
20354
|
+
const cdnDomain = subdomain ? `${subdomain}.${domainName}` : domainName;
|
|
20355
|
+
const cname = await AliyunService.getCdnCname(cdnDomain);
|
|
20356
|
+
if (cname) {
|
|
20357
|
+
this.logDeletedRecords(
|
|
20358
|
+
`Removed CNAME record for ${cdnDomain}`,
|
|
20359
|
+
await AliyunService.deleteDomainRecords({
|
|
20360
|
+
domainName,
|
|
20361
|
+
rr,
|
|
20362
|
+
type: "CNAME",
|
|
20363
|
+
value: cname
|
|
20364
|
+
})
|
|
20365
|
+
);
|
|
20366
|
+
} else {
|
|
20367
|
+
ui.warn(`No CDN CNAME found for ${cdnDomain}; deleting matching CNAME records by host.`);
|
|
20368
|
+
this.logDeletedRecords(
|
|
20369
|
+
`Removed CNAME record for ${cdnDomain}`,
|
|
20370
|
+
await AliyunService.deleteDomainRecords({
|
|
20371
|
+
domainName,
|
|
20372
|
+
rr,
|
|
20373
|
+
type: "CNAME"
|
|
20374
|
+
})
|
|
20375
|
+
);
|
|
20376
|
+
}
|
|
20377
|
+
if (!subdomain) {
|
|
20378
|
+
this.logDeletedRecords(
|
|
20379
|
+
`Removed CNAME record for www.${domainName}`,
|
|
20380
|
+
await AliyunService.deleteDomainRecords({
|
|
20381
|
+
domainName,
|
|
20382
|
+
rr: "www",
|
|
20383
|
+
type: "CNAME",
|
|
20384
|
+
value: domainName
|
|
20385
|
+
})
|
|
20386
|
+
);
|
|
20387
|
+
}
|
|
20388
|
+
await AliyunService.deleteCdnDomain(cdnDomain);
|
|
20389
|
+
await AliyunService.deleteBucketAndContents(bucketName);
|
|
20390
|
+
}
|
|
20391
|
+
async deleteServerResources(service) {
|
|
20392
|
+
const network = this.getNetworkConfig(service);
|
|
20393
|
+
const subdomain = network.subdomain?.trim();
|
|
20394
|
+
if (!subdomain) {
|
|
20395
|
+
ui.warn(`No subdomain configured for ${service.id}; nothing to tear down on DNS/nginx.`);
|
|
20396
|
+
return;
|
|
20397
|
+
}
|
|
20398
|
+
const server = network.server?.trim();
|
|
20399
|
+
if (!server) {
|
|
20400
|
+
throw new Error(`Missing network.server for ${service.id}`);
|
|
20401
|
+
}
|
|
20402
|
+
await this.removeRemoteConfig(server, `/etc/nginx/sites-enabled/${subdomain}.conf`);
|
|
20403
|
+
ui.success(`Removed nginx config for ${subdomain} from ${server}`);
|
|
20404
|
+
await this.reloadNginx(server);
|
|
20405
|
+
ui.success(`Reloaded nginx on ${server}`);
|
|
20406
|
+
const domainName = network.domain?.trim() || "pmate.chat";
|
|
20407
|
+
const serverAddress = await resolveServerAddress(server);
|
|
20408
|
+
this.logDeletedRecords(
|
|
20409
|
+
`Removed A record for ${subdomain}.${domainName}`,
|
|
20410
|
+
await AliyunService.deleteDomainRecords({
|
|
20411
|
+
domainName,
|
|
20412
|
+
rr: subdomain,
|
|
20413
|
+
type: "A",
|
|
20414
|
+
value: serverAddress
|
|
20415
|
+
})
|
|
20416
|
+
);
|
|
20417
|
+
}
|
|
20418
|
+
async deleteFcResources(service) {
|
|
20419
|
+
const fc = this.getFcConfig(service);
|
|
20420
|
+
const domainName = fc.domain?.trim();
|
|
20421
|
+
if (!domainName) {
|
|
20422
|
+
ui.warn(`No fc.domain configured for ${service.id}; nothing to tear down on DNS/FC custom domain.`);
|
|
20423
|
+
return;
|
|
20424
|
+
}
|
|
20425
|
+
const region = fc.region?.trim();
|
|
20426
|
+
if (!region) {
|
|
20427
|
+
throw new Error(`Missing fc.region for ${service.id}`);
|
|
20428
|
+
}
|
|
20429
|
+
const subdomain = fc.subdomain?.trim();
|
|
20430
|
+
const rr = subdomain || "@";
|
|
20431
|
+
const host = subdomain ? `${subdomain}.${domainName}` : domainName;
|
|
20432
|
+
await AliyunService.deleteFcCustomDomain(host, region);
|
|
20433
|
+
const accountId = await AliyunService.getAccountId();
|
|
20434
|
+
this.logDeletedRecords(
|
|
20435
|
+
`Removed CNAME record for ${host}`,
|
|
20436
|
+
await AliyunService.deleteDomainRecords({
|
|
20437
|
+
domainName,
|
|
20438
|
+
rr,
|
|
20439
|
+
type: "CNAME",
|
|
20440
|
+
value: `${accountId}.${region}.fc.aliyuncs.com`
|
|
20441
|
+
})
|
|
20442
|
+
);
|
|
20443
|
+
}
|
|
20444
|
+
getServiceType(service) {
|
|
20445
|
+
return "runtimeType" in service ? service.runtimeType : service.type;
|
|
20446
|
+
}
|
|
20447
|
+
getStaticSiteConfig(service) {
|
|
20448
|
+
if ("runtimeType" in service) {
|
|
20449
|
+
return {
|
|
20450
|
+
bucket: service.deploy?.bucket,
|
|
20451
|
+
domain: service.deploy?.domain,
|
|
20452
|
+
subdomain: service.deploy?.subdomain
|
|
20453
|
+
};
|
|
20454
|
+
}
|
|
20455
|
+
return service.site ?? {};
|
|
20456
|
+
}
|
|
20457
|
+
getNetworkConfig(service) {
|
|
20458
|
+
if ("runtimeType" in service) {
|
|
20459
|
+
return {
|
|
20460
|
+
server: service.deploy?.server,
|
|
20461
|
+
domain: service.deploy?.domain,
|
|
20462
|
+
subdomain: service.deploy?.subdomain
|
|
20463
|
+
};
|
|
20464
|
+
}
|
|
20465
|
+
return service.network ?? {};
|
|
20466
|
+
}
|
|
20467
|
+
getFcConfig(service) {
|
|
20468
|
+
if ("runtimeType" in service) {
|
|
20469
|
+
return {
|
|
20470
|
+
region: void 0,
|
|
20471
|
+
domain: service.deploy?.domain,
|
|
20472
|
+
subdomain: service.deploy?.subdomain
|
|
20473
|
+
};
|
|
20474
|
+
}
|
|
20475
|
+
return service.fc ?? {};
|
|
20476
|
+
}
|
|
20477
|
+
logDeletedRecords(message, deletedCount) {
|
|
20478
|
+
if (deletedCount > 0) {
|
|
20479
|
+
ui.success(message, { deletedCount });
|
|
20480
|
+
return;
|
|
20481
|
+
}
|
|
20482
|
+
ui.warn(`${message} skipped`, { deletedCount });
|
|
20483
|
+
}
|
|
20484
|
+
removeRemoteConfig(server, remotePath) {
|
|
20485
|
+
return new Promise((resolve, reject) => {
|
|
20486
|
+
const target = `pmate@${server}`;
|
|
20487
|
+
const child = (0, import_node_child_process11.spawn)("ssh", [target, "sudo", "rm", "-f", remotePath], {
|
|
20488
|
+
stdio: ["ignore", "inherit", "inherit"]
|
|
20489
|
+
});
|
|
20490
|
+
child.on("error", (error) => {
|
|
20491
|
+
reject(error);
|
|
20492
|
+
});
|
|
20493
|
+
child.on("close", (code) => {
|
|
20494
|
+
if (code === 0) {
|
|
20495
|
+
resolve();
|
|
20496
|
+
return;
|
|
20497
|
+
}
|
|
20498
|
+
reject(new Error(`ssh to ${server} exited with code ${code}`));
|
|
20499
|
+
});
|
|
20500
|
+
});
|
|
20501
|
+
}
|
|
20502
|
+
reloadNginx(server) {
|
|
20503
|
+
return new Promise((resolve, reject) => {
|
|
20504
|
+
const target = `pmate@${server}`;
|
|
20505
|
+
const child = (0, import_node_child_process11.spawn)("ssh", [target, "sudo", "nginx", "-s", "reload"], {
|
|
20506
|
+
stdio: ["ignore", "inherit", "inherit"]
|
|
20507
|
+
});
|
|
20508
|
+
child.on("error", (error) => {
|
|
20509
|
+
reject(error);
|
|
20510
|
+
});
|
|
20511
|
+
child.on("close", (code) => {
|
|
20512
|
+
if (code === 0) {
|
|
20513
|
+
resolve();
|
|
20514
|
+
return;
|
|
20515
|
+
}
|
|
20516
|
+
reject(new Error(`nginx reload on ${server} exited with code ${code}`));
|
|
20517
|
+
});
|
|
20518
|
+
});
|
|
20519
|
+
}
|
|
20055
20520
|
renderJson(value, asJson) {
|
|
20056
20521
|
if (!asJson) {
|
|
20057
20522
|
return;
|
|
@@ -20059,11 +20524,31 @@ var ServiceCommandHandler = class {
|
|
|
20059
20524
|
ui.plain(JSON.stringify(value, null, 2));
|
|
20060
20525
|
}
|
|
20061
20526
|
};
|
|
20527
|
+
function requireString(value, field) {
|
|
20528
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
20529
|
+
throw new Error(`Missing ${field}`);
|
|
20530
|
+
}
|
|
20531
|
+
return value.trim();
|
|
20532
|
+
}
|
|
20533
|
+
function splitPrimaryDomain(host) {
|
|
20534
|
+
const normalized = host?.trim();
|
|
20535
|
+
if (!normalized) {
|
|
20536
|
+
return { domain: "pmate.chat" };
|
|
20537
|
+
}
|
|
20538
|
+
const parts = normalized.split(".").filter(Boolean);
|
|
20539
|
+
if (parts.length <= 2) {
|
|
20540
|
+
return { domain: normalized };
|
|
20541
|
+
}
|
|
20542
|
+
return {
|
|
20543
|
+
subdomain: parts.slice(0, -2).join("."),
|
|
20544
|
+
domain: parts.slice(-2).join(".")
|
|
20545
|
+
};
|
|
20546
|
+
}
|
|
20062
20547
|
|
|
20063
20548
|
// src/commands/VercelCommandHandler.ts
|
|
20064
|
-
var
|
|
20549
|
+
var import_node_child_process12 = require("child_process");
|
|
20065
20550
|
var import_node_util2 = require("util");
|
|
20066
|
-
var execFileAsync2 = (0, import_node_util2.promisify)(
|
|
20551
|
+
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process12.execFile);
|
|
20067
20552
|
function parseDeploymentTimestamp(deployment) {
|
|
20068
20553
|
const candidates = [deployment.createdAt, deployment.readyAt, deployment.ready];
|
|
20069
20554
|
for (const value of candidates) {
|
|
@@ -22307,10 +22792,14 @@ init_namespacedRef();
|
|
|
22307
22792
|
function parseServiceArgs(tokens) {
|
|
22308
22793
|
const rest = [...tokens];
|
|
22309
22794
|
const rawAction = rest.shift();
|
|
22310
|
-
if (rawAction && looksLikeNamespacedRef(rawAction) && rest[0] === "env") {
|
|
22795
|
+
if (rawAction && looksLikeNamespacedRef(rawAction) && rest[0] === "env-vars") {
|
|
22311
22796
|
rest.shift();
|
|
22312
22797
|
return parseServiceEnvArgs(rawAction, rest);
|
|
22313
22798
|
}
|
|
22799
|
+
if (rawAction && looksLikeNamespacedRef(rawAction) && rest[0] === "env") {
|
|
22800
|
+
rest.shift();
|
|
22801
|
+
return parseServiceEnvDefinitionArgs(rawAction, rest);
|
|
22802
|
+
}
|
|
22314
22803
|
const action = rawAction === "view" ? "view" : rawAction;
|
|
22315
22804
|
if (!action) {
|
|
22316
22805
|
throw new Error("Missing service action. Use: service list|get|view|create|update|rename|delete|deploy|stop|init|log");
|
|
@@ -22380,6 +22869,7 @@ function parseServiceArgs(tokens) {
|
|
|
22380
22869
|
let history = false;
|
|
22381
22870
|
let search;
|
|
22382
22871
|
let follow = false;
|
|
22872
|
+
let env;
|
|
22383
22873
|
while (rest.length > 0) {
|
|
22384
22874
|
const token = rest.shift();
|
|
22385
22875
|
switch (token) {
|
|
@@ -22392,6 +22882,12 @@ function parseServiceArgs(tokens) {
|
|
|
22392
22882
|
}
|
|
22393
22883
|
cwd = requireValue6(rest, token);
|
|
22394
22884
|
break;
|
|
22885
|
+
case "--env":
|
|
22886
|
+
if (action !== "deploy" && action !== "init" && action !== "stop") {
|
|
22887
|
+
throw new Error(`Unknown service ${action} option: ${token}`);
|
|
22888
|
+
}
|
|
22889
|
+
env = requireValue6(rest, token);
|
|
22890
|
+
break;
|
|
22395
22891
|
case "--page":
|
|
22396
22892
|
page = Number.parseInt(requireValue6(rest, token), 10);
|
|
22397
22893
|
break;
|
|
@@ -22419,10 +22915,16 @@ function parseServiceArgs(tokens) {
|
|
|
22419
22915
|
return { type: "service" /* Service */, action, namespace, name, baseUrl, json, page, history, search, follow };
|
|
22420
22916
|
}
|
|
22421
22917
|
if (action === "deploy" || action === "stop") {
|
|
22422
|
-
|
|
22918
|
+
if (action === "deploy" && !env) {
|
|
22919
|
+
throw new Error("Missing required option --env for service deploy");
|
|
22920
|
+
}
|
|
22921
|
+
return { type: "service" /* Service */, action, namespace, name, env, baseUrl, json };
|
|
22423
22922
|
}
|
|
22424
22923
|
if (action === "init") {
|
|
22425
|
-
|
|
22924
|
+
if (!env) {
|
|
22925
|
+
throw new Error("Missing required option --env for service init");
|
|
22926
|
+
}
|
|
22927
|
+
return { type: "service" /* Service */, action, namespace, name, env, cwd, baseUrl, json };
|
|
22426
22928
|
}
|
|
22427
22929
|
return { type: "service" /* Service */, action, namespace, name, baseUrl, json };
|
|
22428
22930
|
}
|
|
@@ -22590,11 +23092,111 @@ function parseBareRenameId3(value, entityName) {
|
|
|
22590
23092
|
function looksLikeNamespacedRef(value) {
|
|
22591
23093
|
return value.includes(":") && !value.startsWith("-");
|
|
22592
23094
|
}
|
|
23095
|
+
function parseServiceEnvDefinitionArgs(appId, tokens) {
|
|
23096
|
+
const rest = [...tokens];
|
|
23097
|
+
const action = rest.shift();
|
|
23098
|
+
if (!action) {
|
|
23099
|
+
throw new Error("Usage: service <ns:service> env list|get|add|expose");
|
|
23100
|
+
}
|
|
23101
|
+
let baseUrl;
|
|
23102
|
+
let json = false;
|
|
23103
|
+
if (action === "list") {
|
|
23104
|
+
while (rest.length > 0) {
|
|
23105
|
+
const token = rest.shift();
|
|
23106
|
+
switch (token) {
|
|
23107
|
+
case "--base-url":
|
|
23108
|
+
baseUrl = requireValue6(rest, token);
|
|
23109
|
+
break;
|
|
23110
|
+
case "--json":
|
|
23111
|
+
json = true;
|
|
23112
|
+
break;
|
|
23113
|
+
default:
|
|
23114
|
+
throw new Error(`Unknown service env list option: ${token}`);
|
|
23115
|
+
}
|
|
23116
|
+
}
|
|
23117
|
+
return { type: "service" /* Service */, action: "service-env-list", appId, baseUrl, json };
|
|
23118
|
+
}
|
|
23119
|
+
if (action === "get" || action === "add") {
|
|
23120
|
+
const envName = rest.shift();
|
|
23121
|
+
if (!envName || envName.startsWith("-")) {
|
|
23122
|
+
throw new Error(`Usage: service <ns:service> env ${action} <env> [--base-url <url>] [--json]`);
|
|
23123
|
+
}
|
|
23124
|
+
while (rest.length > 0) {
|
|
23125
|
+
const token = rest.shift();
|
|
23126
|
+
switch (token) {
|
|
23127
|
+
case "--base-url":
|
|
23128
|
+
baseUrl = requireValue6(rest, token);
|
|
23129
|
+
break;
|
|
23130
|
+
case "--json":
|
|
23131
|
+
json = true;
|
|
23132
|
+
break;
|
|
23133
|
+
default:
|
|
23134
|
+
throw new Error(`Unknown service env ${action} option: ${token}`);
|
|
23135
|
+
}
|
|
23136
|
+
}
|
|
23137
|
+
return {
|
|
23138
|
+
type: "service" /* Service */,
|
|
23139
|
+
action: action === "get" ? "service-env-get" : "service-env-add",
|
|
23140
|
+
appId,
|
|
23141
|
+
envName,
|
|
23142
|
+
baseUrl,
|
|
23143
|
+
json
|
|
23144
|
+
};
|
|
23145
|
+
}
|
|
23146
|
+
if (action === "expose") {
|
|
23147
|
+
const envName = rest.shift();
|
|
23148
|
+
if (!envName || envName.startsWith("-")) {
|
|
23149
|
+
throw new Error("Usage: service <ns:service> env expose <env> [--type https|websocket] [--domain <domain>] [--off]");
|
|
23150
|
+
}
|
|
23151
|
+
let exposeType;
|
|
23152
|
+
let domain;
|
|
23153
|
+
let off = false;
|
|
23154
|
+
while (rest.length > 0) {
|
|
23155
|
+
const token = rest.shift();
|
|
23156
|
+
switch (token) {
|
|
23157
|
+
case "--type": {
|
|
23158
|
+
const value = requireValue6(rest, token);
|
|
23159
|
+
if (value !== "https" && value !== "websocket") {
|
|
23160
|
+
throw new Error("--type must be https or websocket");
|
|
23161
|
+
}
|
|
23162
|
+
exposeType = value;
|
|
23163
|
+
break;
|
|
23164
|
+
}
|
|
23165
|
+
case "--domain":
|
|
23166
|
+
domain = requireValue6(rest, token);
|
|
23167
|
+
break;
|
|
23168
|
+
case "--off":
|
|
23169
|
+
off = true;
|
|
23170
|
+
break;
|
|
23171
|
+
case "--base-url":
|
|
23172
|
+
baseUrl = requireValue6(rest, token);
|
|
23173
|
+
break;
|
|
23174
|
+
case "--json":
|
|
23175
|
+
json = true;
|
|
23176
|
+
break;
|
|
23177
|
+
default:
|
|
23178
|
+
throw new Error(`Unknown service env expose option: ${token}`);
|
|
23179
|
+
}
|
|
23180
|
+
}
|
|
23181
|
+
return {
|
|
23182
|
+
type: "service" /* Service */,
|
|
23183
|
+
action: "service-env-expose",
|
|
23184
|
+
appId,
|
|
23185
|
+
envName,
|
|
23186
|
+
exposeType,
|
|
23187
|
+
domain,
|
|
23188
|
+
off,
|
|
23189
|
+
baseUrl,
|
|
23190
|
+
json
|
|
23191
|
+
};
|
|
23192
|
+
}
|
|
23193
|
+
throw new Error(`Unknown service env action: ${action}`);
|
|
23194
|
+
}
|
|
22593
23195
|
function parseServiceEnvArgs(appId, tokens) {
|
|
22594
23196
|
const rest = [...tokens];
|
|
22595
23197
|
const action = rest.shift();
|
|
22596
23198
|
if (!action) {
|
|
22597
|
-
throw new Error("Usage: service <ns:app> env list|get|set|unset|resolve|pull|copy-from");
|
|
23199
|
+
throw new Error("Usage: service <ns:app> env list|get|set|unset|resolve|pull|copy-from|update-scope");
|
|
22598
23200
|
}
|
|
22599
23201
|
let baseUrl;
|
|
22600
23202
|
let json = false;
|
|
@@ -22606,6 +23208,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22606
23208
|
const token = rest.shift();
|
|
22607
23209
|
switch (token) {
|
|
22608
23210
|
case "--scope":
|
|
23211
|
+
case "--env":
|
|
22609
23212
|
scope = requireValue6(rest, token);
|
|
22610
23213
|
break;
|
|
22611
23214
|
case "--include-secret-meta":
|
|
@@ -22637,6 +23240,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22637
23240
|
const token = rest.shift();
|
|
22638
23241
|
switch (token) {
|
|
22639
23242
|
case "--scope":
|
|
23243
|
+
case "--env":
|
|
22640
23244
|
scope = requireValue6(rest, token);
|
|
22641
23245
|
break;
|
|
22642
23246
|
case "--include-secret-value":
|
|
@@ -22652,9 +23256,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22652
23256
|
throw new Error(`Unknown service env get option: ${token}`);
|
|
22653
23257
|
}
|
|
22654
23258
|
}
|
|
22655
|
-
|
|
22656
|
-
throw new Error("Usage: service <ns:app> env get <key> --scope <scope> [--include-secret-value]");
|
|
22657
|
-
}
|
|
23259
|
+
scope = scope ?? "all";
|
|
22658
23260
|
return { type: "service" /* Service */, action: "env-get", appId, key, scope, includeSecretValue, baseUrl, json };
|
|
22659
23261
|
}
|
|
22660
23262
|
if (action === "set") {
|
|
@@ -22673,6 +23275,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22673
23275
|
const token = rest.shift();
|
|
22674
23276
|
switch (token) {
|
|
22675
23277
|
case "--scope":
|
|
23278
|
+
case "--env":
|
|
22676
23279
|
scope = requireValue6(rest, token);
|
|
22677
23280
|
break;
|
|
22678
23281
|
case "--secret":
|
|
@@ -22691,9 +23294,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22691
23294
|
throw new Error(`Unknown service env set option: ${token}`);
|
|
22692
23295
|
}
|
|
22693
23296
|
}
|
|
22694
|
-
|
|
22695
|
-
throw new Error("Usage: service <ns:app> env set <key> [value] --scope <scope> [--secret] [--prompt]");
|
|
22696
|
-
}
|
|
23297
|
+
scope = scope ?? "all";
|
|
22697
23298
|
if (!value && !secret && !prompt) {
|
|
22698
23299
|
throw new Error("Missing env value. Pass a value or use --prompt.");
|
|
22699
23300
|
}
|
|
@@ -22709,6 +23310,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22709
23310
|
const token = rest.shift();
|
|
22710
23311
|
switch (token) {
|
|
22711
23312
|
case "--scope":
|
|
23313
|
+
case "--env":
|
|
22712
23314
|
scope = requireValue6(rest, token);
|
|
22713
23315
|
break;
|
|
22714
23316
|
case "--base-url":
|
|
@@ -22721,9 +23323,7 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22721
23323
|
throw new Error(`Unknown service env unset option: ${token}`);
|
|
22722
23324
|
}
|
|
22723
23325
|
}
|
|
22724
|
-
|
|
22725
|
-
throw new Error("Usage: service <ns:app> env unset <key> --scope <scope>");
|
|
22726
|
-
}
|
|
23326
|
+
scope = scope ?? "all";
|
|
22727
23327
|
return { type: "service" /* Service */, action: "env-unset", appId, key, scope, baseUrl, json };
|
|
22728
23328
|
}
|
|
22729
23329
|
if (action === "resolve") {
|
|
@@ -22824,6 +23424,53 @@ function parseServiceEnvArgs(appId, tokens) {
|
|
|
22824
23424
|
}
|
|
22825
23425
|
return { type: "service" /* Service */, action: "env-copy-from", targetAppId: appId, sourceAppId, scope, includeSecret, overwrite, onlyKeys, baseUrl, json };
|
|
22826
23426
|
}
|
|
23427
|
+
if (action === "update-scope") {
|
|
23428
|
+
let fromScope;
|
|
23429
|
+
let toScope;
|
|
23430
|
+
let overwrite = false;
|
|
23431
|
+
let onlyKeys;
|
|
23432
|
+
while (rest.length > 0) {
|
|
23433
|
+
const token = rest.shift();
|
|
23434
|
+
switch (token) {
|
|
23435
|
+
case "--from":
|
|
23436
|
+
case "--from-scope":
|
|
23437
|
+
fromScope = requireValue6(rest, token);
|
|
23438
|
+
break;
|
|
23439
|
+
case "--to":
|
|
23440
|
+
case "--to-scope":
|
|
23441
|
+
toScope = requireValue6(rest, token);
|
|
23442
|
+
break;
|
|
23443
|
+
case "--overwrite":
|
|
23444
|
+
overwrite = true;
|
|
23445
|
+
break;
|
|
23446
|
+
case "--only":
|
|
23447
|
+
onlyKeys = requireValue6(rest, token).split(",").map((item) => item.trim()).filter(Boolean);
|
|
23448
|
+
break;
|
|
23449
|
+
case "--base-url":
|
|
23450
|
+
baseUrl = requireValue6(rest, token);
|
|
23451
|
+
break;
|
|
23452
|
+
case "--json":
|
|
23453
|
+
json = true;
|
|
23454
|
+
break;
|
|
23455
|
+
default:
|
|
23456
|
+
throw new Error(`Unknown service env update-scope option: ${token}`);
|
|
23457
|
+
}
|
|
23458
|
+
}
|
|
23459
|
+
if (!fromScope || !toScope) {
|
|
23460
|
+
throw new Error("Usage: service <ns:app> env update-scope --from <scope> --to <scope> [--overwrite] [--only <key,key>] [--base-url <url>] [--json]");
|
|
23461
|
+
}
|
|
23462
|
+
return {
|
|
23463
|
+
type: "service" /* Service */,
|
|
23464
|
+
action: "env-update-scope",
|
|
23465
|
+
appId,
|
|
23466
|
+
fromScope,
|
|
23467
|
+
toScope,
|
|
23468
|
+
overwrite,
|
|
23469
|
+
onlyKeys,
|
|
23470
|
+
baseUrl,
|
|
23471
|
+
json
|
|
23472
|
+
};
|
|
23473
|
+
}
|
|
22827
23474
|
throw new Error(`Unknown service env action: ${action}`);
|
|
22828
23475
|
}
|
|
22829
23476
|
|