@pmate/cli 0.24.29 → 0.24.31
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 +1 -0
- package/dist/index.js +185 -15
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -18201,6 +18201,13 @@ var ServiceRegistryClient = class {
|
|
|
18201
18201
|
);
|
|
18202
18202
|
return payload.items;
|
|
18203
18203
|
}
|
|
18204
|
+
async listServiceEnvs(serviceId) {
|
|
18205
|
+
const payload = await this.request(
|
|
18206
|
+
"GET",
|
|
18207
|
+
`/services/by-id/${encodeURIComponent(serviceId)}/envs`
|
|
18208
|
+
);
|
|
18209
|
+
return payload.items;
|
|
18210
|
+
}
|
|
18204
18211
|
async resolveEnv(serviceId, options) {
|
|
18205
18212
|
return this.requestWithBody(
|
|
18206
18213
|
"POST",
|
|
@@ -18355,7 +18362,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18355
18362
|
await this.deployNode(service, options);
|
|
18356
18363
|
return;
|
|
18357
18364
|
case "node-job":
|
|
18358
|
-
await this.deployScriptManaged(service);
|
|
18365
|
+
await this.deployScriptManaged(service, options);
|
|
18359
18366
|
return;
|
|
18360
18367
|
case "vite":
|
|
18361
18368
|
await this.deployVite(service, options);
|
|
@@ -18368,7 +18375,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18368
18375
|
return;
|
|
18369
18376
|
case "rust":
|
|
18370
18377
|
case "python":
|
|
18371
|
-
await this.deployScriptManaged(service);
|
|
18378
|
+
await this.deployScriptManaged(service, options);
|
|
18372
18379
|
return;
|
|
18373
18380
|
case "fc":
|
|
18374
18381
|
await this.deployFc(service, options);
|
|
@@ -18382,12 +18389,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18382
18389
|
throw new Error(`Unsupported service type for deploy: ${this.getType(service)}`);
|
|
18383
18390
|
}
|
|
18384
18391
|
}
|
|
18385
|
-
async stop(service) {
|
|
18392
|
+
async stop(service, options = {}) {
|
|
18386
18393
|
switch (this.getType(service)) {
|
|
18387
18394
|
case "node-job":
|
|
18388
18395
|
case "rust":
|
|
18389
18396
|
case "python":
|
|
18390
|
-
await this.stopScriptManaged(service);
|
|
18397
|
+
await this.stopScriptManaged(service, options);
|
|
18391
18398
|
return;
|
|
18392
18399
|
case "node":
|
|
18393
18400
|
throw new Error("service stop is only supported for script-managed python/rust services for now");
|
|
@@ -18813,7 +18820,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18813
18820
|
`echo "[pmate] Synced env to $env_local"`
|
|
18814
18821
|
].join(" && ");
|
|
18815
18822
|
}
|
|
18816
|
-
async deployScriptManaged(service) {
|
|
18823
|
+
async deployScriptManaged(service, options = {}) {
|
|
18817
18824
|
const network = this.getNetwork(service);
|
|
18818
18825
|
const runner = this.getRunner(service);
|
|
18819
18826
|
const server = network.server?.trim();
|
|
@@ -18832,6 +18839,8 @@ var ServiceRuntimeRunner = class {
|
|
|
18832
18839
|
const repoUrl = this.getRepoUrl(repository);
|
|
18833
18840
|
const gitUrl = this.withToken(repoUrl);
|
|
18834
18841
|
const scriptPath = script.startsWith("/") || script.startsWith("./") ? script : `./${script}`;
|
|
18842
|
+
const envName = options.envName ?? "prod";
|
|
18843
|
+
const envSyncCommand = await this.buildScriptEnvSyncCommand(service.id, envName);
|
|
18835
18844
|
const command = [
|
|
18836
18845
|
`cd "$HOME"`,
|
|
18837
18846
|
`[ -d "${repoDir}/.git" ] || git clone "${gitUrl}" "${repoDir}"`,
|
|
@@ -18840,11 +18849,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18840
18849
|
`if [ -f ~/.bashrc ]; then . ~/.bashrc; fi`,
|
|
18841
18850
|
`if [ -n "$(git status --porcelain)" ]; then git reset --hard HEAD; git clean -fd; fi`,
|
|
18842
18851
|
`git pull`,
|
|
18843
|
-
|
|
18852
|
+
...envSyncCommand ? [envSyncCommand] : [],
|
|
18853
|
+
`"${scriptPath}" restart --env ${shellQuote2(envName)}`
|
|
18844
18854
|
].join(" && ");
|
|
18845
18855
|
await this.runRemoteCommand(server, command);
|
|
18846
18856
|
}
|
|
18847
|
-
async stopScriptManaged(service) {
|
|
18857
|
+
async stopScriptManaged(service, options = {}) {
|
|
18848
18858
|
const network = this.getNetwork(service);
|
|
18849
18859
|
const runner = this.getRunner(service);
|
|
18850
18860
|
const server = network.server?.trim();
|
|
@@ -18861,15 +18871,51 @@ var ServiceRuntimeRunner = class {
|
|
|
18861
18871
|
}
|
|
18862
18872
|
const repoDir = this.getRepoDirName(repository);
|
|
18863
18873
|
const scriptPath = script.startsWith("/") || script.startsWith("./") ? script : `./${script}`;
|
|
18874
|
+
const envName = options.envName ?? "prod";
|
|
18875
|
+
const envSyncCommand = await this.buildScriptEnvSyncCommand(service.id, envName);
|
|
18864
18876
|
const command = [
|
|
18865
18877
|
`cd "$HOME"`,
|
|
18866
18878
|
`cd "${repoDir}"`,
|
|
18867
18879
|
`if [ -f ~/.profile ]; then . ~/.profile; fi`,
|
|
18868
18880
|
`if [ -f ~/.bashrc ]; then . ~/.bashrc; fi`,
|
|
18869
|
-
|
|
18881
|
+
...envSyncCommand ? [envSyncCommand] : [],
|
|
18882
|
+
`"${scriptPath}" stop --env ${shellQuote2(envName)}`
|
|
18870
18883
|
].join(" && ");
|
|
18871
18884
|
await this.runRemoteCommand(server, command);
|
|
18872
18885
|
}
|
|
18886
|
+
async buildScriptEnvSyncCommand(serviceId, envName) {
|
|
18887
|
+
if (!this.envProvider) {
|
|
18888
|
+
return void 0;
|
|
18889
|
+
}
|
|
18890
|
+
let pulled;
|
|
18891
|
+
try {
|
|
18892
|
+
pulled = await this.envProvider(serviceId, { stage: this.envNameToStage(envName), format: "dotenv" });
|
|
18893
|
+
} catch (error) {
|
|
18894
|
+
if (error instanceof ServiceEnvNotFoundError) {
|
|
18895
|
+
ui.warn(`No env found for ${serviceId}; skipping PMate env file sync.`);
|
|
18896
|
+
return void 0;
|
|
18897
|
+
}
|
|
18898
|
+
throw error;
|
|
18899
|
+
}
|
|
18900
|
+
const serviceRef = parseServiceRef(serviceId);
|
|
18901
|
+
const envFile = `.pmate/services/${serviceRef.namespace}/${serviceRef.name}/${envName}.env`;
|
|
18902
|
+
const content = [
|
|
18903
|
+
`PMATE_SERVICE_ID=${serviceId}`,
|
|
18904
|
+
`PMATE_SERVICE_NAMESPACE=${serviceRef.namespace}`,
|
|
18905
|
+
`PMATE_SERVICE_NAME=${serviceRef.name}`,
|
|
18906
|
+
`PMATE_SERVICE_ENV=${envName}`,
|
|
18907
|
+
pulled?.content?.trimEnd() ?? "",
|
|
18908
|
+
""
|
|
18909
|
+
].join("\n");
|
|
18910
|
+
const encodedContent = Buffer.from(content, "utf8").toString("base64");
|
|
18911
|
+
return [
|
|
18912
|
+
`env_file="$HOME/${envFile}"`,
|
|
18913
|
+
`mkdir -p "$(dirname "$env_file")"`,
|
|
18914
|
+
`printf '%s' ${shellQuote2(encodedContent)} | base64 --decode > "$env_file"`,
|
|
18915
|
+
`chmod 600 "$env_file"`,
|
|
18916
|
+
`echo "[pmate] Synced env to $env_file"`
|
|
18917
|
+
].join(" && ");
|
|
18918
|
+
}
|
|
18873
18919
|
async initStaticLike(service) {
|
|
18874
18920
|
const site = this.getSite(service);
|
|
18875
18921
|
const bucketName = site.bucket?.trim();
|
|
@@ -19698,6 +19744,13 @@ var ServiceRuntimeRunner = class {
|
|
|
19698
19744
|
function shellQuote2(value) {
|
|
19699
19745
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
19700
19746
|
}
|
|
19747
|
+
function parseServiceRef(serviceId) {
|
|
19748
|
+
const [namespace, name, extra] = serviceId.split(":");
|
|
19749
|
+
if (!namespace || !name || extra !== void 0) {
|
|
19750
|
+
throw new Error(`Invalid service id: ${serviceId}`);
|
|
19751
|
+
}
|
|
19752
|
+
return { namespace, name };
|
|
19753
|
+
}
|
|
19701
19754
|
|
|
19702
19755
|
// src/commands/ServiceCommandHandler.ts
|
|
19703
19756
|
init_namespacedRef();
|
|
@@ -19718,12 +19771,36 @@ var ServiceCommandHandler = class {
|
|
|
19718
19771
|
this.renderList(items, args.json);
|
|
19719
19772
|
return;
|
|
19720
19773
|
}
|
|
19721
|
-
case "get":
|
|
19722
|
-
case "view": {
|
|
19774
|
+
case "get": {
|
|
19723
19775
|
const record = await registry.getService(args.namespace, args.name);
|
|
19724
19776
|
this.renderJson(record, true);
|
|
19725
19777
|
return;
|
|
19726
19778
|
}
|
|
19779
|
+
case "view": {
|
|
19780
|
+
const record = await registry.getService(args.namespace, args.name);
|
|
19781
|
+
const [envsResult, envVarsResult] = await Promise.allSettled([
|
|
19782
|
+
registry.listServiceEnvs(record.id),
|
|
19783
|
+
registry.listEnvItems(record.id, { includeSecretMeta: true })
|
|
19784
|
+
]);
|
|
19785
|
+
const envs = envsResult.status === "fulfilled" ? envsResult.value : [];
|
|
19786
|
+
const envVars = envVarsResult.status === "fulfilled" ? envVarsResult.value : [];
|
|
19787
|
+
const errors = [
|
|
19788
|
+
envsResult.status === "rejected" ? { section: "envs", message: errorMessage(envsResult.reason) } : void 0,
|
|
19789
|
+
envVarsResult.status === "rejected" ? { section: "envVars", message: errorMessage(envVarsResult.reason) } : void 0
|
|
19790
|
+
].filter((item) => item !== void 0);
|
|
19791
|
+
const payload = {
|
|
19792
|
+
service: record,
|
|
19793
|
+
envs,
|
|
19794
|
+
envVars,
|
|
19795
|
+
...errors.length > 0 ? { errors } : {}
|
|
19796
|
+
};
|
|
19797
|
+
if (args.json) {
|
|
19798
|
+
this.renderJson(payload, true);
|
|
19799
|
+
} else {
|
|
19800
|
+
this.renderServiceView(payload);
|
|
19801
|
+
}
|
|
19802
|
+
return;
|
|
19803
|
+
}
|
|
19727
19804
|
case "create": {
|
|
19728
19805
|
const payload = this.readJsonFile(args.filePath);
|
|
19729
19806
|
await this.requireNamespace(payload, baseUrl);
|
|
@@ -19820,7 +19897,7 @@ var ServiceCommandHandler = class {
|
|
|
19820
19897
|
case "stop": {
|
|
19821
19898
|
const record = await registry.getService(args.namespace, args.name);
|
|
19822
19899
|
const service = args.env ? await this.materializeServiceEnv(registry, record, args.env) : record;
|
|
19823
|
-
await runtime.stop(service);
|
|
19900
|
+
await runtime.stop(service, { envName: args.env });
|
|
19824
19901
|
return;
|
|
19825
19902
|
}
|
|
19826
19903
|
case "init": {
|
|
@@ -19831,11 +19908,13 @@ var ServiceCommandHandler = class {
|
|
|
19831
19908
|
}
|
|
19832
19909
|
case "log": {
|
|
19833
19910
|
const record = await registry.getService(args.namespace, args.name);
|
|
19834
|
-
await
|
|
19911
|
+
const service = args.env ? await this.materializeServiceEnv(registry, record, args.env) : record;
|
|
19912
|
+
await runtime.log(service, {
|
|
19835
19913
|
page: args.page,
|
|
19836
19914
|
history: args.history,
|
|
19837
19915
|
search: args.search,
|
|
19838
|
-
follow: args.follow
|
|
19916
|
+
follow: args.follow,
|
|
19917
|
+
envName: args.env
|
|
19839
19918
|
});
|
|
19840
19919
|
return;
|
|
19841
19920
|
}
|
|
@@ -20370,6 +20449,85 @@ var ServiceCommandHandler = class {
|
|
|
20370
20449
|
ui.info(`${time} ${item.environment} ${status}${message}`, item);
|
|
20371
20450
|
}
|
|
20372
20451
|
}
|
|
20452
|
+
renderServiceView(payload) {
|
|
20453
|
+
const service = payload.service;
|
|
20454
|
+
ui.title(`Service ${service.id}`);
|
|
20455
|
+
ui.plain("");
|
|
20456
|
+
this.renderField("Type", this.getServiceType(service));
|
|
20457
|
+
this.renderField("Repository", "repository" in service ? service.repository : void 0);
|
|
20458
|
+
this.renderField("Directory", "dir" in service ? service.dir : void 0);
|
|
20459
|
+
this.renderField("Status", "status" in service ? service.status : void 0);
|
|
20460
|
+
this.renderField("Updated", formatTimestamp("updatedAt" in service ? service.updatedAt : void 0));
|
|
20461
|
+
ui.plain("");
|
|
20462
|
+
ui.title("Environments");
|
|
20463
|
+
if (payload.envs.length === 0) {
|
|
20464
|
+
ui.plain(" none");
|
|
20465
|
+
} else {
|
|
20466
|
+
for (const env of payload.envs) {
|
|
20467
|
+
ui.plain(` ${env.name}`);
|
|
20468
|
+
const runtime = env.runtime;
|
|
20469
|
+
if (runtime) {
|
|
20470
|
+
this.renderField("Runtime", runtime.type, 4);
|
|
20471
|
+
this.renderRuntimeFields(runtime);
|
|
20472
|
+
} else {
|
|
20473
|
+
this.renderField("Runtime", "none", 4);
|
|
20474
|
+
}
|
|
20475
|
+
const network = env.network;
|
|
20476
|
+
if (network) {
|
|
20477
|
+
this.renderField("Network", network.type, 4);
|
|
20478
|
+
this.renderField("Domain", network.domain ? `https://${network.domain}` : void 0, 4);
|
|
20479
|
+
} else {
|
|
20480
|
+
this.renderField("Network", "none", 4);
|
|
20481
|
+
}
|
|
20482
|
+
}
|
|
20483
|
+
}
|
|
20484
|
+
ui.plain("");
|
|
20485
|
+
ui.title("Env Vars");
|
|
20486
|
+
if (payload.envVars.length === 0) {
|
|
20487
|
+
ui.plain(" none");
|
|
20488
|
+
} else {
|
|
20489
|
+
for (const item of payload.envVars) {
|
|
20490
|
+
const key = item.key ?? item.name ?? item.id ?? "unknown";
|
|
20491
|
+
const scope = item.scope ? ` [${item.scope}]` : "";
|
|
20492
|
+
const kind = item.kind ? ` ${item.kind}` : "";
|
|
20493
|
+
const value = item.value !== void 0 ? ` = ${item.value}` : "";
|
|
20494
|
+
ui.plain(` ${key}${scope}${kind}${value}`);
|
|
20495
|
+
}
|
|
20496
|
+
}
|
|
20497
|
+
for (const error of payload.errors ?? []) {
|
|
20498
|
+
ui.warn(`Could not load ${error.section}`, { message: error.message });
|
|
20499
|
+
}
|
|
20500
|
+
}
|
|
20501
|
+
renderRuntimeFields(runtime) {
|
|
20502
|
+
if ("bucket" in runtime) {
|
|
20503
|
+
this.renderField("Bucket", runtime.bucket, 4);
|
|
20504
|
+
}
|
|
20505
|
+
if ("server" in runtime) {
|
|
20506
|
+
this.renderField("Server", runtime.server, 4);
|
|
20507
|
+
}
|
|
20508
|
+
if ("port" in runtime) {
|
|
20509
|
+
this.renderField("Port", runtime.port, 4);
|
|
20510
|
+
}
|
|
20511
|
+
if ("region" in runtime) {
|
|
20512
|
+
this.renderField("Region", runtime.region, 4);
|
|
20513
|
+
}
|
|
20514
|
+
if ("functionName" in runtime) {
|
|
20515
|
+
this.renderField("Function", runtime.functionName, 4);
|
|
20516
|
+
}
|
|
20517
|
+
if ("command" in runtime) {
|
|
20518
|
+
this.renderField("Command", runtime.command, 4);
|
|
20519
|
+
}
|
|
20520
|
+
if ("cwd" in runtime) {
|
|
20521
|
+
this.renderField("Cwd", runtime.cwd, 4);
|
|
20522
|
+
}
|
|
20523
|
+
}
|
|
20524
|
+
renderField(label, value, indent = 0) {
|
|
20525
|
+
if (value === void 0 || value === null || value === "") {
|
|
20526
|
+
return;
|
|
20527
|
+
}
|
|
20528
|
+
const padding = " ".repeat(indent);
|
|
20529
|
+
ui.plain(`${padding}${label.padEnd(11)} ${String(value)}`);
|
|
20530
|
+
}
|
|
20373
20531
|
async deleteServiceResources(service) {
|
|
20374
20532
|
switch (this.getServiceType(service)) {
|
|
20375
20533
|
case "vite":
|
|
@@ -20583,6 +20741,15 @@ function requireString(value, field) {
|
|
|
20583
20741
|
}
|
|
20584
20742
|
return value.trim();
|
|
20585
20743
|
}
|
|
20744
|
+
function errorMessage(error) {
|
|
20745
|
+
return error instanceof Error ? error.message : String(error);
|
|
20746
|
+
}
|
|
20747
|
+
function formatTimestamp(value) {
|
|
20748
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
20749
|
+
return void 0;
|
|
20750
|
+
}
|
|
20751
|
+
return new Date(value).toISOString();
|
|
20752
|
+
}
|
|
20586
20753
|
function splitPrimaryDomain(host) {
|
|
20587
20754
|
const normalized = host?.trim();
|
|
20588
20755
|
if (!normalized) {
|
|
@@ -22905,6 +23072,9 @@ function parseServiceArgs(tokens) {
|
|
|
22905
23072
|
case "--base-url":
|
|
22906
23073
|
baseUrl = requireValue6(rest, token);
|
|
22907
23074
|
break;
|
|
23075
|
+
case "--json":
|
|
23076
|
+
json = true;
|
|
23077
|
+
break;
|
|
22908
23078
|
default:
|
|
22909
23079
|
throw new Error(`Unknown service view option: ${token}`);
|
|
22910
23080
|
}
|
|
@@ -22943,7 +23113,7 @@ function parseServiceArgs(tokens) {
|
|
|
22943
23113
|
cwd = requireValue6(rest, token);
|
|
22944
23114
|
break;
|
|
22945
23115
|
case "--env":
|
|
22946
|
-
if (action !== "deploy" && action !== "init" && action !== "stop" && action !== "deploy-logs" && action !== "deploy-history") {
|
|
23116
|
+
if (action !== "deploy" && action !== "init" && action !== "stop" && action !== "log" && action !== "deploy-logs" && action !== "deploy-history") {
|
|
22947
23117
|
throw new Error(`Unknown service ${action} option: ${token}`);
|
|
22948
23118
|
}
|
|
22949
23119
|
env = requireValue6(rest, token);
|
|
@@ -22972,7 +23142,7 @@ function parseServiceArgs(tokens) {
|
|
|
22972
23142
|
const namespace = parsedRef.namespace;
|
|
22973
23143
|
const name = parsedRef.objectId;
|
|
22974
23144
|
if (action === "log") {
|
|
22975
|
-
return { type: "service" /* Service */, action, namespace, name, baseUrl, json, page, history, search, follow };
|
|
23145
|
+
return { type: "service" /* Service */, action, namespace, name, baseUrl, json, page, history, search, follow, env };
|
|
22976
23146
|
}
|
|
22977
23147
|
if (action === "deploy-logs" || action === "deploy-history") {
|
|
22978
23148
|
return { type: "service" /* Service */, action, namespace, name, env, page, baseUrl, json };
|