turnzero 0.21.6 → 0.22.0-next.1

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.
@@ -2358,9 +2358,89 @@ var credentialFileName = (name) => {
2358
2358
  var looksLikeCredential = (name, data) => credentialFileName(name) || holdsPrivateKey(data);
2359
2359
  var credentialAdvice = (subject) => `Where ${subject} holds a secret, move it out of the application's folder before the next deploy, and store a secret value the application needs with ${SECRET_ACTION.store}. The ${HASH_SUBCOMMAND} subcommand with ${HASH_OPTION.list} prints every file the zip holds.`;
2360
2360
  var credentialLineOf = (names) => names.length === 0 ? null : names.length === 1 ? `${WARNING_LINE_HEAD}the zip holds a file that looks like a key or a credential, and the upload includes it: ${listedNames(names)}. ${credentialAdvice("it")}` : `${WARNING_LINE_HEAD}the zip holds ${names.length} files that look like keys or credentials, and the upload includes them: ${listedNames(names)}. ${credentialAdvice("one")}`;
2361
+ var LOCAL_WRITE_EXTENSIONS = Object.freeze([".js", ".mjs", ".cjs", ".ts"]);
2362
+ var LOCAL_WRITE_UNREAD_FOLDERS = Object.freeze(["client/", "lib/"]);
2363
+ var LOCAL_WRITE_CALLS = Object.freeze(["writeFile", "writeFileSync", "appendFile", "appendFileSync", "createWriteStream", "mkdir", "mkdirSync"]);
2364
+ var LOCAL_WRITE_BASES = Object.freeze(["__dirname", "import.meta.dirname", "process.cwd()"]);
2365
+ var LOCAL_WRITE_SET_ASIDE = Object.freeze(["tmpdir(", "process.env"]);
2366
+ var LOCAL_WRITE_ARGUMENT_MAX = 400;
2367
+ var readForLocalWrite = (name) => {
2368
+ const last = lastSegmentOf(name);
2369
+ return LOCAL_WRITE_EXTENSIONS.some((extension) => last.endsWith(extension)) && !LOCAL_WRITE_UNREAD_FOLDERS.some((folder) => name.startsWith(folder));
2370
+ };
2371
+ var firstArgumentOf = (text, from) => {
2372
+ const open = [];
2373
+ let quote = null;
2374
+ const end = Math.min(text.length, from + LOCAL_WRITE_ARGUMENT_MAX);
2375
+ for (let at = from; at < end; at += 1) {
2376
+ const character = text[at];
2377
+ if (quote !== null) {
2378
+ if (character === "\\") at += 1;
2379
+ else if (character === quote) quote = null;
2380
+ else if (quote === "`" && character === "$" && text[at + 1] === "{") {
2381
+ open.push("`");
2382
+ quote = null;
2383
+ at += 1;
2384
+ }
2385
+ continue;
2386
+ }
2387
+ if (character === "'" || character === '"' || character === "`") quote = character;
2388
+ else if (character === "(" || character === "[" || character === "{") open.push(character);
2389
+ else if (character === ")" || character === "]" || character === "}") {
2390
+ if (open.length === 0) return character === ")" ? text.slice(from, at) : null;
2391
+ if (open.pop() === "`") quote = "`";
2392
+ } else if (character === "," && open.length === 0) return text.slice(from, at);
2393
+ }
2394
+ return null;
2395
+ };
2396
+ var literalTextOf = (argument) => {
2397
+ const quote = argument[0];
2398
+ if (argument.length < 2 || quote !== "'" && quote !== '"' && quote !== "`" || argument.at(-1) !== quote) return null;
2399
+ const inner = argument.slice(1, -1);
2400
+ if (quote === "`" && inner.includes("${")) return null;
2401
+ for (let at = 0; at < inner.length; at += 1) {
2402
+ if (inner[at] === "\\") at += 1;
2403
+ else if (inner[at] === quote) return null;
2404
+ }
2405
+ return inner;
2406
+ };
2407
+ var relativePathText = (path) => path !== "" && !/^([/\\~]|[A-Za-z][A-Za-z0-9+.-]*:)/.test(path);
2408
+ var holdsBase = (argument, base) => {
2409
+ for (let at = argument.indexOf(base); at >= 0; at = argument.indexOf(base, at + 1)) {
2410
+ const before = argument[at - 1];
2411
+ const after = argument[at + base.length];
2412
+ if ((before === void 0 || !/[\w$.]/.test(before)) && (after === void 0 || !/[\w$]/.test(after))) return true;
2413
+ }
2414
+ return false;
2415
+ };
2416
+ var writesInsideFolder = (argument) => {
2417
+ const trimmed = argument.trim();
2418
+ if (LOCAL_WRITE_SET_ASIDE.some((aside) => trimmed.includes(aside))) return false;
2419
+ const literal = literalTextOf(trimmed);
2420
+ if (literal !== null) return relativePathText(literal);
2421
+ return LOCAL_WRITE_BASES.some((base) => holdsBase(trimmed, base));
2422
+ };
2423
+ var LOCAL_WRITE_CALL = new RegExp(`(?<![\\w$])(${[...LOCAL_WRITE_CALLS].sort((a, b) => b.length - a.length).join("|")})\\s*\\(`, "g");
2424
+ var LOCAL_WRITE_OPENINGS = ["writeFile", "appendFile", "createWriteStream", "mkdir"].map((name) => Buffer.from(name, "ascii"));
2425
+ var localWriteLineIn = (data) => {
2426
+ if (!LOCAL_WRITE_OPENINGS.some((opening) => data.includes(opening))) return null;
2427
+ const text = data.toString("utf8");
2428
+ let line = 1;
2429
+ let counted = 0;
2430
+ for (const match of text.matchAll(LOCAL_WRITE_CALL)) {
2431
+ for (let at = text.indexOf("\n", counted); at >= 0 && at < match.index; at = text.indexOf("\n", at + 1)) line += 1;
2432
+ counted = match.index;
2433
+ const head = text.slice(text.lastIndexOf("\n", match.index - 1) + 1, match.index).trimStart();
2434
+ if (head.startsWith("//") || head.startsWith("/*") || head.startsWith("*")) continue;
2435
+ const argument = firstArgumentOf(text, match.index + match[0].length);
2436
+ if (argument !== null && writesInsideFolder(argument)) return line;
2437
+ }
2438
+ return null;
2439
+ };
2440
+ var localWriteLineOf = (found) => found === null ? null : `${WARNING_LINE_HEAD}${shownNoteName(found.name)}, line ${found.line}, writes to a local file inside the application's folder. A running copy's disk is lost whenever the copy is replaced or stops: keep files in a storage area and records in a database, as read_documentation's pages /cloud/guides/store-files/ and /cloud/guides/add-a-database/ describe.`;
2361
2441
  var LIST_LINE_HEAD = "file: ";
2362
2442
  var listLineOf = (file) => `${LIST_LINE_HEAD}${file.size} ${shownWhole(file.name)}`;
2363
- var NO_NOTES = Object.freeze({ leftOut: Object.freeze([]), rootZips: Object.freeze([]), credentialFiles: Object.freeze([]), unservedHealthPath: null });
2443
+ var NO_NOTES = Object.freeze({ leftOut: Object.freeze([]), rootZips: Object.freeze([]), credentialFiles: Object.freeze([]), localWrite: null, unservedHealthPath: null });
2364
2444
  var noteLinesOf = (notes, health, zipped = null) => {
2365
2445
  const lines = [];
2366
2446
  const files = zipped === null ? null : filesLineOf(zipped.map((file) => file.name));
@@ -2371,6 +2451,8 @@ var noteLinesOf = (notes, health, zipped = null) => {
2371
2451
  if (rootZip !== null) lines.push(rootZip);
2372
2452
  const credential = credentialLineOf(notes.credentialFiles);
2373
2453
  if (credential !== null) lines.push(credential);
2454
+ const localWrite = localWriteLineOf(notes.localWrite);
2455
+ if (localWrite !== null) lines.push(localWrite);
2374
2456
  if (health && notes.unservedHealthPath !== null) lines.push(healthLineOf(notes.unservedHealthPath));
2375
2457
  return lines;
2376
2458
  };
@@ -3376,6 +3458,7 @@ function zipFolder(root, seams = {}) {
3376
3458
  let held = healthPath !== null && segment !== null && files.some((file) => pathCountsForHealth(file.name, healthPath, segment));
3377
3459
  const zipped = [];
3378
3460
  const credentialFiles = [];
3461
+ let localWrite = null;
3379
3462
  const places = [];
3380
3463
  const zip = zipFiles(
3381
3464
  files,
@@ -3383,6 +3466,10 @@ function zipFolder(root, seams = {}) {
3383
3466
  (file, data) => {
3384
3467
  zipped.push({ name: file.name, size: data.length });
3385
3468
  if (looksLikeCredential(file.name, data)) credentialFiles.push(file.name);
3469
+ if (localWrite === null && readForLocalWrite(file.name)) {
3470
+ const line = localWriteLineIn(data);
3471
+ if (line !== null) localWrite = { name: file.name, line };
3472
+ }
3386
3473
  if (segment !== null && !held && readForHealth(file.name) && holdsSegment(data, segment)) held = true;
3387
3474
  },
3388
3475
  (place) => places.push(place)
@@ -3396,6 +3483,7 @@ function zipFolder(root, seams = {}) {
3396
3483
  leftOut,
3397
3484
  rootZips: files.filter((file) => !file.name.includes("/") && zipFileName(file.name)).map((file) => file.name),
3398
3485
  credentialFiles,
3486
+ localWrite,
3399
3487
  unservedHealthPath: segment !== null && !held ? healthPath : null
3400
3488
  }
3401
3489
  };
@@ -9278,7 +9366,7 @@ var SUBCOMMANDS = Object.freeze([
9278
9366
  WHOAMI_ROW
9279
9367
  ]);
9280
9368
  var SERVED = LINE_RUNNER;
9281
- var NPX_FORM_SENTENCE = `Where the command is not installed, install it with ${installLineOf(DEFAULT_COMMAND_ORIGIN)}, or run the same line through npx: write ${commandRunnerOf("latest")} for ${LINE_RUNNER}.`;
9369
+ var NPX_FORM_SENTENCE = `Where the command is not installed, install it with ${installLineOf(DEFAULT_COMMAND_ORIGIN)}. A person or a job may instead run the same line through npx: write ${commandRunnerOf("latest")} for ${LINE_RUNNER}. A tool where the command is not installed uses deploy_files within its caps, or the deploy skill's setup steps, never the npx line.`;
9282
9370
  var namedWithActs = (subcommand) => subcommand.acts ? `${subcommand.name} ${subcommand.acts.join("|")}` : subcommand.name;
9283
9371
  var shown = (option) => option.flag ? option.name : `${option.name} ${option.value}`;
9284
9372
  var listed = (names) => names.length < 3 ? names.join(" and ") : `${names.slice(0, -1).join(", ")}, and ${names[names.length - 1]}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turnzero",
3
- "version": "0.21.6",
3
+ "version": "0.22.0-next.1",
4
4
  "type": "module",
5
5
  "description": "The Turn Zero Cloud command, which an AI coding tool runs on your machine to deploy an application, store a secret, upload a file, download an export, take a library entry, write a local run's settings, start the application locally, and scaffold a new service from a template.",
6
6
  "license": "Apache-2.0",