turnzero 0.18.1-next.1 → 0.18.2-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.
@@ -895,7 +895,7 @@ var variableReadSentence = (origin, standing) => {
895
895
  };
896
896
  var fileReadSentence = (origin) => `The credential this run read was this computer's token for ${origin}, from its credential file: where the platform no longer accepts it, run ${LOGIN_SUBCOMMAND}${originWordsOf(origin)} to authorize this computer again.`;
897
897
  var noTokenSentence = (origin, expiredAt) => expiredAt === null ? `No credential was read, so nothing was sent: ${MINTED_TOKEN_VARIABLE} is not set, and this computer's credential file holds no token for ${origin}.` : `No credential was read, so nothing was sent: ${MINTED_TOKEN_VARIABLE} is not set, and this computer's token for ${origin} in its credential file expired at ${expiredAt}.`;
898
- var VARIABLE_ROUTE_SENTENCES = `A tool connected by a minted token, or a job, cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone. It sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a line, and ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the line again. A tool sets ${MINTED_TOKEN_VARIABLE} for the deploy or check line alone and unsets it once that line ends.`;
898
+ var VARIABLE_ROUTE_SENTENCES = `A tool connected by a minted token, or a job, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a line, and ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the line again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone. A tool sets ${MINTED_TOKEN_VARIABLE} for the deploy or check line alone and unsets it once that line ends.`;
899
899
  var LOGIN_ROUTE_OPENER = "A person logs this computer in once, in a terminal of their own, and its token then stays on this computer for 30 days:";
900
900
  var DEPLOY_FILES_ROUTE_SENTENCE = "A folder within the caps of your tool's deploy_files call deploys now through deploy_files, with no login.";
901
901
  var loginRouteLines = (io2, origin) => [LOGIN_ROUTE_OPENER, ...loginLinesFor(io2, origin), DEPLOY_FILES_ROUTE_SENTENCE];
@@ -3584,9 +3584,9 @@ var DEPLOY_ROW = Object.freeze({
3584
3584
  variables: [[DEPLOY_NO_WAIT_VARIABLE, "any value returns the command once the deploy has started, without waiting for it."]],
3585
3585
  note: [
3586
3586
  `A deploy is one line, which carries no credential: run the line your tool's deploy call answers, or ${DEPLOY_SUBCOMMAND} ${DEPLOY_OPTION.application} <application id>, from the application's folder. It reads no standard input. On an authorized computer it runs under this computer's token, which ${LOGIN_SUBCOMMAND} or ${AUTHORIZE_SUBCOMMAND} keeps in the credential file for each platform address, and sends it only to the address it is kept under: ${DEPLOY_OPTION.origin} where the line names one, else the address ${ORIGIN_VARIABLE} holds, else ${DEFAULT_COMMAND_ORIGIN}.`,
3587
- `On a computer with no token for that address, or one that has expired, it sends nothing, ends 3, and prints two routes, in this order. A tool connected by a minted token, or a job with no tool, such as a CI job's, cannot use ${MINT_TOKEN_ACTION}: it sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, such as the job's secret store, never by writing the value in a line, and ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the deploy line again.`,
3587
+ `On a computer with no token for that address, or one that has expired, it sends nothing, ends 3, and prints two routes, in this order. A tool connected by a minted token, or a job with no tool, such as a CI job's, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, such as the job's secret store, never by writing the value in a line. It sets ${ORIGIN_VARIABLE} to the address that minted the token where that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the deploy line again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which takes a sign-in alone.`,
3588
3588
  `Otherwise a person logs this computer in once with ${LOGIN_SUBCOMMAND}, in a terminal of their own, then runs the deploy line again; a folder within the caps of the tool's deploy_files call deploys now through deploy_files, with no login. The credential file is ${CREDENTIAL_FILE_WORDS}.`,
3589
- `A tool sets ${MINTED_TOKEN_VARIABLE} for the deploy or check line alone and unsets it once that line ends, since the command cannot unset a variable of the shell that started it. A job's token is minted for the application, with an expiry. The variable's token wins over the credential file: the command makes the preparing call under that token, and sends the token in no other request.`,
3589
+ `A tool sets ${MINTED_TOKEN_VARIABLE} for the deploy or check line alone and unsets it once that line ends, since the command cannot unset a variable of the shell that started it. A value a job's environment already supplies stays as it stands. A job's token is minted for the application, with an expiry. The variable's token wins over the credential file: the command makes the preparing call under that token, and sends the token in no other request.`,
3590
3590
  `Under the variable, the command sends its token only to the address ${ORIGIN_VARIABLE} holds, or to ${DEFAULT_COMMAND_ORIGIN} where that variable is unset: under the token, ${DEPLOY_OPTION.origin} may name that address alone, and where the line names none the command addresses it. ${DEPLOY_OPTION.env} names the environment where a line names one, ${COMMAND_ENVIRONMENTS.join(" or ")}; where none is named, the platform chooses, and the command deploys to the environment the platform answers.`,
3591
3591
  `A progress read answered 502, 503, or 504, which is often temporary, is made again, at most three more times, and an upload answered 503 credential_lookup_busy, which wrote nothing, is made again after the wait it names, at most twice.`,
3592
3592
  `After its zip line, ${DEPLOY_SUBCOMMAND} prints the folder's top-level entries the zip holds on one line, at most ten and then the count of the rest, and ${HASH_SUBCOMMAND} ${HASH_OPTION.list} names every file; no such line prints for a .zip file.`,
@@ -4511,7 +4511,8 @@ var npmEntryOf = (io2, nodePath) => npmEntryCandidatesOf(io2.env, nodePath).find
4511
4511
  return false;
4512
4512
  }
4513
4513
  }) ?? null;
4514
- var npmStartOf = (viaShell = NPM_NEEDS_SHELL, entry = null, nodePath = process.execPath) => entry !== null ? { command: nodePath, args: [entry, "start"] } : viaShell ? { command: "npm start", args: [], shell: true } : { command: "npm", args: ["start"] };
4514
+ var npmStartOf = (viaShell = NPM_NEEDS_SHELL, entry = null, nodePath = process.execPath) => entry !== null ? { command: nodePath, args: [entry, ...START_ARGS] } : viaShell ? { command: ["npm", ...START_ARGS].join(" "), args: [], shell: true } : { command: "npm", args: START_ARGS };
4515
+ var START_ARGS = Object.freeze(["start", "--no-update-notifier"]);
4515
4516
  var npmRunOf = (words, viaShell = NPM_NEEDS_SHELL, entry = null, nodePath = process.execPath) => entry !== null ? { command: nodePath, args: [entry, ...words] } : viaShell ? { command: ["npm", ...words].join(" "), args: [], shell: true } : { command: "npm", args: words };
4516
4517
  var INTERRUPTED_ON_WINDOWS = 'The application has ended. cmd may ask "Terminate batch job (Y/N)?" next: either answer returns the prompt.';
4517
4518
  var afterInterruptLineOf = (ended, onWindows2 = NPM_NEEDS_SHELL) => onWindows2 && ended.interrupted === true ? INTERRUPTED_ON_WINDOWS : null;
@@ -5050,6 +5051,7 @@ var committedFilesOf = (copied, written) => {
5050
5051
  return `${files.slice(0, -1).join(", ")}${files.length > 2 ? "," : ""} and ${files[files.length - 1]}`;
5051
5052
  };
5052
5053
  var COPY_PACKAGES_CLAUSE = "copy the packages line into the application manifest's packages member at each submission; ";
5054
+ var KEEP_PACKAGES_CLAUSE = "the application manifest was written whole, so read it again before patching it, and carry its packages member over in any later rewrite; ";
5053
5055
  var installFailedSentence = (folder) => `npm install in ${folder} did not finish: the entry, its row, and the copy are written. Run npm install there again; running this line again takes the entry again whole.`;
5054
5056
  var LIBRARY_AFTER_OWN_ERROR = "the entry's folder, its manifest row, or the application's copy may stand in part, and running the line again replaces each whole";
5055
5057
  async function readTake(io2, options, userAgent, planOf, planeChecked = false) {
@@ -5183,7 +5185,7 @@ async function installTake(io2, root, plan, manifestText, application) {
5183
5185
  io2.print(`${packagesLineOf(packagesOf(manifestText))} ${packagesWhereOf(root, application)}`);
5184
5186
  if (!("written" in application) && application.unwritten === "write_failed") status = COMMAND_STATUS.failed;
5185
5187
  io2.print(
5186
- `next: commit ${committedFilesOf(plan !== null, "written" in application)}; ${"written" in application ? "" : COPY_PACKAGES_CLAUSE}and, where the project holds the registrar, pin the version in its instance file and run validate with kind library.`
5188
+ `next: commit ${committedFilesOf(plan !== null, "written" in application)}; ${"written" in application ? KEEP_PACKAGES_CLAUSE : COPY_PACKAGES_CLAUSE}and, where the project holds the registrar, pin the version in its instance file and run validate with kind library.`
5187
5189
  );
5188
5190
  printAfterInterrupt(io2, afterInterrupt);
5189
5191
  return status;
@@ -5772,7 +5774,7 @@ var startUpgradeCheck = (io2, subcommand, named, running) => {
5772
5774
  };
5773
5775
 
5774
5776
  // src/turnzero_cloud_command/provision.ts
5775
- import { basename as basename3 } from "node:path";
5777
+ import { basename as basename3, dirname as dirname5, join as join8 } from "node:path";
5776
5778
  var PROVISION_OPTIONS = Object.freeze([
5777
5779
  {
5778
5780
  name: PROVISION_OPTION.application,
@@ -5824,6 +5826,15 @@ var provisionOptionsOf = (call, cwd, stands = () => false) => {
5824
5826
  if (!environmentFileName(basename3(envFile))) return { refusal: envFileNameRefusalOf(stands(envFile)) };
5825
5827
  return { application, envFile, origin: origin.origin };
5826
5828
  };
5829
+ var APPLICATION_FOLDER_MARKS = Object.freeze(["package.json", "manifest.json"]);
5830
+ var outsideApplicationWarningOf = (folder) => `warning: ${folder} holds neither ${APPLICATION_FOLDER_MARKS[0]} nor ${APPLICATION_FOLDER_MARKS[1]}, so it may not be the application's folder, and the environment file was written there all the same. Where the application stands in another folder, move the file into that folder: a local run reads the environment file from the folder it runs in.`;
5831
+ var outsideApplicationFolder = (io2, envFile) => APPLICATION_FOLDER_MARKS.every((mark) => {
5832
+ try {
5833
+ return io2.stat(join8(dirname5(envFile), mark))?.folder !== false;
5834
+ } catch {
5835
+ return false;
5836
+ }
5837
+ });
5827
5838
  var charactersOf = (value) => `<${value.length} characters>`;
5828
5839
  var transportText = (error) => {
5829
5840
  const oneLine2 = (text) => text.replace(/\s+/g, " ").trim();
@@ -6110,6 +6121,7 @@ async function remintAndWrite(io2, { application, envFile, origin }, userAgent,
6110
6121
  );
6111
6122
  }
6112
6123
  if (typeof platform.answer.detail === "string") io2.print(oneLine(platform.answer.detail));
6124
+ if (outsideApplicationFolder(io2, envFile)) io2.print(outsideApplicationWarningOf(dirname5(envFile)));
6113
6125
  if (facts !== null && limitCarried !== null) {
6114
6126
  const cause = limitMember ? "the plan's database-connection-limit holds no usable quantity, which platform staff set with set_plan_quota" : "the platform that answered serves no such member yet";
6115
6127
  io2.print(
@@ -6146,7 +6158,7 @@ var PROVISION_ROW = Object.freeze({
6146
6158
  });
6147
6159
 
6148
6160
  // src/turnzero_cloud_command/scaffold.ts
6149
- import { basename as basename4, dirname as dirname5, isAbsolute as isAbsolute5, join as join8, relative as relative5, resolve as resolve11 } from "node:path";
6161
+ import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute5, join as join9, relative as relative5, resolve as resolve11 } from "node:path";
6150
6162
 
6151
6163
  // src/turnzero_cloud_command/scaffold_template.ts
6152
6164
  var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
@@ -7540,6 +7552,7 @@ var templatesDescribed = () => [
7540
7552
  `The template to write, one of ${andListed(SCAFFOLD_TEMPLATES)}, ${SCAFFOLD_DEFAULT_TEMPLATE} where absent.`,
7541
7553
  ...SCAFFOLD_TEMPLATES.map((template) => `The ${template} template is ${TEMPLATE_FACTS[template].is}.`)
7542
7554
  ].join(" ");
7555
+ var OTHER_TYPE_WAY_ON = "For a type outside these, name the nearest kind, then change the written migration and routes: the files are your service's own.";
7543
7556
  var SCAFFOLD_OPTIONS = Object.freeze([
7544
7557
  {
7545
7558
  name: SCAFFOLD_OPTION.template,
@@ -7563,7 +7576,7 @@ var SCAFFOLD_OPTIONS = Object.freeze([
7563
7576
  name: SCAFFOLD_OPTION.fields,
7564
7577
  value: "<list>",
7565
7578
  required: false,
7566
- description: `Under ${RESOURCE_TEMPLATES_NAMED}, the resource's columns: fields separated by commas, each a name, a colon, and a kind, such as "name:text,message:text", written between double quotes. A name is an ASCII lower-case letter, then ASCII lower-case letters, digits, and underscores, at most 30 characters. It is never a column the migration writes itself: ${perResourceTemplate((kept2) => kept2.columns)}. A kind is ${orListed(SCAFFOLD_FIELD_KINDS)}. Every column is required, and a list holds one to ${SCAFFOLD_FIELDS_MAX} fields. Where absent, the service keeps one text column, title. A template that keeps no resource refuses it.`
7579
+ description: `Under ${RESOURCE_TEMPLATES_NAMED}, the resource's columns: fields separated by commas, each a name, a colon, and a kind, such as "name:text,message:text", written between double quotes. A name is an ASCII lower-case letter, then ASCII lower-case letters, digits, and underscores, at most 30 characters. It is never a column the migration writes itself: ${perResourceTemplate((kept2) => kept2.columns)}. A kind is ${orListed(SCAFFOLD_FIELD_KINDS)}. ${OTHER_TYPE_WAY_ON} Every column is required, and a list holds one to ${SCAFFOLD_FIELDS_MAX} fields. Where absent, the service keeps one text column, title. A template that keeps no resource refuses it.`
7567
7580
  },
7568
7581
  {
7569
7582
  name: SCAFFOLD_OPTION.path,
@@ -7645,8 +7658,9 @@ var FIELD_REFUSAL = Object.freeze({
7645
7658
  nameForm: `${SCAFFOLD_OPTION.fields} takes each field's name as an ASCII lower-case letter, then ASCII lower-case letters, digits, and underscores, at most 30 characters, such as due_date, and ${FIELD_KINDS_CLAUSE}. ${NOTHING_WRITTEN2}`,
7646
7659
  /** A name of SCAFFOLD_FIELD_RESERVED. */
7647
7660
  reservedName: reservedFieldRefusal(SCAFFOLD_FIELD_RESERVED),
7648
- /** A kind outside SCAFFOLD_FIELD_KINDS. */
7649
- kindUnknown: `${SCAFFOLD_OPTION.fields} takes each field's kind after its name and a colon, ${FIELD_KINDS_CLAUSE}, such as count:integer. ${NOTHING_WRITTEN2}`,
7661
+ /** A kind outside SCAFFOLD_FIELD_KINDS, with the way on for another type
7662
+ * (#4572). */
7663
+ kindUnknown: `${SCAFFOLD_OPTION.fields} takes each field's kind after its name and a colon, ${FIELD_KINDS_CLAUSE}, such as count:integer. ${OTHER_TYPE_WAY_ON} ${NOTHING_WRITTEN2}`,
7650
7664
  /** Two fields under one name. */
7651
7665
  duplicate: `${SCAFFOLD_OPTION.fields} takes each field's name once, and two fields of the list share a name, ${FIELD_KINDS_CLAUSE} after each: name each field once. ${NOTHING_WRITTEN2}`
7652
7666
  });
@@ -8047,18 +8061,18 @@ var ownStage = (io2, stage, files) => {
8047
8061
  const folders = new Set([...texts.keys()].flatMap((path) => path.split("/").slice(0, -1).map((_, index, segments) => segments.slice(0, index + 1).join("/"))));
8048
8062
  const own = (at, prefix) => (io2.listFolder(at) ?? []).every((name) => {
8049
8063
  const path = prefix === "" ? name : `${prefix}/${name}`;
8050
- const standing = io2.stat(join8(at, name));
8064
+ const standing = io2.stat(join9(at, name));
8051
8065
  if (standing === null) return false;
8052
- if (standing.folder) return folders.has(path) && own(join8(at, name), path);
8066
+ if (standing.folder) return folders.has(path) && own(join9(at, name), path);
8053
8067
  const text = texts.get(path);
8054
- return text !== void 0 && ownFile(io2, join8(at, name), standing.size, path, text);
8068
+ return text !== void 0 && ownFile(io2, join9(at, name), standing.size, path, text);
8055
8069
  });
8056
8070
  return own(stage, "");
8057
8071
  };
8058
- var danglingAt = (io2, folder, name) => io2.stat(join8(folder, name)) === null && (io2.listFolder(folder) ?? []).some((held) => held.toLowerCase() === name.toLowerCase() && io2.stat(join8(folder, held)) === null);
8072
+ var danglingAt = (io2, folder, name) => io2.stat(join9(folder, name)) === null && (io2.listFolder(folder) ?? []).some((held) => held.toLowerCase() === name.toLowerCase() && io2.stat(join9(folder, held)) === null);
8059
8073
  var standsAt = (io2, folder, name) => {
8060
8074
  try {
8061
- return io2.stat(join8(folder, name)) !== null || danglingAt(io2, folder, name);
8075
+ return io2.stat(join9(folder, name)) !== null || danglingAt(io2, folder, name);
8062
8076
  } catch {
8063
8077
  return true;
8064
8078
  }
@@ -8081,16 +8095,16 @@ var applicationStandsLines = (template, takeLines) => {
8081
8095
  var STAGE_NOT_OWN = `Something that is not this run's own stands at ${STAGE_FOLDER} in the project's root, the name the scaffold writes under, an earlier run's files under another template or another resource name among it: move or remove ${STAGE_FOLDER}, then run the line again. ${NOTHING_WRITTEN2}`;
8082
8096
  var folderRefusalOf = (io2, options, files, takeLines) => {
8083
8097
  const { root } = options;
8084
- for (let at = root; ; at = dirname5(at)) {
8098
+ for (let at = root; ; at = dirname6(at)) {
8085
8099
  const standing2 = io2.stat(at);
8086
- const what = standing2 !== null ? standing2.folder ? null : "a file" : danglingAt(io2, dirname5(at), basename4(at)) ? "a link whose target does not stand" : null;
8100
+ const what = standing2 !== null ? standing2.folder ? null : "a file" : danglingAt(io2, dirname6(at), basename4(at)) ? "a link whose target does not stand" : null;
8087
8101
  if (what !== null) {
8088
8102
  return [`${options.named ? `${SCAFFOLD_OPTION.path} names ${what}, or a place under one` : `The folder the line runs in is ${what}, or stands under one`}, where the project's root stands or is made. ${NOTHING_WRITTEN2}`];
8089
8103
  }
8090
- if (standing2 !== null || dirname5(at) === at) break;
8104
+ if (standing2 !== null || dirname6(at) === at) break;
8091
8105
  }
8092
- const app = join8(root, APPLICATION_FOLDER);
8093
- const stage = join8(root, STAGE_FOLDER);
8106
+ const app = join9(root, APPLICATION_FOLDER);
8107
+ const stage = join9(root, STAGE_FOLDER);
8094
8108
  const notOwn = STAGE_NOT_OWN;
8095
8109
  const standing = io2.stat(app);
8096
8110
  if (standing === null ? danglingAt(io2, root, APPLICATION_FOLDER) : !standing.folder) return [noFolderSentence(APPLICATION_FOLDER, "the scaffold writes the application")];
@@ -8198,8 +8212,8 @@ var nextStepLines = (origin, windows = LINES_IN_WINDOWS_FORM, left = NEITHER_LEF
8198
8212
  var writeTemplate = (io2, stage, app, files) => {
8199
8213
  io2.remove(stage);
8200
8214
  for (const [path, text] of files) {
8201
- const at = join8(stage, ...path.split("/"));
8202
- io2.makeFolder(dirname5(at));
8215
+ const at = join9(stage, ...path.split("/"));
8216
+ io2.makeFolder(dirname6(at));
8203
8217
  io2.writeFile(at, text);
8204
8218
  }
8205
8219
  const standing = io2.stat(app);
@@ -8211,7 +8225,7 @@ var writeTemplate = (io2, stage, app, files) => {
8211
8225
  };
8212
8226
  var writeRootSentence = (io2, root) => {
8213
8227
  try {
8214
- io2.writeNewFile(join8(root, TOOLS_FILE), `${ROOT_SENTENCE}
8228
+ io2.writeNewFile(join9(root, TOOLS_FILE), `${ROOT_SENTENCE}
8215
8229
  `);
8216
8230
  return "written";
8217
8231
  } catch (error) {
@@ -8268,8 +8282,8 @@ async function scaffold(call, io2) {
8268
8282
  const { takes } = TEMPLATE_FACTS[template];
8269
8283
  const defaulted = call.named[SCAFFOLD_OPTION.template] === void 0;
8270
8284
  const files = writtenFilesOf(template, options.names, options.fields);
8271
- const app = join8(root, APPLICATION_FOLDER);
8272
- const stage = join8(root, STAGE_FOLDER);
8285
+ const app = join9(root, APPLICATION_FOLDER);
8286
+ const stage = join9(root, STAGE_FOLDER);
8273
8287
  const takeLines = takes.map((take) => machineLineOf(libraryTakeLineOf({ origin, entry: take.entry }), { windows: io2.windows ?? LINES_IN_WINDOWS_FORM, npx: ranThroughNpx(io2) }, origin));
8274
8288
  let reached = "checks";
8275
8289
  const stateNow = () => {
@@ -8298,7 +8312,7 @@ async function scaffold(call, io2) {
8298
8312
  held = found;
8299
8313
  } else {
8300
8314
  for (const take of takes) {
8301
- const copy = join8(app, "lib", take.entry);
8315
+ const copy = join9(app, "lib", take.entry);
8302
8316
  const planOf = (library) => writesOver(library, copy) ? { refusal: LIBRARY_OVER_APPLICATION } : { application: app, copy, declared: null, declaredAt: null };
8303
8317
  const read2 = await readTake(io2, { entry: take.entry, root, named: options.named, origin }, agent.userAgent, planOf, checks.length > 0);
8304
8318
  if ("lines" in read2) return refuse(...read2.lines);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turnzero",
3
- "version": "0.18.1-next.1",
3
+ "version": "0.18.2-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",