@ashlr/stack 0.3.1 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +73 -17
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1490,9 +1490,9 @@ var init_stack_manifest = __esm(() => {
|
|
|
1490
1490
|
schema_version: 1,
|
|
1491
1491
|
kind: "ashlr-stack-manifest",
|
|
1492
1492
|
components: Object.freeze([
|
|
1493
|
-
Object.freeze({ id: "core", name: "@ashlr/stack-core", version: "0.3.
|
|
1494
|
-
Object.freeze({ id: "cli", name: "@ashlr/stack", version: "0.3.
|
|
1495
|
-
Object.freeze({ id: "mcp", name: "ashlr-stack-mcp", version: "0.3.
|
|
1493
|
+
Object.freeze({ id: "core", name: "@ashlr/stack-core", version: "0.3.7", distribution: "npm" }),
|
|
1494
|
+
Object.freeze({ id: "cli", name: "@ashlr/stack", version: "0.3.7", distribution: "npm" }),
|
|
1495
|
+
Object.freeze({ id: "mcp", name: "ashlr-stack-mcp", version: "0.3.7", distribution: "npm" }),
|
|
1496
1496
|
Object.freeze({
|
|
1497
1497
|
id: "plugin",
|
|
1498
1498
|
name: "stack",
|
|
@@ -1748,7 +1748,7 @@ async function exec(args, opts = {}) {
|
|
|
1748
1748
|
return new Promise((resolvePromise, reject) => {
|
|
1749
1749
|
const hasTimeout = typeof opts.timeoutMs === "number" && Number.isFinite(opts.timeoutMs);
|
|
1750
1750
|
const useGroup = hasTimeout && !opts.interactive && process.platform !== "win32";
|
|
1751
|
-
const child =
|
|
1751
|
+
const child = spawnImpl(binary, args, {
|
|
1752
1752
|
env,
|
|
1753
1753
|
cwd: opts.cwd,
|
|
1754
1754
|
stdio: opts.interactive ? "inherit" : ["pipe", "pipe", "pipe"],
|
|
@@ -1940,7 +1940,7 @@ function formatArgsForError(args) {
|
|
|
1940
1940
|
});
|
|
1941
1941
|
return redacted.join(" ");
|
|
1942
1942
|
}
|
|
1943
|
-
var PhantomTimeoutError, cachedInstalled;
|
|
1943
|
+
var PhantomTimeoutError, cachedInstalled, spawnImpl;
|
|
1944
1944
|
var init_phantom = __esm(() => {
|
|
1945
1945
|
init_errors();
|
|
1946
1946
|
init_phantom_process();
|
|
@@ -1950,6 +1950,7 @@ var init_phantom = __esm(() => {
|
|
|
1950
1950
|
this.name = "PhantomTimeoutError";
|
|
1951
1951
|
}
|
|
1952
1952
|
};
|
|
1953
|
+
spawnImpl = spawn;
|
|
1953
1954
|
});
|
|
1954
1955
|
// ../core/src/env.ts
|
|
1955
1956
|
function resolveOAuthClientId(provider, envOverride) {
|
|
@@ -6663,7 +6664,7 @@ import { mkdir as mkdir3, writeFile as writeFile6 } from "node:fs/promises";
|
|
|
6663
6664
|
import { dirname as dirname3, resolve as resolve8 } from "node:path";
|
|
6664
6665
|
async function wirePhantomForRecipe(recipe, opts = {}) {
|
|
6665
6666
|
const result = { present: [], missing: [], webhooks: [], skipped: [] };
|
|
6666
|
-
if (opts.noWire)
|
|
6667
|
+
if (opts.noWire || recipe.providers.length === 0)
|
|
6667
6668
|
return result;
|
|
6668
6669
|
const cwd = opts.cwd ?? process.cwd();
|
|
6669
6670
|
try {
|
|
@@ -6784,7 +6785,10 @@ function signatureHeaderFor(provider) {
|
|
|
6784
6785
|
}
|
|
6785
6786
|
}
|
|
6786
6787
|
function capitalize(s) {
|
|
6787
|
-
|
|
6788
|
+
if (s === "")
|
|
6789
|
+
return s;
|
|
6790
|
+
const first = String.fromCodePoint(s.codePointAt(0));
|
|
6791
|
+
return first.toUpperCase() + s.slice(first.length);
|
|
6788
6792
|
}
|
|
6789
6793
|
var WEBHOOK_PROVIDERS;
|
|
6790
6794
|
var init_phantom_wire = __esm(() => {
|
|
@@ -9139,7 +9143,7 @@ var init_dist2 = __esm(() => {
|
|
|
9139
9143
|
const e = i(true);
|
|
9140
9144
|
return Object.keys(e);
|
|
9141
9145
|
} });
|
|
9142
|
-
t = typeof process < "u" && process.env && "
|
|
9146
|
+
t = typeof process < "u" && process.env && "production" || "";
|
|
9143
9147
|
f2 = [["APPVEYOR"], ["AWS_AMPLIFY", "AWS_APP_ID", { ci: true }], ["AZURE_PIPELINES", "SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"], ["AZURE_STATIC", "INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN"], ["APPCIRCLE", "AC_APPCIRCLE"], ["BAMBOO", "bamboo_planKey"], ["BITBUCKET", "BITBUCKET_COMMIT"], ["BITRISE", "BITRISE_IO"], ["BUDDY", "BUDDY_WORKSPACE_ID"], ["BUILDKITE"], ["CIRCLE", "CIRCLECI"], ["CIRRUS", "CIRRUS_CI"], ["CLOUDFLARE_PAGES", "CF_PAGES", { ci: true }], ["CODEBUILD", "CODEBUILD_BUILD_ARN"], ["CODEFRESH", "CF_BUILD_ID"], ["DRONE"], ["DRONE", "DRONE_BUILD_EVENT"], ["DSARI"], ["GITHUB_ACTIONS"], ["GITLAB", "GITLAB_CI"], ["GITLAB", "CI_MERGE_REQUEST_ID"], ["GOCD", "GO_PIPELINE_LABEL"], ["LAYERCI"], ["HUDSON", "HUDSON_URL"], ["JENKINS", "JENKINS_URL"], ["MAGNUM"], ["NETLIFY"], ["NETLIFY", "NETLIFY_LOCAL", { ci: false }], ["NEVERCODE"], ["RENDER"], ["SAIL", "SAILCI"], ["SEMAPHORE"], ["SCREWDRIVER"], ["SHIPPABLE"], ["SOLANO", "TDDIUM"], ["STRIDER"], ["TEAMCITY", "TEAMCITY_VERSION"], ["TRAVIS"], ["VERCEL", "NOW_BUILDER"], ["VERCEL", "VERCEL", { ci: false }], ["VERCEL", "VERCEL_ENV", { ci: false }], ["APPCENTER", "APPCENTER_BUILD_ID"], ["CODESANDBOX", "CODESANDBOX_SSE", { ci: false }], ["CODESANDBOX", "CODESANDBOX_HOST", { ci: false }], ["STACKBLITZ"], ["STORMKIT"], ["CLEAVR"], ["ZEABUR"], ["CODESPHERE", "CODESPHERE_APP_ID", { ci: true }], ["RAILWAY", "RAILWAY_PROJECT_ID"], ["RAILWAY", "RAILWAY_SERVICE_ID"], ["DENO-DEPLOY", "DENO_DEPLOYMENT_ID"], ["FIREBASE_APP_HOSTING", "FIREBASE_APP_HOSTING", { ci: true }]];
|
|
9144
9148
|
l = b();
|
|
9145
9149
|
l.name;
|
|
@@ -11705,7 +11709,7 @@ var init_scan = __esm(() => {
|
|
|
11705
11709
|
console.log();
|
|
11706
11710
|
if (!isAuto) {
|
|
11707
11711
|
const suggestion = filtered.map((h) => `stack add ${h.provider}`).join(`
|
|
11708
|
-
|
|
11712
|
+
`);
|
|
11709
11713
|
console.log(colors2.dim(" Next steps:"));
|
|
11710
11714
|
console.log(colors2.dim(` ${suggestion}
|
|
11711
11715
|
`));
|
|
@@ -14515,6 +14519,8 @@ async function openFleetFile(path) {
|
|
|
14515
14519
|
async function readFleetText(path, options = {}) {
|
|
14516
14520
|
const { maxBytes = 16 * 1024 * 1024, tail = false, ioStatus = "invalid" } = options;
|
|
14517
14521
|
try {
|
|
14522
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
14523
|
+
throw new Error("Invalid byte limit");
|
|
14518
14524
|
const file = await openFleetFile(path);
|
|
14519
14525
|
try {
|
|
14520
14526
|
const stat = await file.stat();
|
|
@@ -14529,7 +14535,29 @@ async function readFleetText(path, options = {}) {
|
|
|
14529
14535
|
`);
|
|
14530
14536
|
text = newline < 0 ? "" : chunk.slice(newline + 1);
|
|
14531
14537
|
} else {
|
|
14532
|
-
|
|
14538
|
+
const initial = Math.min(64 * 1024, Math.max(1, stat.size), maxBytes);
|
|
14539
|
+
let buffer = Buffer.alloc(initial);
|
|
14540
|
+
let offset = 0;
|
|
14541
|
+
for (;; ) {
|
|
14542
|
+
if (offset === maxBytes) {
|
|
14543
|
+
const probe = Buffer.alloc(1);
|
|
14544
|
+
if ((await file.read(probe, 0, 1, offset)).bytesRead)
|
|
14545
|
+
throw new Error("Oversized source");
|
|
14546
|
+
break;
|
|
14547
|
+
}
|
|
14548
|
+
if (offset === buffer.length) {
|
|
14549
|
+
const grown = Buffer.alloc(Math.min(maxBytes, buffer.length * 2));
|
|
14550
|
+
buffer.copy(grown, 0, 0, offset);
|
|
14551
|
+
buffer = grown;
|
|
14552
|
+
}
|
|
14553
|
+
const { bytesRead } = await file.read(buffer, offset, buffer.length - offset, offset);
|
|
14554
|
+
if (!bytesRead)
|
|
14555
|
+
break;
|
|
14556
|
+
offset += bytesRead;
|
|
14557
|
+
}
|
|
14558
|
+
if (options.requireInitialSize && offset < stat.size)
|
|
14559
|
+
throw new Error("Incomplete source");
|
|
14560
|
+
text = buffer.subarray(0, offset).toString("utf8");
|
|
14533
14561
|
}
|
|
14534
14562
|
return { status: "ok", text };
|
|
14535
14563
|
} finally {
|
|
@@ -15399,6 +15427,7 @@ async function collectFleetSilent(runs, now = Date.now()) {
|
|
|
15399
15427
|
}
|
|
15400
15428
|
const paths = [...authors, "dispatchd.log", "dispatch-events.log", "metrics/jobs.jsonl"];
|
|
15401
15429
|
const inputs = await Promise.all(paths.map((path) => readFleetJsonl(join18(runs, path), {
|
|
15430
|
+
requireInitialSize: true,
|
|
15402
15431
|
parseLine: parse3,
|
|
15403
15432
|
malformedLines: "flag",
|
|
15404
15433
|
flagRow: wellFormed
|
|
@@ -16074,7 +16103,10 @@ function serveFleet(paths, port) {
|
|
|
16074
16103
|
hostname: "127.0.0.1",
|
|
16075
16104
|
port,
|
|
16076
16105
|
idleTimeout: 0,
|
|
16077
|
-
fetch(request) {
|
|
16106
|
+
fetch(request, server) {
|
|
16107
|
+
const host = request.headers.get("host");
|
|
16108
|
+
if (host !== `127.0.0.1:${server.port}` && host !== `localhost:${server.port}`)
|
|
16109
|
+
return new Response("Forbidden", { status: 403 });
|
|
16078
16110
|
if (new URL(request.url).pathname !== "/events")
|
|
16079
16111
|
return new Response("Not found", { status: 404 });
|
|
16080
16112
|
const abort = new AbortController;
|
|
@@ -18607,6 +18639,11 @@ var init_apply = __esm(() => {
|
|
|
18607
18639
|
type: "boolean",
|
|
18608
18640
|
default: false,
|
|
18609
18641
|
description: "On partial failure, leave successfully-added services in .stack.toml instead of rolling them back."
|
|
18642
|
+
},
|
|
18643
|
+
dryRun: {
|
|
18644
|
+
type: "boolean",
|
|
18645
|
+
default: false,
|
|
18646
|
+
description: "Preview provisioning and wiring without making changes."
|
|
18610
18647
|
}
|
|
18611
18648
|
},
|
|
18612
18649
|
async run({ args }) {
|
|
@@ -18614,6 +18651,23 @@ var init_apply = __esm(() => {
|
|
|
18614
18651
|
const recipe = await pickRecipe(args.recipeId ? String(args.recipeId) : undefined);
|
|
18615
18652
|
if (!recipe)
|
|
18616
18653
|
return;
|
|
18654
|
+
if (args.dryRun) {
|
|
18655
|
+
console.log(` recipe ${recipe.id}`);
|
|
18656
|
+
await provisionProviders(recipe.providers, { rollback: false, dryRun: true });
|
|
18657
|
+
if (!args.noWire) {
|
|
18658
|
+
console.log(" Would check these secrets in Phantom and create applicable webhook stubs:");
|
|
18659
|
+
for (const { name } of recipe.providers) {
|
|
18660
|
+
const ref = findProviderRef(name);
|
|
18661
|
+
if (!ref)
|
|
18662
|
+
console.log(` ${name}: unknown provider`);
|
|
18663
|
+
else
|
|
18664
|
+
for (const secret of ref.secrets)
|
|
18665
|
+
console.log(` ${name}: ${secret}`);
|
|
18666
|
+
}
|
|
18667
|
+
}
|
|
18668
|
+
outro("Dry run complete — no changes made.");
|
|
18669
|
+
return;
|
|
18670
|
+
}
|
|
18617
18671
|
if (!hasConfig()) {
|
|
18618
18672
|
console.log(colors2.dim(" ○ no .stack.toml — auto-running `stack init --noInteractive`"));
|
|
18619
18673
|
try {
|
|
@@ -18639,7 +18693,9 @@ var init_apply = __esm(() => {
|
|
|
18639
18693
|
return;
|
|
18640
18694
|
}
|
|
18641
18695
|
}
|
|
18642
|
-
|
|
18696
|
+
if (recipe.providers.length > 0) {
|
|
18697
|
+
await requirePhantom();
|
|
18698
|
+
}
|
|
18643
18699
|
console.log();
|
|
18644
18700
|
console.log(` ${colors2.bold("recipe")} ${recipe.id}`);
|
|
18645
18701
|
console.log(` ${colors2.dim("query")} ${recipe.query}`);
|
|
@@ -19161,7 +19217,7 @@ var init_completion = __esm(() => {
|
|
|
19161
19217
|
]
|
|
19162
19218
|
},
|
|
19163
19219
|
apply: {
|
|
19164
|
-
flags: [{ name: "noWire" }, { name: "noRollback" }]
|
|
19220
|
+
flags: [{ name: "noWire" }, { name: "noRollback" }, { name: "dryRun" }]
|
|
19165
19221
|
},
|
|
19166
19222
|
swap: {
|
|
19167
19223
|
completesProviders: true,
|
|
@@ -19262,7 +19318,7 @@ var package_default;
|
|
|
19262
19318
|
var init_package = __esm(() => {
|
|
19263
19319
|
package_default = {
|
|
19264
19320
|
name: "@ashlr/stack",
|
|
19265
|
-
version: "0.3.
|
|
19321
|
+
version: "0.3.7",
|
|
19266
19322
|
description: "Ashlr Stack CLI — the control plane for your entire dev stack. One command to provision, wire, and operate every third-party service in your project. 39 providers, MCP-native.",
|
|
19267
19323
|
license: "MIT",
|
|
19268
19324
|
author: {
|
|
@@ -19310,13 +19366,13 @@ var init_package = __esm(() => {
|
|
|
19310
19366
|
node: ">=20"
|
|
19311
19367
|
},
|
|
19312
19368
|
scripts: {
|
|
19313
|
-
build: `bun build src/index.ts --outdir dist --target node --format esm && node -e "const fs=require('fs');const f='dist/index.js';let c=fs.readFileSync(f,'utf8');if(c.startsWith('#!'))c=c.slice(c.indexOf('\\n')+1);fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c);fs.chmodSync(f,0o755)"`,
|
|
19369
|
+
build: `NODE_ENV=production bun build src/index.ts --outdir dist --target node --format esm && node -e "const fs=require('fs');const f='dist/index.js';let c=fs.readFileSync(f,'utf8');if(c.startsWith('#!'))c=c.slice(c.indexOf('\\n')+1);fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c);fs.chmodSync(f,0o755)"`,
|
|
19314
19370
|
prepack: "bun run build",
|
|
19315
19371
|
dev: "bun run src/index.ts",
|
|
19316
19372
|
typecheck: "bunx tsc --noEmit"
|
|
19317
19373
|
},
|
|
19318
19374
|
dependencies: {
|
|
19319
|
-
"@ashlr/stack-core": "^0.3.
|
|
19375
|
+
"@ashlr/stack-core": "^0.3.7",
|
|
19320
19376
|
"@clack/prompts": "^0.8.2",
|
|
19321
19377
|
citty: "^0.1.6",
|
|
19322
19378
|
picocolors: "^1.1.1"
|
|
@@ -19802,7 +19858,7 @@ async function checkForUpdate(currentVersion, _cacheFile) {
|
|
|
19802
19858
|
}
|
|
19803
19859
|
|
|
19804
19860
|
// src/index.ts
|
|
19805
|
-
var VERSION = "0.3.
|
|
19861
|
+
var VERSION = "0.3.7";
|
|
19806
19862
|
var main = defineCommand({
|
|
19807
19863
|
meta: {
|
|
19808
19864
|
name: "stack",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ashlr/stack",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Ashlr Stack CLI — the control plane for your entire dev stack. One command to provision, wire, and operate every third-party service in your project. 39 providers, MCP-native.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
"node": ">=20"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
|
-
"build": "bun build src/index.ts --outdir dist --target node --format esm && node -e \"const fs=require('fs');const f='dist/index.js';let c=fs.readFileSync(f,'utf8');if(c.startsWith('#!'))c=c.slice(c.indexOf('\\n')+1);fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c);fs.chmodSync(f,0o755)\"",
|
|
51
|
+
"build": "NODE_ENV=production bun build src/index.ts --outdir dist --target node --format esm && node -e \"const fs=require('fs');const f='dist/index.js';let c=fs.readFileSync(f,'utf8');if(c.startsWith('#!'))c=c.slice(c.indexOf('\\n')+1);fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c);fs.chmodSync(f,0o755)\"",
|
|
52
52
|
"prepack": "bun run build",
|
|
53
53
|
"dev": "bun run src/index.ts",
|
|
54
54
|
"typecheck": "bunx tsc --noEmit"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@ashlr/stack-core": "^0.3.
|
|
57
|
+
"@ashlr/stack-core": "^0.3.7",
|
|
58
58
|
"@clack/prompts": "^0.8.2",
|
|
59
59
|
"citty": "^0.1.6",
|
|
60
60
|
"picocolors": "^1.1.1"
|