@gadgetinc/ggt 0.2.2 → 0.2.3

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 CHANGED
@@ -129,7 +129,7 @@ EXAMPLES
129
129
  Goodbye!
130
130
  ```
131
131
 
132
- _See code: [src/commands/sync.ts](https://github.com/gadget-inc/ggt/blob/v0.2.2/src/commands/sync.ts)_
132
+ _See code: [src/commands/sync.ts](https://github.com/gadget-inc/ggt/blob/v0.2.3/src/commands/sync.ts)_
133
133
 
134
134
  ### `ggt help [COMMAND]`
135
135
 
@@ -143,7 +143,7 @@ ARGUMENTS
143
143
  COMMAND The command to show help for.
144
144
  ```
145
145
 
146
- _See code: [src/commands/help.ts](https://github.com/gadget-inc/ggt/blob/v0.2.2/src/commands/help.ts)_
146
+ _See code: [src/commands/help.ts](https://github.com/gadget-inc/ggt/blob/v0.2.3/src/commands/help.ts)_
147
147
 
148
148
  ### `ggt list`
149
149
 
@@ -170,7 +170,7 @@ EXAMPLES
170
170
  $ ggt list --sort=slug
171
171
  ```
172
172
 
173
- _See code: [src/commands/list.ts](https://github.com/gadget-inc/ggt/blob/v0.2.2/src/commands/list.ts)_
173
+ _See code: [src/commands/list.ts](https://github.com/gadget-inc/ggt/blob/v0.2.3/src/commands/list.ts)_
174
174
 
175
175
  ### `ggt login`
176
176
 
@@ -189,7 +189,7 @@ EXAMPLES
189
189
  Hello, Jane Doe (jane@example.com)
190
190
  ```
191
191
 
192
- _See code: [src/commands/login.ts](https://github.com/gadget-inc/ggt/blob/v0.2.2/src/commands/login.ts)_
192
+ _See code: [src/commands/login.ts](https://github.com/gadget-inc/ggt/blob/v0.2.3/src/commands/login.ts)_
193
193
 
194
194
  ### `ggt logout`
195
195
 
@@ -204,7 +204,7 @@ EXAMPLES
204
204
  Goodbye
205
205
  ```
206
206
 
207
- _See code: [src/commands/logout.ts](https://github.com/gadget-inc/ggt/blob/v0.2.2/src/commands/logout.ts)_
207
+ _See code: [src/commands/logout.ts](https://github.com/gadget-inc/ggt/blob/v0.2.3/src/commands/logout.ts)_
208
208
 
209
209
  ### `ggt whoami`
210
210
 
@@ -219,7 +219,7 @@ EXAMPLES
219
219
  You are logged in as Jane Doe (jane@example.com)
220
220
  ```
221
221
 
222
- _See code: [src/commands/whoami.ts](https://github.com/gadget-inc/ggt/blob/v0.2.2/src/commands/whoami.ts)_
222
+ _See code: [src/commands/whoami.ts](https://github.com/gadget-inc/ggt/blob/v0.2.3/src/commands/whoami.ts)_
223
223
 
224
224
  <!-- commandsstop -->
225
225
 
@@ -492,6 +492,9 @@ class Sync extends BaseCommand {
492
492
  }
493
493
  }
494
494
  });
495
+ if (BigInt(publishFileSyncEvents.remoteFilesVersion) > this.state.filesVersion) {
496
+ this.state.filesVersion = publishFileSyncEvents.remoteFilesVersion;
497
+ }
495
498
  context.addBreadcrumb({
496
499
  category: "sync",
497
500
  message: "Published file sync events",
@@ -502,9 +505,6 @@ class Sync extends BaseCommand {
502
505
  deleted: _.map(deleted, "path")
503
506
  }
504
507
  });
505
- if (BigInt(publishFileSyncEvents.remoteFilesVersion) > this.state.filesVersion) {
506
- this.state.filesVersion = publishFileSyncEvents.remoteFilesVersion;
507
- }
508
508
  this.log(chalkTemplate`Sent {gray ${format(new Date(), "pp")}}`);
509
509
  this.logPaths("→", _.map(changed, "path"), _.map(deleted, "path"));
510
510
  });
@@ -888,7 +888,7 @@ export var Action;
888
888
  Action["MERGE"] = "Merge local files with remote ones";
889
889
  Action["RESET"] = "Reset local files to remote ones";
890
890
  })(Action || (Action = {}));
891
- export const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = /* GraphQL */ `
891
+ export const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = dedent(/* GraphQL */ `
892
892
  subscription RemoteFileSyncEvents($localFilesVersion: String!) {
893
893
  remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {
894
894
  remoteFilesVersion
@@ -903,18 +903,18 @@ export const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = /* GraphQL */ `
903
903
  }
904
904
  }
905
905
  }
906
- `;
907
- export const REMOTE_FILES_VERSION_QUERY = /* GraphQL */ `
906
+ `);
907
+ export const REMOTE_FILES_VERSION_QUERY = dedent(/* GraphQL */ `
908
908
  query RemoteFilesVersion {
909
909
  remoteFilesVersion
910
910
  }
911
- `;
912
- export const PUBLISH_FILE_SYNC_EVENTS_MUTATION = /* GraphQL */ `
911
+ `);
912
+ export const PUBLISH_FILE_SYNC_EVENTS_MUTATION = dedent(/* GraphQL */ `
913
913
  mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {
914
914
  publishFileSyncEvents(input: $input) {
915
915
  remoteFilesVersion
916
916
  }
917
917
  }
918
- `;
918
+ `);
919
919
 
920
920
  //# sourceMappingURL=sync.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/sync.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport assert from \"assert\";\nimport chalkTemplate from \"chalk-template\";\nimport { format } from \"date-fns\";\nimport { execa } from \"execa\";\nimport type { Stats } from \"fs-extra\";\nimport fs from \"fs-extra\";\nimport inquirer from \"inquirer\";\nimport _ from \"lodash\";\nimport normalizePath from \"normalize-path\";\nimport pMap from \"p-map\";\nimport PQueue from \"p-queue\";\nimport path from \"path\";\nimport pluralize from \"pluralize\";\nimport { dedent } from \"ts-dedent\";\nimport FSWatcher from \"watcher\";\nimport which from \"which\";\nimport type {\n FileSyncChangedEventInput,\n FileSyncDeletedEventInput,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n} from \"../__generated__/graphql.js\";\nimport { FileSyncEncoding } from \"../__generated__/graphql.js\";\nimport { BaseCommand } from \"../services/base-command.js\";\nimport type { Query } from \"../services/client.js\";\nimport { Client } from \"../services/client.js\";\nimport { context } from \"../services/context.js\";\nimport { InvalidSyncAppFlagError, InvalidSyncFileError, YarnNotFoundError } from \"../services/errors.js\";\nimport { app } from \"../services/flags.js\";\nimport { FSIgnorer, ignoreEnoent, isEmptyDir, walkDir } from \"../services/fs-utils.js\";\nimport { PromiseSignal } from \"../services/promise.js\";\n\nexport default class Sync extends BaseCommand<typeof Sync> {\n static override priority = 1;\n\n static override summary = \"Sync your Gadget application's source code to and from your local filesystem.\";\n\n static override usage = \"sync [DIRECTORY] [--app <name>]\";\n\n static override description = dedent(chalkTemplate`\n Sync provides the ability to sync your Gadget application's source code to and from your local\n filesystem. While {gray ggt sync} is running, local file changes are immediately reflected within\n Gadget, while files that are changed remotely are immediately saved to your local filesystem.\n\n Use cases for this include:\n - Developing locally with your own editor like VSCode {gray (https://code.visualstudio.com/)}\n - Storing your source code in a Git repository like GitHub {gray (https://github.com/)}\n\n Sync includes the concept of a {gray .ignore} file. This file may contain a list of files and\n directories that won't be received or sent to Gadget when syncing. The format of this file is\n identical to the one used by Git {gray (https://git-scm.com/docs/gitignore)}.\n\n The following files and directories are always ignored:\n - .gadget\n - .git\n - node_modules\n\n Note:\n - If you have separate development and production environments, {gray ggt sync} will only sync with your development environment\n - Gadget applications only support installing dependencies with Yarn 1 {gray (https://classic.yarnpkg.com/lang/en/)}\n - Since file changes are immediately reflected in Gadget, avoid the following while {gray ggt sync} is running:\n - Deleting all your files\n - Moving all your files to a different directory\n `);\n\n static override args = {\n directory: Args.string({\n description: \"The directory to sync files to. If the directory doesn't exist, it will be created.\",\n default: \".\",\n }),\n };\n\n static override flags = {\n app: app({\n summary: \"The Gadget application to sync files to.\",\n }),\n force: Flags.boolean({\n summary: \"Whether to sync even if we can't determine the state of your local files relative to your remote ones.\",\n default: false,\n }),\n \"file-push-delay\": Flags.integer({\n summary: \"Delay in milliseconds before pushing files to your app.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 100,\n hidden: true,\n }),\n // The following flags are passed to FSWatcher (https://github.com/fabiospampinato/watcher)\n \"file-watch-debounce\": Flags.integer({\n summary: \"Amount of milliseconds to debounce file changed events\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 300,\n hidden: true,\n }),\n \"file-watch-poll-interval\": Flags.integer({\n summary:\n \"Polling is used as a last resort measure when watching non-existent paths inside non-existent directories, this controls how often polling is performed, in milliseconds. You can set it to a lower value to make the app detect events much more quickly, but don't set it too low if you are watching many paths that require polling as polling is expensive.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 3_000,\n hidden: true,\n }),\n \"file-watch-poll-timeout\": Flags.integer({\n summary:\n \"Sometimes polling will fail, for example if there are too many file descriptors currently open, usually eventually polling will succeed after a few tries though, this controls the amount of milliseconds the library should keep retrying for.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 20_000,\n hidden: true,\n }),\n \"file-watch-rename-timeout\": Flags.integer({\n summary:\n \"Amount of milliseconds to wait for a potential rename/renameDir event to be detected. The higher this value is the more reliably renames will be detected, but don't set this too high, or the emission of some events could be delayed by that amount. The higher this value is the longer the library will take to emit add/addDir/unlink/unlinkDir events.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 1_250,\n hidden: true,\n }),\n };\n\n static override examples = [\n dedent(chalkTemplate`\n {gray $ ggt sync --app my-app ~/gadget/my-app}\n\n App my-app\n Editor https://my-app.gadget.app/edit\n Playground https://my-app.gadget.app/api/graphql/playground\n Docs https://docs.gadget.dev/api/my-app\n\n {underline Endpoints}\n - https://my-app.gadget.app\n - https://my-app--development.gadget.app\n\n Watching for file changes... {gray Press Ctrl+C to stop}\n\n Received {gray 12:00:00 PM}\n {green ←} routes/GET.js {gray (changed)}\n {green ←} user/signUp/signIn.js {gray (changed)}\n {gray 2 files in total. 2 changed, 0 deleted.}\n\n Sent {gray 12:00:03 PM}\n {green →} routes/GET.ts {gray (changed)}\n {gray 1 file in total. 1 changed, 0 deleted.}\n\n ^C Stopping... {gray (press Ctrl+C again to force)}\n Goodbye!\n `),\n ];\n\n override requireUser = true;\n\n /**\n * The current status of the sync process.\n */\n status = SyncStatus.STARTING;\n\n /**\n * The absolute path to the directory to sync files to.\n */\n dir!: string;\n\n /**\n * A list of filepaths that have changed because of a remote file-sync event. This is used to avoid sending files that\n * we recently received from a remote file-sync event.\n */\n recentRemoteChanges = new Set<string>();\n\n /**\n * A FIFO async callback queue that ensures we process file-sync events in the order they occurred.\n */\n queue = new PQueue({ concurrency: 1 });\n\n /**\n * A GraphQL client connected to the app's /edit/api/graphql-ws endpoint\n */\n client!: Client;\n\n /**\n * Loads the .ignore file and provides methods for checking if a file should be ignored.\n */\n ignorer!: FSIgnorer;\n\n /**\n * Watches the local filesystem for changes.\n */\n watcher!: FSWatcher;\n\n /**\n * The state of the local filesystem.\n */\n state!: SyncState;\n\n /**\n * A debounced function that enqueue's local file changes to be sent to Gadget.\n */\n publish!: _.DebouncedFunc<() => void>;\n\n /**\n * Gracefully stops the sync.\n */\n stop!: (error?: unknown) => Promise<void>;\n\n /**\n * Turns an absolute filepath into a relative one from {@linkcode dir}.\n */\n relative(to: string): string {\n return path.relative(this.dir, to);\n }\n\n /**\n * Combines path segments into an absolute filepath that starts at {@linkcode dir}.\n */\n absolute(...pathSegments: string[]): string {\n return path.resolve(this.dir, ...pathSegments);\n }\n\n /**\n * Similar to {@linkcode relative} in that it turns a filepath into a relative one from {@linkcode dir}. However, it\n * also changes any slashes to be posix/unix-like forward slashes, condenses repeated slashes into a single slash, and\n * adds a trailing slash if the filepath is a directory.\n *\n * This is used when sending file-sync events to Gadget to ensure that the paths are consistent across platforms.\n *\n * @see https://www.npmjs.com/package/normalize-path\n */\n normalize(filepath: string, isDirectory: boolean): string {\n return normalizePath(path.isAbsolute(filepath) ? this.relative(filepath) : filepath) + (isDirectory ? \"/\" : \"\");\n }\n\n /**\n * Instead of deleting files, we move them to .gadget/backup so that users can recover them if something goes wrong.\n */\n async softDelete(normalizedPath: string): Promise<void> {\n try {\n await fs.move(this.absolute(normalizedPath), this.absolute(\".gadget/backup\", normalizedPath), {\n overwrite: true,\n });\n } catch (error) {\n // replicate the behavior of `rm -rf` and ignore ENOENT\n ignoreEnoent(error);\n }\n }\n\n /**\n * Pretty-prints changed and deleted filepaths to the console.\n *\n * @param prefix The prefix to print before each line.\n * @param changed The normalized paths that have changed.\n * @param deleted The normalized paths that have been deleted.\n * @param options.limit The maximum number of lines to print. Defaults to 10. If debug is enabled, this is ignored.\n */\n logPaths(prefix: string, changed: string[], deleted: string[], { limit = 10 } = {}): void {\n const lines = _.sortBy(\n [\n ..._.map(changed, (normalizedPath) => chalkTemplate`{green ${prefix}} ${normalizedPath} {gray (changed)}`),\n ..._.map(deleted, (normalizedPath) => chalkTemplate`{red ${prefix}} ${normalizedPath} {gray (deleted)}`),\n ],\n (line) => line.slice(line.indexOf(\" \") + 1),\n );\n\n let logged = 0;\n for (const line of lines) {\n this.log(line);\n if (++logged == limit && !this.debugEnabled) break;\n }\n\n if (lines.length > logged) {\n this.log(chalkTemplate`{gray … ${lines.length - logged} more}`);\n }\n\n this.log(\n chalkTemplate`{gray ${pluralize(\"file\", lines.length, true)} in total. ${changed.length} changed, ${deleted.length} deleted.}`,\n );\n this.log();\n }\n\n /**\n * Initializes the sync process.\n * - Ensures the directory exists.\n * - Ensures the directory is empty or contains a `.gadget/sync.json` file.\n * - Ensures an app is selected and that it matches the app the directory was previously synced to.\n * - Ensures yarn v1 is installed.\n * - Prompts the user how to resolve conflicts if the local filesystem has changed since the last sync.\n */\n override async init(): Promise<void> {\n await super.init();\n\n this.dir =\n this.config.windows && _.startsWith(this.args.directory, \"~/\")\n ? path.join(this.config.home, this.args.directory.slice(2))\n : path.resolve(this.args.directory);\n\n const getApp = async (): Promise<string> => {\n if (this.flags.app) {\n return this.flags.app;\n }\n\n // this.state can be undefined if the user is running `ggt sync` for the first time\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state?.app) {\n return this.state.app;\n }\n\n const selected = await inquirer.prompt<{ app: string }>({\n type: \"list\",\n name: \"app\",\n message: \"Please select the app to sync to.\",\n choices: await context.getAvailableApps().then((apps) => _.map(apps, \"slug\")),\n });\n\n return selected.app;\n };\n\n if (await isEmptyDir(this.dir)) {\n const app = await getApp();\n this.state = SyncState.create(this.dir, { app });\n } else {\n try {\n this.state = SyncState.load(this.dir);\n } catch (error) {\n if (!this.flags.force) {\n throw new InvalidSyncFileError(error, this, this.flags.app);\n }\n const app = await getApp();\n this.state = SyncState.create(this.dir, { app });\n }\n }\n\n if (this.flags.app && this.flags.app !== this.state.app && !this.flags.force) {\n throw new InvalidSyncAppFlagError(this);\n }\n\n await context.setApp(this.state.app);\n\n this.client = new Client();\n\n // local files/folders that should never be published\n this.ignorer = new FSIgnorer(this.dir, [\"node_modules\", \".gadget\", \".git\"]);\n\n if (!which.sync(\"yarn\", { nothrow: true })) {\n throw new YarnNotFoundError();\n }\n\n await fs.ensureDir(this.dir);\n\n const { remoteFilesVersion } = await this.client.queryUnwrap({ query: REMOTE_FILES_VERSION_QUERY });\n const hasRemoteChanges = BigInt(remoteFilesVersion) > BigInt(this.state.filesVersion);\n\n const getChangedFiles = async (): Promise<Map<string, Stats>> => {\n const files = new Map();\n for await (const absolutePath of walkDir(this.dir, { ignorer: this.ignorer })) {\n const stats = await fs.stat(absolutePath);\n if (stats.mtime.getTime() > this.state.mtime) {\n files.set(this.normalize(absolutePath, stats.isDirectory()), stats);\n }\n }\n\n // never include the root directory\n files.delete(\"/\");\n\n return files;\n };\n\n let changedFiles = await getChangedFiles();\n const hasLocalChanges = changedFiles.size > 0;\n if (hasLocalChanges) {\n this.log(\"Local files have changed since you last synced\");\n this.logPaths(\"-\", Array.from(changedFiles.keys()), [], { limit: changedFiles.size });\n this.log();\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Initializing\",\n data: {\n state: this.state,\n remoteFilesVersion,\n hasRemoteChanges,\n hasLocalChanges,\n changed: Array.from(changedFiles.keys()),\n },\n });\n\n let action: Action | undefined;\n if (hasLocalChanges) {\n ({ action } = await inquirer.prompt({\n type: \"list\",\n name: \"action\",\n choices: [Action.CANCEL, Action.MERGE, Action.RESET],\n message: hasRemoteChanges ? \"Remote files have also changed. How would you like to proceed?\" : \"How would you like to proceed?\",\n }));\n }\n\n // get all the changed files again in case more changed\n changedFiles = await getChangedFiles();\n\n switch (action) {\n case Action.MERGE: {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Merging local changes\",\n data: {\n state: this.state,\n remoteFilesVersion,\n changed: Array.from(changedFiles.keys()),\n },\n });\n\n // We purposefully don't set the returned remoteFilesVersion here because we haven't received the remote changes\n // yet. This will cause us to receive the local files that we just published + the remote files that were\n // changed since the last sync.\n await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: {\n input: {\n expectedRemoteFilesVersion: remoteFilesVersion,\n changed: await pMap(changedFiles, async ([normalizedPath, stats]) => {\n if (stats.mtime.getTime() > this.state.mtime) {\n this.state.mtime = stats.mtime.getTime();\n }\n\n return {\n path: normalizedPath,\n mode: stats.mode,\n content: stats.isDirectory() ? \"\" : await fs.readFile(this.absolute(normalizedPath), \"base64\"),\n encoding: FileSyncEncoding.Base64,\n };\n }),\n deleted: [],\n },\n },\n });\n break;\n }\n case Action.RESET: {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Resetting local changes\",\n data: {\n state: this.state,\n remoteFilesVersion,\n changed: Array.from(changedFiles.keys()),\n },\n });\n\n // delete all the local files that have changed since the last sync and set the files version to 0 so we receive\n // all the remote files again, including any files that we just deleted that still exist\n await pMap(changedFiles.keys(), (normalizedPath) => this.softDelete(normalizedPath));\n this.state.filesVersion = 0n;\n break;\n }\n case Action.CANCEL: {\n process.exit(0);\n }\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Initialized\",\n data: {\n state: this.state,\n },\n });\n }\n\n /**\n * Runs the sync process until it is stopped or an error occurs.\n */\n async run(): Promise<void> {\n let error: unknown;\n const stopped = new PromiseSignal();\n\n this.stop = async (e?: unknown) => {\n if (this.status != SyncStatus.RUNNING) return;\n\n this.status = SyncStatus.STOPPING;\n error = e;\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Stopping\",\n level: error ? \"error\" : undefined,\n data: {\n state: this.state,\n error,\n },\n });\n\n try {\n unsubscribe();\n this.watcher.removeAllListeners();\n this.publish.flush();\n await this.queue.onIdle();\n } finally {\n this.state.flush();\n await Promise.allSettled([this.watcher.close(), this.client.dispose()]);\n\n this.status = SyncStatus.STOPPED;\n stopped.resolve();\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Stopped\",\n data: {\n state: this.state,\n },\n });\n }\n };\n\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.on(signal, () => {\n if (this.status != SyncStatus.RUNNING) return;\n\n this.log(chalkTemplate` Stopping... {gray (press Ctrl+C again to force)}`);\n void this.stop();\n\n // When ggt is run via npx, and the user presses Ctrl+C, npx sends SIGINT twice in quick succession. In order to prevent the second\n // SIGINT from triggering the force exit listener, we wait a bit before registering it. This is a bit of a hack, but it works.\n setTimeout(() => {\n process.once(signal, () => {\n this.log(\" Exiting immediately. Note that files may not have finished syncing.\");\n process.exit(1);\n });\n }, 100).unref();\n });\n }\n\n const unsubscribe = this.client.subscribeUnwrap(\n {\n query: REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION,\n variables: () => ({ localFilesVersion: String(this.state.filesVersion) }),\n },\n {\n error: (error) => void this.stop(error),\n next: ({ remoteFileSyncEvents }) => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Received file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n changed: _.map(remoteFileSyncEvents.changed, \"path\"),\n deleted: _.map(remoteFileSyncEvents.deleted, \"path\"),\n },\n });\n\n const remoteFilesVersion = remoteFileSyncEvents.remoteFilesVersion;\n\n // we always ignore .gadget/ files so that we don't publish them (they're managed by gadget), but we still want to receive them\n const filter = (event: { path: string }) => _.startsWith(event.path, \".gadget/\") || !this.ignorer.ignores(event.path);\n const changed = _.filter(remoteFileSyncEvents.changed, filter);\n const deleted = _.filter(remoteFileSyncEvents.deleted, filter);\n\n this._enqueue(async () => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Processing received file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n changed: _.map(remoteFileSyncEvents.changed, \"path\"),\n deleted: _.map(remoteFileSyncEvents.deleted, \"path\"),\n },\n });\n\n if (!changed.length && !deleted.length) {\n if (BigInt(remoteFilesVersion) > this.state.filesVersion) {\n // we still need to update filesVersion, otherwise our expectedFilesVersion will be behind the next time we publish\n this.state.filesVersion = remoteFilesVersion;\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Received empty file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n },\n });\n }\n return;\n }\n\n this.log(chalkTemplate`Received {gray ${format(new Date(), \"pp\")}}`);\n this.logPaths(\"←\", _.map(changed, \"path\"), _.map(deleted, \"path\"));\n\n // we need to processed deleted files first as we may delete an empty directory after a file has been put\n // into it. if processed out of order the new file will be deleted as well\n await pMap(deleted, async (file) => {\n this.recentRemoteChanges.add(file.path);\n await this.softDelete(file.path);\n });\n\n await pMap(changed, async (file) => {\n this.recentRemoteChanges.add(file.path);\n\n const absolutePath = this.absolute(file.path);\n if (_.endsWith(file.path, \"/\")) {\n await fs.ensureDir(absolutePath, { mode: 0o755 });\n return;\n }\n\n // we need to add all parent directories to recentRemoteChanges so that we don't re-publish them\n for (const dir of _.split(path.dirname(file.path), \"/\")) {\n this.recentRemoteChanges.add(dir + \"/\");\n }\n\n await fs.ensureDir(path.dirname(absolutePath), { mode: 0o755 });\n await fs.writeFile(absolutePath, Buffer.from(file.content, file.encoding), { mode: file.mode });\n\n if (absolutePath == this.absolute(\"yarn.lock\")) {\n await execa(\"yarn\", [\"install\"], { cwd: this.dir }).catch((error) => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Yarn install failed\",\n level: \"error\",\n data: {\n state: this.state,\n error,\n },\n });\n });\n }\n\n if (absolutePath == this.ignorer.filepath) {\n this.ignorer.reload();\n }\n });\n\n this.state.filesVersion = remoteFilesVersion;\n\n // always remove the root directory from recentRemoteChanges\n this.recentRemoteChanges.delete(\"./\");\n\n // remove any files in recentRemoteChanges that are ignored (e.g. .gadget/ files)\n for (const filepath of this.recentRemoteChanges) {\n if (this.ignorer.ignores(filepath)) {\n this.recentRemoteChanges.delete(filepath);\n }\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Processed received file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n changed: _.map(remoteFileSyncEvents.changed, \"path\"),\n deleted: _.map(remoteFileSyncEvents.deleted, \"path\"),\n recentRemoteChanges: Array.from(this.recentRemoteChanges.keys()),\n },\n });\n });\n },\n },\n );\n\n const localFilesBuffer = new Map<\n string,\n | { mode: number; isDirectory: boolean }\n | { isDeleted: true; isDirectory: boolean }\n | { mode: number; oldPath: string; newPath: string; isDirectory: boolean }\n >();\n\n this.publish = _.debounce(() => {\n const localFiles = new Map(localFilesBuffer.entries());\n localFilesBuffer.clear();\n\n this._enqueue(async () => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Publishing file sync events\",\n data: {\n state: this.state,\n localFiles: Array.from(localFiles.keys()),\n },\n });\n\n const changed: FileSyncChangedEventInput[] = [];\n const deleted: FileSyncDeletedEventInput[] = [];\n\n await pMap(localFiles, async ([normalizedPath, file]) => {\n if (\"isDeleted\" in file) {\n deleted.push({ path: normalizedPath });\n return;\n }\n\n try {\n changed.push({\n path: normalizedPath,\n oldPath: \"oldPath\" in file ? file.oldPath : undefined,\n mode: file.mode,\n content: file.isDirectory ? \"\" : await fs.readFile(this.absolute(normalizedPath), FileSyncEncoding.Base64),\n encoding: FileSyncEncoding.Base64,\n });\n } catch (error) {\n // A file could have been changed and then deleted before we process the change event, so the readFile\n // above will raise an ENOENT. This is normal operation, so just ignore this event.\n ignoreEnoent(error);\n }\n });\n\n if (!changed.length && !deleted.length) {\n return;\n }\n\n const { publishFileSyncEvents } = await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: { input: { expectedRemoteFilesVersion: String(this.state.filesVersion), changed, deleted } },\n });\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Published file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: publishFileSyncEvents.remoteFilesVersion,\n changed: _.map(changed, \"path\"),\n deleted: _.map(deleted, \"path\"),\n },\n });\n\n if (BigInt(publishFileSyncEvents.remoteFilesVersion) > this.state.filesVersion) {\n this.state.filesVersion = publishFileSyncEvents.remoteFilesVersion;\n }\n\n this.log(chalkTemplate`Sent {gray ${format(new Date(), \"pp\")}}`);\n this.logPaths(\"→\", _.map(changed, \"path\"), _.map(deleted, \"path\"));\n });\n }, this.flags[\"file-push-delay\"]);\n\n this.watcher = new FSWatcher(this.dir, {\n // paths that we never want to publish\n ignore: /(\\.gadget|\\.git|node_modules)/,\n // don't emit an event for every watched file on boot\n ignoreInitial: true,\n renameDetection: true,\n recursive: true,\n debounce: this.flags[\"file-watch-debounce\"],\n pollingInterval: this.flags[\"file-watch-poll-interval\"],\n pollingTimeout: this.flags[\"file-watch-poll-timeout\"],\n renameTimeout: this.flags[\"file-watch-rename-timeout\"],\n });\n\n this.watcher.once(\"error\", (error) => void this.stop(error));\n\n this.watcher.on(\"all\", (event: string, absolutePath: string, renamedPath: string) => {\n const filepath = event === \"rename\" || event === \"renameDir\" ? renamedPath : absolutePath;\n const isDirectory = event === \"renameDir\" || event === \"addDir\" || event === \"unlinkDir\";\n const normalizedPath = this.normalize(filepath, isDirectory);\n\n if (filepath == this.ignorer.filepath) {\n this.ignorer.reload();\n } else if (this.ignorer.ignores(filepath)) {\n this.debug(\"skipping event caused by ignored file %s\", normalizedPath);\n return;\n }\n\n let stats: Stats | undefined;\n try {\n stats = fs.statSync(filepath);\n } catch (error) {\n ignoreEnoent(error);\n }\n\n // we only update the mtime if the file is not ignored, because if we restart and the mtime is set to an ignored\n // file, then it could be greater than the mtime of all non ignored files and we'll think that local files have\n // changed when only an ignored one has\n if (stats && stats.mtime.getTime() > this.state.mtime) {\n this.state.mtime = stats.mtime.getTime();\n }\n\n if (this.recentRemoteChanges.delete(normalizedPath)) {\n this.debug(\"skipping event caused by recent write %s\", normalizedPath);\n return;\n }\n\n this.debug(\"%s %s\", event, normalizedPath);\n\n switch (event) {\n case \"add\":\n case \"change\":\n assert(stats, \"missing stats on add/change event\");\n localFilesBuffer.set(normalizedPath, { mode: stats.mode, isDirectory: false });\n break;\n case \"addDir\":\n assert(stats, \"missing stats on addDir event\");\n localFilesBuffer.set(normalizedPath, { mode: stats.mode, isDirectory: true });\n break;\n case \"unlinkDir\":\n case \"unlink\":\n localFilesBuffer.set(normalizedPath, { isDeleted: true, isDirectory: event === \"unlinkDir\" });\n break;\n case \"rename\":\n case \"renameDir\":\n assert(stats, \"missing stats on rename/renameDir event\");\n localFilesBuffer.set(normalizedPath, {\n oldPath: this.normalize(absolutePath, isDirectory),\n newPath: normalizedPath,\n isDirectory: event === \"renameDir\",\n mode: stats.mode,\n });\n break;\n }\n\n this.publish();\n });\n\n this.status = SyncStatus.RUNNING;\n\n // app should be defined at this point\n assert(context.app);\n\n this.log();\n this.log(\n dedent(chalkTemplate`\n {bold ggt v${this.config.version}}\n\n App ${context.app.slug}\n Editor https://${context.app.slug}.gadget.app/edit\n Playground https://${context.app.slug}.gadget.app/api/graphql/playground\n Docs https://docs.gadget.dev/api/${context.app.slug}\n\n {underline Endpoints} ${\n context.app.hasSplitEnvironments\n ? `\n - https://${context.app.primaryDomain}\n - https://${context.app.slug}--development.gadget.app`\n : `\n - https://${context.app.primaryDomain}`\n }\n\n Watching for file changes... {gray Press Ctrl+C to stop}\n `),\n );\n this.log();\n\n await stopped;\n\n if (error) {\n this.notify({ subtitle: \"Uh oh!\", message: \"An error occurred while syncing files\" });\n throw error as Error;\n } else {\n this.log(\"Goodbye!\");\n }\n }\n\n /**\n * Enqueues a function that handles file-sync events onto the {@linkcode queue}.\n *\n * @param fn The function to enqueue.\n */\n private _enqueue(fn: () => Promise<unknown>): void {\n void this.queue.add(fn).catch(this.stop);\n }\n}\n\n/**\n * Holds information about the state of the local filesystem. It's persisted to `.gadget/sync.json`.\n */\nexport class SyncState {\n private _inner: {\n app: string;\n filesVersion: string;\n mtime: number;\n };\n\n /**\n * Saves the current state of the filesystem to `.gadget/sync.json`.\n */\n #save = _.debounce(() => {\n fs.outputJSONSync(path.join(this._rootDir, \".gadget/sync.json\"), this._inner, { spaces: 2 });\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Saved sync state\",\n data: { state: this._inner },\n });\n }, 100);\n\n private constructor(\n private _rootDir: string,\n inner: { app: string; filesVersion: string; mtime: number },\n ) {\n this._inner = inner;\n }\n\n /**\n * The app this filesystem is synced to.\n */\n get app(): string {\n return this._inner.app;\n }\n\n /**\n * The last filesVersion that was successfully written to the filesystem. This is used to determine if the remote\n * filesystem is ahead of the local one.\n */\n get filesVersion(): bigint {\n return BigInt(this._inner.filesVersion);\n }\n\n set filesVersion(value: bigint | string) {\n this._inner.filesVersion = String(value);\n this.#save();\n }\n\n /**\n * The largest mtime that was seen on the local filesystem before `ggt sync` stopped. This is used to determine if\n * the local filesystem has changed since the last sync.\n *\n * Note: This does not include the mtime of files that are ignored.\n */\n // eslint-disable-next-line @typescript-eslint/member-ordering\n get mtime(): number {\n return this._inner.mtime;\n }\n\n set mtime(value: number) {\n this._inner.mtime = value;\n this.#save();\n }\n\n /**\n * Creates a new SyncFile instance and saves it to the filesystem.\n *\n * @param rootDir The root directory of the app.\n * @param app The app slug.\n * @returns A new SyncFile instance.\n */\n static create(rootDir: string, opts: { app: string; filesVersion?: string; mtime?: number }): SyncState {\n const state = new SyncState(rootDir, { filesVersion: \"0\", mtime: 0, ...opts });\n state.#save();\n state.flush();\n return state;\n }\n\n /**\n * Loads a SyncFile instance from the filesystem.\n *\n * @param rootDir The root directory of the app.\n * @returns The SyncFile instance.\n */\n static load(rootDir: string): SyncState {\n const state = fs.readJsonSync(path.join(rootDir, \".gadget/sync.json\"));\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Loaded sync state\",\n data: { state },\n });\n\n assert(_.isString(state.app), \"missing or invalid app\");\n assert(_.isString(state.filesVersion), \"missing or invalid filesVersion\");\n assert(_.isNumber(state.mtime), \"missing or invalid mtime\");\n\n return new SyncState(rootDir, {\n app: state.app,\n filesVersion: state.filesVersion,\n mtime: state.mtime,\n });\n }\n\n /**\n * Flushes any pending writes to the filesystem.\n */\n flush(): void {\n this.#save.flush();\n }\n\n /**\n * @returns The JSON representation of this instance.\n */\n toJSON() {\n return this._inner;\n }\n}\n\nexport enum SyncStatus {\n STARTING,\n RUNNING,\n STOPPING,\n STOPPED,\n}\n\nexport enum Action {\n CANCEL = \"Cancel (Ctrl+C)\",\n MERGE = \"Merge local files with remote ones\",\n RESET = \"Reset local files to remote ones\",\n}\n\nexport const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION: Query<\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables\n> = /* GraphQL */ `\n subscription RemoteFileSyncEvents($localFilesVersion: String!) {\n remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n deleted {\n path\n }\n }\n }\n`;\n\nexport const REMOTE_FILES_VERSION_QUERY: Query<RemoteFilesVersionQuery, RemoteFilesVersionQueryVariables> = /* GraphQL */ `\n query RemoteFilesVersion {\n remoteFilesVersion\n }\n`;\n\nexport const PUBLISH_FILE_SYNC_EVENTS_MUTATION: Query<\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables\n> = /* GraphQL */ `\n mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {\n publishFileSyncEvents(input: $input) {\n remoteFilesVersion\n }\n }\n`;\n"],"names":["Args","Flags","assert","chalkTemplate","format","execa","fs","inquirer","_","normalizePath","pMap","PQueue","path","pluralize","dedent","FSWatcher","which","FileSyncEncoding","BaseCommand","Client","context","InvalidSyncAppFlagError","InvalidSyncFileError","YarnNotFoundError","app","FSIgnorer","ignoreEnoent","isEmptyDir","walkDir","PromiseSignal","Sync","relative","to","dir","absolute","pathSegments","resolve","normalize","filepath","isDirectory","isAbsolute","softDelete","normalizedPath","move","overwrite","error","logPaths","prefix","changed","deleted","limit","lines","sortBy","map","line","slice","indexOf","logged","log","debugEnabled","length","init","config","windows","startsWith","args","directory","join","home","getApp","flags","state","selected","prompt","type","name","message","choices","getAvailableApps","then","apps","SyncState","create","load","force","setApp","client","ignorer","sync","nothrow","ensureDir","remoteFilesVersion","queryUnwrap","query","REMOTE_FILES_VERSION_QUERY","hasRemoteChanges","BigInt","filesVersion","getChangedFiles","files","Map","absolutePath","stats","stat","mtime","getTime","set","delete","changedFiles","hasLocalChanges","size","Array","from","keys","addBreadcrumb","category","data","action","Action","CANCEL","MERGE","RESET","PUBLISH_FILE_SYNC_EVENTS_MUTATION","variables","input","expectedRemoteFilesVersion","mode","content","readFile","encoding","Base64","process","exit","run","stopped","stop","e","status","SyncStatus","RUNNING","STOPPING","level","undefined","unsubscribe","watcher","removeAllListeners","publish","flush","queue","onIdle","Promise","allSettled","close","dispose","STOPPED","signal","on","setTimeout","once","unref","subscribeUnwrap","REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION","localFilesVersion","String","next","remoteFileSyncEvents","filter","event","ignores","_enqueue","Date","file","recentRemoteChanges","add","endsWith","split","dirname","writeFile","Buffer","cwd","catch","reload","localFilesBuffer","debounce","localFiles","entries","clear","push","oldPath","publishFileSyncEvents","ignore","ignoreInitial","renameDetection","recursive","pollingInterval","pollingTimeout","renameTimeout","renamedPath","debug","statSync","isDeleted","newPath","version","slug","hasSplitEnvironments","primaryDomain","notify","subtitle","fn","requireUser","STARTING","Set","concurrency","priority","summary","usage","description","string","default","boolean","integer","helpGroup","helpValue","hidden","examples","_inner","value","save","rootDir","opts","readJsonSync","isString","isNumber","toJSON","_rootDir","inner","outputJSONSync","spaces"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/sync.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport assert from \"assert\";\nimport chalkTemplate from \"chalk-template\";\nimport { format } from \"date-fns\";\nimport { execa } from \"execa\";\nimport type { Stats } from \"fs-extra\";\nimport fs from \"fs-extra\";\nimport inquirer from \"inquirer\";\nimport _ from \"lodash\";\nimport normalizePath from \"normalize-path\";\nimport pMap from \"p-map\";\nimport PQueue from \"p-queue\";\nimport path from \"path\";\nimport pluralize from \"pluralize\";\nimport { dedent } from \"ts-dedent\";\nimport FSWatcher from \"watcher\";\nimport which from \"which\";\nimport type {\n FileSyncChangedEventInput,\n FileSyncDeletedEventInput,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n} from \"../__generated__/graphql.js\";\nimport { FileSyncEncoding } from \"../__generated__/graphql.js\";\nimport { BaseCommand } from \"../services/base-command.js\";\nimport type { Query } from \"../services/client.js\";\nimport { Client } from \"../services/client.js\";\nimport { context } from \"../services/context.js\";\nimport { InvalidSyncAppFlagError, InvalidSyncFileError, YarnNotFoundError } from \"../services/errors.js\";\nimport { app } from \"../services/flags.js\";\nimport { FSIgnorer, ignoreEnoent, isEmptyDir, walkDir } from \"../services/fs-utils.js\";\nimport { PromiseSignal } from \"../services/promise.js\";\n\nexport default class Sync extends BaseCommand<typeof Sync> {\n static override priority = 1;\n\n static override summary = \"Sync your Gadget application's source code to and from your local filesystem.\";\n\n static override usage = \"sync [DIRECTORY] [--app <name>]\";\n\n static override description = dedent(chalkTemplate`\n Sync provides the ability to sync your Gadget application's source code to and from your local\n filesystem. While {gray ggt sync} is running, local file changes are immediately reflected within\n Gadget, while files that are changed remotely are immediately saved to your local filesystem.\n\n Use cases for this include:\n - Developing locally with your own editor like VSCode {gray (https://code.visualstudio.com/)}\n - Storing your source code in a Git repository like GitHub {gray (https://github.com/)}\n\n Sync includes the concept of a {gray .ignore} file. This file may contain a list of files and\n directories that won't be received or sent to Gadget when syncing. The format of this file is\n identical to the one used by Git {gray (https://git-scm.com/docs/gitignore)}.\n\n The following files and directories are always ignored:\n - .gadget\n - .git\n - node_modules\n\n Note:\n - If you have separate development and production environments, {gray ggt sync} will only sync with your development environment\n - Gadget applications only support installing dependencies with Yarn 1 {gray (https://classic.yarnpkg.com/lang/en/)}\n - Since file changes are immediately reflected in Gadget, avoid the following while {gray ggt sync} is running:\n - Deleting all your files\n - Moving all your files to a different directory\n `);\n\n static override args = {\n directory: Args.string({\n description: \"The directory to sync files to. If the directory doesn't exist, it will be created.\",\n default: \".\",\n }),\n };\n\n static override flags = {\n app: app({\n summary: \"The Gadget application to sync files to.\",\n }),\n force: Flags.boolean({\n summary: \"Whether to sync even if we can't determine the state of your local files relative to your remote ones.\",\n default: false,\n }),\n \"file-push-delay\": Flags.integer({\n summary: \"Delay in milliseconds before pushing files to your app.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 100,\n hidden: true,\n }),\n // The following flags are passed to FSWatcher (https://github.com/fabiospampinato/watcher)\n \"file-watch-debounce\": Flags.integer({\n summary: \"Amount of milliseconds to debounce file changed events\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 300,\n hidden: true,\n }),\n \"file-watch-poll-interval\": Flags.integer({\n summary:\n \"Polling is used as a last resort measure when watching non-existent paths inside non-existent directories, this controls how often polling is performed, in milliseconds. You can set it to a lower value to make the app detect events much more quickly, but don't set it too low if you are watching many paths that require polling as polling is expensive.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 3_000,\n hidden: true,\n }),\n \"file-watch-poll-timeout\": Flags.integer({\n summary:\n \"Sometimes polling will fail, for example if there are too many file descriptors currently open, usually eventually polling will succeed after a few tries though, this controls the amount of milliseconds the library should keep retrying for.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 20_000,\n hidden: true,\n }),\n \"file-watch-rename-timeout\": Flags.integer({\n summary:\n \"Amount of milliseconds to wait for a potential rename/renameDir event to be detected. The higher this value is the more reliably renames will be detected, but don't set this too high, or the emission of some events could be delayed by that amount. The higher this value is the longer the library will take to emit add/addDir/unlink/unlinkDir events.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 1_250,\n hidden: true,\n }),\n };\n\n static override examples = [\n dedent(chalkTemplate`\n {gray $ ggt sync --app my-app ~/gadget/my-app}\n\n App my-app\n Editor https://my-app.gadget.app/edit\n Playground https://my-app.gadget.app/api/graphql/playground\n Docs https://docs.gadget.dev/api/my-app\n\n {underline Endpoints}\n - https://my-app.gadget.app\n - https://my-app--development.gadget.app\n\n Watching for file changes... {gray Press Ctrl+C to stop}\n\n Received {gray 12:00:00 PM}\n {green ←} routes/GET.js {gray (changed)}\n {green ←} user/signUp/signIn.js {gray (changed)}\n {gray 2 files in total. 2 changed, 0 deleted.}\n\n Sent {gray 12:00:03 PM}\n {green →} routes/GET.ts {gray (changed)}\n {gray 1 file in total. 1 changed, 0 deleted.}\n\n ^C Stopping... {gray (press Ctrl+C again to force)}\n Goodbye!\n `),\n ];\n\n override requireUser = true;\n\n /**\n * The current status of the sync process.\n */\n status = SyncStatus.STARTING;\n\n /**\n * The absolute path to the directory to sync files to.\n */\n dir!: string;\n\n /**\n * A list of filepaths that have changed because of a remote file-sync event. This is used to avoid sending files that\n * we recently received from a remote file-sync event.\n */\n recentRemoteChanges = new Set<string>();\n\n /**\n * A FIFO async callback queue that ensures we process file-sync events in the order they occurred.\n */\n queue = new PQueue({ concurrency: 1 });\n\n /**\n * A GraphQL client connected to the app's /edit/api/graphql-ws endpoint\n */\n client!: Client;\n\n /**\n * Loads the .ignore file and provides methods for checking if a file should be ignored.\n */\n ignorer!: FSIgnorer;\n\n /**\n * Watches the local filesystem for changes.\n */\n watcher!: FSWatcher;\n\n /**\n * The state of the local filesystem.\n */\n state!: SyncState;\n\n /**\n * A debounced function that enqueue's local file changes to be sent to Gadget.\n */\n publish!: _.DebouncedFunc<() => void>;\n\n /**\n * Gracefully stops the sync.\n */\n stop!: (error?: unknown) => Promise<void>;\n\n /**\n * Turns an absolute filepath into a relative one from {@linkcode dir}.\n */\n relative(to: string): string {\n return path.relative(this.dir, to);\n }\n\n /**\n * Combines path segments into an absolute filepath that starts at {@linkcode dir}.\n */\n absolute(...pathSegments: string[]): string {\n return path.resolve(this.dir, ...pathSegments);\n }\n\n /**\n * Similar to {@linkcode relative} in that it turns a filepath into a relative one from {@linkcode dir}. However, it\n * also changes any slashes to be posix/unix-like forward slashes, condenses repeated slashes into a single slash, and\n * adds a trailing slash if the filepath is a directory.\n *\n * This is used when sending file-sync events to Gadget to ensure that the paths are consistent across platforms.\n *\n * @see https://www.npmjs.com/package/normalize-path\n */\n normalize(filepath: string, isDirectory: boolean): string {\n return normalizePath(path.isAbsolute(filepath) ? this.relative(filepath) : filepath) + (isDirectory ? \"/\" : \"\");\n }\n\n /**\n * Instead of deleting files, we move them to .gadget/backup so that users can recover them if something goes wrong.\n */\n async softDelete(normalizedPath: string): Promise<void> {\n try {\n await fs.move(this.absolute(normalizedPath), this.absolute(\".gadget/backup\", normalizedPath), {\n overwrite: true,\n });\n } catch (error) {\n // replicate the behavior of `rm -rf` and ignore ENOENT\n ignoreEnoent(error);\n }\n }\n\n /**\n * Pretty-prints changed and deleted filepaths to the console.\n *\n * @param prefix The prefix to print before each line.\n * @param changed The normalized paths that have changed.\n * @param deleted The normalized paths that have been deleted.\n * @param options.limit The maximum number of lines to print. Defaults to 10. If debug is enabled, this is ignored.\n */\n logPaths(prefix: string, changed: string[], deleted: string[], { limit = 10 } = {}): void {\n const lines = _.sortBy(\n [\n ..._.map(changed, (normalizedPath) => chalkTemplate`{green ${prefix}} ${normalizedPath} {gray (changed)}`),\n ..._.map(deleted, (normalizedPath) => chalkTemplate`{red ${prefix}} ${normalizedPath} {gray (deleted)}`),\n ],\n (line) => line.slice(line.indexOf(\" \") + 1),\n );\n\n let logged = 0;\n for (const line of lines) {\n this.log(line);\n if (++logged == limit && !this.debugEnabled) break;\n }\n\n if (lines.length > logged) {\n this.log(chalkTemplate`{gray … ${lines.length - logged} more}`);\n }\n\n this.log(\n chalkTemplate`{gray ${pluralize(\"file\", lines.length, true)} in total. ${changed.length} changed, ${deleted.length} deleted.}`,\n );\n this.log();\n }\n\n /**\n * Initializes the sync process.\n * - Ensures the directory exists.\n * - Ensures the directory is empty or contains a `.gadget/sync.json` file.\n * - Ensures an app is selected and that it matches the app the directory was previously synced to.\n * - Ensures yarn v1 is installed.\n * - Prompts the user how to resolve conflicts if the local filesystem has changed since the last sync.\n */\n override async init(): Promise<void> {\n await super.init();\n\n this.dir =\n this.config.windows && _.startsWith(this.args.directory, \"~/\")\n ? path.join(this.config.home, this.args.directory.slice(2))\n : path.resolve(this.args.directory);\n\n const getApp = async (): Promise<string> => {\n if (this.flags.app) {\n return this.flags.app;\n }\n\n // this.state can be undefined if the user is running `ggt sync` for the first time\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state?.app) {\n return this.state.app;\n }\n\n const selected = await inquirer.prompt<{ app: string }>({\n type: \"list\",\n name: \"app\",\n message: \"Please select the app to sync to.\",\n choices: await context.getAvailableApps().then((apps) => _.map(apps, \"slug\")),\n });\n\n return selected.app;\n };\n\n if (await isEmptyDir(this.dir)) {\n const app = await getApp();\n this.state = SyncState.create(this.dir, { app });\n } else {\n try {\n this.state = SyncState.load(this.dir);\n } catch (error) {\n if (!this.flags.force) {\n throw new InvalidSyncFileError(error, this, this.flags.app);\n }\n const app = await getApp();\n this.state = SyncState.create(this.dir, { app });\n }\n }\n\n if (this.flags.app && this.flags.app !== this.state.app && !this.flags.force) {\n throw new InvalidSyncAppFlagError(this);\n }\n\n await context.setApp(this.state.app);\n\n this.client = new Client();\n\n // local files/folders that should never be published\n this.ignorer = new FSIgnorer(this.dir, [\"node_modules\", \".gadget\", \".git\"]);\n\n if (!which.sync(\"yarn\", { nothrow: true })) {\n throw new YarnNotFoundError();\n }\n\n await fs.ensureDir(this.dir);\n\n const { remoteFilesVersion } = await this.client.queryUnwrap({ query: REMOTE_FILES_VERSION_QUERY });\n const hasRemoteChanges = BigInt(remoteFilesVersion) > BigInt(this.state.filesVersion);\n\n const getChangedFiles = async (): Promise<Map<string, Stats>> => {\n const files = new Map();\n for await (const absolutePath of walkDir(this.dir, { ignorer: this.ignorer })) {\n const stats = await fs.stat(absolutePath);\n if (stats.mtime.getTime() > this.state.mtime) {\n files.set(this.normalize(absolutePath, stats.isDirectory()), stats);\n }\n }\n\n // never include the root directory\n files.delete(\"/\");\n\n return files;\n };\n\n let changedFiles = await getChangedFiles();\n const hasLocalChanges = changedFiles.size > 0;\n if (hasLocalChanges) {\n this.log(\"Local files have changed since you last synced\");\n this.logPaths(\"-\", Array.from(changedFiles.keys()), [], { limit: changedFiles.size });\n this.log();\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Initializing\",\n data: {\n state: this.state,\n remoteFilesVersion,\n hasRemoteChanges,\n hasLocalChanges,\n changed: Array.from(changedFiles.keys()),\n },\n });\n\n let action: Action | undefined;\n if (hasLocalChanges) {\n ({ action } = await inquirer.prompt({\n type: \"list\",\n name: \"action\",\n choices: [Action.CANCEL, Action.MERGE, Action.RESET],\n message: hasRemoteChanges ? \"Remote files have also changed. How would you like to proceed?\" : \"How would you like to proceed?\",\n }));\n }\n\n // get all the changed files again in case more changed\n changedFiles = await getChangedFiles();\n\n switch (action) {\n case Action.MERGE: {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Merging local changes\",\n data: {\n state: this.state,\n remoteFilesVersion,\n changed: Array.from(changedFiles.keys()),\n },\n });\n\n // We purposefully don't set the returned remoteFilesVersion here because we haven't received the remote changes\n // yet. This will cause us to receive the local files that we just published + the remote files that were\n // changed since the last sync.\n await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: {\n input: {\n expectedRemoteFilesVersion: remoteFilesVersion,\n changed: await pMap(changedFiles, async ([normalizedPath, stats]) => {\n if (stats.mtime.getTime() > this.state.mtime) {\n this.state.mtime = stats.mtime.getTime();\n }\n\n return {\n path: normalizedPath,\n mode: stats.mode,\n content: stats.isDirectory() ? \"\" : await fs.readFile(this.absolute(normalizedPath), \"base64\"),\n encoding: FileSyncEncoding.Base64,\n };\n }),\n deleted: [],\n },\n },\n });\n break;\n }\n case Action.RESET: {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Resetting local changes\",\n data: {\n state: this.state,\n remoteFilesVersion,\n changed: Array.from(changedFiles.keys()),\n },\n });\n\n // delete all the local files that have changed since the last sync and set the files version to 0 so we receive\n // all the remote files again, including any files that we just deleted that still exist\n await pMap(changedFiles.keys(), (normalizedPath) => this.softDelete(normalizedPath));\n this.state.filesVersion = 0n;\n break;\n }\n case Action.CANCEL: {\n process.exit(0);\n }\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Initialized\",\n data: {\n state: this.state,\n },\n });\n }\n\n /**\n * Runs the sync process until it is stopped or an error occurs.\n */\n async run(): Promise<void> {\n let error: unknown;\n const stopped = new PromiseSignal();\n\n this.stop = async (e?: unknown) => {\n if (this.status != SyncStatus.RUNNING) return;\n\n this.status = SyncStatus.STOPPING;\n error = e;\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Stopping\",\n level: error ? \"error\" : undefined,\n data: {\n state: this.state,\n error,\n },\n });\n\n try {\n unsubscribe();\n this.watcher.removeAllListeners();\n this.publish.flush();\n await this.queue.onIdle();\n } finally {\n this.state.flush();\n await Promise.allSettled([this.watcher.close(), this.client.dispose()]);\n\n this.status = SyncStatus.STOPPED;\n stopped.resolve();\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Stopped\",\n data: {\n state: this.state,\n },\n });\n }\n };\n\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.on(signal, () => {\n if (this.status != SyncStatus.RUNNING) return;\n\n this.log(chalkTemplate` Stopping... {gray (press Ctrl+C again to force)}`);\n void this.stop();\n\n // When ggt is run via npx, and the user presses Ctrl+C, npx sends SIGINT twice in quick succession. In order to prevent the second\n // SIGINT from triggering the force exit listener, we wait a bit before registering it. This is a bit of a hack, but it works.\n setTimeout(() => {\n process.once(signal, () => {\n this.log(\" Exiting immediately. Note that files may not have finished syncing.\");\n process.exit(1);\n });\n }, 100).unref();\n });\n }\n\n const unsubscribe = this.client.subscribeUnwrap(\n {\n query: REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION,\n variables: () => ({ localFilesVersion: String(this.state.filesVersion) }),\n },\n {\n error: (error) => void this.stop(error),\n next: ({ remoteFileSyncEvents }) => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Received file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n changed: _.map(remoteFileSyncEvents.changed, \"path\"),\n deleted: _.map(remoteFileSyncEvents.deleted, \"path\"),\n },\n });\n\n const remoteFilesVersion = remoteFileSyncEvents.remoteFilesVersion;\n\n // we always ignore .gadget/ files so that we don't publish them (they're managed by gadget), but we still want to receive them\n const filter = (event: { path: string }) => _.startsWith(event.path, \".gadget/\") || !this.ignorer.ignores(event.path);\n const changed = _.filter(remoteFileSyncEvents.changed, filter);\n const deleted = _.filter(remoteFileSyncEvents.deleted, filter);\n\n this._enqueue(async () => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Processing received file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n changed: _.map(remoteFileSyncEvents.changed, \"path\"),\n deleted: _.map(remoteFileSyncEvents.deleted, \"path\"),\n },\n });\n\n if (!changed.length && !deleted.length) {\n if (BigInt(remoteFilesVersion) > this.state.filesVersion) {\n // we still need to update filesVersion, otherwise our expectedFilesVersion will be behind the next time we publish\n this.state.filesVersion = remoteFilesVersion;\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Received empty file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n },\n });\n }\n return;\n }\n\n this.log(chalkTemplate`Received {gray ${format(new Date(), \"pp\")}}`);\n this.logPaths(\"←\", _.map(changed, \"path\"), _.map(deleted, \"path\"));\n\n // we need to processed deleted files first as we may delete an empty directory after a file has been put\n // into it. if processed out of order the new file will be deleted as well\n await pMap(deleted, async (file) => {\n this.recentRemoteChanges.add(file.path);\n await this.softDelete(file.path);\n });\n\n await pMap(changed, async (file) => {\n this.recentRemoteChanges.add(file.path);\n\n const absolutePath = this.absolute(file.path);\n if (_.endsWith(file.path, \"/\")) {\n await fs.ensureDir(absolutePath, { mode: 0o755 });\n return;\n }\n\n // we need to add all parent directories to recentRemoteChanges so that we don't re-publish them\n for (const dir of _.split(path.dirname(file.path), \"/\")) {\n this.recentRemoteChanges.add(dir + \"/\");\n }\n\n await fs.ensureDir(path.dirname(absolutePath), { mode: 0o755 });\n await fs.writeFile(absolutePath, Buffer.from(file.content, file.encoding), { mode: file.mode });\n\n if (absolutePath == this.absolute(\"yarn.lock\")) {\n await execa(\"yarn\", [\"install\"], { cwd: this.dir }).catch((error) => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Yarn install failed\",\n level: \"error\",\n data: {\n state: this.state,\n error,\n },\n });\n });\n }\n\n if (absolutePath == this.ignorer.filepath) {\n this.ignorer.reload();\n }\n });\n\n this.state.filesVersion = remoteFilesVersion;\n\n // always remove the root directory from recentRemoteChanges\n this.recentRemoteChanges.delete(\"./\");\n\n // remove any files in recentRemoteChanges that are ignored (e.g. .gadget/ files)\n for (const filepath of this.recentRemoteChanges) {\n if (this.ignorer.ignores(filepath)) {\n this.recentRemoteChanges.delete(filepath);\n }\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Processed received file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: remoteFileSyncEvents.remoteFilesVersion,\n changed: _.map(remoteFileSyncEvents.changed, \"path\"),\n deleted: _.map(remoteFileSyncEvents.deleted, \"path\"),\n recentRemoteChanges: Array.from(this.recentRemoteChanges.keys()),\n },\n });\n });\n },\n },\n );\n\n const localFilesBuffer = new Map<\n string,\n | { mode: number; isDirectory: boolean }\n | { isDeleted: true; isDirectory: boolean }\n | { mode: number; oldPath: string; newPath: string; isDirectory: boolean }\n >();\n\n this.publish = _.debounce(() => {\n const localFiles = new Map(localFilesBuffer.entries());\n localFilesBuffer.clear();\n\n this._enqueue(async () => {\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Publishing file sync events\",\n data: {\n state: this.state,\n localFiles: Array.from(localFiles.keys()),\n },\n });\n\n const changed: FileSyncChangedEventInput[] = [];\n const deleted: FileSyncDeletedEventInput[] = [];\n\n await pMap(localFiles, async ([normalizedPath, file]) => {\n if (\"isDeleted\" in file) {\n deleted.push({ path: normalizedPath });\n return;\n }\n\n try {\n changed.push({\n path: normalizedPath,\n oldPath: \"oldPath\" in file ? file.oldPath : undefined,\n mode: file.mode,\n content: file.isDirectory ? \"\" : await fs.readFile(this.absolute(normalizedPath), FileSyncEncoding.Base64),\n encoding: FileSyncEncoding.Base64,\n });\n } catch (error) {\n // A file could have been changed and then deleted before we process the change event, so the readFile\n // above will raise an ENOENT. This is normal operation, so just ignore this event.\n ignoreEnoent(error);\n }\n });\n\n if (!changed.length && !deleted.length) {\n return;\n }\n\n const { publishFileSyncEvents } = await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: { input: { expectedRemoteFilesVersion: String(this.state.filesVersion), changed, deleted } },\n });\n\n if (BigInt(publishFileSyncEvents.remoteFilesVersion) > this.state.filesVersion) {\n this.state.filesVersion = publishFileSyncEvents.remoteFilesVersion;\n }\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Published file sync events\",\n data: {\n state: this.state,\n remoteFilesVersion: publishFileSyncEvents.remoteFilesVersion,\n changed: _.map(changed, \"path\"),\n deleted: _.map(deleted, \"path\"),\n },\n });\n\n this.log(chalkTemplate`Sent {gray ${format(new Date(), \"pp\")}}`);\n this.logPaths(\"→\", _.map(changed, \"path\"), _.map(deleted, \"path\"));\n });\n }, this.flags[\"file-push-delay\"]);\n\n this.watcher = new FSWatcher(this.dir, {\n // paths that we never want to publish\n ignore: /(\\.gadget|\\.git|node_modules)/,\n // don't emit an event for every watched file on boot\n ignoreInitial: true,\n renameDetection: true,\n recursive: true,\n debounce: this.flags[\"file-watch-debounce\"],\n pollingInterval: this.flags[\"file-watch-poll-interval\"],\n pollingTimeout: this.flags[\"file-watch-poll-timeout\"],\n renameTimeout: this.flags[\"file-watch-rename-timeout\"],\n });\n\n this.watcher.once(\"error\", (error) => void this.stop(error));\n\n this.watcher.on(\"all\", (event: string, absolutePath: string, renamedPath: string) => {\n const filepath = event === \"rename\" || event === \"renameDir\" ? renamedPath : absolutePath;\n const isDirectory = event === \"renameDir\" || event === \"addDir\" || event === \"unlinkDir\";\n const normalizedPath = this.normalize(filepath, isDirectory);\n\n if (filepath == this.ignorer.filepath) {\n this.ignorer.reload();\n } else if (this.ignorer.ignores(filepath)) {\n this.debug(\"skipping event caused by ignored file %s\", normalizedPath);\n return;\n }\n\n let stats: Stats | undefined;\n try {\n stats = fs.statSync(filepath);\n } catch (error) {\n ignoreEnoent(error);\n }\n\n // we only update the mtime if the file is not ignored, because if we restart and the mtime is set to an ignored\n // file, then it could be greater than the mtime of all non ignored files and we'll think that local files have\n // changed when only an ignored one has\n if (stats && stats.mtime.getTime() > this.state.mtime) {\n this.state.mtime = stats.mtime.getTime();\n }\n\n if (this.recentRemoteChanges.delete(normalizedPath)) {\n this.debug(\"skipping event caused by recent write %s\", normalizedPath);\n return;\n }\n\n this.debug(\"%s %s\", event, normalizedPath);\n\n switch (event) {\n case \"add\":\n case \"change\":\n assert(stats, \"missing stats on add/change event\");\n localFilesBuffer.set(normalizedPath, { mode: stats.mode, isDirectory: false });\n break;\n case \"addDir\":\n assert(stats, \"missing stats on addDir event\");\n localFilesBuffer.set(normalizedPath, { mode: stats.mode, isDirectory: true });\n break;\n case \"unlinkDir\":\n case \"unlink\":\n localFilesBuffer.set(normalizedPath, { isDeleted: true, isDirectory: event === \"unlinkDir\" });\n break;\n case \"rename\":\n case \"renameDir\":\n assert(stats, \"missing stats on rename/renameDir event\");\n localFilesBuffer.set(normalizedPath, {\n oldPath: this.normalize(absolutePath, isDirectory),\n newPath: normalizedPath,\n isDirectory: event === \"renameDir\",\n mode: stats.mode,\n });\n break;\n }\n\n this.publish();\n });\n\n this.status = SyncStatus.RUNNING;\n\n // app should be defined at this point\n assert(context.app);\n\n this.log();\n this.log(\n dedent(chalkTemplate`\n {bold ggt v${this.config.version}}\n\n App ${context.app.slug}\n Editor https://${context.app.slug}.gadget.app/edit\n Playground https://${context.app.slug}.gadget.app/api/graphql/playground\n Docs https://docs.gadget.dev/api/${context.app.slug}\n\n {underline Endpoints} ${\n context.app.hasSplitEnvironments\n ? `\n - https://${context.app.primaryDomain}\n - https://${context.app.slug}--development.gadget.app`\n : `\n - https://${context.app.primaryDomain}`\n }\n\n Watching for file changes... {gray Press Ctrl+C to stop}\n `),\n );\n this.log();\n\n await stopped;\n\n if (error) {\n this.notify({ subtitle: \"Uh oh!\", message: \"An error occurred while syncing files\" });\n throw error as Error;\n } else {\n this.log(\"Goodbye!\");\n }\n }\n\n /**\n * Enqueues a function that handles file-sync events onto the {@linkcode queue}.\n *\n * @param fn The function to enqueue.\n */\n private _enqueue(fn: () => Promise<unknown>): void {\n void this.queue.add(fn).catch(this.stop);\n }\n}\n\n/**\n * Holds information about the state of the local filesystem. It's persisted to `.gadget/sync.json`.\n */\nexport class SyncState {\n private _inner: {\n app: string;\n filesVersion: string;\n mtime: number;\n };\n\n /**\n * Saves the current state of the filesystem to `.gadget/sync.json`.\n */\n #save = _.debounce(() => {\n fs.outputJSONSync(path.join(this._rootDir, \".gadget/sync.json\"), this._inner, { spaces: 2 });\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Saved sync state\",\n data: { state: this._inner },\n });\n }, 100);\n\n private constructor(\n private _rootDir: string,\n inner: { app: string; filesVersion: string; mtime: number },\n ) {\n this._inner = inner;\n }\n\n /**\n * The app this filesystem is synced to.\n */\n get app(): string {\n return this._inner.app;\n }\n\n /**\n * The last filesVersion that was successfully written to the filesystem. This is used to determine if the remote\n * filesystem is ahead of the local one.\n */\n get filesVersion(): bigint {\n return BigInt(this._inner.filesVersion);\n }\n\n set filesVersion(value: bigint | string) {\n this._inner.filesVersion = String(value);\n this.#save();\n }\n\n /**\n * The largest mtime that was seen on the local filesystem before `ggt sync` stopped. This is used to determine if\n * the local filesystem has changed since the last sync.\n *\n * Note: This does not include the mtime of files that are ignored.\n */\n // eslint-disable-next-line @typescript-eslint/member-ordering\n get mtime(): number {\n return this._inner.mtime;\n }\n\n set mtime(value: number) {\n this._inner.mtime = value;\n this.#save();\n }\n\n /**\n * Creates a new SyncFile instance and saves it to the filesystem.\n *\n * @param rootDir The root directory of the app.\n * @param app The app slug.\n * @returns A new SyncFile instance.\n */\n static create(rootDir: string, opts: { app: string; filesVersion?: string; mtime?: number }): SyncState {\n const state = new SyncState(rootDir, { filesVersion: \"0\", mtime: 0, ...opts });\n state.#save();\n state.flush();\n return state;\n }\n\n /**\n * Loads a SyncFile instance from the filesystem.\n *\n * @param rootDir The root directory of the app.\n * @returns The SyncFile instance.\n */\n static load(rootDir: string): SyncState {\n const state = fs.readJsonSync(path.join(rootDir, \".gadget/sync.json\"));\n\n context.addBreadcrumb({\n category: \"sync\",\n message: \"Loaded sync state\",\n data: { state },\n });\n\n assert(_.isString(state.app), \"missing or invalid app\");\n assert(_.isString(state.filesVersion), \"missing or invalid filesVersion\");\n assert(_.isNumber(state.mtime), \"missing or invalid mtime\");\n\n return new SyncState(rootDir, {\n app: state.app,\n filesVersion: state.filesVersion,\n mtime: state.mtime,\n });\n }\n\n /**\n * Flushes any pending writes to the filesystem.\n */\n flush(): void {\n this.#save.flush();\n }\n\n /**\n * @returns The JSON representation of this instance.\n */\n toJSON() {\n return this._inner;\n }\n}\n\nexport enum SyncStatus {\n STARTING,\n RUNNING,\n STOPPING,\n STOPPED,\n}\n\nexport enum Action {\n CANCEL = \"Cancel (Ctrl+C)\",\n MERGE = \"Merge local files with remote ones\",\n RESET = \"Reset local files to remote ones\",\n}\n\nexport const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = dedent(/* GraphQL */ `\n subscription RemoteFileSyncEvents($localFilesVersion: String!) {\n remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n deleted {\n path\n }\n }\n }\n`) as Query<RemoteFileSyncEventsSubscription, RemoteFileSyncEventsSubscriptionVariables>;\n\nexport const REMOTE_FILES_VERSION_QUERY = dedent(/* GraphQL */ `\n query RemoteFilesVersion {\n remoteFilesVersion\n }\n`) as Query<RemoteFilesVersionQuery, RemoteFilesVersionQueryVariables>;\n\nexport const PUBLISH_FILE_SYNC_EVENTS_MUTATION = dedent(/* GraphQL */ `\n mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {\n publishFileSyncEvents(input: $input) {\n remoteFilesVersion\n }\n }\n`) as Query<PublishFileSyncEventsMutation, PublishFileSyncEventsMutationVariables>;\n"],"names":["Args","Flags","assert","chalkTemplate","format","execa","fs","inquirer","_","normalizePath","pMap","PQueue","path","pluralize","dedent","FSWatcher","which","FileSyncEncoding","BaseCommand","Client","context","InvalidSyncAppFlagError","InvalidSyncFileError","YarnNotFoundError","app","FSIgnorer","ignoreEnoent","isEmptyDir","walkDir","PromiseSignal","Sync","relative","to","dir","absolute","pathSegments","resolve","normalize","filepath","isDirectory","isAbsolute","softDelete","normalizedPath","move","overwrite","error","logPaths","prefix","changed","deleted","limit","lines","sortBy","map","line","slice","indexOf","logged","log","debugEnabled","length","init","config","windows","startsWith","args","directory","join","home","getApp","flags","state","selected","prompt","type","name","message","choices","getAvailableApps","then","apps","SyncState","create","load","force","setApp","client","ignorer","sync","nothrow","ensureDir","remoteFilesVersion","queryUnwrap","query","REMOTE_FILES_VERSION_QUERY","hasRemoteChanges","BigInt","filesVersion","getChangedFiles","files","Map","absolutePath","stats","stat","mtime","getTime","set","delete","changedFiles","hasLocalChanges","size","Array","from","keys","addBreadcrumb","category","data","action","Action","CANCEL","MERGE","RESET","PUBLISH_FILE_SYNC_EVENTS_MUTATION","variables","input","expectedRemoteFilesVersion","mode","content","readFile","encoding","Base64","process","exit","run","stopped","stop","e","status","SyncStatus","RUNNING","STOPPING","level","undefined","unsubscribe","watcher","removeAllListeners","publish","flush","queue","onIdle","Promise","allSettled","close","dispose","STOPPED","signal","on","setTimeout","once","unref","subscribeUnwrap","REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION","localFilesVersion","String","next","remoteFileSyncEvents","filter","event","ignores","_enqueue","Date","file","recentRemoteChanges","add","endsWith","split","dirname","writeFile","Buffer","cwd","catch","reload","localFilesBuffer","debounce","localFiles","entries","clear","push","oldPath","publishFileSyncEvents","ignore","ignoreInitial","renameDetection","recursive","pollingInterval","pollingTimeout","renameTimeout","renamedPath","debug","statSync","isDeleted","newPath","version","slug","hasSplitEnvironments","primaryDomain","notify","subtitle","fn","requireUser","STARTING","Set","concurrency","priority","summary","usage","description","string","default","boolean","integer","helpGroup","helpValue","hidden","examples","_inner","value","save","rootDir","opts","readJsonSync","isString","isNumber","toJSON","_rootDir","inner","outputJSONSync","spaces"],"mappings":"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"}
@@ -34,7 +34,7 @@ var ConnectionStatus;
34
34
  category: "client",
35
35
  message: "Re-sending GraphQL query",
36
36
  data: {
37
- type: _.split(subscribePayload.query, /\s+/g, 1)[0],
37
+ type: _.split(subscribePayload.query, " ", 1)[0],
38
38
  query: subscribePayload.query
39
39
  }
40
40
  });
@@ -47,7 +47,7 @@ var ConnectionStatus;
47
47
  category: "client",
48
48
  message: "Sending GraphQL query",
49
49
  data: {
50
- type: _.split(subscribePayload.query, /\s+/g, 1)[0],
50
+ type: _.split(subscribePayload.query, " ", 1)[0],
51
51
  query: subscribePayload.query
52
52
  }
53
53
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/client.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { GraphQLError } from \"graphql\";\nimport type { ExecutionResult, SubscribePayload } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport type { ClientRequestArgs } from \"http\";\nimport _ from \"lodash\";\nimport type { JsonObject, SetOptional } from \"type-fest\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport WebSocket from \"ws\";\nimport { context } from \"./context.js\";\nimport { ClientError } from \"./errors.js\";\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\n\n/**\n * Client is a GraphQL client connected to a Gadget application's /edit/api/graphql-ws endpoint.\n *\n * NOTE: In order to use the Client, the user must be logged in and an app must have been selected (`context.app` and\n * `context.session` must be set).\n */\nexport class Client {\n // assume the client is going to connect\n status = ConnectionStatus.CONNECTED;\n\n private _client: ReturnType<typeof createClient>;\n\n constructor() {\n assert(context.app, \"context.app must be set before instantiating the Client\");\n\n this._client = createClient({\n url: `wss://${context.app.slug}.${context.domains.app}/edit/api/graphql-ws`,\n shouldRetry: _.constant(true),\n webSocketImpl: class extends WebSocket {\n constructor(address: string | URL, protocols?: string | string[], wsOptions?: WebSocket.ClientOptions | ClientRequestArgs) {\n assert(context.session, \"context.session must be set before instantiating the Client\");\n super(address, protocols, {\n ...wsOptions,\n headers: {\n ...wsOptions?.headers,\n \"user-agent\": context.config.userAgent,\n cookie: `session=${encodeURIComponent(context.session)};`,\n },\n });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n context.addBreadcrumb({ category: \"client\", message: \"Reconnecting\" });\n break;\n case ConnectionStatus.RECONNECTING:\n context.addBreadcrumb({ category: \"client\", message: \"Retrying\" });\n break;\n default:\n context.addBreadcrumb({ category: \"client\", message: \"Connecting\" });\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n context.addBreadcrumb({ category: \"client\", message: \"Reconnected\" });\n } else {\n context.addBreadcrumb({ category: \"client\", message: \"Connected\" });\n }\n\n // let the other on connected listeners see what status we're in\n setImmediate(() => (this.status = ConnectionStatus.CONNECTED));\n },\n closed: (e) => {\n const event = e as CloseEvent;\n if (event.wasClean) {\n context.addBreadcrumb({ category: \"client\", message: \"Connection Closed\" });\n return;\n }\n\n if (this.status === ConnectionStatus.CONNECTED) {\n this.status = ConnectionStatus.DISCONNECTED;\n context.addBreadcrumb({ category: \"client\", message: \"Disconnected\" });\n }\n },\n error: (error) => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n context.addBreadcrumb({ category: \"client\", message: \"Failed to reconnect\", level: \"error\", data: { error } });\n } else {\n context.addBreadcrumb({ category: \"client\", message: \"Connection error\", level: \"error\", data: { error } });\n }\n },\n },\n });\n }\n\n subscribe<Data extends JsonObject, Variables extends JsonObject, Extensions extends JsonObject = JsonObject>(\n payload: Payload<Data, Variables>,\n sink: SetOptional<Sink<Data, Extensions>, \"complete\">,\n ): () => void {\n let subscribePayload: SubscribePayload;\n let removeConnectedListener = _.noop.bind(_);\n\n if (_.isFunction(payload.variables)) {\n // the caller wants us to re-evaluate the variables every time graphql-ws re-subscribes after reconnecting\n subscribePayload = { ...payload, variables: payload.variables() };\n removeConnectedListener = this._client.on(\"connected\", () => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n // subscribePayload.variables is supposed to be readonly (it's not) and payload.variables may have been re-assigned (it won't)\n (subscribePayload as any).variables = (payload.variables as any)();\n context.addBreadcrumb({\n category: \"client\",\n message: \"Re-sending GraphQL query\",\n data: {\n type: _.split(subscribePayload.query, /\\s+/g, 1)[0],\n query: subscribePayload.query,\n },\n });\n }\n });\n } else {\n subscribePayload = payload as SubscribePayload;\n }\n\n context.addBreadcrumb({\n category: \"client\",\n message: \"Sending GraphQL query\",\n data: {\n type: _.split(subscribePayload.query, /\\s+/g, 1)[0],\n query: subscribePayload.query,\n },\n });\n\n const unsubscribe = this._client.subscribe(subscribePayload, {\n next: (result: ExecutionResult<Data, Extensions>) => {\n sink.next(result);\n },\n error: (error) => {\n sink.error(new ClientError(subscribePayload, error as Error | GraphQLError[] | CloseEvent | ErrorEvent));\n },\n complete: () => {\n sink.complete?.();\n },\n });\n\n return () => {\n removeConnectedListener();\n unsubscribe();\n };\n }\n\n subscribeUnwrap<Data extends JsonObject, Variables extends JsonObject>(\n payload: Payload<Data, Variables>,\n sink: { next: (data: Data) => void; error: (error: ClientError) => void },\n ): () => void {\n const unsubscribe = this.subscribe(payload, {\n ...sink,\n next: (result) => {\n if (result.errors) {\n unsubscribe();\n sink.error(new ClientError(payload, result.errors));\n return;\n }\n\n if (!result.data) {\n sink.error(new ClientError(payload, \"We received a response without data\"));\n unsubscribe();\n return;\n }\n\n sink.next(result.data);\n },\n });\n\n return unsubscribe;\n }\n\n query<Data extends JsonObject, Variables extends JsonObject, Extensions extends JsonObject = JsonObject>(\n payload: Payload<Data, Variables>,\n ): Promise<ExecutionResult<Data, Extensions>> {\n return new Promise((resolve, reject) => {\n this.subscribe<Data, Variables, Extensions>(payload, { next: resolve, error: reject });\n });\n }\n\n async queryUnwrap<Data extends JsonObject, Variables extends JsonObject>(payload: Payload<Data, Variables>): Promise<Data> {\n const result = await this.query(payload);\n if (result.errors) throw new ClientError(payload, result.errors);\n if (!result.data) throw new ClientError(payload, \"We received a response without data\");\n return result.data;\n }\n\n async dispose(): Promise<void> {\n await this._client.dispose();\n }\n}\n\nexport type Query<\n Data extends JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n> = string & {\n __TData?: Data;\n __TVariables?: Variables;\n __TExtensions?: Extensions;\n};\n\nexport interface Payload<Data extends JsonObject, Variables extends JsonObject> {\n readonly query: Query<Data, Variables>;\n readonly variables?: Variables | (() => Variables) | null;\n}\n\nexport interface Sink<Data extends JsonObject, Extensions extends JsonObject> {\n next(value: ExecutionResult<Data, Extensions>): void;\n error(error: ClientError): void;\n complete(): void;\n}\n"],"names":["assert","createClient","_","WebSocket","context","ClientError","ConnectionStatus","CONNECTED","DISCONNECTED","RECONNECTING","Client","subscribe","payload","sink","subscribePayload","removeConnectedListener","noop","bind","isFunction","variables","_client","on","status","addBreadcrumb","category","message","data","type","split","query","unsubscribe","next","result","error","complete","subscribeUnwrap","errors","Promise","resolve","reject","queryUnwrap","dispose","constructor","app","url","slug","domains","shouldRetry","constant","webSocketImpl","address","protocols","wsOptions","session","headers","config","userAgent","cookie","encodeURIComponent","connecting","connected","setImmediate","closed","e","event","wasClean","level"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/services/client.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { GraphQLError } from \"graphql\";\nimport type { ExecutionResult, SubscribePayload } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport type { ClientRequestArgs } from \"http\";\nimport _ from \"lodash\";\nimport type { JsonObject, SetOptional } from \"type-fest\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport WebSocket from \"ws\";\nimport { context } from \"./context.js\";\nimport { ClientError } from \"./errors.js\";\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\n\n/**\n * Client is a GraphQL client connected to a Gadget application's /edit/api/graphql-ws endpoint.\n *\n * NOTE: In order to use the Client, the user must be logged in and an app must have been selected (`context.app` and\n * `context.session` must be set).\n */\nexport class Client {\n // assume the client is going to connect\n status = ConnectionStatus.CONNECTED;\n\n private _client: ReturnType<typeof createClient>;\n\n constructor() {\n assert(context.app, \"context.app must be set before instantiating the Client\");\n\n this._client = createClient({\n url: `wss://${context.app.slug}.${context.domains.app}/edit/api/graphql-ws`,\n shouldRetry: _.constant(true),\n webSocketImpl: class extends WebSocket {\n constructor(address: string | URL, protocols?: string | string[], wsOptions?: WebSocket.ClientOptions | ClientRequestArgs) {\n assert(context.session, \"context.session must be set before instantiating the Client\");\n super(address, protocols, {\n ...wsOptions,\n headers: {\n ...wsOptions?.headers,\n \"user-agent\": context.config.userAgent,\n cookie: `session=${encodeURIComponent(context.session)};`,\n },\n });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n context.addBreadcrumb({ category: \"client\", message: \"Reconnecting\" });\n break;\n case ConnectionStatus.RECONNECTING:\n context.addBreadcrumb({ category: \"client\", message: \"Retrying\" });\n break;\n default:\n context.addBreadcrumb({ category: \"client\", message: \"Connecting\" });\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n context.addBreadcrumb({ category: \"client\", message: \"Reconnected\" });\n } else {\n context.addBreadcrumb({ category: \"client\", message: \"Connected\" });\n }\n\n // let the other on connected listeners see what status we're in\n setImmediate(() => (this.status = ConnectionStatus.CONNECTED));\n },\n closed: (e) => {\n const event = e as CloseEvent;\n if (event.wasClean) {\n context.addBreadcrumb({ category: \"client\", message: \"Connection Closed\" });\n return;\n }\n\n if (this.status === ConnectionStatus.CONNECTED) {\n this.status = ConnectionStatus.DISCONNECTED;\n context.addBreadcrumb({ category: \"client\", message: \"Disconnected\" });\n }\n },\n error: (error) => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n context.addBreadcrumb({ category: \"client\", message: \"Failed to reconnect\", level: \"error\", data: { error } });\n } else {\n context.addBreadcrumb({ category: \"client\", message: \"Connection error\", level: \"error\", data: { error } });\n }\n },\n },\n });\n }\n\n subscribe<Data extends JsonObject, Variables extends JsonObject, Extensions extends JsonObject = JsonObject>(\n payload: Payload<Data, Variables>,\n sink: SetOptional<Sink<Data, Extensions>, \"complete\">,\n ): () => void {\n let subscribePayload: SubscribePayload;\n let removeConnectedListener = _.noop.bind(_);\n\n if (_.isFunction(payload.variables)) {\n // the caller wants us to re-evaluate the variables every time graphql-ws re-subscribes after reconnecting\n subscribePayload = { ...payload, variables: payload.variables() };\n removeConnectedListener = this._client.on(\"connected\", () => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n // subscribePayload.variables is supposed to be readonly (it's not) and payload.variables may have been re-assigned (it won't)\n (subscribePayload as any).variables = (payload.variables as any)();\n context.addBreadcrumb({\n category: \"client\",\n message: \"Re-sending GraphQL query\",\n data: {\n type: _.split(subscribePayload.query, \" \", 1)[0],\n query: subscribePayload.query,\n },\n });\n }\n });\n } else {\n subscribePayload = payload as SubscribePayload;\n }\n\n context.addBreadcrumb({\n category: \"client\",\n message: \"Sending GraphQL query\",\n data: {\n type: _.split(subscribePayload.query, \" \", 1)[0],\n query: subscribePayload.query,\n },\n });\n\n const unsubscribe = this._client.subscribe(subscribePayload, {\n next: (result: ExecutionResult<Data, Extensions>) => {\n sink.next(result);\n },\n error: (error) => {\n sink.error(new ClientError(subscribePayload, error as Error | GraphQLError[] | CloseEvent | ErrorEvent));\n },\n complete: () => {\n sink.complete?.();\n },\n });\n\n return () => {\n removeConnectedListener();\n unsubscribe();\n };\n }\n\n subscribeUnwrap<Data extends JsonObject, Variables extends JsonObject>(\n payload: Payload<Data, Variables>,\n sink: { next: (data: Data) => void; error: (error: ClientError) => void },\n ): () => void {\n const unsubscribe = this.subscribe(payload, {\n ...sink,\n next: (result) => {\n if (result.errors) {\n unsubscribe();\n sink.error(new ClientError(payload, result.errors));\n return;\n }\n\n if (!result.data) {\n sink.error(new ClientError(payload, \"We received a response without data\"));\n unsubscribe();\n return;\n }\n\n sink.next(result.data);\n },\n });\n\n return unsubscribe;\n }\n\n query<Data extends JsonObject, Variables extends JsonObject, Extensions extends JsonObject = JsonObject>(\n payload: Payload<Data, Variables>,\n ): Promise<ExecutionResult<Data, Extensions>> {\n return new Promise((resolve, reject) => {\n this.subscribe<Data, Variables, Extensions>(payload, { next: resolve, error: reject });\n });\n }\n\n async queryUnwrap<Data extends JsonObject, Variables extends JsonObject>(payload: Payload<Data, Variables>): Promise<Data> {\n const result = await this.query(payload);\n if (result.errors) throw new ClientError(payload, result.errors);\n if (!result.data) throw new ClientError(payload, \"We received a response without data\");\n return result.data;\n }\n\n async dispose(): Promise<void> {\n await this._client.dispose();\n }\n}\n\nexport type Query<\n Data extends JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n> = string & {\n __TData?: Data;\n __TVariables?: Variables;\n __TExtensions?: Extensions;\n};\n\nexport interface Payload<Data extends JsonObject, Variables extends JsonObject> {\n readonly query: Query<Data, Variables>;\n readonly variables?: Variables | (() => Variables) | null;\n}\n\nexport interface Sink<Data extends JsonObject, Extensions extends JsonObject> {\n next(value: ExecutionResult<Data, Extensions>): void;\n error(error: ClientError): void;\n complete(): void;\n}\n"],"names":["assert","createClient","_","WebSocket","context","ClientError","ConnectionStatus","CONNECTED","DISCONNECTED","RECONNECTING","Client","subscribe","payload","sink","subscribePayload","removeConnectedListener","noop","bind","isFunction","variables","_client","on","status","addBreadcrumb","category","message","data","type","split","query","unsubscribe","next","result","error","complete","subscribeUnwrap","errors","Promise","resolve","reject","queryUnwrap","dispose","constructor","app","url","slug","domains","shouldRetry","constant","webSocketImpl","address","protocols","wsOptions","session","headers","config","userAgent","cookie","encodeURIComponent","connecting","connected","setImmediate","closed","e","event","wasClean","level"],"mappings":";AAAA,OAAOA,YAAY,SAAS;AAG5B,SAASC,YAAY,QAAQ,aAAa;AAE1C,OAAOC,OAAO,SAAS;AAGvB,OAAOC,eAAe,KAAK;AAC3B,SAASC,OAAO,QAAQ,eAAe;AACvC,SAASC,WAAW,QAAQ,cAAc;IAE1C;UAAKC,gBAAgB;IAAhBA,iBAAAA,iBACHC,eAAAA,KAAAA;IADGD,iBAAAA,iBAEHE,kBAAAA,KAAAA;IAFGF,iBAAAA,iBAGHG,kBAAAA,KAAAA;GAHGH,qBAAAA;AAML;;;;;CAKC,GACD,OAAO,MAAMI;IAyEXC,UACEC,OAAiC,EACjCC,IAAqD,EACzC;QACZ,IAAIC;QACJ,IAAIC,0BAA0Bb,EAAEc,IAAI,CAACC,IAAI,CAACf;QAE1C,IAAIA,EAAEgB,UAAU,CAACN,QAAQO,SAAS,GAAG;YACnC,0GAA0G;YAC1GL,mBAAmB;gBAAE,GAAGF,OAAO;gBAAEO,WAAWP,QAAQO,SAAS;YAAG;YAChEJ,0BAA0B,IAAI,CAACK,OAAO,CAACC,EAAE,CAAC,aAAa;gBACrD,IAAI,IAAI,CAACC,MAAM,IAAIhB,iBAAiBG,YAAY,EAAE;oBAChD,8HAA8H;oBAC7HK,iBAAyBK,SAAS,GAAG,AAACP,QAAQO,SAAS;oBACxDf,QAAQmB,aAAa,CAAC;wBACpBC,UAAU;wBACVC,SAAS;wBACTC,MAAM;4BACJC,MAAMzB,EAAE0B,KAAK,CAACd,iBAAiBe,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE;4BAChDA,OAAOf,iBAAiBe,KAAK;wBAC/B;oBACF;gBACF;YACF;QACF,OAAO;YACLf,mBAAmBF;QACrB;QAEAR,QAAQmB,aAAa,CAAC;YACpBC,UAAU;YACVC,SAAS;YACTC,MAAM;gBACJC,MAAMzB,EAAE0B,KAAK,CAACd,iBAAiBe,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE;gBAChDA,OAAOf,iBAAiBe,KAAK;YAC/B;QACF;QAEA,MAAMC,cAAc,IAAI,CAACV,OAAO,CAACT,SAAS,CAACG,kBAAkB;YAC3DiB,MAAM,CAACC;gBACLnB,KAAKkB,IAAI,CAACC;YACZ;YACAC,OAAO,CAACA;gBACNpB,KAAKoB,KAAK,CAAC,IAAI5B,YAAYS,kBAAkBmB;YAC/C;YACAC,UAAU;gBACRrB,KAAKqB,QAAQ;YACf;QACF;QAEA,OAAO;YACLnB;YACAe;QACF;IACF;IAEAK,gBACEvB,OAAiC,EACjCC,IAAyE,EAC7D;QACZ,MAAMiB,cAAc,IAAI,CAACnB,SAAS,CAACC,SAAS;YAC1C,GAAGC,IAAI;YACPkB,MAAM,CAACC;gBACL,IAAIA,OAAOI,MAAM,EAAE;oBACjBN;oBACAjB,KAAKoB,KAAK,CAAC,IAAI5B,YAAYO,SAASoB,OAAOI,MAAM;oBACjD;gBACF;gBAEA,IAAI,CAACJ,OAAON,IAAI,EAAE;oBAChBb,KAAKoB,KAAK,CAAC,IAAI5B,YAAYO,SAAS;oBACpCkB;oBACA;gBACF;gBAEAjB,KAAKkB,IAAI,CAACC,OAAON,IAAI;YACvB;QACF;QAEA,OAAOI;IACT;IAEAD,MACEjB,OAAiC,EACW;QAC5C,OAAO,IAAIyB,QAAQ,CAACC,SAASC;YAC3B,IAAI,CAAC5B,SAAS,CAA8BC,SAAS;gBAAEmB,MAAMO;gBAASL,OAAOM;YAAO;QACtF;IACF;IAEA,MAAMC,YAAmE5B,OAAiC,EAAiB;QACzH,MAAMoB,SAAS,MAAM,IAAI,CAACH,KAAK,CAACjB;QAChC,IAAIoB,OAAOI,MAAM,EAAE,MAAM,IAAI/B,YAAYO,SAASoB,OAAOI,MAAM;QAC/D,IAAI,CAACJ,OAAON,IAAI,EAAE,MAAM,IAAIrB,YAAYO,SAAS;QACjD,OAAOoB,OAAON,IAAI;IACpB;IAEA,MAAMe,UAAyB;QAC7B,MAAM,IAAI,CAACrB,OAAO,CAACqB,OAAO;IAC5B;IArKAC,aAAc;QALd,wCAAwC;QACxCpB,uBAAAA,UAAShB,iBAAiBC,SAAS;QAEnC,uBAAQa,WAAR,KAAA;QAGEpB,OAAOI,QAAQuC,GAAG,EAAE;QAEpB,IAAI,CAACvB,OAAO,GAAGnB,aAAa;YAC1B2C,KAAK,CAAC,MAAM,EAAExC,QAAQuC,GAAG,CAACE,IAAI,CAAC,CAAC,EAAEzC,QAAQ0C,OAAO,CAACH,GAAG,CAAC,oBAAoB,CAAC;YAC3EI,aAAa7C,EAAE8C,QAAQ,CAAC;YACxBC,eAAe,cAAc9C;gBAC3BuC,YAAYQ,OAAqB,EAAEC,SAA6B,EAAEC,SAAuD,CAAE;oBACzHpD,OAAOI,QAAQiD,OAAO,EAAE;oBACxB,KAAK,CAACH,SAASC,WAAW;wBACxB,GAAGC,SAAS;wBACZE,SAAS;4BACP,GAAGF,WAAWE,OAAO;4BACrB,cAAclD,QAAQmD,MAAM,CAACC,SAAS;4BACtCC,QAAQ,CAAC,QAAQ,EAAEC,mBAAmBtD,QAAQiD,OAAO,EAAE,CAAC,CAAC;wBAC3D;oBACF;gBACF;YACF;YACAhC,IAAI;gBACFsC,YAAY;oBACV,OAAQ,IAAI,CAACrC,MAAM;wBACjB,KAAKhB,iBAAiBE,YAAY;4BAChC,IAAI,CAACc,MAAM,GAAGhB,iBAAiBG,YAAY;4BAC3CL,QAAQmB,aAAa,CAAC;gCAAEC,UAAU;gCAAUC,SAAS;4BAAe;4BACpE;wBACF,KAAKnB,iBAAiBG,YAAY;4BAChCL,QAAQmB,aAAa,CAAC;gCAAEC,UAAU;gCAAUC,SAAS;4BAAW;4BAChE;wBACF;4BACErB,QAAQmB,aAAa,CAAC;gCAAEC,UAAU;gCAAUC,SAAS;4BAAa;4BAClE;oBACJ;gBACF;gBACAmC,WAAW;oBACT,IAAI,IAAI,CAACtC,MAAM,KAAKhB,iBAAiBG,YAAY,EAAE;wBACjDL,QAAQmB,aAAa,CAAC;4BAAEC,UAAU;4BAAUC,SAAS;wBAAc;oBACrE,OAAO;wBACLrB,QAAQmB,aAAa,CAAC;4BAAEC,UAAU;4BAAUC,SAAS;wBAAY;oBACnE;oBAEA,gEAAgE;oBAChEoC,aAAa,IAAO,IAAI,CAACvC,MAAM,GAAGhB,iBAAiBC,SAAS;gBAC9D;gBACAuD,QAAQ,CAACC;oBACP,MAAMC,QAAQD;oBACd,IAAIC,MAAMC,QAAQ,EAAE;wBAClB7D,QAAQmB,aAAa,CAAC;4BAAEC,UAAU;4BAAUC,SAAS;wBAAoB;wBACzE;oBACF;oBAEA,IAAI,IAAI,CAACH,MAAM,KAAKhB,iBAAiBC,SAAS,EAAE;wBAC9C,IAAI,CAACe,MAAM,GAAGhB,iBAAiBE,YAAY;wBAC3CJ,QAAQmB,aAAa,CAAC;4BAAEC,UAAU;4BAAUC,SAAS;wBAAe;oBACtE;gBACF;gBACAQ,OAAO,CAACA;oBACN,IAAI,IAAI,CAACX,MAAM,IAAIhB,iBAAiBG,YAAY,EAAE;wBAChDL,QAAQmB,aAAa,CAAC;4BAAEC,UAAU;4BAAUC,SAAS;4BAAuByC,OAAO;4BAASxC,MAAM;gCAAEO;4BAAM;wBAAE;oBAC9G,OAAO;wBACL7B,QAAQmB,aAAa,CAAC;4BAAEC,UAAU;4BAAUC,SAAS;4BAAoByC,OAAO;4BAASxC,MAAM;gCAAEO;4BAAM;wBAAE;oBAC3G;gBACF;YACF;QACF;IACF;AAqGF"}
@@ -70,8 +70,16 @@ export class Context {
70
70
  setUser(null);
71
71
  }
72
72
  addBreadcrumb(breadcrumb) {
73
- addBreadcrumb(breadcrumb);
74
73
  debug("breadcrumb %O", breadcrumb);
74
+ // clone any objects in the data so that we get a snapshot of the object at the time the breadcrumb was added
75
+ if (breadcrumb.data) {
76
+ for (const [key, value] of Object.entries(breadcrumb.data)){
77
+ if (_.isObjectLike(value)) {
78
+ breadcrumb.data[key] = _.cloneDeep(value);
79
+ }
80
+ }
81
+ }
82
+ addBreadcrumb(breadcrumb);
75
83
  }
76
84
  constructor(){
77
85
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/context.ts"],"sourcesContent":["import type { Config } from \"@oclif/core\";\nimport { addBreadcrumb, setUser, type Breadcrumb as SentryBreadcrumb } from \"@sentry/node\";\nimport assert from \"assert\";\nimport Debug from \"debug\";\nimport fs from \"fs-extra\";\nimport { HTTPError, got } from \"got\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { ignoreEnoent } from \"./fs-utils.js\";\n\nconst debug = Debug(\"ggt:context\");\n\nexport class Context {\n /**\n * A reference to oclif's {@linkcode Config}.\n *\n * By default, oclif's {@linkcode Config} is only available as an instance property on a Command, but we want to be\n * able to access it from anywhere. To do this, we created this global variable that references the Config. It is set\n * by the init function in the BaseCommand.\n */\n config!: Config;\n\n /**\n * Captures the name and nature of the environment\n */\n env = {\n get value(): string {\n return process.env[\"GGT_ENV\"] ?? \"production\";\n },\n get productionLike(): boolean {\n return _.startsWith(this.value, \"production\");\n },\n get developmentLike(): boolean {\n return _.startsWith(this.value, \"development\");\n },\n get testLike(): boolean {\n return _.startsWith(this.value, \"test\");\n },\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n },\n };\n\n /**\n * Domains for various Gadget services.\n */\n domains = {\n /**\n * The domain for the Gadget applications. This is where the user applications are hosted.\n */\n app: process.env[\"GGT_GADGET_APP_DOMAIN\"] ?? (this.env.productionLike ? \"gadget.app\" : \"ggt.pub\"),\n\n /**\n * The domain for the Gadget services. This is where the Gadget's API is hosted.\n */\n services: process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] ?? (this.env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\"),\n };\n\n /**\n * The current Gadget application the CLI is operating on.\n */\n app?: App;\n\n private _session?: string;\n\n private _user?: User;\n\n private _availableApps: App[] = [];\n\n private _request = got.extend({\n hooks: {\n beforeRequest: [\n (options) => {\n options.headers[\"user-agent\"] = this.config.userAgent;\n if (options.url instanceof URL && options.url.host === this.domains.services && this.session) {\n options.headers[\"cookie\"] = `session=${encodeURIComponent(this.session)};`;\n }\n },\n ],\n },\n });\n\n get session(): string | undefined {\n if (this._session) return this._session;\n\n try {\n this._session = fs.readFileSync(path.join(this.config.configDir, \"session.txt\"), \"utf-8\");\n return this._session;\n } catch (error) {\n ignoreEnoent(error);\n return undefined;\n }\n }\n\n set session(value: string | undefined) {\n this.clear();\n this._session = value;\n if (this._session) {\n fs.outputFileSync(path.join(this.config.configDir, \"session.txt\"), this._session);\n } else {\n fs.removeSync(path.join(this.config.configDir, \"session.txt\"));\n }\n }\n\n /**\n * @returns The current user, or undefined if the user is not logged in.\n */\n async getUser(): Promise<User | undefined> {\n if (!this.session) return undefined;\n if (this._user) return this._user;\n\n try {\n this._user = await this._request(`https://${this.domains.services}/auth/api/current-user`).json<User>();\n setUser(this._user);\n return this._user;\n } catch (error) {\n if (error instanceof HTTPError && error.response.statusCode === 401) {\n this.session = undefined;\n return undefined;\n }\n throw error;\n }\n }\n\n /**\n * @returns The list of Gadget applications the current user has access to.\n */\n async getAvailableApps(): Promise<App[]> {\n if (!this.session) return [];\n if (this._availableApps.length > 0) return this._availableApps;\n\n this._availableApps = await this._request(`https://${this.domains.services}/auth/api/apps`).json<App[]>();\n return this._availableApps;\n }\n\n async setApp(appOrSlug?: App | string): Promise<void> {\n if (_.isString(appOrSlug)) {\n const app = await this.getAvailableApps().then((apps) => _.find(apps, (app) => app.slug == appOrSlug));\n assert(app, `attempted to set app to \"${appOrSlug}\" but no app with that name or slug was found`);\n this.app = app;\n } else {\n this.app = appOrSlug;\n }\n }\n\n clear(): void {\n this._session = undefined;\n this._user = undefined;\n this.app = undefined;\n this._availableApps = [];\n setUser(null);\n }\n\n addBreadcrumb(breadcrumb: Breadcrumb) {\n addBreadcrumb(breadcrumb);\n debug(\"breadcrumb %O\", breadcrumb);\n }\n}\n\nexport const context = new Context();\n\nexport interface Breadcrumb extends SentryBreadcrumb {\n category: \"command\" | \"client\" | \"sync\";\n message: Capitalize<string>;\n}\n\nexport interface User {\n id: string | number;\n email: string;\n name?: string;\n}\n\nexport interface App {\n id: string | number;\n slug: string;\n primaryDomain: string;\n hasSplitEnvironments: boolean;\n}\n"],"names":["addBreadcrumb","setUser","assert","Debug","fs","HTTPError","got","_","path","ignoreEnoent","debug","Context","session","_session","readFileSync","join","config","configDir","error","undefined","value","clear","outputFileSync","removeSync","getUser","_user","_request","domains","services","json","response","statusCode","getAvailableApps","_availableApps","length","setApp","appOrSlug","isString","app","then","apps","find","slug","breadcrumb","env","process","productionLike","startsWith","developmentLike","testLike","developmentOrTestLike","extend","hooks","beforeRequest","options","headers","userAgent","url","URL","host","encodeURIComponent","context"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/services/context.ts"],"sourcesContent":["import type { Config } from \"@oclif/core\";\nimport { addBreadcrumb, setUser, type Breadcrumb as SentryBreadcrumb } from \"@sentry/node\";\nimport assert from \"assert\";\nimport Debug from \"debug\";\nimport fs from \"fs-extra\";\nimport { HTTPError, got } from \"got\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { ignoreEnoent } from \"./fs-utils.js\";\n\nconst debug = Debug(\"ggt:context\");\n\nexport class Context {\n /**\n * A reference to oclif's {@linkcode Config}.\n *\n * By default, oclif's {@linkcode Config} is only available as an instance property on a Command, but we want to be\n * able to access it from anywhere. To do this, we created this global variable that references the Config. It is set\n * by the init function in the BaseCommand.\n */\n config!: Config;\n\n /**\n * Captures the name and nature of the environment\n */\n env = {\n get value(): string {\n return process.env[\"GGT_ENV\"] ?? \"production\";\n },\n get productionLike(): boolean {\n return _.startsWith(this.value, \"production\");\n },\n get developmentLike(): boolean {\n return _.startsWith(this.value, \"development\");\n },\n get testLike(): boolean {\n return _.startsWith(this.value, \"test\");\n },\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n },\n };\n\n /**\n * Domains for various Gadget services.\n */\n domains = {\n /**\n * The domain for the Gadget applications. This is where the user applications are hosted.\n */\n app: process.env[\"GGT_GADGET_APP_DOMAIN\"] ?? (this.env.productionLike ? \"gadget.app\" : \"ggt.pub\"),\n\n /**\n * The domain for the Gadget services. This is where the Gadget's API is hosted.\n */\n services: process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] ?? (this.env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\"),\n };\n\n /**\n * The current Gadget application the CLI is operating on.\n */\n app?: App;\n\n private _session?: string;\n\n private _user?: User;\n\n private _availableApps: App[] = [];\n\n private _request = got.extend({\n hooks: {\n beforeRequest: [\n (options) => {\n options.headers[\"user-agent\"] = this.config.userAgent;\n if (options.url instanceof URL && options.url.host === this.domains.services && this.session) {\n options.headers[\"cookie\"] = `session=${encodeURIComponent(this.session)};`;\n }\n },\n ],\n },\n });\n\n get session(): string | undefined {\n if (this._session) return this._session;\n\n try {\n this._session = fs.readFileSync(path.join(this.config.configDir, \"session.txt\"), \"utf-8\");\n return this._session;\n } catch (error) {\n ignoreEnoent(error);\n return undefined;\n }\n }\n\n set session(value: string | undefined) {\n this.clear();\n this._session = value;\n if (this._session) {\n fs.outputFileSync(path.join(this.config.configDir, \"session.txt\"), this._session);\n } else {\n fs.removeSync(path.join(this.config.configDir, \"session.txt\"));\n }\n }\n\n /**\n * @returns The current user, or undefined if the user is not logged in.\n */\n async getUser(): Promise<User | undefined> {\n if (!this.session) return undefined;\n if (this._user) return this._user;\n\n try {\n this._user = await this._request(`https://${this.domains.services}/auth/api/current-user`).json<User>();\n setUser(this._user);\n return this._user;\n } catch (error) {\n if (error instanceof HTTPError && error.response.statusCode === 401) {\n this.session = undefined;\n return undefined;\n }\n throw error;\n }\n }\n\n /**\n * @returns The list of Gadget applications the current user has access to.\n */\n async getAvailableApps(): Promise<App[]> {\n if (!this.session) return [];\n if (this._availableApps.length > 0) return this._availableApps;\n\n this._availableApps = await this._request(`https://${this.domains.services}/auth/api/apps`).json<App[]>();\n return this._availableApps;\n }\n\n async setApp(appOrSlug?: App | string): Promise<void> {\n if (_.isString(appOrSlug)) {\n const app = await this.getAvailableApps().then((apps) => _.find(apps, (app) => app.slug == appOrSlug));\n assert(app, `attempted to set app to \"${appOrSlug}\" but no app with that name or slug was found`);\n this.app = app;\n } else {\n this.app = appOrSlug;\n }\n }\n\n clear(): void {\n this._session = undefined;\n this._user = undefined;\n this.app = undefined;\n this._availableApps = [];\n setUser(null);\n }\n\n addBreadcrumb(breadcrumb: Breadcrumb) {\n debug(\"breadcrumb %O\", breadcrumb);\n\n // clone any objects in the data so that we get a snapshot of the object at the time the breadcrumb was added\n if (breadcrumb.data) {\n for (const [key, value] of Object.entries(breadcrumb.data)) {\n if (_.isObjectLike(value)) {\n breadcrumb.data[key] = _.cloneDeep(value);\n }\n }\n }\n\n addBreadcrumb(breadcrumb);\n }\n}\n\nexport const context = new Context();\n\nexport interface Breadcrumb extends SentryBreadcrumb {\n category: \"command\" | \"client\" | \"sync\";\n message: Capitalize<string>;\n}\n\nexport interface User {\n id: string | number;\n email: string;\n name?: string;\n}\n\nexport interface App {\n id: string | number;\n slug: string;\n primaryDomain: string;\n hasSplitEnvironments: boolean;\n}\n"],"names":["addBreadcrumb","setUser","assert","Debug","fs","HTTPError","got","_","path","ignoreEnoent","debug","Context","session","_session","readFileSync","join","config","configDir","error","undefined","value","clear","outputFileSync","removeSync","getUser","_user","_request","domains","services","json","response","statusCode","getAvailableApps","_availableApps","length","setApp","appOrSlug","isString","app","then","apps","find","slug","breadcrumb","data","key","Object","entries","isObjectLike","cloneDeep","env","process","productionLike","startsWith","developmentLike","testLike","developmentOrTestLike","extend","hooks","beforeRequest","options","headers","userAgent","url","URL","host","encodeURIComponent","context"],"mappings":"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"}
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@gadgetinc/ggt",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@gadgetinc/ggt",
9
- "version": "0.2.2",
9
+ "version": "0.2.3",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@oclif/core": "^2.9.4",
13
13
  "@oclif/errors": "^1.3.6",
14
- "@oclif/plugin-not-found": "^2.3.31",
14
+ "@oclif/plugin-not-found": "^2.3.32",
15
15
  "@oclif/plugin-warn-if-update-available": "^2.0.44",
16
- "@sentry/node": "^7.59.2",
16
+ "@sentry/node": "^7.60.0",
17
17
  "@swc/helpers": "^0.5.1",
18
18
  "chalk": "^5.3.0",
19
19
  "chalk-template": "^1.1.0",
@@ -51,8 +51,8 @@
51
51
  "@graphql-codegen/cli": "^4.0.1",
52
52
  "@graphql-codegen/typescript": "^4.0.0",
53
53
  "@graphql-codegen/typescript-operations": "^4.0.1",
54
- "@oclif/plugin-plugins": "^3.1.6",
55
- "@oclif/test": "^2.3.30",
54
+ "@oclif/plugin-plugins": "^3.1.7",
55
+ "@oclif/test": "^2.3.31",
56
56
  "@swc/cli": "^0.1.62",
57
57
  "@swc/core": "^1.3.70",
58
58
  "@types/debug": "^4.1.8",
@@ -77,7 +77,7 @@
77
77
  "eslint-plugin-import": "^2.27.5",
78
78
  "eslint-plugin-lodash": "^7.4.0",
79
79
  "nock": "^13.3.2",
80
- "oclif": "^3.9.1",
80
+ "oclif": "^3.10.0",
81
81
  "patch-package": "^7.0.2",
82
82
  "prettier": "^3.0.0",
83
83
  "prettier-plugin-organize-imports": "^3.2.3",
@@ -4731,125 +4731,22 @@
4731
4731
  "node": ">= 4.0.0"
4732
4732
  }
4733
4733
  },
4734
- "node_modules/@oclif/linewrap": {
4735
- "version": "1.0.0",
4736
- "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz",
4737
- "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==",
4738
- "dev": true
4739
- },
4740
4734
  "node_modules/@oclif/plugin-help": {
4741
- "version": "5.1.20",
4742
- "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.1.20.tgz",
4743
- "integrity": "sha512-N8xRxE/isFcdBDI8cobixEZA5toxIK5jbxpwALNTr4s8KNAtBA3ORQrSiY0fWGkcv0sCGMwZw7rJ0Izh18JPsw==",
4735
+ "version": "5.2.14",
4736
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.2.14.tgz",
4737
+ "integrity": "sha512-7hMLc6zqxeRfG4nvHHQPpbaBj60efM3ULFkCpHZkdLms/ezIkNo40F661QuraIjMP/NN+U6VSfBCGuPkRyxVkA==",
4744
4738
  "dev": true,
4745
4739
  "dependencies": {
4746
- "@oclif/core": "^1.21.0"
4740
+ "@oclif/core": "^2.9.3"
4747
4741
  },
4748
4742
  "engines": {
4749
4743
  "node": ">=12.0.0"
4750
4744
  }
4751
4745
  },
4752
- "node_modules/@oclif/plugin-help/node_modules/@oclif/core": {
4753
- "version": "1.26.1",
4754
- "resolved": "https://registry.npmjs.org/@oclif/core/-/core-1.26.1.tgz",
4755
- "integrity": "sha512-g+OWJcM7JOVI53caTEtq0BB1nPotWctRLUyFODPgvDqXhVR7QED+Qz3LwFAMD8dt7/Ar2ZNq15U3bnpnOv453A==",
4756
- "dev": true,
4757
- "dependencies": {
4758
- "@oclif/linewrap": "^1.0.0",
4759
- "@oclif/screen": "^3.0.4",
4760
- "ansi-escapes": "^4.3.2",
4761
- "ansi-styles": "^4.3.0",
4762
- "cardinal": "^2.1.1",
4763
- "chalk": "^4.1.2",
4764
- "clean-stack": "^3.0.1",
4765
- "cli-progress": "^3.10.0",
4766
- "debug": "^4.3.4",
4767
- "ejs": "^3.1.6",
4768
- "fs-extra": "^9.1.0",
4769
- "get-package-type": "^0.1.0",
4770
- "globby": "^11.1.0",
4771
- "hyperlinker": "^1.0.0",
4772
- "indent-string": "^4.0.0",
4773
- "is-wsl": "^2.2.0",
4774
- "js-yaml": "^3.14.1",
4775
- "natural-orderby": "^2.0.3",
4776
- "object-treeify": "^1.1.33",
4777
- "password-prompt": "^1.1.2",
4778
- "semver": "^7.3.7",
4779
- "string-width": "^4.2.3",
4780
- "strip-ansi": "^6.0.1",
4781
- "supports-color": "^8.1.1",
4782
- "supports-hyperlinks": "^2.2.0",
4783
- "tslib": "^2.4.1",
4784
- "widest-line": "^3.1.0",
4785
- "wrap-ansi": "^7.0.0"
4786
- },
4787
- "engines": {
4788
- "node": ">=14.0.0"
4789
- }
4790
- },
4791
- "node_modules/@oclif/plugin-help/node_modules/chalk": {
4792
- "version": "4.1.2",
4793
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
4794
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
4795
- "dev": true,
4796
- "dependencies": {
4797
- "ansi-styles": "^4.1.0",
4798
- "supports-color": "^7.1.0"
4799
- },
4800
- "engines": {
4801
- "node": ">=10"
4802
- },
4803
- "funding": {
4804
- "url": "https://github.com/chalk/chalk?sponsor=1"
4805
- }
4806
- },
4807
- "node_modules/@oclif/plugin-help/node_modules/chalk/node_modules/supports-color": {
4808
- "version": "7.2.0",
4809
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
4810
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
4811
- "dev": true,
4812
- "dependencies": {
4813
- "has-flag": "^4.0.0"
4814
- },
4815
- "engines": {
4816
- "node": ">=8"
4817
- }
4818
- },
4819
- "node_modules/@oclif/plugin-help/node_modules/clean-stack": {
4820
- "version": "3.0.1",
4821
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz",
4822
- "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==",
4823
- "dev": true,
4824
- "dependencies": {
4825
- "escape-string-regexp": "4.0.0"
4826
- },
4827
- "engines": {
4828
- "node": ">=10"
4829
- },
4830
- "funding": {
4831
- "url": "https://github.com/sponsors/sindresorhus"
4832
- }
4833
- },
4834
- "node_modules/@oclif/plugin-help/node_modules/fs-extra": {
4835
- "version": "9.1.0",
4836
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
4837
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
4838
- "dev": true,
4839
- "dependencies": {
4840
- "at-least-node": "^1.0.0",
4841
- "graceful-fs": "^4.2.0",
4842
- "jsonfile": "^6.0.1",
4843
- "universalify": "^2.0.0"
4844
- },
4845
- "engines": {
4846
- "node": ">=10"
4847
- }
4848
- },
4849
4746
  "node_modules/@oclif/plugin-not-found": {
4850
- "version": "2.3.31",
4851
- "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-2.3.31.tgz",
4852
- "integrity": "sha512-KHBCDJbDrkFc5vuPxg4JZ3wBTrdPPHOQOWp4bLCV4cnVSUHBKnfCqnCg2aXmRb97nbzY3P13/i8Th3KQjArqmg==",
4747
+ "version": "2.3.32",
4748
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-2.3.32.tgz",
4749
+ "integrity": "sha512-tVFHfR9XRUWrcxBugHjFr7HUmbLheDX05IaFr7fMF2hcvcqDs3DBjy42WKEoXSaBVTcST6KKhoSy2UVX8pk9Fg==",
4853
4750
  "dependencies": {
4854
4751
  "@oclif/color": "^1.0.8",
4855
4752
  "@oclif/core": "^2.9.3",
@@ -4860,9 +4757,9 @@
4860
4757
  }
4861
4758
  },
4862
4759
  "node_modules/@oclif/plugin-plugins": {
4863
- "version": "3.1.6",
4864
- "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-3.1.6.tgz",
4865
- "integrity": "sha512-bri3GHqUs2d9mMoqm0/CIef+u+nJrNDzno5xpnB0cg7x3mAhXM/miuzdNz7D8opupuJeiJMv+A/WSMG2nY2IEw==",
4760
+ "version": "3.1.7",
4761
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-3.1.7.tgz",
4762
+ "integrity": "sha512-rGH3unndc5bY73b63K9IrGnXM6XeB7vOALKVHbbiia3fPIf4oG2ybjo1MBHyUsfwZYifRc/GK2RAZ8cle0GqDA==",
4866
4763
  "dev": true,
4867
4764
  "dependencies": {
4868
4765
  "@oclif/color": "^1.0.4",
@@ -5004,19 +4901,10 @@
5004
4901
  "node": ">=8"
5005
4902
  }
5006
4903
  },
5007
- "node_modules/@oclif/screen": {
5008
- "version": "3.0.4",
5009
- "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-3.0.4.tgz",
5010
- "integrity": "sha512-IMsTN1dXEXaOSre27j/ywGbBjrzx0FNd1XmuhCWCB9NTPrhWI1Ifbz+YLSEcstfQfocYsrbrIessxXb2oon4lA==",
5011
- "dev": true,
5012
- "engines": {
5013
- "node": ">=12.0.0"
5014
- }
5015
- },
5016
4904
  "node_modules/@oclif/test": {
5017
- "version": "2.3.30",
5018
- "resolved": "https://registry.npmjs.org/@oclif/test/-/test-2.3.30.tgz",
5019
- "integrity": "sha512-zuOv23wiF+H7cRGMjcKx/91qhdcNMcZnr+1TCpbyDeQBIvRs/nGWyuwfrmoF2fXs+HtNZsNFvwbjg7Ue5JfAug==",
4905
+ "version": "2.3.31",
4906
+ "resolved": "https://registry.npmjs.org/@oclif/test/-/test-2.3.31.tgz",
4907
+ "integrity": "sha512-dTWCni+Zv9aSuzyamS95+GJaIub6EAI+CT+pA1MP10RZF54mF7CKaas7t8dvNvDp1Y194hi64cqe+cNwZlR5ng==",
5020
4908
  "dev": true,
5021
4909
  "dependencies": {
5022
4910
  "@oclif/core": "^2.9.3",
@@ -5280,13 +5168,13 @@
5280
5168
  "dev": true
5281
5169
  },
5282
5170
  "node_modules/@sentry-internal/tracing": {
5283
- "version": "7.59.2",
5284
- "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.59.2.tgz",
5285
- "integrity": "sha512-02gteChV/lMobWU06VlITq+myEWk0MzhnDCm8n/DMigB47I9HkWZFAJ+CYG6Ns0rTL+3+/c2V0bPyQkZwIC+Sg==",
5171
+ "version": "7.60.0",
5172
+ "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.60.0.tgz",
5173
+ "integrity": "sha512-2qvxmR954H+K7u4o92sS2u+hntzshem9XwfHAqDvBe51arNbFVy8LfJTJ5fffgZq/6jXlozCO0/6aR5yLR5mBg==",
5286
5174
  "dependencies": {
5287
- "@sentry/core": "7.59.2",
5288
- "@sentry/types": "7.59.2",
5289
- "@sentry/utils": "7.59.2",
5175
+ "@sentry/core": "7.60.0",
5176
+ "@sentry/types": "7.60.0",
5177
+ "@sentry/utils": "7.60.0",
5290
5178
  "tslib": "^2.4.1 || ^1.9.3"
5291
5179
  },
5292
5180
  "engines": {
@@ -5294,12 +5182,12 @@
5294
5182
  }
5295
5183
  },
5296
5184
  "node_modules/@sentry/core": {
5297
- "version": "7.59.2",
5298
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.59.2.tgz",
5299
- "integrity": "sha512-GRhoPw6b6GkvOsa060aREc9yyHjgAKITgITNbzUmn0GqIeWD5SMoCBAcENRHVgUnpQWOpnkEF1/sqxvwx+rf6Q==",
5185
+ "version": "7.60.0",
5186
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.60.0.tgz",
5187
+ "integrity": "sha512-B02OlFMoqdkfDZlbQfmk7tL2vObShofk7ySd/7mp+oRdUuCvX0tyrGlwI87YJvd8YWSZOCKINs3aVYivw/b6gg==",
5300
5188
  "dependencies": {
5301
- "@sentry/types": "7.59.2",
5302
- "@sentry/utils": "7.59.2",
5189
+ "@sentry/types": "7.60.0",
5190
+ "@sentry/utils": "7.60.0",
5303
5191
  "tslib": "^2.4.1 || ^1.9.3"
5304
5192
  },
5305
5193
  "engines": {
@@ -5307,14 +5195,14 @@
5307
5195
  }
5308
5196
  },
5309
5197
  "node_modules/@sentry/node": {
5310
- "version": "7.59.2",
5311
- "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.59.2.tgz",
5312
- "integrity": "sha512-cvTW4VwQdvNeAtBGVGE5hGmsWstGK4PwWe5PccBWJBQGM/rYzwk2tM9ZQnM5M5+yDV4bZ+21sJhvyhsHoTjmzQ==",
5313
- "dependencies": {
5314
- "@sentry-internal/tracing": "7.59.2",
5315
- "@sentry/core": "7.59.2",
5316
- "@sentry/types": "7.59.2",
5317
- "@sentry/utils": "7.59.2",
5198
+ "version": "7.60.0",
5199
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.60.0.tgz",
5200
+ "integrity": "sha512-I27gr7BSkdT1uwDPcbdPm7+w2yke5tojVGgothtvKfql1en4/cJZmk2bkvO2Di41+EF0UrTlUgLQff5X/q24WQ==",
5201
+ "dependencies": {
5202
+ "@sentry-internal/tracing": "7.60.0",
5203
+ "@sentry/core": "7.60.0",
5204
+ "@sentry/types": "7.60.0",
5205
+ "@sentry/utils": "7.60.0",
5318
5206
  "cookie": "^0.4.1",
5319
5207
  "https-proxy-agent": "^5.0.0",
5320
5208
  "lru_map": "^0.3.3",
@@ -5325,19 +5213,19 @@
5325
5213
  }
5326
5214
  },
5327
5215
  "node_modules/@sentry/types": {
5328
- "version": "7.59.2",
5329
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.59.2.tgz",
5330
- "integrity": "sha512-rylG7UQ0cC/xbV6trSuaAE/bsruSZy92jxQ1/KSOYKwBBvRFPXJBuiBtA81b8eYa4THZ+mE/ol2qOTJYuuV4Ug==",
5216
+ "version": "7.60.0",
5217
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.60.0.tgz",
5218
+ "integrity": "sha512-MSEuF9YjE0j+UKdqee2AzcNlMnShVNTkCB2Wnng6Bc5hHhn4fyYeTLbuFpNxL0ffN65lxblaWx6doDsMcvRxcA==",
5331
5219
  "engines": {
5332
5220
  "node": ">=8"
5333
5221
  }
5334
5222
  },
5335
5223
  "node_modules/@sentry/utils": {
5336
- "version": "7.59.2",
5337
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.59.2.tgz",
5338
- "integrity": "sha512-uxC8xH9wsB/tZUnjmaQ1uGtsumFOc19KWfedVHXzcNwqdt5uS3EB4+D1d8WwiJyLy2nm61DdmTC9SiB4HS+OSw==",
5224
+ "version": "7.60.0",
5225
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.60.0.tgz",
5226
+ "integrity": "sha512-Oc/PQqzeNDOSy4ZzVj6h9U+GEGRkg2PEVn9PC2V9/v3HDD20mndFqR/S2B5OOgDb/6pNGyz8XiZYI5rb29WFHA==",
5339
5227
  "dependencies": {
5340
- "@sentry/types": "7.59.2",
5228
+ "@sentry/types": "7.60.0",
5341
5229
  "tslib": "^2.4.1 || ^1.9.3"
5342
5230
  },
5343
5231
  "engines": {
@@ -16467,15 +16355,15 @@
16467
16355
  }
16468
16356
  },
16469
16357
  "node_modules/oclif": {
16470
- "version": "3.9.1",
16471
- "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.9.1.tgz",
16472
- "integrity": "sha512-gJ8gJrohFY8qEeVBOw7wgAFdwPt2CTTkEFXDTkfUeXap6URIy6ngP7g/E1A2zFt2I0wH/qQHwcfuTpfBbj1+Uw==",
16358
+ "version": "3.10.0",
16359
+ "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.10.0.tgz",
16360
+ "integrity": "sha512-Kf/nL7GrfezePsZGQytbPJG1EGNFRAG+lC6NhYqPOgeBIGppLuQDg6vO9wz0QRoijSJv/Yf4wCe2URMoCFtBNw==",
16473
16361
  "dev": true,
16474
16362
  "dependencies": {
16475
- "@oclif/core": "^2.8.4",
16476
- "@oclif/plugin-help": "^5.1.19",
16477
- "@oclif/plugin-not-found": "^2.3.7",
16478
- "@oclif/plugin-warn-if-update-available": "^2.0.14",
16363
+ "@oclif/core": "^2.9.4",
16364
+ "@oclif/plugin-help": "^5.2.14",
16365
+ "@oclif/plugin-not-found": "^2.3.32",
16366
+ "@oclif/plugin-warn-if-update-available": "^2.0.44",
16479
16367
  "aws-sdk": "^2.1231.0",
16480
16368
  "concurrently": "^7.6.0",
16481
16369
  "debug": "^4.3.3",
@@ -24892,105 +24780,19 @@
24892
24780
  }
24893
24781
  }
24894
24782
  },
24895
- "@oclif/linewrap": {
24896
- "version": "1.0.0",
24897
- "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz",
24898
- "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==",
24899
- "dev": true
24900
- },
24901
24783
  "@oclif/plugin-help": {
24902
- "version": "5.1.20",
24903
- "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.1.20.tgz",
24904
- "integrity": "sha512-N8xRxE/isFcdBDI8cobixEZA5toxIK5jbxpwALNTr4s8KNAtBA3ORQrSiY0fWGkcv0sCGMwZw7rJ0Izh18JPsw==",
24784
+ "version": "5.2.14",
24785
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.2.14.tgz",
24786
+ "integrity": "sha512-7hMLc6zqxeRfG4nvHHQPpbaBj60efM3ULFkCpHZkdLms/ezIkNo40F661QuraIjMP/NN+U6VSfBCGuPkRyxVkA==",
24905
24787
  "dev": true,
24906
24788
  "requires": {
24907
- "@oclif/core": "^1.21.0"
24908
- },
24909
- "dependencies": {
24910
- "@oclif/core": {
24911
- "version": "1.26.1",
24912
- "resolved": "https://registry.npmjs.org/@oclif/core/-/core-1.26.1.tgz",
24913
- "integrity": "sha512-g+OWJcM7JOVI53caTEtq0BB1nPotWctRLUyFODPgvDqXhVR7QED+Qz3LwFAMD8dt7/Ar2ZNq15U3bnpnOv453A==",
24914
- "dev": true,
24915
- "requires": {
24916
- "@oclif/linewrap": "^1.0.0",
24917
- "@oclif/screen": "^3.0.4",
24918
- "ansi-escapes": "^4.3.2",
24919
- "ansi-styles": "^4.3.0",
24920
- "cardinal": "^2.1.1",
24921
- "chalk": "^4.1.2",
24922
- "clean-stack": "^3.0.1",
24923
- "cli-progress": "^3.10.0",
24924
- "debug": "^4.3.4",
24925
- "ejs": "^3.1.6",
24926
- "fs-extra": "^9.1.0",
24927
- "get-package-type": "^0.1.0",
24928
- "globby": "^11.1.0",
24929
- "hyperlinker": "^1.0.0",
24930
- "indent-string": "^4.0.0",
24931
- "is-wsl": "^2.2.0",
24932
- "js-yaml": "^3.14.1",
24933
- "natural-orderby": "^2.0.3",
24934
- "object-treeify": "^1.1.33",
24935
- "password-prompt": "^1.1.2",
24936
- "semver": "^7.3.7",
24937
- "string-width": "^4.2.3",
24938
- "strip-ansi": "^6.0.1",
24939
- "supports-color": "^8.1.1",
24940
- "supports-hyperlinks": "^2.2.0",
24941
- "tslib": "^2.4.1",
24942
- "widest-line": "^3.1.0",
24943
- "wrap-ansi": "^7.0.0"
24944
- }
24945
- },
24946
- "chalk": {
24947
- "version": "4.1.2",
24948
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
24949
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
24950
- "dev": true,
24951
- "requires": {
24952
- "ansi-styles": "^4.1.0",
24953
- "supports-color": "^7.1.0"
24954
- },
24955
- "dependencies": {
24956
- "supports-color": {
24957
- "version": "7.2.0",
24958
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
24959
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
24960
- "dev": true,
24961
- "requires": {
24962
- "has-flag": "^4.0.0"
24963
- }
24964
- }
24965
- }
24966
- },
24967
- "clean-stack": {
24968
- "version": "3.0.1",
24969
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz",
24970
- "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==",
24971
- "dev": true,
24972
- "requires": {
24973
- "escape-string-regexp": "4.0.0"
24974
- }
24975
- },
24976
- "fs-extra": {
24977
- "version": "9.1.0",
24978
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
24979
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
24980
- "dev": true,
24981
- "requires": {
24982
- "at-least-node": "^1.0.0",
24983
- "graceful-fs": "^4.2.0",
24984
- "jsonfile": "^6.0.1",
24985
- "universalify": "^2.0.0"
24986
- }
24987
- }
24789
+ "@oclif/core": "^2.9.3"
24988
24790
  }
24989
24791
  },
24990
24792
  "@oclif/plugin-not-found": {
24991
- "version": "2.3.31",
24992
- "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-2.3.31.tgz",
24993
- "integrity": "sha512-KHBCDJbDrkFc5vuPxg4JZ3wBTrdPPHOQOWp4bLCV4cnVSUHBKnfCqnCg2aXmRb97nbzY3P13/i8Th3KQjArqmg==",
24793
+ "version": "2.3.32",
24794
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-2.3.32.tgz",
24795
+ "integrity": "sha512-tVFHfR9XRUWrcxBugHjFr7HUmbLheDX05IaFr7fMF2hcvcqDs3DBjy42WKEoXSaBVTcST6KKhoSy2UVX8pk9Fg==",
24994
24796
  "requires": {
24995
24797
  "@oclif/color": "^1.0.8",
24996
24798
  "@oclif/core": "^2.9.3",
@@ -24998,9 +24800,9 @@
24998
24800
  }
24999
24801
  },
25000
24802
  "@oclif/plugin-plugins": {
25001
- "version": "3.1.6",
25002
- "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-3.1.6.tgz",
25003
- "integrity": "sha512-bri3GHqUs2d9mMoqm0/CIef+u+nJrNDzno5xpnB0cg7x3mAhXM/miuzdNz7D8opupuJeiJMv+A/WSMG2nY2IEw==",
24803
+ "version": "3.1.7",
24804
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-3.1.7.tgz",
24805
+ "integrity": "sha512-rGH3unndc5bY73b63K9IrGnXM6XeB7vOALKVHbbiia3fPIf4oG2ybjo1MBHyUsfwZYifRc/GK2RAZ8cle0GqDA==",
25004
24806
  "dev": true,
25005
24807
  "requires": {
25006
24808
  "@oclif/color": "^1.0.4",
@@ -25112,16 +24914,10 @@
25112
24914
  }
25113
24915
  }
25114
24916
  },
25115
- "@oclif/screen": {
25116
- "version": "3.0.4",
25117
- "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-3.0.4.tgz",
25118
- "integrity": "sha512-IMsTN1dXEXaOSre27j/ywGbBjrzx0FNd1XmuhCWCB9NTPrhWI1Ifbz+YLSEcstfQfocYsrbrIessxXb2oon4lA==",
25119
- "dev": true
25120
- },
25121
24917
  "@oclif/test": {
25122
- "version": "2.3.30",
25123
- "resolved": "https://registry.npmjs.org/@oclif/test/-/test-2.3.30.tgz",
25124
- "integrity": "sha512-zuOv23wiF+H7cRGMjcKx/91qhdcNMcZnr+1TCpbyDeQBIvRs/nGWyuwfrmoF2fXs+HtNZsNFvwbjg7Ue5JfAug==",
24918
+ "version": "2.3.31",
24919
+ "resolved": "https://registry.npmjs.org/@oclif/test/-/test-2.3.31.tgz",
24920
+ "integrity": "sha512-dTWCni+Zv9aSuzyamS95+GJaIub6EAI+CT+pA1MP10RZF54mF7CKaas7t8dvNvDp1Y194hi64cqe+cNwZlR5ng==",
25125
24921
  "dev": true,
25126
24922
  "requires": {
25127
24923
  "@oclif/core": "^2.9.3",
@@ -25344,35 +25140,35 @@
25344
25140
  "dev": true
25345
25141
  },
25346
25142
  "@sentry-internal/tracing": {
25347
- "version": "7.59.2",
25348
- "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.59.2.tgz",
25349
- "integrity": "sha512-02gteChV/lMobWU06VlITq+myEWk0MzhnDCm8n/DMigB47I9HkWZFAJ+CYG6Ns0rTL+3+/c2V0bPyQkZwIC+Sg==",
25143
+ "version": "7.60.0",
25144
+ "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.60.0.tgz",
25145
+ "integrity": "sha512-2qvxmR954H+K7u4o92sS2u+hntzshem9XwfHAqDvBe51arNbFVy8LfJTJ5fffgZq/6jXlozCO0/6aR5yLR5mBg==",
25350
25146
  "requires": {
25351
- "@sentry/core": "7.59.2",
25352
- "@sentry/types": "7.59.2",
25353
- "@sentry/utils": "7.59.2",
25147
+ "@sentry/core": "7.60.0",
25148
+ "@sentry/types": "7.60.0",
25149
+ "@sentry/utils": "7.60.0",
25354
25150
  "tslib": "^2.4.1 || ^1.9.3"
25355
25151
  }
25356
25152
  },
25357
25153
  "@sentry/core": {
25358
- "version": "7.59.2",
25359
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.59.2.tgz",
25360
- "integrity": "sha512-GRhoPw6b6GkvOsa060aREc9yyHjgAKITgITNbzUmn0GqIeWD5SMoCBAcENRHVgUnpQWOpnkEF1/sqxvwx+rf6Q==",
25154
+ "version": "7.60.0",
25155
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.60.0.tgz",
25156
+ "integrity": "sha512-B02OlFMoqdkfDZlbQfmk7tL2vObShofk7ySd/7mp+oRdUuCvX0tyrGlwI87YJvd8YWSZOCKINs3aVYivw/b6gg==",
25361
25157
  "requires": {
25362
- "@sentry/types": "7.59.2",
25363
- "@sentry/utils": "7.59.2",
25158
+ "@sentry/types": "7.60.0",
25159
+ "@sentry/utils": "7.60.0",
25364
25160
  "tslib": "^2.4.1 || ^1.9.3"
25365
25161
  }
25366
25162
  },
25367
25163
  "@sentry/node": {
25368
- "version": "7.59.2",
25369
- "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.59.2.tgz",
25370
- "integrity": "sha512-cvTW4VwQdvNeAtBGVGE5hGmsWstGK4PwWe5PccBWJBQGM/rYzwk2tM9ZQnM5M5+yDV4bZ+21sJhvyhsHoTjmzQ==",
25371
- "requires": {
25372
- "@sentry-internal/tracing": "7.59.2",
25373
- "@sentry/core": "7.59.2",
25374
- "@sentry/types": "7.59.2",
25375
- "@sentry/utils": "7.59.2",
25164
+ "version": "7.60.0",
25165
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.60.0.tgz",
25166
+ "integrity": "sha512-I27gr7BSkdT1uwDPcbdPm7+w2yke5tojVGgothtvKfql1en4/cJZmk2bkvO2Di41+EF0UrTlUgLQff5X/q24WQ==",
25167
+ "requires": {
25168
+ "@sentry-internal/tracing": "7.60.0",
25169
+ "@sentry/core": "7.60.0",
25170
+ "@sentry/types": "7.60.0",
25171
+ "@sentry/utils": "7.60.0",
25376
25172
  "cookie": "^0.4.1",
25377
25173
  "https-proxy-agent": "^5.0.0",
25378
25174
  "lru_map": "^0.3.3",
@@ -25380,16 +25176,16 @@
25380
25176
  }
25381
25177
  },
25382
25178
  "@sentry/types": {
25383
- "version": "7.59.2",
25384
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.59.2.tgz",
25385
- "integrity": "sha512-rylG7UQ0cC/xbV6trSuaAE/bsruSZy92jxQ1/KSOYKwBBvRFPXJBuiBtA81b8eYa4THZ+mE/ol2qOTJYuuV4Ug=="
25179
+ "version": "7.60.0",
25180
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.60.0.tgz",
25181
+ "integrity": "sha512-MSEuF9YjE0j+UKdqee2AzcNlMnShVNTkCB2Wnng6Bc5hHhn4fyYeTLbuFpNxL0ffN65lxblaWx6doDsMcvRxcA=="
25386
25182
  },
25387
25183
  "@sentry/utils": {
25388
- "version": "7.59.2",
25389
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.59.2.tgz",
25390
- "integrity": "sha512-uxC8xH9wsB/tZUnjmaQ1uGtsumFOc19KWfedVHXzcNwqdt5uS3EB4+D1d8WwiJyLy2nm61DdmTC9SiB4HS+OSw==",
25184
+ "version": "7.60.0",
25185
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.60.0.tgz",
25186
+ "integrity": "sha512-Oc/PQqzeNDOSy4ZzVj6h9U+GEGRkg2PEVn9PC2V9/v3HDD20mndFqR/S2B5OOgDb/6pNGyz8XiZYI5rb29WFHA==",
25391
25187
  "requires": {
25392
- "@sentry/types": "7.59.2",
25188
+ "@sentry/types": "7.60.0",
25393
25189
  "tslib": "^2.4.1 || ^1.9.3"
25394
25190
  }
25395
25191
  },
@@ -33208,15 +33004,15 @@
33208
33004
  }
33209
33005
  },
33210
33006
  "oclif": {
33211
- "version": "3.9.1",
33212
- "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.9.1.tgz",
33213
- "integrity": "sha512-gJ8gJrohFY8qEeVBOw7wgAFdwPt2CTTkEFXDTkfUeXap6URIy6ngP7g/E1A2zFt2I0wH/qQHwcfuTpfBbj1+Uw==",
33007
+ "version": "3.10.0",
33008
+ "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.10.0.tgz",
33009
+ "integrity": "sha512-Kf/nL7GrfezePsZGQytbPJG1EGNFRAG+lC6NhYqPOgeBIGppLuQDg6vO9wz0QRoijSJv/Yf4wCe2URMoCFtBNw==",
33214
33010
  "dev": true,
33215
33011
  "requires": {
33216
- "@oclif/core": "^2.8.4",
33217
- "@oclif/plugin-help": "^5.1.19",
33218
- "@oclif/plugin-not-found": "^2.3.7",
33219
- "@oclif/plugin-warn-if-update-available": "^2.0.14",
33012
+ "@oclif/core": "^2.9.4",
33013
+ "@oclif/plugin-help": "^5.2.14",
33014
+ "@oclif/plugin-not-found": "^2.3.32",
33015
+ "@oclif/plugin-warn-if-update-available": "^2.0.44",
33220
33016
  "aws-sdk": "^2.1231.0",
33221
33017
  "concurrently": "^7.6.0",
33222
33018
  "debug": "^4.3.3",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.2",
2
+ "version": "0.2.3",
3
3
  "commands": {
4
4
  "help": {
5
5
  "id": "help",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gadgetinc/ggt",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "The command-line interface for Gadget",
5
5
  "homepage": "https://github.com/gadget-inc/ggt",
6
6
  "bugs": "https://github.com/gadget-inc/ggt/issues",
@@ -39,9 +39,9 @@
39
39
  "dependencies": {
40
40
  "@oclif/core": "^2.9.4",
41
41
  "@oclif/errors": "^1.3.6",
42
- "@oclif/plugin-not-found": "^2.3.31",
42
+ "@oclif/plugin-not-found": "^2.3.32",
43
43
  "@oclif/plugin-warn-if-update-available": "^2.0.44",
44
- "@sentry/node": "^7.59.2",
44
+ "@sentry/node": "^7.60.0",
45
45
  "@swc/helpers": "^0.5.1",
46
46
  "chalk": "^5.3.0",
47
47
  "chalk-template": "^1.1.0",
@@ -76,8 +76,8 @@
76
76
  "@graphql-codegen/cli": "^4.0.1",
77
77
  "@graphql-codegen/typescript": "^4.0.0",
78
78
  "@graphql-codegen/typescript-operations": "^4.0.1",
79
- "@oclif/plugin-plugins": "^3.1.6",
80
- "@oclif/test": "^2.3.30",
79
+ "@oclif/plugin-plugins": "^3.1.7",
80
+ "@oclif/test": "^2.3.31",
81
81
  "@swc/cli": "^0.1.62",
82
82
  "@swc/core": "^1.3.70",
83
83
  "@types/debug": "^4.1.8",
@@ -102,7 +102,7 @@
102
102
  "eslint-plugin-import": "^2.27.5",
103
103
  "eslint-plugin-lodash": "^7.4.0",
104
104
  "nock": "^13.3.2",
105
- "oclif": "^3.9.1",
105
+ "oclif": "^3.10.0",
106
106
  "patch-package": "^7.0.2",
107
107
  "prettier": "^3.0.0",
108
108
  "prettier-plugin-organize-imports": "^3.2.3",