@anvil-works/anvil-cli 0.8.0-canary.18 → 0.8.0-canary.19

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/cli.js CHANGED
@@ -12904,9 +12904,6 @@ var __webpack_exports__ = {};
12904
12904
  function getGlobalOutputConfig() {
12905
12905
  return globalOutputConfig;
12906
12906
  }
12907
- function canPrompt() {
12908
- return !globalOutputConfig.jsonMode && !!(process.stdin.isTTY && process.stdout.isTTY);
12909
- }
12910
12907
  function assertCanPrompt(action = "This command", explicitAlternative = "Pass explicit flags instead.") {
12911
12908
  if (globalOutputConfig.jsonMode) throw new Error(`${action} requires interactive input, but --json disables prompts. ${explicitAlternative}`);
12912
12909
  if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error(`${action} requires interactive input, but stdin/stdout is not a TTY. ${explicitAlternative}`);
@@ -23676,21 +23673,22 @@ print(json.dumps({"issues": issues}))
23676
23673
  if (!response.ok) throw new Error(formatHttpError("Failed to apply database schema", response.status, await response.text()));
23677
23674
  return await response.json();
23678
23675
  }
23679
- async function confirmSchemaApplication(message) {
23680
- if (!canPrompt()) return true;
23681
- return logger_logger.confirm(message, true);
23676
+ async function confirmSchemaApplication(force = false) {
23677
+ if (force) return true;
23678
+ assertCanPrompt("Applying database schema", "Pass --force to apply without prompting.");
23679
+ return logger_logger.confirm("Apply the app environment's schema to its database? This may delete tables, columns, or data.", true);
23682
23680
  }
23683
23681
  function registerDbCommand(program) {
23684
23682
  if ("1" !== process.env.ANVIL_AGENT_HOST) return;
23685
23683
  const db = program.command("db").description("Manage app databases");
23686
- db.command("apply-schema").description("Apply the app schema to the database for the current environment").action(async ()=>{
23684
+ db.command("apply-schema").description("Apply the app schema to the database for the current environment").option("-f, --force", "Apply the schema without asking for confirmation").action(async (options)=>{
23687
23685
  try {
23688
23686
  const projectRoot = process.cwd();
23689
23687
  auth_setRepoContext(projectRoot);
23690
23688
  const anvilUrl = await resolveAuthAnvilUrl();
23691
23689
  const appId = await resolvePrimaryAppId(projectRoot, anvilUrl);
23692
23690
  if (!appId) throw new Error("No Anvil app found in current directory. Make sure you're in a directory with an Anvil app git remote.");
23693
- if (!await confirmSchemaApplication("Apply the app environment's schema to its database? This may delete tables, columns, or data.")) return void logger_logger.info("Schema application cancelled.");
23691
+ if (!await confirmSchemaApplication(options.force)) return void logger_logger.info("Schema application cancelled.");
23694
23692
  const response = await applyDatabaseSchema(appId, {
23695
23693
  anvilUrl,
23696
23694
  projectRoot
@@ -23805,6 +23803,232 @@ print(json.dumps({"issues": issues}))
23805
23803
  }
23806
23804
  });
23807
23805
  }
23806
+ const external_events_namespaceObject = require("events");
23807
+ function replError(error) {
23808
+ if ("string" == typeof error) return {
23809
+ message: error
23810
+ };
23811
+ if (error && "object" == typeof error) {
23812
+ const value = error;
23813
+ return {
23814
+ message: String(value.message ?? value["anvil/server-error"] ?? JSON.stringify(value)),
23815
+ ..."string" == typeof value.type ? {
23816
+ type: value.type
23817
+ } : {},
23818
+ ...Array.isArray(value.trace) ? {
23819
+ trace: value.trace.filter((frame)=>Array.isArray(frame) && "string" == typeof frame[0] && "number" == typeof frame[1])
23820
+ } : {}
23821
+ };
23822
+ }
23823
+ return {
23824
+ message: String(error)
23825
+ };
23826
+ }
23827
+ class ReplServerError extends Error {
23828
+ detail;
23829
+ constructor(detail){
23830
+ super(detail.message), this.detail = detail;
23831
+ }
23832
+ }
23833
+ async function runRepl(appId, envPid, options) {
23834
+ const interrupted = ()=>new Error("REPL interrupted.");
23835
+ const anvilUrl = options.anvilUrl ?? await resolveAuthAnvilUrl();
23836
+ const token = await auth_getValidAuthToken(anvilUrl);
23837
+ const url = new URL(`${anvilUrl.replace(/\/$/, "")}/ide/api/_/apps/${encodeURIComponent(appId)}/environments/${encodeURIComponent(envPid)}/ws`);
23838
+ url.protocol = "https:" === url.protocol ? "wss:" : "ws:";
23839
+ if (options.signal?.aborted) throw interrupted();
23840
+ const ws = new (external_ws_default())(url, {
23841
+ headers: {
23842
+ Authorization: `Bearer ${token}`
23843
+ },
23844
+ handshakeTimeout: 30000
23845
+ });
23846
+ const controller = new AbortController();
23847
+ let repl;
23848
+ let nextId = 1;
23849
+ let output = "";
23850
+ let keepalive;
23851
+ let pongTimeout;
23852
+ let closeTimeout;
23853
+ const startupTimeout = setTimeout(()=>{
23854
+ controller.abort(new Error("Timed out waiting for the REPL to start."));
23855
+ }, 30000);
23856
+ const onAbort = ()=>controller.abort(interrupted());
23857
+ const markResponsive = ()=>{
23858
+ clearTimeout(pongTimeout);
23859
+ pongTimeout = void 0;
23860
+ };
23861
+ options.signal?.addEventListener("abort", onAbort, {
23862
+ once: true
23863
+ });
23864
+ ws.on("pong", markResponsive);
23865
+ ws.on("unexpected-response", (request, response)=>{
23866
+ response.resume();
23867
+ controller.abort(new Error(`REPL websocket handshake failed (${response.statusCode} ${response.statusMessage}).`));
23868
+ request.destroy();
23869
+ });
23870
+ ws.on("error", (error)=>controller.abort(new Error(`REPL websocket connection failed: ${error.message}`)));
23871
+ ws.on("close", (code, reason)=>{
23872
+ clearTimeout(closeTimeout);
23873
+ controller.abort(new Error(`REPL websocket disconnected unexpectedly (code ${code}${reason.length ? `: ${reason}` : ""}).`));
23874
+ });
23875
+ const messages = (0, external_events_namespaceObject.on)(ws, "message", {
23876
+ signal: controller.signal
23877
+ });
23878
+ function send(message) {
23879
+ const id = nextId++;
23880
+ ws.send(JSON.stringify({
23881
+ ...message,
23882
+ id
23883
+ }), (error)=>{
23884
+ if (error) controller.abort(new Error(`REPL websocket send failed: ${error.message}`));
23885
+ });
23886
+ return id;
23887
+ }
23888
+ async function readUntil(matches) {
23889
+ while(true){
23890
+ const { value, done } = await messages.next();
23891
+ options.signal?.throwIfAborted();
23892
+ if (done) throw new Error("REPL websocket message stream ended unexpectedly.");
23893
+ markResponsive();
23894
+ let message;
23895
+ try {
23896
+ message = JSON.parse(value[0].toString());
23897
+ if (!message || "object" != typeof message || Array.isArray(message)) throw new Error("Expected an object");
23898
+ } catch {
23899
+ throw new Error("Invalid REPL websocket message.");
23900
+ }
23901
+ if ("REPL_UPDATE" === message.event) {
23902
+ if (!repl || message.repl !== repl) continue;
23903
+ if ("string" == typeof message.output) {
23904
+ output += message.output;
23905
+ options.onOutput?.(message.output);
23906
+ options.signal?.throwIfAborted();
23907
+ }
23908
+ }
23909
+ if (message.error) throw new ReplServerError(replError(message.error));
23910
+ if ("REPL_UPDATE" === message.event && message.terminated) throw new Error("REPL terminated unexpectedly.");
23911
+ if (matches(message)) return message;
23912
+ }
23913
+ }
23914
+ try {
23915
+ await (0, external_events_namespaceObject.once)(ws, "open", {
23916
+ signal: controller.signal
23917
+ });
23918
+ const launchId = send({
23919
+ cmd: "LAUNCH_REPL"
23920
+ });
23921
+ const launched = await readUntil((message)=>message.id === launchId);
23922
+ if ("string" != typeof launched.repl || !launched.repl) throw new Error("Invalid REPL launch response: missing REPL ID.");
23923
+ repl = launched.repl;
23924
+ keepalive = setInterval(()=>{
23925
+ try {
23926
+ send({
23927
+ cmd: "REPL_KEEPALIVE",
23928
+ repl
23929
+ });
23930
+ pongTimeout = setTimeout(()=>controller.abort(new Error("REPL websocket heartbeat timed out.")), 10000);
23931
+ ws.ping();
23932
+ } catch (error) {
23933
+ controller.abort(error);
23934
+ }
23935
+ }, 20000);
23936
+ const isReady = (message)=>"REPL_UPDATE" === message.event && true === message.ready;
23937
+ await readUntil(isReady);
23938
+ clearTimeout(startupTimeout);
23939
+ send({
23940
+ cmd: "REPL_COMMAND",
23941
+ repl,
23942
+ command: options.code
23943
+ });
23944
+ await readUntil(isReady);
23945
+ return {
23946
+ output
23947
+ };
23948
+ } catch (error) {
23949
+ if (error instanceof ReplServerError) return {
23950
+ output,
23951
+ error: error.detail
23952
+ };
23953
+ const failure = controller.signal.aborted ? controller.signal.reason : error;
23954
+ throw failure instanceof Error ? failure : new Error(String(failure));
23955
+ } finally{
23956
+ clearTimeout(startupTimeout);
23957
+ clearInterval(keepalive);
23958
+ clearTimeout(pongTimeout);
23959
+ options.signal?.removeEventListener("abort", onAbort);
23960
+ controller.abort();
23961
+ await messages.return?.();
23962
+ if (ws.readyState === external_ws_default().OPEN) {
23963
+ if (repl) ws.send(JSON.stringify({
23964
+ id: nextId++,
23965
+ cmd: "TERMINATE_REPL",
23966
+ repl
23967
+ }), ()=>{});
23968
+ ws.close();
23969
+ } else if (ws.readyState === external_ws_default().CONNECTING) ws.terminate();
23970
+ if (ws.readyState !== external_ws_default().CLOSED) {
23971
+ closeTimeout = setTimeout(()=>ws.terminate(), 1000);
23972
+ closeTimeout.unref();
23973
+ }
23974
+ }
23975
+ }
23976
+ function writeJsonReplOutput(output) {
23977
+ process.stdout.write(JSON.stringify({
23978
+ type: "repl_output",
23979
+ output,
23980
+ timestamp: new Date().toISOString()
23981
+ }) + "\n");
23982
+ }
23983
+ function registerReplCommand(program) {
23984
+ if ("1" !== process.env.ANVIL_AGENT_HOST) return;
23985
+ program.command("repl <code>").description("Run Python in a fresh server REPL for the current environment; use - to read stdin").addHelpText("after", `
23986
+ Examples:
23987
+ anvil repl '1 + 2'
23988
+ anvil --json repl '1 + 2'
23989
+ anvil repl - < script.py
23990
+ `).action(async (code)=>{
23991
+ const controller = new AbortController();
23992
+ const onInterrupt = ()=>controller.abort();
23993
+ try {
23994
+ const { appId, envPid, anvilUrl } = await resolveEnvironmentContext();
23995
+ if ("-" === code) {
23996
+ const chunks = [];
23997
+ for await (const chunk of process.stdin)chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
23998
+ code = Buffer.concat(chunks).toString("utf8");
23999
+ }
24000
+ process.on("SIGINT", onInterrupt);
24001
+ const response = await runRepl(appId, envPid, {
24002
+ code,
24003
+ anvilUrl,
24004
+ signal: controller.signal,
24005
+ onOutput: getGlobalOutputConfig().jsonMode ? writeJsonReplOutput : (output)=>{
24006
+ process.stdout.write(output);
24007
+ }
24008
+ });
24009
+ const error = response.error;
24010
+ const message = error ? `${error.type ? `${error.type}: ` : ""}${error.message}` : void 0;
24011
+ if (getGlobalOutputConfig().jsonMode) logJsonResult(!error, {
24012
+ data: response,
24013
+ error: message
24014
+ });
24015
+ else if (error) {
24016
+ process.stderr.write(`${message}\n`);
24017
+ for (const [file, line] of error.trace ?? [])process.stderr.write(` at ${file}:${line}\n`);
24018
+ }
24019
+ if (error) process.exitCode = 1;
24020
+ } catch (error) {
24021
+ const message = errors_getErrorMessage(error);
24022
+ if (getGlobalOutputConfig().jsonMode) logJsonResult(false, {
24023
+ error: message
24024
+ });
24025
+ else logger_logger.error(message);
24026
+ process.exitCode = controller.signal.aborted ? 130 : 1;
24027
+ } finally{
24028
+ process.removeListener("SIGINT", onInterrupt);
24029
+ }
24030
+ });
24031
+ }
23808
24032
  const program_packageJson = JSON.parse((0, external_fs_.readFileSync)((0, external_path_namespaceObject.join)(__dirname, "../package.json"), "utf-8"));
23809
24033
  const VERSION = program_packageJson.version;
23810
24034
  setLogger(new CLILogger({
@@ -24227,6 +24451,7 @@ print(json.dumps({"issues": issues}))
24227
24451
  registerDepsCommand(program);
24228
24452
  registerDbCommand(program);
24229
24453
  registerEnvCommand(program);
24454
+ registerReplCommand(program);
24230
24455
  program.command("update").description("Update anvil to the latest version").alias("u").action(async ()=>{
24231
24456
  await handleUpdateCommand();
24232
24457
  });
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/commands/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2CxD"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/commands/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2CxD"}
@@ -1,3 +1,8 @@
1
1
  import { Command } from "commander";
2
+ export declare function resolveEnvironmentContext(): Promise<{
3
+ envPid: string;
4
+ anvilUrl: string;
5
+ appId: string;
6
+ }>;
2
7
  export declare function registerEnvCommand(program: Command): void;
3
8
  //# sourceMappingURL=env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0BpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoDzD"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAsB,yBAAyB;;;;GAe9C;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoDzD"}
@@ -15,4 +15,5 @@ export { registerConfigureCommand } from "./configure";
15
15
  export { registerDepsCommand } from "./deps";
16
16
  export { registerDbCommand } from "./db";
17
17
  export { registerEnvCommand } from "./env";
18
+ export { registerReplCommand } from "./repl";
18
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerReplCommand(program: Command): void;
3
+ //# sourceMappingURL=repl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../src/commands/repl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+D1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC,OAAO,EAAyD,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAiC3G,KAAK,sBAAsB,GAAG,eAAe,GAAG;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAoKF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAO7F;AAmLD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CAezE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwFzD;AAiBD,wBAAgB,YAAY,IAAI,OAAO,CAmGtC"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgCpC,OAAO,EAAyD,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAiC3G,KAAK,sBAAsB,GAAG,eAAe,GAAG;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAoKF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAO7F;AAmLD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CAezE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwFzD;AAiBD,wBAAgB,YAAY,IAAI,OAAO,CAoGtC"}
@@ -0,0 +1,18 @@
1
+ export interface RunReplOptions {
2
+ code: string;
3
+ anvilUrl?: string;
4
+ /** Receives each output chunk immediately; the result also contains the full transcript. */
5
+ onOutput?: (output: string) => void;
6
+ signal?: AbortSignal;
7
+ }
8
+ export interface ReplResult {
9
+ output: string;
10
+ error?: {
11
+ type?: string;
12
+ message: string;
13
+ trace?: Array<[string, number]>;
14
+ };
15
+ }
16
+ /** Run one command in a fresh environment scope, then terminate it. */
17
+ export declare function runRepl(appId: string, envPid: string, options: RunReplOptions): Promise<ReplResult>;
18
+ //# sourceMappingURL=repl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../src/services/repl.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KACnC,CAAC;CACL;AAwBD,uEAAuE;AACvE,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA2IzG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anvil-works/anvil-cli",
3
- "version": "0.8.0-canary.18",
3
+ "version": "0.8.0-canary.19",
4
4
  "description": "CLI tool for developing Anvil apps locally",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/api.d.ts",