@mesh-tech/mesh-cli 0.12.7 → 0.14.0
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/README.md +227 -0
- package/assets/app-skill/SKILL.md +59 -0
- package/dist/bin/mesh.js +579 -140
- package/dist/bin/mesh.js.map +4 -4
- package/dist/build-info.json +2 -2
- package/dist/src/commands/create-app.d.ts +37 -0
- package/dist/src/commands/create-app.d.ts.map +1 -1
- package/dist/src/commands/create-app.js +141 -26
- package/dist/src/commands/create-app.js.map +1 -1
- package/dist/src/commands/secrets/index.d.ts +1 -0
- package/dist/src/commands/secrets/index.d.ts.map +1 -1
- package/dist/src/commands/secrets/index.js +12 -0
- package/dist/src/commands/secrets/index.js.map +1 -1
- package/dist/src/commands/secrets/reindex.d.ts +48 -0
- package/dist/src/commands/secrets/reindex.d.ts.map +1 -0
- package/dist/src/commands/secrets/reindex.js +157 -0
- package/dist/src/commands/secrets/reindex.js.map +1 -0
- package/dist/src/commands/secrets/set.d.ts +63 -0
- package/dist/src/commands/secrets/set.d.ts.map +1 -1
- package/dist/src/commands/secrets/set.js +78 -3
- package/dist/src/commands/secrets/set.js.map +1 -1
- package/dist/src/commands/skills.d.ts +48 -8
- package/dist/src/commands/skills.d.ts.map +1 -1
- package/dist/src/commands/skills.js +204 -12
- package/dist/src/commands/skills.js.map +1 -1
- package/dist/src/utils/scaffold-versions.d.ts +57 -0
- package/dist/src/utils/scaffold-versions.d.ts.map +1 -0
- package/dist/src/utils/scaffold-versions.js +75 -0
- package/dist/src/utils/scaffold-versions.js.map +1 -0
- package/fragments/agents/AGENTS.md.hbs +4 -3
- package/fragments/base/package.json.hbs +4 -5
- package/fragments/service/api/package.json.hbs +5 -5
- package/fragments/temporal/worker/package.json.hbs +5 -5
- package/package.json +3 -2
- package/skills/core/SKILL.md +15 -3
- package/templates/apps-repo/package.json.hbs +2 -1
- package/templates/apps-repo/pnpm-workspace.yaml +9 -1
package/dist/bin/mesh.js
CHANGED
|
@@ -890,8 +890,8 @@ ${body}${MANAGED_END}
|
|
|
890
890
|
return existing.slice(0, startIdx) + section + existing.slice(tail);
|
|
891
891
|
}
|
|
892
892
|
if (existing.length === 0) return section;
|
|
893
|
-
const
|
|
894
|
-
return existing +
|
|
893
|
+
const sep5 = existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
894
|
+
return existing + sep5 + section;
|
|
895
895
|
}
|
|
896
896
|
function newStsClient() {
|
|
897
897
|
return new STSClient({ region: DEFAULT_REGION });
|
|
@@ -1859,8 +1859,8 @@ function resolveHubPlatformName(platform) {
|
|
|
1859
1859
|
return platform?.name ?? "mesh";
|
|
1860
1860
|
}
|
|
1861
1861
|
async function ssmGetParameter(name) {
|
|
1862
|
-
const { SSMClient:
|
|
1863
|
-
const ssm = new
|
|
1862
|
+
const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2 } = await import("@aws-sdk/client-ssm");
|
|
1863
|
+
const ssm = new SSMClient5({ region: process.env.AWS_REGION || "us-east-2" });
|
|
1864
1864
|
const resp = await ssm.send(new GetParameterCommand2({ Name: name, WithDecryption: true }));
|
|
1865
1865
|
return resp.Parameter?.Value;
|
|
1866
1866
|
}
|
|
@@ -1901,8 +1901,8 @@ var init_kubeconfig = __esm({
|
|
|
1901
1901
|
// libs/mesh-cli/src/utils/temporal-auth.ts
|
|
1902
1902
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
1903
1903
|
async function resolveTemporalAuth(tenant, env, platformName = tenant) {
|
|
1904
|
-
const { SSMClient:
|
|
1905
|
-
const ssm = new
|
|
1904
|
+
const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2 } = await import("@aws-sdk/client-ssm");
|
|
1905
|
+
const ssm = new SSMClient5({ region: process.env.AWS_REGION || "us-east-2" });
|
|
1906
1906
|
const results = {};
|
|
1907
1907
|
async function trySSM(name) {
|
|
1908
1908
|
try {
|
|
@@ -2297,8 +2297,8 @@ function buildFabricCheckPayload(targetBytes = 8e3) {
|
|
|
2297
2297
|
return JSON.stringify({ ...base, pad: "x".repeat(Math.max(0, targetBytes - overhead)) });
|
|
2298
2298
|
}
|
|
2299
2299
|
async function verifyFabric() {
|
|
2300
|
-
const { SSMClient:
|
|
2301
|
-
const ssm = new
|
|
2300
|
+
const { SSMClient: SSMClient5, PutParameterCommand, GetParameterCommand: GetParameterCommand2, GetParametersByPathCommand: GetParametersByPathCommand3, DeleteParametersCommand } = await import("@aws-sdk/client-ssm");
|
|
2301
|
+
const ssm = new SSMClient5(AWS_CONFIG);
|
|
2302
2302
|
const payload = buildFabricCheckPayload();
|
|
2303
2303
|
const mainParam = FABRIC_CHECK_PATH;
|
|
2304
2304
|
const childParams = [`${FABRIC_CHECK_PATH}/vpc`, `${FABRIC_CHECK_PATH}/eks`];
|
|
@@ -2350,8 +2350,8 @@ async function verifyFabric() {
|
|
|
2350
2350
|
}
|
|
2351
2351
|
}
|
|
2352
2352
|
async function registerTenantEnv(tenant, opts = {}) {
|
|
2353
|
-
const { SSMClient:
|
|
2354
|
-
const ssm = new
|
|
2353
|
+
const { SSMClient: SSMClient5, PutParameterCommand } = await import("@aws-sdk/client-ssm");
|
|
2354
|
+
const ssm = new SSMClient5(AWS_CONFIG);
|
|
2355
2355
|
await ssm.send(
|
|
2356
2356
|
new PutParameterCommand({
|
|
2357
2357
|
Name: `/mesh-platform/${tenant}`,
|
|
@@ -2379,8 +2379,8 @@ async function registerTenantEnv(tenant, opts = {}) {
|
|
|
2379
2379
|
);
|
|
2380
2380
|
}
|
|
2381
2381
|
async function seedLocalPlatform() {
|
|
2382
|
-
const { SSMClient:
|
|
2383
|
-
const ssm = new
|
|
2382
|
+
const { SSMClient: SSMClient5, PutParameterCommand } = await import("@aws-sdk/client-ssm");
|
|
2383
|
+
const ssm = new SSMClient5(AWS_CONFIG);
|
|
2384
2384
|
await ssm.send(
|
|
2385
2385
|
new PutParameterCommand({
|
|
2386
2386
|
Name: APP_TENANTS_PARAM,
|
|
@@ -2434,14 +2434,14 @@ var init_seed = __esm({
|
|
|
2434
2434
|
// libs/mesh-cli/src/commands/local/helpers.ts
|
|
2435
2435
|
import * as net2 from "net";
|
|
2436
2436
|
async function upsertLocalSecret(secretId, value, client) {
|
|
2437
|
-
const { SecretsManagerClient:
|
|
2438
|
-
const sm = client ?? new
|
|
2437
|
+
const { SecretsManagerClient: SecretsManagerClient9, CreateSecretCommand: CreateSecretCommand4, PutSecretValueCommand: PutSecretValueCommand4 } = await import("@aws-sdk/client-secrets-manager");
|
|
2438
|
+
const sm = client ?? new SecretsManagerClient9(LOCAL_AWS_CONFIG);
|
|
2439
2439
|
const secretString = JSON.stringify(value);
|
|
2440
2440
|
try {
|
|
2441
|
-
await sm.send(new
|
|
2441
|
+
await sm.send(new CreateSecretCommand4({ Name: secretId, SecretString: secretString }));
|
|
2442
2442
|
} catch (err) {
|
|
2443
2443
|
if (err?.name === "ResourceExistsException") {
|
|
2444
|
-
await sm.send(new
|
|
2444
|
+
await sm.send(new PutSecretValueCommand4({ SecretId: secretId, SecretString: secretString }));
|
|
2445
2445
|
} else {
|
|
2446
2446
|
throw err;
|
|
2447
2447
|
}
|
|
@@ -3158,12 +3158,12 @@ async function fetchRemoteExternalCredentials(tenant, env, external, profile) {
|
|
|
3158
3158
|
const region = process.env.MESH_PLATFORM_REGION ?? process.env.AWS_REGION ?? "us-east-2";
|
|
3159
3159
|
const fallbackProfile = !process.env.AWS_ACCESS_KEY_ID && !process.env.AWS_PROFILE ? process.env.MESH_AWS_PROFILE ?? profile : void 0;
|
|
3160
3160
|
try {
|
|
3161
|
-
const { SecretsManagerClient:
|
|
3161
|
+
const { SecretsManagerClient: SecretsManagerClient9, GetSecretValueCommand: GetSecretValueCommand9 } = await import("@aws-sdk/client-secrets-manager");
|
|
3162
3162
|
if (fallbackProfile) process.env.AWS_PROFILE = fallbackProfile;
|
|
3163
|
-
const sm = new
|
|
3163
|
+
const sm = new SecretsManagerClient9({ region });
|
|
3164
3164
|
let res;
|
|
3165
3165
|
try {
|
|
3166
|
-
res = await sm.send(new
|
|
3166
|
+
res = await sm.send(new GetSecretValueCommand9({ SecretId: secretId }));
|
|
3167
3167
|
} finally {
|
|
3168
3168
|
if (fallbackProfile) delete process.env.AWS_PROFILE;
|
|
3169
3169
|
}
|
|
@@ -3277,8 +3277,8 @@ async function seedLocalMock(args) {
|
|
|
3277
3277
|
`${secretName}/.config`,
|
|
3278
3278
|
Object.fromEntries(Object.entries(value).filter(([key]) => !SECRET_KEY_RE.test(key)))
|
|
3279
3279
|
);
|
|
3280
|
-
const { SSMClient:
|
|
3281
|
-
const ssm = new
|
|
3280
|
+
const { SSMClient: SSMClient5, PutParameterCommand } = await import("@aws-sdk/client-ssm");
|
|
3281
|
+
const ssm = new SSMClient5(LOCAL_AWS_CONFIG);
|
|
3282
3282
|
const base = `/mesh-platform/${tenant}/${LOCAL_ENV}/apps/${app}/stacks/local/external-services/${decl.external}`;
|
|
3283
3283
|
await ssm.send(
|
|
3284
3284
|
new PutParameterCommand({
|
|
@@ -3720,8 +3720,8 @@ async function seedHubAuth(pat) {
|
|
|
3720
3720
|
return config;
|
|
3721
3721
|
}
|
|
3722
3722
|
async function writeRegistryParams(cliClientId, awsConfig) {
|
|
3723
|
-
const { SSMClient:
|
|
3724
|
-
const ssm = new
|
|
3723
|
+
const { SSMClient: SSMClient5, PutParameterCommand } = await import("@aws-sdk/client-ssm");
|
|
3724
|
+
const ssm = new SSMClient5(awsConfig);
|
|
3725
3725
|
await ssm.send(
|
|
3726
3726
|
new PutParameterCommand({
|
|
3727
3727
|
Name: ZITADEL_SSM_PARAM,
|
|
@@ -3911,9 +3911,9 @@ async function ensureM2mCaller(pat, tenant, app, orgId, projectId, roles) {
|
|
|
3911
3911
|
return false;
|
|
3912
3912
|
}
|
|
3913
3913
|
async function authSecretExists(tenant, app, service) {
|
|
3914
|
-
const { SecretsManagerClient:
|
|
3915
|
-
const sm = new
|
|
3916
|
-
return sm.send(new
|
|
3914
|
+
const { SecretsManagerClient: SecretsManagerClient9, GetSecretValueCommand: GetSecretValueCommand9 } = await import("@aws-sdk/client-secrets-manager");
|
|
3915
|
+
const sm = new SecretsManagerClient9(LOCAL_AWS_CONFIG);
|
|
3916
|
+
return sm.send(new GetSecretValueCommand9({ SecretId: authSecretPath(tenant, app, service) })).then(
|
|
3917
3917
|
() => true,
|
|
3918
3918
|
() => false
|
|
3919
3919
|
);
|
|
@@ -3924,8 +3924,8 @@ async function writeAuthSecret(tenant, app, service, value) {
|
|
|
3924
3924
|
logSuccess(`Stored service credentials \u2192 ${name}`);
|
|
3925
3925
|
}
|
|
3926
3926
|
async function registerLocalApp(args) {
|
|
3927
|
-
const { SSMClient:
|
|
3928
|
-
const ssm = new
|
|
3927
|
+
const { SSMClient: SSMClient5, PutParameterCommand } = await import("@aws-sdk/client-ssm");
|
|
3928
|
+
const ssm = new SSMClient5(LOCAL_AWS_CONFIG);
|
|
3929
3929
|
const put2 = (name, value, description) => ssm.send(
|
|
3930
3930
|
new PutParameterCommand({ Name: name, Type: "String", Overwrite: true, Value: JSON.stringify(value), Description: description })
|
|
3931
3931
|
);
|
|
@@ -3975,8 +3975,8 @@ async function registerLocalApp(args) {
|
|
|
3975
3975
|
}
|
|
3976
3976
|
async function reconcileRegistryFromZitadel() {
|
|
3977
3977
|
const pat = readSeederPat();
|
|
3978
|
-
const { SSMClient:
|
|
3979
|
-
const ssm = new
|
|
3978
|
+
const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2, PutParameterCommand } = await import("@aws-sdk/client-ssm");
|
|
3979
|
+
const ssm = new SSMClient5(LOCAL_AWS_CONFIG);
|
|
3980
3980
|
const orgs = await api(pat, "POST", "/admin/v1/orgs/_search", { query: { limit: 200 } });
|
|
3981
3981
|
const tenants = [];
|
|
3982
3982
|
let apps = 0;
|
|
@@ -7297,8 +7297,8 @@ function registerDevCommand(program2) {
|
|
|
7297
7297
|
});
|
|
7298
7298
|
dev.command("test-user [name]").description("Get Temporal test user credentials (from Pulumi-managed test users)").option("--tenant <tenant>", "Tenant name", "mesh").option("--env <env>", "Environment", "dev").option("--region <region>", "AWS region", "us-east-2").action(
|
|
7299
7299
|
async (name, opts) => {
|
|
7300
|
-
const { SSMClient:
|
|
7301
|
-
const ssm = new
|
|
7300
|
+
const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2, GetParametersByPathCommand: GetParametersByPathCommand3 } = await import("@aws-sdk/client-ssm");
|
|
7301
|
+
const ssm = new SSMClient5({ region: opts.region });
|
|
7302
7302
|
const basePath = `/mesh-platform/${opts.tenant}/${opts.env}/temporal/test-users`;
|
|
7303
7303
|
if (!name) {
|
|
7304
7304
|
try {
|
|
@@ -9291,9 +9291,9 @@ function parseTenantEnv(context) {
|
|
|
9291
9291
|
}
|
|
9292
9292
|
async function getRegistrySsmExport(tenant, env) {
|
|
9293
9293
|
try {
|
|
9294
|
-
const { SSMClient:
|
|
9294
|
+
const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2 } = await import("@aws-sdk/client-ssm");
|
|
9295
9295
|
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? CA_REGION;
|
|
9296
|
-
const ssm = new
|
|
9296
|
+
const ssm = new SSMClient5({ region });
|
|
9297
9297
|
const ssmPath = `/mesh-platform/${tenant}/${env}/registry`;
|
|
9298
9298
|
const response = await ssm.send(new GetParameterCommand2({ Name: ssmPath }));
|
|
9299
9299
|
if (!response.Parameter?.Value) return null;
|
|
@@ -9883,9 +9883,9 @@ async function discoverConfigFromSsm(context) {
|
|
|
9883
9883
|
const ssmPath = `/mesh-platform/${tenant}/${env}/platform/zitadel`;
|
|
9884
9884
|
logInfo(`Attempting SSM discovery from ${ssmPath}...`);
|
|
9885
9885
|
try {
|
|
9886
|
-
const { SSMClient:
|
|
9886
|
+
const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2 } = await import("@aws-sdk/client-ssm");
|
|
9887
9887
|
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? "us-east-2";
|
|
9888
|
-
const ssm = new
|
|
9888
|
+
const ssm = new SSMClient5({ region });
|
|
9889
9889
|
const resp = await ssm.send(new GetParameterCommand2({ Name: ssmPath }));
|
|
9890
9890
|
const raw = resp.Parameter?.Value;
|
|
9891
9891
|
if (!raw) {
|
|
@@ -11415,6 +11415,63 @@ ${raw}`;
|
|
|
11415
11415
|
${MANAGED_MARKER}
|
|
11416
11416
|
${raw.slice(frontmatter.length)}`;
|
|
11417
11417
|
}
|
|
11418
|
+
function meshTechScopeDirs(root, maxDepth = 6) {
|
|
11419
|
+
const scopes = [];
|
|
11420
|
+
const walk = (dir, depth) => {
|
|
11421
|
+
if (depth > maxDepth) return;
|
|
11422
|
+
let entries;
|
|
11423
|
+
try {
|
|
11424
|
+
entries = fs21.readdirSync(dir, { withFileTypes: true });
|
|
11425
|
+
} catch {
|
|
11426
|
+
return;
|
|
11427
|
+
}
|
|
11428
|
+
for (const entry of entries) {
|
|
11429
|
+
if (!entry.isDirectory()) continue;
|
|
11430
|
+
if (entry.name === "node_modules") {
|
|
11431
|
+
const scope = path23.join(dir, entry.name, "@mesh-tech");
|
|
11432
|
+
if (fs21.existsSync(scope)) scopes.push(scope);
|
|
11433
|
+
continue;
|
|
11434
|
+
}
|
|
11435
|
+
if (entry.name.startsWith(".")) continue;
|
|
11436
|
+
walk(path23.join(dir, entry.name), depth + 1);
|
|
11437
|
+
}
|
|
11438
|
+
};
|
|
11439
|
+
walk(root, 0);
|
|
11440
|
+
return scopes;
|
|
11441
|
+
}
|
|
11442
|
+
function listPackageSkills(root) {
|
|
11443
|
+
const byName = /* @__PURE__ */ new Map();
|
|
11444
|
+
for (const scopeDir of meshTechScopeDirs(root)) {
|
|
11445
|
+
for (const pkg of fs21.readdirSync(scopeDir, { withFileTypes: true })) {
|
|
11446
|
+
if (!pkg.isDirectory() && !pkg.isSymbolicLink()) continue;
|
|
11447
|
+
if (pkg.name === BASE_SKILL_PACKAGE) continue;
|
|
11448
|
+
const skillsDir = path23.join(scopeDir, pkg.name, "skills");
|
|
11449
|
+
if (!fs21.existsSync(skillsDir)) continue;
|
|
11450
|
+
for (const domain of fs21.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
11451
|
+
const source = path23.join(skillsDir, domain.name, "SKILL.md");
|
|
11452
|
+
if (!fs21.existsSync(source)) continue;
|
|
11453
|
+
const name = `mesh-${pkg.name}-${domain.name}`;
|
|
11454
|
+
if (!byName.has(name)) byName.set(name, { name, dir: path23.join(skillsDir, domain.name), source });
|
|
11455
|
+
}
|
|
11456
|
+
}
|
|
11457
|
+
}
|
|
11458
|
+
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
11459
|
+
}
|
|
11460
|
+
function copySkillExtras(sourceDir, targetDir) {
|
|
11461
|
+
for (const entry of fs21.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
11462
|
+
if (entry.name === "SKILL.md") continue;
|
|
11463
|
+
fs21.cpSync(path23.join(sourceDir, entry.name), path23.join(targetDir, entry.name), { recursive: true });
|
|
11464
|
+
}
|
|
11465
|
+
}
|
|
11466
|
+
function seedAppSkill(root, appName, appRelPath) {
|
|
11467
|
+
const target = path23.join(root, ".claude", "skills", appName, "SKILL.md");
|
|
11468
|
+
if (fs21.existsSync(target)) return null;
|
|
11469
|
+
const template = fs21.readFileSync(cliAsset("assets", "app-skill", "SKILL.md"), "utf-8");
|
|
11470
|
+
const body = template.replaceAll("__APP_NAME__", appName).replaceAll("__APP_PATH__", appRelPath || ".");
|
|
11471
|
+
fs21.mkdirSync(path23.dirname(target), { recursive: true });
|
|
11472
|
+
fs21.writeFileSync(target, body);
|
|
11473
|
+
return path23.relative(root, target);
|
|
11474
|
+
}
|
|
11418
11475
|
function planSync(root) {
|
|
11419
11476
|
const items = [];
|
|
11420
11477
|
for (const skill of listBaseSkills()) {
|
|
@@ -11441,6 +11498,43 @@ function planSync(root) {
|
|
|
11441
11498
|
}
|
|
11442
11499
|
}
|
|
11443
11500
|
}
|
|
11501
|
+
const packageSkills = listPackageSkills(root);
|
|
11502
|
+
for (const skill of packageSkills) {
|
|
11503
|
+
const targetDir = path23.join(root, ".claude", "skills", skill.name);
|
|
11504
|
+
const target = path23.join(targetDir, "SKILL.md");
|
|
11505
|
+
const desired = renderManagedSkill(skill.source);
|
|
11506
|
+
const label = `.claude/skills/${skill.name}/SKILL.md (platform skill)`;
|
|
11507
|
+
if (!fs21.existsSync(target)) {
|
|
11508
|
+
items.push({
|
|
11509
|
+
label,
|
|
11510
|
+
state: "write",
|
|
11511
|
+
apply: () => {
|
|
11512
|
+
fs21.mkdirSync(targetDir, { recursive: true });
|
|
11513
|
+
fs21.writeFileSync(target, desired);
|
|
11514
|
+
copySkillExtras(skill.dir, targetDir);
|
|
11515
|
+
}
|
|
11516
|
+
});
|
|
11517
|
+
} else {
|
|
11518
|
+
const current = fs21.readFileSync(target, "utf-8");
|
|
11519
|
+
if (current === desired) {
|
|
11520
|
+
items.push({ label, state: "ok" });
|
|
11521
|
+
} else if (current.includes(MANAGED_MARKER)) {
|
|
11522
|
+
items.push({
|
|
11523
|
+
label,
|
|
11524
|
+
state: "write",
|
|
11525
|
+
apply: () => {
|
|
11526
|
+
fs21.writeFileSync(target, desired);
|
|
11527
|
+
copySkillExtras(skill.dir, targetDir);
|
|
11528
|
+
}
|
|
11529
|
+
});
|
|
11530
|
+
} else {
|
|
11531
|
+
items.push({ label: `${label} \u2014 exists without the managed marker, leaving as-is`, state: "skip" });
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
}
|
|
11535
|
+
if (packageSkills.length === 0 && meshTechScopeDirs(root).length === 0) {
|
|
11536
|
+
logInfo("No @mesh-tech packages installed yet \u2014 run `pnpm install`, then `mesh skills sync` again for the platform skills.");
|
|
11537
|
+
}
|
|
11444
11538
|
const hookSource = cliAsset("assets", "intent", "intent-claude-gate.mjs");
|
|
11445
11539
|
const hookTarget = path23.join(root, HOOK_RELATIVE);
|
|
11446
11540
|
const hookDesired = fs21.readFileSync(hookSource, "utf-8");
|
|
@@ -11455,6 +11549,38 @@ function planSync(root) {
|
|
|
11455
11549
|
}
|
|
11456
11550
|
}
|
|
11457
11551
|
);
|
|
11552
|
+
const rootPkgPath = path23.join(root, "package.json");
|
|
11553
|
+
if (fs21.existsSync(rootPkgPath)) {
|
|
11554
|
+
let rootPkg = null;
|
|
11555
|
+
try {
|
|
11556
|
+
rootPkg = JSON.parse(fs21.readFileSync(rootPkgPath, "utf-8"));
|
|
11557
|
+
} catch {
|
|
11558
|
+
rootPkg = null;
|
|
11559
|
+
}
|
|
11560
|
+
const label = "package.json (@tanstack/intent devDependency)";
|
|
11561
|
+
if (!rootPkg) {
|
|
11562
|
+
items.push({ label: `${label} \u2014 package.json is unparseable, leaving as-is`, state: "skip" });
|
|
11563
|
+
} else if (rootPkg.devDependencies?.["@tanstack/intent"] || rootPkg.dependencies?.["@tanstack/intent"]) {
|
|
11564
|
+
items.push({ label, state: "ok" });
|
|
11565
|
+
} else {
|
|
11566
|
+
items.push({
|
|
11567
|
+
label,
|
|
11568
|
+
// Writing the dependency does not install it. Bare `mesh skills sync`
|
|
11569
|
+
// in an already-installed repo leaves `pnpm exec intent` unresolvable
|
|
11570
|
+
// until the next install, so say so rather than reporting success.
|
|
11571
|
+
remediation: "Added @tanstack/intent \u2014 run `pnpm install` so `pnpm exec intent` resolves.",
|
|
11572
|
+
state: "write",
|
|
11573
|
+
apply: () => {
|
|
11574
|
+
rootPkg.devDependencies = rootPkg.devDependencies ?? {};
|
|
11575
|
+
rootPkg.devDependencies["@tanstack/intent"] = INTENT_RANGE;
|
|
11576
|
+
rootPkg.devDependencies = Object.fromEntries(
|
|
11577
|
+
Object.entries(rootPkg.devDependencies).sort(([a], [b]) => a.localeCompare(b))
|
|
11578
|
+
);
|
|
11579
|
+
fs21.writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + "\n");
|
|
11580
|
+
}
|
|
11581
|
+
});
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11458
11584
|
const settingsPath = path23.join(root, ".claude", "settings.json");
|
|
11459
11585
|
let settings = {};
|
|
11460
11586
|
try {
|
|
@@ -11523,6 +11649,7 @@ function syncSkills(root, opts = {}) {
|
|
|
11523
11649
|
} else {
|
|
11524
11650
|
item.apply?.();
|
|
11525
11651
|
logSuccess(`synced: ${item.label}`);
|
|
11652
|
+
if (item.remediation) logInfo(item.remediation);
|
|
11526
11653
|
}
|
|
11527
11654
|
}
|
|
11528
11655
|
if (!dirty) {
|
|
@@ -11533,7 +11660,7 @@ function syncSkills(root, opts = {}) {
|
|
|
11533
11660
|
function registerSkillsCommands(program2) {
|
|
11534
11661
|
const skills = program2.command("skills").description("Agent-skill distribution (base skills + Intent discovery)");
|
|
11535
11662
|
skills.command("sync").description(
|
|
11536
|
-
"Install the base building-with-Mesh skills into .claude/skills
|
|
11663
|
+
"Install the base building-with-Mesh skills into .claude/skills/, fetch the platform skills shipped by the repo's installed @mesh-tech/* packages, and wire TanStack-Intent discovery (intent devDependency + hook + settings + AGENTS.md fence)"
|
|
11537
11664
|
).option("--check", "verify only (CI/doctor): exit 1 when anything is missing or stale", false).option("--root <path>", "target repo root (default: enclosing git root)").action((opts) => {
|
|
11538
11665
|
const root = path23.resolve(opts.root ?? resolveTargetRoot());
|
|
11539
11666
|
const ok = syncSkills(root, { check: opts.check });
|
|
@@ -11544,7 +11671,7 @@ function registerSkillsCommands(program2) {
|
|
|
11544
11671
|
}
|
|
11545
11672
|
});
|
|
11546
11673
|
}
|
|
11547
|
-
var MANAGED_MARKER, FENCE_START, HOOK_RELATIVE;
|
|
11674
|
+
var MANAGED_MARKER, FENCE_START, HOOK_RELATIVE, INTENT_RANGE, BASE_SKILL_PACKAGE;
|
|
11548
11675
|
var init_skills = __esm({
|
|
11549
11676
|
"libs/mesh-cli/src/commands/skills.ts"() {
|
|
11550
11677
|
"use strict";
|
|
@@ -11554,26 +11681,78 @@ var init_skills = __esm({
|
|
|
11554
11681
|
MANAGED_MARKER = "<!-- managed-by: mesh skills sync \u2014 edits are overwritten; copy content elsewhere to customize -->";
|
|
11555
11682
|
FENCE_START = "<!-- intent-skills:start -->";
|
|
11556
11683
|
HOOK_RELATIVE = path23.join(".intent", "hooks", "intent-claude-gate.mjs");
|
|
11684
|
+
INTENT_RANGE = "^0.3.6";
|
|
11685
|
+
BASE_SKILL_PACKAGE = "mesh-cli";
|
|
11686
|
+
}
|
|
11687
|
+
});
|
|
11688
|
+
|
|
11689
|
+
// libs/mesh-cli/src/utils/scaffold-versions.ts
|
|
11690
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
11691
|
+
function isPrerelease(range) {
|
|
11692
|
+
return /[-+]/.test(range.replace(/^\^/, ""));
|
|
11693
|
+
}
|
|
11694
|
+
function toCaretRange(version) {
|
|
11695
|
+
const trimmed = version.trim();
|
|
11696
|
+
return /^\d+\.\d+\.\d+(?:[-+].*)?$/.test(trimmed) ? `^${trimmed}` : null;
|
|
11697
|
+
}
|
|
11698
|
+
function resolvePublishedRange(pkg, cwd) {
|
|
11699
|
+
try {
|
|
11700
|
+
const out = execFileSync18("npm", ["view", pkg, "version"], {
|
|
11701
|
+
cwd,
|
|
11702
|
+
encoding: "utf-8",
|
|
11703
|
+
timeout: 15e3,
|
|
11704
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
11705
|
+
});
|
|
11706
|
+
const range = toCaretRange(out);
|
|
11707
|
+
if (range && !isPrerelease(range)) return { range, resolved: true };
|
|
11708
|
+
} catch {
|
|
11709
|
+
}
|
|
11710
|
+
return { range: SCAFFOLD_PACKAGE_LINES[pkg], resolved: false };
|
|
11711
|
+
}
|
|
11712
|
+
var SCAFFOLD_PACKAGE_LINES, SCAFFOLD_TOOLCHAIN;
|
|
11713
|
+
var init_scaffold_versions = __esm({
|
|
11714
|
+
"libs/mesh-cli/src/utils/scaffold-versions.ts"() {
|
|
11715
|
+
"use strict";
|
|
11716
|
+
SCAFFOLD_PACKAGE_LINES = {
|
|
11717
|
+
"@mesh-tech/app-kit": "^1.45.0",
|
|
11718
|
+
"@mesh-tech/esm-bundle": "^0.1.1"
|
|
11719
|
+
};
|
|
11720
|
+
SCAFFOLD_TOOLCHAIN = {
|
|
11721
|
+
"@types/node": "^24.2.1",
|
|
11722
|
+
tsx: "^4.20.4",
|
|
11723
|
+
typescript: "^5.9.2"
|
|
11724
|
+
};
|
|
11557
11725
|
}
|
|
11558
11726
|
});
|
|
11559
11727
|
|
|
11560
11728
|
// libs/mesh-cli/src/commands/create-app.ts
|
|
11561
11729
|
var create_app_exports = {};
|
|
11562
11730
|
__export(create_app_exports, {
|
|
11731
|
+
PLATFORM_MONOREPO_NAME: () => PLATFORM_MONOREPO_NAME,
|
|
11563
11732
|
bootstrapAppsRepo: () => bootstrapAppsRepo,
|
|
11564
11733
|
copyTemplate: () => copyTemplate,
|
|
11734
|
+
ensureWorkspaceGlobs: () => ensureWorkspaceGlobs,
|
|
11735
|
+
isInsidePlatformMonorepo: () => isInsidePlatformMonorepo,
|
|
11565
11736
|
registerCreateAppCommand: () => registerCreateAppCommand,
|
|
11566
|
-
shouldBootstrapAppsRepo: () => shouldBootstrapAppsRepo
|
|
11737
|
+
shouldBootstrapAppsRepo: () => shouldBootstrapAppsRepo,
|
|
11738
|
+
workspaceGlobForApp: () => workspaceGlobForApp
|
|
11567
11739
|
});
|
|
11568
11740
|
import * as fs22 from "fs";
|
|
11569
11741
|
import * as os8 from "os";
|
|
11570
11742
|
import * as path24 from "path";
|
|
11571
11743
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11572
11744
|
import Handlebars from "handlebars";
|
|
11573
|
-
|
|
11745
|
+
import { parse as parseYaml2 } from "yaml";
|
|
11746
|
+
function isInsidePlatformMonorepo(dir) {
|
|
11574
11747
|
let cur = path24.resolve(dir);
|
|
11575
11748
|
while (cur !== path24.dirname(cur)) {
|
|
11576
|
-
if (fs22.existsSync(path24.join(cur, "pnpm-workspace.yaml")))
|
|
11749
|
+
if (fs22.existsSync(path24.join(cur, "pnpm-workspace.yaml"))) {
|
|
11750
|
+
try {
|
|
11751
|
+
const pkg = JSON.parse(fs22.readFileSync(path24.join(cur, "package.json"), "utf-8"));
|
|
11752
|
+
if (pkg?.name === PLATFORM_MONOREPO_NAME) return true;
|
|
11753
|
+
} catch {
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11577
11756
|
cur = path24.dirname(cur);
|
|
11578
11757
|
}
|
|
11579
11758
|
return false;
|
|
@@ -11583,7 +11762,7 @@ function resolveDeployerRoleArn(tenant, platformName, env) {
|
|
|
11583
11762
|
return `arn:aws:iam::${account}:role/${tenant}-${env}-apps-deployer`;
|
|
11584
11763
|
}
|
|
11585
11764
|
function shouldBootstrapAppsRepo(cwd) {
|
|
11586
|
-
return fs22.existsSync(path24.join(cwd, ".git")) && !
|
|
11765
|
+
return fs22.existsSync(path24.join(cwd, ".git")) && !isInsidePlatformMonorepo(cwd) && !fs22.existsSync(path24.join(cwd, "package.json")) && !fs22.existsSync(path24.join(cwd, "tenants")) && !fs22.existsSync(path24.join(cwd, "apps"));
|
|
11587
11766
|
}
|
|
11588
11767
|
function bootstrapAppsRepo(cwd, tenant) {
|
|
11589
11768
|
const templateDir = path24.join(packageRoot, "templates", "apps-repo");
|
|
@@ -11592,7 +11771,8 @@ function bootstrapAppsRepo(cwd, tenant) {
|
|
|
11592
11771
|
repoName: path24.basename(cwd),
|
|
11593
11772
|
tenant,
|
|
11594
11773
|
tenantTitle: tenant.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
|
|
11595
|
-
registryUrl: `https://mesh-platform-${registryAccount}.d.codeartifact.us-east-2.amazonaws.com/npm/mesh-packages
|
|
11774
|
+
registryUrl: `https://mesh-platform-${registryAccount}.d.codeartifact.us-east-2.amazonaws.com/npm/mesh-packages/`,
|
|
11775
|
+
intentRange: INTENT_RANGE
|
|
11596
11776
|
};
|
|
11597
11777
|
const staging = fs22.mkdtempSync(path24.join(os8.tmpdir(), "mesh-apps-repo-"));
|
|
11598
11778
|
try {
|
|
@@ -11618,6 +11798,41 @@ function bootstrapAppsRepo(cwd, tenant) {
|
|
|
11618
11798
|
fs22.rmSync(staging, { recursive: true, force: true });
|
|
11619
11799
|
}
|
|
11620
11800
|
}
|
|
11801
|
+
function ensureWorkspaceGlobs(root, required) {
|
|
11802
|
+
const file = path24.join(root, "pnpm-workspace.yaml");
|
|
11803
|
+
if (!fs22.existsSync(file)) return [];
|
|
11804
|
+
const text = fs22.readFileSync(file, "utf-8");
|
|
11805
|
+
let declared;
|
|
11806
|
+
try {
|
|
11807
|
+
declared = parseYaml2(text)?.packages ?? [];
|
|
11808
|
+
} catch {
|
|
11809
|
+
return [];
|
|
11810
|
+
}
|
|
11811
|
+
const missing = required.filter((glob) => !declared.includes(glob));
|
|
11812
|
+
if (missing.length === 0) return [];
|
|
11813
|
+
const lines = text.split("\n");
|
|
11814
|
+
const start = lines.findIndex((line) => /^packages:\s*$/.test(line));
|
|
11815
|
+
if (start === -1) return [];
|
|
11816
|
+
let end = start;
|
|
11817
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
11818
|
+
const line = lines[i] ?? "";
|
|
11819
|
+
const isEntry = /^\s+-\s/.test(line);
|
|
11820
|
+
if (isEntry || /^\s*#/.test(line) || line.trim() === "") {
|
|
11821
|
+
if (isEntry) end = i;
|
|
11822
|
+
continue;
|
|
11823
|
+
}
|
|
11824
|
+
break;
|
|
11825
|
+
}
|
|
11826
|
+
const indent = (lines[end] ?? "").match(/^(\s*)-/)?.[1] ?? " ";
|
|
11827
|
+
lines.splice(end + 1, 0, ...missing.map((glob) => `${indent}- ${glob}`));
|
|
11828
|
+
fs22.writeFileSync(file, lines.join("\n"));
|
|
11829
|
+
return missing;
|
|
11830
|
+
}
|
|
11831
|
+
function workspaceGlobForApp(root, appDir) {
|
|
11832
|
+
const rel = path24.relative(root, appDir).split(path24.sep).join("/");
|
|
11833
|
+
if (rel === "" || rel.split("/")[0] === "..") return null;
|
|
11834
|
+
return `${path24.posix.dirname(rel)}/*/*`;
|
|
11835
|
+
}
|
|
11621
11836
|
function maybeBootstrapAppsRepo(cwd, tenant, test) {
|
|
11622
11837
|
if (test || !shouldBootstrapAppsRepo(cwd)) return;
|
|
11623
11838
|
const created = bootstrapAppsRepo(cwd, tenant);
|
|
@@ -11858,15 +12073,22 @@ async function runLegacyTemplate(tenant, name, template, test) {
|
|
|
11858
12073
|
fs22.rmSync(appDir, { recursive: true, force: true });
|
|
11859
12074
|
process.exit(1);
|
|
11860
12075
|
}
|
|
11861
|
-
autoSyncSkills(appDir);
|
|
12076
|
+
autoSyncSkills(appDir, name);
|
|
11862
12077
|
printLegacyNextSteps(appDir, template);
|
|
11863
12078
|
}
|
|
11864
|
-
function autoSyncSkills(appDir) {
|
|
12079
|
+
function autoSyncSkills(appDir, appName) {
|
|
12080
|
+
const root = resolveTargetRoot(appDir);
|
|
11865
12081
|
try {
|
|
11866
|
-
syncSkills(
|
|
12082
|
+
syncSkills(root);
|
|
11867
12083
|
} catch (err) {
|
|
11868
12084
|
logWarn(`Agent-skill sync skipped: ${err instanceof Error ? err.message : err} \u2014 run: mesh skills sync`);
|
|
11869
12085
|
}
|
|
12086
|
+
try {
|
|
12087
|
+
const seeded = seedAppSkill(root, appName, path24.relative(root, appDir));
|
|
12088
|
+
if (seeded) logSuccess(`seeded: ${seeded} (yours to grow \u2014 not managed by mesh skills sync)`);
|
|
12089
|
+
} catch (err) {
|
|
12090
|
+
logWarn(`App skill stub skipped: ${err instanceof Error ? err.message : err}`);
|
|
12091
|
+
}
|
|
11870
12092
|
}
|
|
11871
12093
|
async function runComposable(tenant, name, primitives, test) {
|
|
11872
12094
|
logInfo(`Creating app '${name}' for tenant '${tenant}'...`);
|
|
@@ -11883,6 +12105,15 @@ async function runComposable(tenant, name, primitives, test) {
|
|
|
11883
12105
|
const region = "us-east-2";
|
|
11884
12106
|
const platformName = "mesh";
|
|
11885
12107
|
const platformEnv = "dev";
|
|
12108
|
+
const workspaceDeps = isInsidePlatformMonorepo(appDir);
|
|
12109
|
+
const repoRoot2 = resolveTargetRoot(process.cwd());
|
|
12110
|
+
const mesh = workspaceDeps ? { range: "", resolved: true } : resolvePublishedRange("@mesh-tech/app-kit", repoRoot2);
|
|
12111
|
+
const esmBundle = workspaceDeps ? { range: "", resolved: true } : resolvePublishedRange("@mesh-tech/esm-bundle", repoRoot2);
|
|
12112
|
+
if (!workspaceDeps) {
|
|
12113
|
+
logInfo(
|
|
12114
|
+
mesh.resolved ? `@mesh-tech/* pinned to ${mesh.range} (current published line)` : `Registry lookup unavailable \u2014 pinning @mesh-tech/* to ${mesh.range}; run \`pnpm up @mesh-tech/*\` once you have registry auth`
|
|
12115
|
+
);
|
|
12116
|
+
}
|
|
11886
12117
|
const context = {
|
|
11887
12118
|
name,
|
|
11888
12119
|
tenant,
|
|
@@ -11891,9 +12122,12 @@ async function runComposable(tenant, name, primitives, test) {
|
|
|
11891
12122
|
temporal: primitives.includes("temporal"),
|
|
11892
12123
|
bucket: primitives.includes("bucket"),
|
|
11893
12124
|
region,
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
12125
|
+
workspaceDeps,
|
|
12126
|
+
meshRange: mesh.range,
|
|
12127
|
+
esmBundleRange: esmBundle.range,
|
|
12128
|
+
typesNodeRange: SCAFFOLD_TOOLCHAIN["@types/node"],
|
|
12129
|
+
tsxRange: SCAFFOLD_TOOLCHAIN.tsx,
|
|
12130
|
+
typescriptRange: SCAFFOLD_TOOLCHAIN.typescript,
|
|
11897
12131
|
deployerRoleArn: resolveDeployerRoleArn(tenant, platformName, platformEnv)
|
|
11898
12132
|
};
|
|
11899
12133
|
fs22.mkdirSync(appDir, { recursive: true });
|
|
@@ -11905,20 +12139,18 @@ async function runComposable(tenant, name, primitives, test) {
|
|
|
11905
12139
|
fs22.rmSync(appDir, { recursive: true, force: true });
|
|
11906
12140
|
process.exit(1);
|
|
11907
12141
|
}
|
|
11908
|
-
const
|
|
11909
|
-
|
|
11910
|
-
|
|
11911
|
-
|
|
12142
|
+
const nested = fs22.readdirSync(appDir, { withFileTypes: true }).some((entry) => entry.isDirectory() && fs22.existsSync(path24.join(appDir, entry.name, "package.json")));
|
|
12143
|
+
const glob = workspaceGlobForApp(repoRoot2, appDir);
|
|
12144
|
+
if (nested && glob) {
|
|
12145
|
+
const added = ensureWorkspaceGlobs(repoRoot2, [glob]);
|
|
12146
|
+
if (added.length > 0) {
|
|
12147
|
+
logInfo(`pnpm-workspace.yaml: added ${added.join(", ")} so the app's api/worker packages install`);
|
|
12148
|
+
}
|
|
11912
12149
|
}
|
|
11913
|
-
autoSyncSkills(appDir);
|
|
12150
|
+
autoSyncSkills(appDir, name);
|
|
11914
12151
|
printComposableNextSteps(appDir, context);
|
|
11915
12152
|
}
|
|
11916
12153
|
function printLegacyNextSteps(appDir, _template) {
|
|
11917
|
-
const configPath = path24.join(path24.dirname(appDir), "config.ts");
|
|
11918
|
-
if (!fs22.existsSync(configPath)) {
|
|
11919
|
-
logWarn(`No config.ts found at ${configPath}`);
|
|
11920
|
-
logInfo("You may need to create a shared config.ts for tenant apps.");
|
|
11921
|
-
}
|
|
11922
12154
|
console.log("");
|
|
11923
12155
|
logSuccess("App created successfully!");
|
|
11924
12156
|
console.log("");
|
|
@@ -11955,18 +12187,21 @@ function printComposableNextSteps(appDir, context) {
|
|
|
11955
12187
|
console.log("Next steps:");
|
|
11956
12188
|
console.log(` cd ${appDir}`);
|
|
11957
12189
|
console.log(" pnpm install");
|
|
12190
|
+
console.log(" mesh skills sync # re-run once deps are installed: picks up package skills + Intent");
|
|
12191
|
+
console.log(" pnpm install # again only if skills sync reports it added @tanstack/intent");
|
|
11958
12192
|
console.log(" mesh stack init # personal dev stack (deploy: false)");
|
|
11959
12193
|
console.log(" mesh deploy up --yes # deploy via the stack's deployer role");
|
|
11960
12194
|
console.log(" mesh dev # run locally");
|
|
11961
12195
|
console.log("");
|
|
11962
12196
|
}
|
|
11963
|
-
var __filename, __dirname, packageRoot, TEMPLATES, REMOVED_TEMPLATES, PRIMITIVES, HUB_ACCOUNTS, VALID_PRIMITIVES;
|
|
12197
|
+
var __filename, __dirname, packageRoot, TEMPLATES, REMOVED_TEMPLATES, PRIMITIVES, HUB_ACCOUNTS, PLATFORM_MONOREPO_NAME, VALID_PRIMITIVES;
|
|
11964
12198
|
var init_create_app = __esm({
|
|
11965
12199
|
"libs/mesh-cli/src/commands/create-app.ts"() {
|
|
11966
12200
|
"use strict";
|
|
11967
12201
|
init_utils();
|
|
11968
12202
|
init_skills();
|
|
11969
12203
|
init_stack();
|
|
12204
|
+
init_scaffold_versions();
|
|
11970
12205
|
__filename = fileURLToPath2(import.meta.url);
|
|
11971
12206
|
__dirname = path24.dirname(__filename);
|
|
11972
12207
|
packageRoot = findPackageRoot(__dirname);
|
|
@@ -11989,6 +12224,7 @@ var init_create_app = __esm({
|
|
|
11989
12224
|
HUB_ACCOUNTS = {
|
|
11990
12225
|
mesh: "159923586610"
|
|
11991
12226
|
};
|
|
12227
|
+
PLATFORM_MONOREPO_NAME = "mesh-platform";
|
|
11992
12228
|
VALID_PRIMITIVES = Object.keys(PRIMITIVES);
|
|
11993
12229
|
Handlebars.registerHelper("titleCase", (str) => {
|
|
11994
12230
|
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -12600,8 +12836,8 @@ var init_db = __esm({
|
|
|
12600
12836
|
|
|
12601
12837
|
// libs/mesh-cli/src/utils/deploy-preflight.ts
|
|
12602
12838
|
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
|
|
12603
|
-
import { dirname as dirname22, join as join25, relative as
|
|
12604
|
-
import { parse as
|
|
12839
|
+
import { dirname as dirname22, join as join25, relative as relative5 } from "node:path";
|
|
12840
|
+
import { parse as parseYaml3 } from "yaml";
|
|
12605
12841
|
function isGated(name) {
|
|
12606
12842
|
return GATED_PREFIXES.some((p) => name.startsWith(p));
|
|
12607
12843
|
}
|
|
@@ -12659,14 +12895,14 @@ function checkDeployDepsFresh(appRoot) {
|
|
|
12659
12895
|
if (!lockPath) return null;
|
|
12660
12896
|
let lockDoc;
|
|
12661
12897
|
try {
|
|
12662
|
-
lockDoc =
|
|
12898
|
+
lockDoc = parseYaml3(readFileSync21(lockPath, "utf8"));
|
|
12663
12899
|
} catch {
|
|
12664
12900
|
logWarn(
|
|
12665
12901
|
`deploy preflight: could not parse ${lockPath} \u2014 skipping the stale-node_modules check.`
|
|
12666
12902
|
);
|
|
12667
12903
|
return null;
|
|
12668
12904
|
}
|
|
12669
|
-
const importerRel =
|
|
12905
|
+
const importerRel = relative5(dirname22(lockPath), appRoot) || ".";
|
|
12670
12906
|
const expected = extractImporterMeshVersions(lockDoc, importerRel);
|
|
12671
12907
|
const names = Object.keys(expected);
|
|
12672
12908
|
if (names.length === 0) return [];
|
|
@@ -12715,7 +12951,7 @@ var init_deploy_preflight = __esm({
|
|
|
12715
12951
|
});
|
|
12716
12952
|
|
|
12717
12953
|
// libs/mesh-cli/src/commands/deploy.ts
|
|
12718
|
-
import { execFileSync as
|
|
12954
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
12719
12955
|
function buildPulumiArgs(pulumiArgs, stack) {
|
|
12720
12956
|
const base = pulumiArgs.length === 0 || pulumiArgs[0]?.startsWith("-") ? ["up", ...pulumiArgs] : [...pulumiArgs];
|
|
12721
12957
|
const op = base[0];
|
|
@@ -12778,7 +13014,7 @@ function registerDeployCommand(program2) {
|
|
|
12778
13014
|
delete env.AWS_PROFILE;
|
|
12779
13015
|
const finalArgs = buildPulumiArgs(pulumiArgs, stack);
|
|
12780
13016
|
try {
|
|
12781
|
-
|
|
13017
|
+
execFileSync19("pulumi", finalArgs, {
|
|
12782
13018
|
cwd: appRoot,
|
|
12783
13019
|
env,
|
|
12784
13020
|
stdio: "inherit"
|
|
@@ -13071,10 +13307,10 @@ var init_discover = __esm({
|
|
|
13071
13307
|
});
|
|
13072
13308
|
|
|
13073
13309
|
// libs/mesh-cli/src/docs/assemble.ts
|
|
13074
|
-
import { execFileSync as
|
|
13310
|
+
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
13075
13311
|
import { mkdirSync as mkdirSync15, readFileSync as readFileSync23, rmSync as rmSync5, writeFileSync as writeFileSync15 } from "node:fs";
|
|
13076
13312
|
import path27 from "node:path";
|
|
13077
|
-
import { parse as
|
|
13313
|
+
import { parse as parseYaml4 } from "yaml";
|
|
13078
13314
|
function splitFrontMatter(markdown) {
|
|
13079
13315
|
const normalized = markdown.replace(/^\uFEFF/, "");
|
|
13080
13316
|
if (!normalized.startsWith("---\n") && !normalized.startsWith("---\r\n")) {
|
|
@@ -13086,7 +13322,7 @@ function splitFrontMatter(markdown) {
|
|
|
13086
13322
|
const bodyStart = normalized.indexOf("\n", end + 1);
|
|
13087
13323
|
const body = (bodyStart === -1 ? "" : normalized.slice(bodyStart + 1)).replace(/^\r?\n/, "");
|
|
13088
13324
|
try {
|
|
13089
|
-
const data =
|
|
13325
|
+
const data = parseYaml4(rawBlock);
|
|
13090
13326
|
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
13091
13327
|
return {
|
|
13092
13328
|
data,
|
|
@@ -13562,7 +13798,7 @@ function renderVersionJson(args) {
|
|
|
13562
13798
|
}
|
|
13563
13799
|
function currentCommit(repoRoot2) {
|
|
13564
13800
|
try {
|
|
13565
|
-
return
|
|
13801
|
+
return execFileSync20("git", ["rev-parse", "--short", "HEAD"], {
|
|
13566
13802
|
cwd: repoRoot2,
|
|
13567
13803
|
encoding: "utf-8"
|
|
13568
13804
|
}).trim();
|
|
@@ -13581,7 +13817,7 @@ function currentBaseline(repoRoot2) {
|
|
|
13581
13817
|
}
|
|
13582
13818
|
}
|
|
13583
13819
|
function publishSetAtRef(repoRoot2, ref) {
|
|
13584
|
-
const git = (gitArgs) =>
|
|
13820
|
+
const git = (gitArgs) => execFileSync20("git", gitArgs, {
|
|
13585
13821
|
cwd: repoRoot2,
|
|
13586
13822
|
encoding: "utf-8",
|
|
13587
13823
|
maxBuffer: 64 * 1024 * 1024
|
|
@@ -14069,7 +14305,7 @@ var init_portal = __esm({
|
|
|
14069
14305
|
});
|
|
14070
14306
|
|
|
14071
14307
|
// libs/mesh-cli/src/utils/build-info.ts
|
|
14072
|
-
import { execFileSync as
|
|
14308
|
+
import { execFileSync as execFileSync21 } from "child_process";
|
|
14073
14309
|
import * as fs24 from "fs";
|
|
14074
14310
|
import * as path29 from "path";
|
|
14075
14311
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -14127,7 +14363,7 @@ function resolveCliRuntime(opts) {
|
|
|
14127
14363
|
}
|
|
14128
14364
|
if (!vcs) return info;
|
|
14129
14365
|
try {
|
|
14130
|
-
const git = (args) =>
|
|
14366
|
+
const git = (args) => execFileSync21("git", args, {
|
|
14131
14367
|
cwd: root,
|
|
14132
14368
|
encoding: "utf-8",
|
|
14133
14369
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -14147,10 +14383,10 @@ var init_build_info = __esm({
|
|
|
14147
14383
|
// libs/mesh-cli/src/docs/serve.ts
|
|
14148
14384
|
import { createServer as createServer8 } from "node:http";
|
|
14149
14385
|
import { readFile } from "node:fs/promises";
|
|
14150
|
-
import { extname, join as join27, normalize, sep as
|
|
14386
|
+
import { extname, join as join27, normalize, sep as sep4 } from "node:path";
|
|
14151
14387
|
async function serveDocsSite(args) {
|
|
14152
14388
|
const root = normalize(args.root);
|
|
14153
|
-
const rootPrefix = root.endsWith(
|
|
14389
|
+
const rootPrefix = root.endsWith(sep4) ? root : root + sep4;
|
|
14154
14390
|
const server = createServer8((req, res) => {
|
|
14155
14391
|
void (async () => {
|
|
14156
14392
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
@@ -14224,7 +14460,7 @@ var init_serve = __esm({
|
|
|
14224
14460
|
});
|
|
14225
14461
|
|
|
14226
14462
|
// libs/mesh-cli/src/docs/registry-docs.ts
|
|
14227
|
-
import { execFileSync as
|
|
14463
|
+
import { execFileSync as execFileSync22 } from "node:child_process";
|
|
14228
14464
|
import { existsSync as existsSync23, mkdirSync as mkdirSync17, readFileSync as readFileSync26, renameSync as renameSync3, rmSync as rmSync6, writeFileSync as writeFileSync17 } from "node:fs";
|
|
14229
14465
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
14230
14466
|
import path30 from "node:path";
|
|
@@ -14316,7 +14552,7 @@ async function fetchDocsArtifact(auth, version, cacheRoot = docsCacheRoot(), fet
|
|
|
14316
14552
|
rmSync6(staging, { recursive: true, force: true });
|
|
14317
14553
|
mkdirSync17(staging, { recursive: true });
|
|
14318
14554
|
try {
|
|
14319
|
-
|
|
14555
|
+
execFileSync22("tar", ["-xzf", tgzPath, "-C", staging, "--strip-components", "1"], {
|
|
14320
14556
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14321
14557
|
});
|
|
14322
14558
|
} finally {
|
|
@@ -14354,7 +14590,7 @@ __export(start_exports, {
|
|
|
14354
14590
|
tmuxInstallHint: () => tmuxInstallHint,
|
|
14355
14591
|
tmuxServeArgs: () => tmuxServeArgs
|
|
14356
14592
|
});
|
|
14357
|
-
import { execFileSync as
|
|
14593
|
+
import { execFileSync as execFileSync23 } from "node:child_process";
|
|
14358
14594
|
import { appendFileSync as appendFileSync2, existsSync as existsSync24, writeFileSync as writeFileSync18 } from "node:fs";
|
|
14359
14595
|
import path31 from "node:path";
|
|
14360
14596
|
function registryAuthOrThrow() {
|
|
@@ -14387,7 +14623,7 @@ function tmuxInstallHint(platform = process.platform) {
|
|
|
14387
14623
|
}
|
|
14388
14624
|
function tmuxAvailable() {
|
|
14389
14625
|
try {
|
|
14390
|
-
|
|
14626
|
+
execFileSync23("tmux", ["-V"], { stdio: ["pipe", "pipe", "pipe"] });
|
|
14391
14627
|
return true;
|
|
14392
14628
|
} catch {
|
|
14393
14629
|
return false;
|
|
@@ -14398,7 +14634,7 @@ function shouldDetach(args) {
|
|
|
14398
14634
|
}
|
|
14399
14635
|
function docsSessionExists() {
|
|
14400
14636
|
try {
|
|
14401
|
-
|
|
14637
|
+
execFileSync23("tmux", ["has-session", "-t", DOCS_TMUX_SESSION], { stdio: ["pipe", "pipe", "pipe"] });
|
|
14402
14638
|
return true;
|
|
14403
14639
|
} catch {
|
|
14404
14640
|
return false;
|
|
@@ -14422,12 +14658,12 @@ Or run in the foreground instead: mesh docs start --foreground`
|
|
|
14422
14658
|
if (docsSessionExists()) {
|
|
14423
14659
|
logInfo(`Replacing the docs server already running in tmux session "${DOCS_TMUX_SESSION}".`);
|
|
14424
14660
|
try {
|
|
14425
|
-
|
|
14661
|
+
execFileSync23("tmux", ["kill-session", "-t", DOCS_TMUX_SESSION], { stdio: ["pipe", "pipe", "pipe"] });
|
|
14426
14662
|
} catch {
|
|
14427
14663
|
}
|
|
14428
14664
|
}
|
|
14429
14665
|
const { command, cwd } = tmuxServeArgs(args);
|
|
14430
|
-
|
|
14666
|
+
execFileSync23(
|
|
14431
14667
|
"tmux",
|
|
14432
14668
|
["new-session", "-d", "-s", DOCS_TMUX_SESSION, "-c", cwd, "--", ...command],
|
|
14433
14669
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -14465,7 +14701,7 @@ function printReady(url, label) {
|
|
|
14465
14701
|
}
|
|
14466
14702
|
function runDocsStop() {
|
|
14467
14703
|
try {
|
|
14468
|
-
|
|
14704
|
+
execFileSync23("tmux", ["kill-session", "-t", DOCS_TMUX_SESSION], { stdio: ["pipe", "pipe", "pipe"] });
|
|
14469
14705
|
logSuccess(`Stopped the docs server (tmux session "${DOCS_TMUX_SESSION}").`);
|
|
14470
14706
|
} catch {
|
|
14471
14707
|
logInfo(`No docs server is running (no tmux session named "${DOCS_TMUX_SESSION}").`);
|
|
@@ -14838,7 +15074,7 @@ var init_docs = __esm({
|
|
|
14838
15074
|
});
|
|
14839
15075
|
|
|
14840
15076
|
// libs/mesh-cli/src/commands/hub/index.ts
|
|
14841
|
-
import { execFileSync as
|
|
15077
|
+
import { execFileSync as execFileSync24 } from "node:child_process";
|
|
14842
15078
|
import * as fs26 from "node:fs";
|
|
14843
15079
|
import * as net12 from "node:net";
|
|
14844
15080
|
import * as os10 from "node:os";
|
|
@@ -14904,7 +15140,7 @@ function parseTmuxEnv(output) {
|
|
|
14904
15140
|
}
|
|
14905
15141
|
function readTmuxSessionEnv(sessionName) {
|
|
14906
15142
|
try {
|
|
14907
|
-
const out =
|
|
15143
|
+
const out = execFileSync24("tmux", ["show-environment", "-t", sessionName], {
|
|
14908
15144
|
encoding: "utf-8",
|
|
14909
15145
|
stdio: ["ignore", "pipe", "ignore"]
|
|
14910
15146
|
});
|
|
@@ -14915,7 +15151,7 @@ function readTmuxSessionEnv(sessionName) {
|
|
|
14915
15151
|
}
|
|
14916
15152
|
function tmuxSessionExists(sessionName) {
|
|
14917
15153
|
try {
|
|
14918
|
-
|
|
15154
|
+
execFileSync24("tmux", ["has-session", "-t", sessionName], { stdio: "ignore" });
|
|
14919
15155
|
return true;
|
|
14920
15156
|
} catch {
|
|
14921
15157
|
return false;
|
|
@@ -15079,7 +15315,7 @@ function redactEnv(env) {
|
|
|
15079
15315
|
async function hubDevAction(opts) {
|
|
15080
15316
|
if (opts.kill) {
|
|
15081
15317
|
if (tmuxSessionExists(HUB_SESSION)) {
|
|
15082
|
-
|
|
15318
|
+
execFileSync24("tmux", ["kill-session", "-t", HUB_SESSION], { stdio: "ignore" });
|
|
15083
15319
|
fs26.rmSync(hubEnvDir(), { recursive: true, force: true });
|
|
15084
15320
|
logSuccess(`Killed Hub session '${HUB_SESSION}'.`);
|
|
15085
15321
|
} else {
|
|
@@ -15133,17 +15369,17 @@ async function hubDevAction(opts) {
|
|
|
15133
15369
|
for (const warning of assembled.warnings) logWarn(warning);
|
|
15134
15370
|
const apiDir = path33.join(platformDir, "apps", "hub", "api");
|
|
15135
15371
|
const uiDir = path33.join(platformDir, "apps", "hub", "ui");
|
|
15136
|
-
|
|
15372
|
+
execFileSync24("tmux", ["new-session", "-d", "-s", HUB_SESSION, "-n", "api", "-c", apiDir]);
|
|
15137
15373
|
if (!assembled.apiEnv.DEV_USER_TOKEN_URL && assembled.apiEnv.DEV_USER_ID_TOKEN) {
|
|
15138
15374
|
const platform = session.state.devOutput.platform;
|
|
15139
15375
|
const credContext = `mesh.${platform.env}`;
|
|
15140
15376
|
const tokenPort = await findFreePort4();
|
|
15141
15377
|
const tokenUrl = `http://127.0.0.1:${tokenPort}`;
|
|
15142
|
-
|
|
15143
|
-
|
|
15378
|
+
execFileSync24("tmux", ["new-window", "-t", HUB_SESSION, "-n", "token-server", "-c", platformDir]);
|
|
15379
|
+
execFileSync24("tmux", ["set-option", "-t", `${HUB_SESSION}:token-server`, "remain-on-exit", "on"], {
|
|
15144
15380
|
stdio: "ignore"
|
|
15145
15381
|
});
|
|
15146
|
-
|
|
15382
|
+
execFileSync24("tmux", [
|
|
15147
15383
|
"send-keys",
|
|
15148
15384
|
"-t",
|
|
15149
15385
|
`${HUB_SESSION}:token-server`,
|
|
@@ -15161,12 +15397,12 @@ async function hubDevAction(opts) {
|
|
|
15161
15397
|
const envFile = path33.join(hubEnvDir(), `${window}.env.sh`);
|
|
15162
15398
|
writeEnvFile(envFile, env);
|
|
15163
15399
|
if (createWindow) {
|
|
15164
|
-
|
|
15400
|
+
execFileSync24("tmux", ["new-window", "-t", HUB_SESSION, "-n", window, "-c", dir]);
|
|
15165
15401
|
}
|
|
15166
|
-
|
|
15402
|
+
execFileSync24("tmux", ["set-option", "-t", `${HUB_SESSION}:${window}`, "remain-on-exit", "on"], {
|
|
15167
15403
|
stdio: "ignore"
|
|
15168
15404
|
});
|
|
15169
|
-
|
|
15405
|
+
execFileSync24("tmux", ["send-keys", "-t", `${HUB_SESSION}:${window}`, buildLaunchCommand(envFile, dir, cmd), "Enter"]);
|
|
15170
15406
|
};
|
|
15171
15407
|
launch("api", apiDir, assembled.apiEnv, "pnpm dev", false);
|
|
15172
15408
|
launch("ui", uiDir, assembled.uiEnv, `pnpm dev -- --port ${uiPort} --strictPort`, true);
|
|
@@ -15492,7 +15728,7 @@ var init_init = __esm({
|
|
|
15492
15728
|
});
|
|
15493
15729
|
|
|
15494
15730
|
// libs/mesh-cli/src/commands/install-shim.ts
|
|
15495
|
-
import { execFileSync as
|
|
15731
|
+
import { execFileSync as execFileSync25 } from "child_process";
|
|
15496
15732
|
import * as fs28 from "fs";
|
|
15497
15733
|
import * as os11 from "os";
|
|
15498
15734
|
import * as path35 from "path";
|
|
@@ -15605,7 +15841,7 @@ function registerInstallShimCommand(program2) {
|
|
|
15605
15841
|
let status = 0;
|
|
15606
15842
|
let ok = true;
|
|
15607
15843
|
try {
|
|
15608
|
-
stdout =
|
|
15844
|
+
stdout = execFileSync25(target, ["--help"], {
|
|
15609
15845
|
cwd: process.cwd(),
|
|
15610
15846
|
encoding: "utf8",
|
|
15611
15847
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -15652,7 +15888,7 @@ var init_install_shim = __esm({
|
|
|
15652
15888
|
});
|
|
15653
15889
|
|
|
15654
15890
|
// libs/mesh-cli/src/commands/local/hub-local.ts
|
|
15655
|
-
import { execFile as execFile3, execFileSync as
|
|
15891
|
+
import { execFile as execFile3, execFileSync as execFileSync26 } from "child_process";
|
|
15656
15892
|
import * as fs29 from "fs";
|
|
15657
15893
|
import * as os12 from "os";
|
|
15658
15894
|
import * as path36 from "path";
|
|
@@ -15674,7 +15910,7 @@ function npmrcPath() {
|
|
|
15674
15910
|
}
|
|
15675
15911
|
function imageExists(tag) {
|
|
15676
15912
|
try {
|
|
15677
|
-
|
|
15913
|
+
execFileSync26("docker", ["image", "inspect", tag], { stdio: ["ignore", "pipe", "pipe"] });
|
|
15678
15914
|
return true;
|
|
15679
15915
|
} catch {
|
|
15680
15916
|
return false;
|
|
@@ -15684,7 +15920,7 @@ function ensureHubAuthImage() {
|
|
|
15684
15920
|
if (imageExists(HUB_AUTH_IMAGE)) return;
|
|
15685
15921
|
logInfo(`Building ${HUB_AUTH_IMAGE} (Hub auth proxy)\u2026`);
|
|
15686
15922
|
const hubStackDir = path36.join(findPackageRoot(), "stack", "hub");
|
|
15687
|
-
|
|
15923
|
+
execFileSync26(
|
|
15688
15924
|
"docker",
|
|
15689
15925
|
["build", "-f", path36.join(hubStackDir, "Dockerfile.auth"), "-t", HUB_AUTH_IMAGE, hubStackDir],
|
|
15690
15926
|
{ stdio: ["ignore", "inherit", "inherit"], env: { ...process.env, DOCKER_BUILDKIT: "1" } }
|
|
@@ -15698,7 +15934,7 @@ function hasRegistryAuth() {
|
|
|
15698
15934
|
function localHubVersion() {
|
|
15699
15935
|
const versions = HUB_IMAGES.map((name) => {
|
|
15700
15936
|
try {
|
|
15701
|
-
const out =
|
|
15937
|
+
const out = execFileSync26("docker", ["images", name, "--format", "{{.Tag}}"], {
|
|
15702
15938
|
encoding: "utf-8",
|
|
15703
15939
|
stdio: ["ignore", "pipe", "pipe"]
|
|
15704
15940
|
});
|
|
@@ -15777,7 +16013,7 @@ async function ensureHubImages() {
|
|
|
15777
16013
|
const context = path36.join(cacheDir(), `context-${version}`);
|
|
15778
16014
|
fs29.rmSync(context, { recursive: true, force: true });
|
|
15779
16015
|
fs29.mkdirSync(context, { recursive: true });
|
|
15780
|
-
|
|
16016
|
+
execFileSync26("tar", ["-xzf", tarball, "-C", context, "--strip-components", "1"], {
|
|
15781
16017
|
stdio: ["ignore", "pipe", "pipe"]
|
|
15782
16018
|
});
|
|
15783
16019
|
const hubStackDir = path36.join(findPackageRoot(), "stack", "hub");
|
|
@@ -15788,7 +16024,7 @@ async function ensureHubImages() {
|
|
|
15788
16024
|
const tag = `${name}:${version}`;
|
|
15789
16025
|
if (imageExists(tag)) continue;
|
|
15790
16026
|
logInfo(`Building ${tag} from the published tarball\u2026`);
|
|
15791
|
-
|
|
16027
|
+
execFileSync26(
|
|
15792
16028
|
"docker",
|
|
15793
16029
|
[
|
|
15794
16030
|
"build",
|
|
@@ -16285,6 +16521,12 @@ import {
|
|
|
16285
16521
|
} from "@aws-sdk/client-secrets-manager";
|
|
16286
16522
|
import input from "@inquirer/input";
|
|
16287
16523
|
import password from "@inquirer/password";
|
|
16524
|
+
import {
|
|
16525
|
+
buildInstanceIndexValue,
|
|
16526
|
+
instanceIndexSecretId,
|
|
16527
|
+
isInstanceKey,
|
|
16528
|
+
parseInstanceIndex
|
|
16529
|
+
} from "@mesh-tech/secrets";
|
|
16288
16530
|
async function ensureAwsCredentialsForStack(stack) {
|
|
16289
16531
|
if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_SESSION_TOKEN) return;
|
|
16290
16532
|
if (!stack) return;
|
|
@@ -16469,6 +16711,12 @@ Usage: mesh secrets set external/<name>`);
|
|
|
16469
16711
|
);
|
|
16470
16712
|
process.exit(1);
|
|
16471
16713
|
}
|
|
16714
|
+
if (opts.key && !isInstanceKey(opts.key)) {
|
|
16715
|
+
logError(
|
|
16716
|
+
`Invalid instance key "${opts.key}": keys must not contain "/", start with ".", or end with ".config" \u2014 those names are reserved for the index and config mirrors.`
|
|
16717
|
+
);
|
|
16718
|
+
process.exit(1);
|
|
16719
|
+
}
|
|
16472
16720
|
let existing = {};
|
|
16473
16721
|
try {
|
|
16474
16722
|
const response = await smClient.send(
|
|
@@ -16493,6 +16741,9 @@ Usage: mesh secrets set external/<name>`);
|
|
|
16493
16741
|
const merged2 = deepMerge(existing, values2);
|
|
16494
16742
|
await writeSecret(smClient, secretId, merged2, svc.meta);
|
|
16495
16743
|
await writeConfigMirror(smClient, secretId, schema, merged2, svc.meta);
|
|
16744
|
+
if (opts.key) {
|
|
16745
|
+
await addKeyToInstanceIndex(smClient, secretPrefix, opts.key, serviceName);
|
|
16746
|
+
}
|
|
16496
16747
|
logSuccess(`Credentials written to ${secretId}`);
|
|
16497
16748
|
return;
|
|
16498
16749
|
}
|
|
@@ -16508,6 +16759,9 @@ Usage: mesh secrets set external/<name>`);
|
|
|
16508
16759
|
const merged = deepMerge(existing, values);
|
|
16509
16760
|
await writeSecret(smClient, secretId, merged, svc.meta);
|
|
16510
16761
|
await writeConfigMirror(smClient, secretId, schema, merged, svc.meta);
|
|
16762
|
+
if (opts.key) {
|
|
16763
|
+
await addKeyToInstanceIndex(smClient, secretPrefix, opts.key, serviceName);
|
|
16764
|
+
}
|
|
16511
16765
|
logSuccess(`Credentials written to ${secretId}`);
|
|
16512
16766
|
console.error("\nStored fields:");
|
|
16513
16767
|
displaySummary(schema.fields, merged);
|
|
@@ -16573,6 +16827,45 @@ function extractNonSecretFields(fields, values) {
|
|
|
16573
16827
|
}
|
|
16574
16828
|
return result;
|
|
16575
16829
|
}
|
|
16830
|
+
async function addKeyToInstanceIndex(client, secretPrefix, key, serviceName) {
|
|
16831
|
+
const indexId = instanceIndexSecretId(secretPrefix);
|
|
16832
|
+
try {
|
|
16833
|
+
let keys = [];
|
|
16834
|
+
try {
|
|
16835
|
+
const res = await client.send(new GetSecretValueCommand5({ SecretId: indexId }));
|
|
16836
|
+
keys = parseInstanceIndex(res.SecretString ?? "");
|
|
16837
|
+
} catch (err) {
|
|
16838
|
+
if (!isResourceNotFound(err)) throw err;
|
|
16839
|
+
}
|
|
16840
|
+
if (keys.includes(key)) return;
|
|
16841
|
+
const secretString = buildInstanceIndexValue([...keys, key]);
|
|
16842
|
+
try {
|
|
16843
|
+
await client.send(
|
|
16844
|
+
new PutSecretValueCommand({ SecretId: indexId, SecretString: secretString })
|
|
16845
|
+
);
|
|
16846
|
+
} catch (err) {
|
|
16847
|
+
if (!isResourceNotFound(err)) throw err;
|
|
16848
|
+
await client.send(
|
|
16849
|
+
new CreateSecretCommand({
|
|
16850
|
+
Name: indexId,
|
|
16851
|
+
Description: `Instance-key index for ${serviceName} (read by listInstances(); maintained by mesh secrets set/reindex and the Hub)`,
|
|
16852
|
+
SecretString: secretString,
|
|
16853
|
+
Tags: [
|
|
16854
|
+
{ Key: "mesh:type", Value: "external-service-index" },
|
|
16855
|
+
{ Key: "mesh:service", Value: serviceName }
|
|
16856
|
+
]
|
|
16857
|
+
})
|
|
16858
|
+
);
|
|
16859
|
+
logInfo(
|
|
16860
|
+
`Created ${indexId} OUT OF BAND \u2014 the declaring stack does not manage it. Deploy the declaring stack (it creates the index) before writing keys, or import this secret into the stack before its next deploy.`
|
|
16861
|
+
);
|
|
16862
|
+
}
|
|
16863
|
+
} catch (err) {
|
|
16864
|
+
logInfo(
|
|
16865
|
+
`Warning: failed to record instance "${key}" in ${indexId} \u2014 listInstances() will not see it until you run: mesh secrets reindex external/${serviceName} (${err})`
|
|
16866
|
+
);
|
|
16867
|
+
}
|
|
16868
|
+
}
|
|
16576
16869
|
async function writeConfigMirror(client, secretId, schema, merged, meta) {
|
|
16577
16870
|
const configId = `${secretId}/.config`;
|
|
16578
16871
|
const configValues = extractNonSecretFields(schema.fields, merged);
|
|
@@ -16614,17 +16907,157 @@ var init_set = __esm({
|
|
|
16614
16907
|
}
|
|
16615
16908
|
});
|
|
16616
16909
|
|
|
16910
|
+
// libs/mesh-cli/src/commands/secrets/reindex.ts
|
|
16911
|
+
import { SSMClient as SSMClient3 } from "@aws-sdk/client-ssm";
|
|
16912
|
+
import {
|
|
16913
|
+
SecretsManagerClient as SecretsManagerClient6,
|
|
16914
|
+
ListSecretsCommand,
|
|
16915
|
+
GetSecretValueCommand as GetSecretValueCommand6,
|
|
16916
|
+
PutSecretValueCommand as PutSecretValueCommand2,
|
|
16917
|
+
CreateSecretCommand as CreateSecretCommand2
|
|
16918
|
+
} from "@aws-sdk/client-secrets-manager";
|
|
16919
|
+
import {
|
|
16920
|
+
buildInstanceIndexValue as buildInstanceIndexValue2,
|
|
16921
|
+
instanceIndexSecretId as instanceIndexSecretId2,
|
|
16922
|
+
instanceKeyFromSecretName,
|
|
16923
|
+
parseInstanceIndex as parseInstanceIndex2
|
|
16924
|
+
} from "@mesh-tech/secrets";
|
|
16925
|
+
async function scanInstanceKeys(client, secretPrefix) {
|
|
16926
|
+
const keys = [];
|
|
16927
|
+
let nextToken;
|
|
16928
|
+
do {
|
|
16929
|
+
const response = await client.send(
|
|
16930
|
+
new ListSecretsCommand({
|
|
16931
|
+
Filters: [{ Key: "name", Values: [`${secretPrefix}/`] }],
|
|
16932
|
+
NextToken: nextToken
|
|
16933
|
+
})
|
|
16934
|
+
);
|
|
16935
|
+
for (const secret of response.SecretList ?? []) {
|
|
16936
|
+
const key = secret.Name ? instanceKeyFromSecretName(secretPrefix, secret.Name) : null;
|
|
16937
|
+
if (key) keys.push(key);
|
|
16938
|
+
}
|
|
16939
|
+
nextToken = response.NextToken;
|
|
16940
|
+
} while (nextToken);
|
|
16941
|
+
return keys;
|
|
16942
|
+
}
|
|
16943
|
+
function indexAlreadyMatches(missing, stale, indexExists, malformed) {
|
|
16944
|
+
return missing.length === 0 && stale.length === 0 && indexExists && !malformed;
|
|
16945
|
+
}
|
|
16946
|
+
async function reindexCommand(servicePath, opts) {
|
|
16947
|
+
const stackOpt = resolveStackOption(opts);
|
|
16948
|
+
const context = detectContext(stackOpt);
|
|
16949
|
+
const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
|
|
16950
|
+
await ensureAwsCredentialsForStack(stackOpt ?? context.stage);
|
|
16951
|
+
const ssmClient = new SSMClient3({ region });
|
|
16952
|
+
const smClient = new SecretsManagerClient6({ region });
|
|
16953
|
+
const services = await discoverExternalServices(
|
|
16954
|
+
ssmClient,
|
|
16955
|
+
context.tenant,
|
|
16956
|
+
context.platformEnv
|
|
16957
|
+
);
|
|
16958
|
+
const serviceName = servicePath?.replace(/^external\//, "");
|
|
16959
|
+
if (!serviceName || !services.has(serviceName)) {
|
|
16960
|
+
if (serviceName) {
|
|
16961
|
+
logError(`External service "${serviceName}" not found.`);
|
|
16962
|
+
}
|
|
16963
|
+
const keyed = [...services.entries()].filter(([, s]) => s.schema?.keyedBy);
|
|
16964
|
+
console.error("\nMulti-instance external services:");
|
|
16965
|
+
for (const [name, svc2] of keyed) {
|
|
16966
|
+
console.error(` ${name} (keyed by ${svc2.schema.keyedBy})`);
|
|
16967
|
+
}
|
|
16968
|
+
if (keyed.length === 0) console.error(" (none)");
|
|
16969
|
+
console.error(`
|
|
16970
|
+
Usage: mesh secrets reindex external/<name>`);
|
|
16971
|
+
process.exit(serviceName ? 1 : 0);
|
|
16972
|
+
}
|
|
16973
|
+
const svc = services.get(serviceName);
|
|
16974
|
+
if (!svc.schema?.keyedBy) {
|
|
16975
|
+
logError(
|
|
16976
|
+
`"${serviceName}" is single-instance (no keyedBy) \u2014 it has no instance index.`
|
|
16977
|
+
);
|
|
16978
|
+
process.exit(1);
|
|
16979
|
+
}
|
|
16980
|
+
const secretPrefix = svc.meta.secretPrefix;
|
|
16981
|
+
const indexId = instanceIndexSecretId2(secretPrefix);
|
|
16982
|
+
const actual = [...new Set(await scanInstanceKeys(smClient, secretPrefix))].sort();
|
|
16983
|
+
let listed = [];
|
|
16984
|
+
let indexExists = true;
|
|
16985
|
+
let malformed = false;
|
|
16986
|
+
try {
|
|
16987
|
+
const res = await smClient.send(new GetSecretValueCommand6({ SecretId: indexId }));
|
|
16988
|
+
try {
|
|
16989
|
+
listed = parseInstanceIndex2(res.SecretString ?? "");
|
|
16990
|
+
} catch {
|
|
16991
|
+
malformed = true;
|
|
16992
|
+
logInfo(`Existing index at ${indexId} is malformed \u2014 rebuilding from scratch.`);
|
|
16993
|
+
}
|
|
16994
|
+
} catch (err) {
|
|
16995
|
+
if (!isResourceNotFound(err)) throw err;
|
|
16996
|
+
indexExists = false;
|
|
16997
|
+
logInfo(`No index at ${indexId} yet \u2014 it will be created.`);
|
|
16998
|
+
}
|
|
16999
|
+
const missing = actual.filter((k) => !listed.includes(k));
|
|
17000
|
+
const stale = listed.filter((k) => !actual.includes(k));
|
|
17001
|
+
logInfo(`Instances in Secrets Manager: ${actual.length ? actual.join(", ") : "(none)"}`);
|
|
17002
|
+
if (missing.length > 0) logInfo(`Missing from index: ${missing.join(", ")}`);
|
|
17003
|
+
if (stale.length > 0) logInfo(`Stale in index (secret gone): ${stale.join(", ")}`);
|
|
17004
|
+
if (indexAlreadyMatches(missing, stale, indexExists, malformed)) {
|
|
17005
|
+
logSuccess(`Index at ${indexId} already matches \u2014 nothing to do.`);
|
|
17006
|
+
return;
|
|
17007
|
+
}
|
|
17008
|
+
if (opts.dryRun) {
|
|
17009
|
+
logInfo(`Dry run \u2014 would write ${indexId} with ${actual.length} instance(s).`);
|
|
17010
|
+
return;
|
|
17011
|
+
}
|
|
17012
|
+
await writeInstanceIndex(smClient, secretPrefix, serviceName, actual);
|
|
17013
|
+
logSuccess(`Index rebuilt: ${indexId} now lists ${actual.length} instance(s).`);
|
|
17014
|
+
}
|
|
17015
|
+
async function writeInstanceIndex(client, secretPrefix, serviceName, keys) {
|
|
17016
|
+
const indexId = instanceIndexSecretId2(secretPrefix);
|
|
17017
|
+
const secretString = buildInstanceIndexValue2(keys);
|
|
17018
|
+
try {
|
|
17019
|
+
await client.send(
|
|
17020
|
+
new PutSecretValueCommand2({ SecretId: indexId, SecretString: secretString })
|
|
17021
|
+
);
|
|
17022
|
+
} catch (err) {
|
|
17023
|
+
if (!isResourceNotFound(err)) throw err;
|
|
17024
|
+
await client.send(
|
|
17025
|
+
new CreateSecretCommand2({
|
|
17026
|
+
Name: indexId,
|
|
17027
|
+
Description: `Instance-key index for ${serviceName} (read by listInstances(); maintained by mesh secrets set/reindex and the Hub)`,
|
|
17028
|
+
SecretString: secretString,
|
|
17029
|
+
Tags: [
|
|
17030
|
+
{ Key: "mesh:type", Value: "external-service-index" },
|
|
17031
|
+
{ Key: "mesh:service", Value: serviceName }
|
|
17032
|
+
]
|
|
17033
|
+
})
|
|
17034
|
+
);
|
|
17035
|
+
logInfo(
|
|
17036
|
+
`Created ${indexId} OUT OF BAND \u2014 the declaring stack does not manage it. Deploy the declaring stack BEFORE reindex next time, or import this secret into the stack before its next deploy.`
|
|
17037
|
+
);
|
|
17038
|
+
}
|
|
17039
|
+
}
|
|
17040
|
+
var init_reindex = __esm({
|
|
17041
|
+
"libs/mesh-cli/src/commands/secrets/reindex.ts"() {
|
|
17042
|
+
"use strict";
|
|
17043
|
+
init_context();
|
|
17044
|
+
init_log();
|
|
17045
|
+
init_stack_flag();
|
|
17046
|
+
init_set();
|
|
17047
|
+
}
|
|
17048
|
+
});
|
|
17049
|
+
|
|
16617
17050
|
// libs/mesh-cli/src/commands/secrets/migrate-config.ts
|
|
16618
17051
|
import {
|
|
16619
|
-
SSMClient as
|
|
17052
|
+
SSMClient as SSMClient4,
|
|
16620
17053
|
GetParametersByPathCommand as GetParametersByPathCommand2
|
|
16621
17054
|
} from "@aws-sdk/client-ssm";
|
|
16622
17055
|
import {
|
|
16623
|
-
SecretsManagerClient as
|
|
16624
|
-
GetSecretValueCommand as
|
|
16625
|
-
PutSecretValueCommand as
|
|
16626
|
-
CreateSecretCommand as
|
|
16627
|
-
ListSecretsCommand
|
|
17056
|
+
SecretsManagerClient as SecretsManagerClient7,
|
|
17057
|
+
GetSecretValueCommand as GetSecretValueCommand7,
|
|
17058
|
+
PutSecretValueCommand as PutSecretValueCommand3,
|
|
17059
|
+
CreateSecretCommand as CreateSecretCommand3,
|
|
17060
|
+
ListSecretsCommand as ListSecretsCommand2
|
|
16628
17061
|
} from "@aws-sdk/client-secrets-manager";
|
|
16629
17062
|
function normalizeEntry2(raw) {
|
|
16630
17063
|
if (raw.type === "group" && raw.fields) {
|
|
@@ -16710,7 +17143,7 @@ function isResourceNotFound2(err) {
|
|
|
16710
17143
|
}
|
|
16711
17144
|
async function readSecret(client, secretId) {
|
|
16712
17145
|
try {
|
|
16713
|
-
const res = await client.send(new
|
|
17146
|
+
const res = await client.send(new GetSecretValueCommand7({ SecretId: secretId }));
|
|
16714
17147
|
return res.SecretString ? JSON.parse(res.SecretString) : null;
|
|
16715
17148
|
} catch (err) {
|
|
16716
17149
|
if (isResourceNotFound2(err)) return null;
|
|
@@ -16720,10 +17153,10 @@ async function readSecret(client, secretId) {
|
|
|
16720
17153
|
async function writeSecret2(client, secretId, values, description) {
|
|
16721
17154
|
const secretString = JSON.stringify(values);
|
|
16722
17155
|
try {
|
|
16723
|
-
await client.send(new
|
|
17156
|
+
await client.send(new PutSecretValueCommand3({ SecretId: secretId, SecretString: secretString }));
|
|
16724
17157
|
} catch (err) {
|
|
16725
17158
|
if (isResourceNotFound2(err)) {
|
|
16726
|
-
await client.send(new
|
|
17159
|
+
await client.send(new CreateSecretCommand3({
|
|
16727
17160
|
Name: secretId,
|
|
16728
17161
|
Description: description,
|
|
16729
17162
|
SecretString: secretString,
|
|
@@ -16736,7 +17169,7 @@ async function writeSecret2(client, secretId, values, description) {
|
|
|
16736
17169
|
}
|
|
16737
17170
|
async function secretExists(client, secretId) {
|
|
16738
17171
|
try {
|
|
16739
|
-
await client.send(new
|
|
17172
|
+
await client.send(new GetSecretValueCommand7({ SecretId: secretId }));
|
|
16740
17173
|
return true;
|
|
16741
17174
|
} catch (err) {
|
|
16742
17175
|
if (isResourceNotFound2(err)) return false;
|
|
@@ -16749,7 +17182,7 @@ async function listInstanceKeys(client, secretPrefix) {
|
|
|
16749
17182
|
let nextToken;
|
|
16750
17183
|
do {
|
|
16751
17184
|
const response = await client.send(
|
|
16752
|
-
new
|
|
17185
|
+
new ListSecretsCommand2({
|
|
16753
17186
|
Filters: [{ Key: "name", Values: [prefix2] }],
|
|
16754
17187
|
NextToken: nextToken
|
|
16755
17188
|
})
|
|
@@ -16815,8 +17248,8 @@ async function migrateService(smClient, meta, schema, opts) {
|
|
|
16815
17248
|
async function migrateConfigCommand(opts) {
|
|
16816
17249
|
const context = detectContext(resolveStackOption(opts));
|
|
16817
17250
|
const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
|
|
16818
|
-
const ssmClient = new
|
|
16819
|
-
const smClient = new
|
|
17251
|
+
const ssmClient = new SSMClient4({ region });
|
|
17252
|
+
const smClient = new SecretsManagerClient7({ region });
|
|
16820
17253
|
logInfo(`Migrating .config mirrors for ${context.tenant}/${context.platformEnv}`);
|
|
16821
17254
|
if (opts.dryRun) logInfo("DRY-RUN mode \u2014 no writes");
|
|
16822
17255
|
if (opts.force) logInfo("FORCE mode \u2014 overwrite existing .config");
|
|
@@ -16869,6 +17302,11 @@ function registerSecretsCommands(program2) {
|
|
|
16869
17302
|
secrets.command("set [service]").description("Set credentials for an external service (e.g., mesh secrets set external/symitar)").option("--key <key>", "Instance key for multi-instance services (e.g., FI ID)").option("--all", "Prompt for all fields including optional ones").option("--json <json>", "Non-interactive: provide values as JSON").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (service, opts) => {
|
|
16870
17303
|
await setCommand(service, opts);
|
|
16871
17304
|
});
|
|
17305
|
+
secrets.command("reindex [service]").description(
|
|
17306
|
+
"Rebuild a multi-instance external service's instance index (the {prefix}/.index secret listInstances() reads) from the per-key secrets actually in Secrets Manager \u2014 the repair for an instance secret created or deleted out of band"
|
|
17307
|
+
).option("--dry-run", "Show what would change without writing").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (service, opts) => {
|
|
17308
|
+
await reindexCommand(service, opts);
|
|
17309
|
+
});
|
|
16872
17310
|
secrets.command("migrate-config").description("Backfill .config mirror secrets for all external services").option("--force", "Overwrite existing .config mirrors").option("--dry-run", "Show what would be written without writing").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (opts) => {
|
|
16873
17311
|
await migrateConfigCommand(opts);
|
|
16874
17312
|
});
|
|
@@ -16878,15 +17316,16 @@ var init_secrets = __esm({
|
|
|
16878
17316
|
"use strict";
|
|
16879
17317
|
init_exec2();
|
|
16880
17318
|
init_set();
|
|
17319
|
+
init_reindex();
|
|
16881
17320
|
init_migrate_config();
|
|
16882
17321
|
}
|
|
16883
17322
|
});
|
|
16884
17323
|
|
|
16885
17324
|
// libs/mesh-cli/src/commands/stack.ts
|
|
16886
|
-
import { execFileSync as
|
|
17325
|
+
import { execFileSync as execFileSync27 } from "child_process";
|
|
16887
17326
|
import * as path37 from "path";
|
|
16888
17327
|
import * as fs30 from "fs";
|
|
16889
|
-
import { parse as
|
|
17328
|
+
import { parse as parseYaml5 } from "yaml";
|
|
16890
17329
|
function readTopLevelYamlKey(appRoot, stack, key) {
|
|
16891
17330
|
const configFile = path37.join(appRoot, `Pulumi.${stack}.yaml`);
|
|
16892
17331
|
if (!fs30.existsSync(configFile)) return null;
|
|
@@ -16963,7 +17402,7 @@ function readBaseConfigFromYaml(appRoot, stack) {
|
|
|
16963
17402
|
if (!fs30.existsSync(file)) return {};
|
|
16964
17403
|
let doc;
|
|
16965
17404
|
try {
|
|
16966
|
-
doc =
|
|
17405
|
+
doc = parseYaml5(fs30.readFileSync(file, "utf-8"));
|
|
16967
17406
|
} catch {
|
|
16968
17407
|
return {};
|
|
16969
17408
|
}
|
|
@@ -16976,7 +17415,7 @@ function readBaseConfigFromYaml(appRoot, stack) {
|
|
|
16976
17415
|
}
|
|
16977
17416
|
function getGitHubUsername() {
|
|
16978
17417
|
try {
|
|
16979
|
-
const result =
|
|
17418
|
+
const result = execFileSync27("gh", ["api", "user", "--jq", ".login"], {
|
|
16980
17419
|
encoding: "utf-8",
|
|
16981
17420
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16982
17421
|
});
|
|
@@ -16985,7 +17424,7 @@ function getGitHubUsername() {
|
|
|
16985
17424
|
} catch {
|
|
16986
17425
|
}
|
|
16987
17426
|
try {
|
|
16988
|
-
const result =
|
|
17427
|
+
const result = execFileSync27("git", ["config", "user.email"], {
|
|
16989
17428
|
encoding: "utf-8",
|
|
16990
17429
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16991
17430
|
});
|
|
@@ -17071,7 +17510,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17071
17510
|
if (!opts.adopt) {
|
|
17072
17511
|
let existing = [];
|
|
17073
17512
|
try {
|
|
17074
|
-
const raw =
|
|
17513
|
+
const raw = execFileSync27("pulumi", ["stack", "ls", "--json"], {
|
|
17075
17514
|
cwd: appRoot,
|
|
17076
17515
|
encoding: "utf-8",
|
|
17077
17516
|
env: pulumiEnv,
|
|
@@ -17095,7 +17534,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17095
17534
|
logInfo(`Using KMS secrets provider: ${secretsProvider}`);
|
|
17096
17535
|
}
|
|
17097
17536
|
try {
|
|
17098
|
-
|
|
17537
|
+
execFileSync27("pulumi", initArgs, {
|
|
17099
17538
|
cwd: appRoot,
|
|
17100
17539
|
env: pulumiEnv,
|
|
17101
17540
|
stdio: "inherit"
|
|
@@ -17112,7 +17551,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17112
17551
|
}
|
|
17113
17552
|
}
|
|
17114
17553
|
try {
|
|
17115
|
-
|
|
17554
|
+
execFileSync27("pulumi", ["stack", "select", newStack], {
|
|
17116
17555
|
cwd: appRoot,
|
|
17117
17556
|
env: pulumiEnv,
|
|
17118
17557
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -17122,7 +17561,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17122
17561
|
if (!configExists) {
|
|
17123
17562
|
let baseConfig = {};
|
|
17124
17563
|
try {
|
|
17125
|
-
const raw =
|
|
17564
|
+
const raw = execFileSync27(
|
|
17126
17565
|
"pulumi",
|
|
17127
17566
|
["config", "--json", "--stack", baseStack],
|
|
17128
17567
|
{ cwd: appRoot, env: pulumiEnv, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -17140,19 +17579,19 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17140
17579
|
if (key === "mesh:deploy") continue;
|
|
17141
17580
|
try {
|
|
17142
17581
|
if (entry.objectValue !== void 0) {
|
|
17143
|
-
|
|
17582
|
+
execFileSync27(
|
|
17144
17583
|
"pulumi",
|
|
17145
17584
|
["config", "set", key, JSON.stringify(entry.objectValue)],
|
|
17146
17585
|
{ cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
|
|
17147
17586
|
);
|
|
17148
17587
|
} else if (entry.value === "true" || entry.value === "false") {
|
|
17149
|
-
|
|
17588
|
+
execFileSync27(
|
|
17150
17589
|
"pulumi",
|
|
17151
17590
|
["config", "set", "--type", "bool", key, entry.value],
|
|
17152
17591
|
{ cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
|
|
17153
17592
|
);
|
|
17154
17593
|
} else {
|
|
17155
|
-
|
|
17594
|
+
execFileSync27(
|
|
17156
17595
|
"pulumi",
|
|
17157
17596
|
["config", "set", key, entry.value],
|
|
17158
17597
|
{ cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -17165,7 +17604,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17165
17604
|
const baseEnv = readConfigBlockKey(appRoot, baseStack, "mesh:coreEnv") ?? (baseTenant && baseStack.startsWith(`${baseTenant}-`) ? baseStack.slice(baseTenant.length + 1) : baseStack);
|
|
17166
17605
|
const setCfg = (args) => {
|
|
17167
17606
|
try {
|
|
17168
|
-
|
|
17607
|
+
execFileSync27("pulumi", ["config", "set", ...args], {
|
|
17169
17608
|
cwd: appRoot,
|
|
17170
17609
|
env: pulumiEnv,
|
|
17171
17610
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -17214,7 +17653,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17214
17653
|
`Configured Pulumi.${newStack}.yaml (personal platform env on core '${baseEnv}'${opts.parentZone ? `, DNS zone ${newStack.startsWith(`${baseTenant}-`) ? newStack.slice(baseTenant.length + 1) : newStack}.${opts.parentZone}` : ""})`
|
|
17215
17654
|
);
|
|
17216
17655
|
} else {
|
|
17217
|
-
|
|
17656
|
+
execFileSync27("pulumi", ["config", "set", "--type", "bool", "mesh:deploy", "false"], {
|
|
17218
17657
|
cwd: appRoot,
|
|
17219
17658
|
env: pulumiEnv,
|
|
17220
17659
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -17244,7 +17683,7 @@ Specify which to base on: mesh stack init --from <stack>`
|
|
|
17244
17683
|
const args = ["stack", "rm", name];
|
|
17245
17684
|
if (opts.yes) args.push("--yes");
|
|
17246
17685
|
try {
|
|
17247
|
-
|
|
17686
|
+
execFileSync27("pulumi", args, { cwd: appRoot, env: pulumiEnv, stdio: "inherit" });
|
|
17248
17687
|
logSuccess(`Removed stack ${name}`);
|
|
17249
17688
|
} catch (err) {
|
|
17250
17689
|
process.exit(err.status ?? 1);
|
|
@@ -17456,12 +17895,12 @@ var init_recover_conversation = __esm({
|
|
|
17456
17895
|
});
|
|
17457
17896
|
|
|
17458
17897
|
// libs/mesh-cli/src/utils/temporal-codec.ts
|
|
17459
|
-
import { execFileSync as
|
|
17898
|
+
import { execFileSync as execFileSync28 } from "child_process";
|
|
17460
17899
|
import { webcrypto as crypto4 } from "node:crypto";
|
|
17461
17900
|
function resolveTemporalEncodingKeyFromK8s(namespace) {
|
|
17462
17901
|
const secretName = `${namespace}-temporal-encoding-key`;
|
|
17463
17902
|
try {
|
|
17464
|
-
const b64 =
|
|
17903
|
+
const b64 = execFileSync28(
|
|
17465
17904
|
"kubectl",
|
|
17466
17905
|
[
|
|
17467
17906
|
"get",
|
|
@@ -18519,8 +18958,8 @@ import * as fs32 from "fs";
|
|
|
18519
18958
|
import * as os13 from "os";
|
|
18520
18959
|
import * as path39 from "path";
|
|
18521
18960
|
import {
|
|
18522
|
-
SecretsManagerClient as
|
|
18523
|
-
GetSecretValueCommand as
|
|
18961
|
+
SecretsManagerClient as SecretsManagerClient8,
|
|
18962
|
+
GetSecretValueCommand as GetSecretValueCommand8
|
|
18524
18963
|
} from "@aws-sdk/client-secrets-manager";
|
|
18525
18964
|
function resolveTenantEnv(options) {
|
|
18526
18965
|
if (options.tenant && options.env) {
|
|
@@ -18783,10 +19222,10 @@ async function tunnelExternal(name, options) {
|
|
|
18783
19222
|
const { appTenant, appStage } = resolveCredentialAxis(options);
|
|
18784
19223
|
const secretId = externalSecretId(appTenant, appStage, name, key);
|
|
18785
19224
|
const setHint = `mesh secrets set external/${name}${key ? ` --key=${key}` : ""}`;
|
|
18786
|
-
const sm = new
|
|
19225
|
+
const sm = new SecretsManagerClient8({});
|
|
18787
19226
|
let creds;
|
|
18788
19227
|
try {
|
|
18789
|
-
const out = await sm.send(new
|
|
19228
|
+
const out = await sm.send(new GetSecretValueCommand8({ SecretId: secretId }));
|
|
18790
19229
|
creds = JSON.parse(out.SecretString ?? "{}");
|
|
18791
19230
|
} catch (err) {
|
|
18792
19231
|
logError(
|
|
@@ -20339,7 +20778,7 @@ var init_src3 = __esm({
|
|
|
20339
20778
|
import * as fs33 from "fs";
|
|
20340
20779
|
import * as path40 from "path";
|
|
20341
20780
|
import { createRequire as createRequire2 } from "module";
|
|
20342
|
-
import { execFileSync as
|
|
20781
|
+
import { execFileSync as execFileSync29 } from "child_process";
|
|
20343
20782
|
function resolveExtractorPath() {
|
|
20344
20783
|
try {
|
|
20345
20784
|
const require2 = createRequire2(import.meta.url);
|
|
@@ -20394,7 +20833,7 @@ for (const file of files) {
|
|
|
20394
20833
|
process.stdout.write(JSON.stringify(results));
|
|
20395
20834
|
`;
|
|
20396
20835
|
try {
|
|
20397
|
-
const result =
|
|
20836
|
+
const result = execFileSync29("npx", ["tsx", "--eval", script], {
|
|
20398
20837
|
encoding: "utf-8",
|
|
20399
20838
|
stdio: ["pipe", "pipe", "inherit"],
|
|
20400
20839
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -20436,7 +20875,7 @@ for (const file of files) {
|
|
|
20436
20875
|
process.stdout.write(JSON.stringify(results));
|
|
20437
20876
|
`;
|
|
20438
20877
|
try {
|
|
20439
|
-
const result =
|
|
20878
|
+
const result = execFileSync29("npx", ["tsx", "--eval", script], {
|
|
20440
20879
|
encoding: "utf-8",
|
|
20441
20880
|
stdio: ["pipe", "pipe", "inherit"],
|
|
20442
20881
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -20491,7 +20930,7 @@ for (const file of files) {
|
|
|
20491
20930
|
process.stdout.write(JSON.stringify(results));
|
|
20492
20931
|
`;
|
|
20493
20932
|
try {
|
|
20494
|
-
const result =
|
|
20933
|
+
const result = execFileSync29("npx", ["tsx", "--eval", script], {
|
|
20495
20934
|
encoding: "utf-8",
|
|
20496
20935
|
stdio: ["pipe", "pipe", "inherit"],
|
|
20497
20936
|
maxBuffer: 10 * 1024 * 1024
|