@gadgetinc/ggt 0.0.0-alpha.1 → 0.0.0-alpha.2
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 +9 -6
- package/bin/dev +1 -1
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.js +22 -12
- package/dist/commands/sync.js.map +1 -1
- package/dist/lib/base-command.d.ts +8 -0
- package/dist/lib/base-command.js +15 -1
- package/dist/lib/base-command.js.map +1 -1
- package/dist/lib/errors.d.ts +10 -4
- package/dist/lib/errors.js +48 -12
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/fs-utils.d.ts +1 -2
- package/dist/lib/fs-utils.js +6 -16
- package/dist/lib/fs-utils.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -71,6 +71,9 @@ USAGE
|
|
|
71
71
|
ARGUMENTS
|
|
72
72
|
DIRECTORY [default: .] The directory to sync files to. If the directory doesn't exist, it will be created.
|
|
73
73
|
|
|
74
|
+
FLAGS
|
|
75
|
+
--force Sync even if we can't determine the state of your local files relative to your remote ones.
|
|
76
|
+
|
|
74
77
|
DESCRIPTION
|
|
75
78
|
Sync provides the ability to sync your Gadget application's source code to and from your local
|
|
76
79
|
filesystem. While `ggt sync` is running, local file changes are immediately reflected within
|
|
@@ -90,7 +93,7 @@ DESCRIPTION
|
|
|
90
93
|
* node_modules
|
|
91
94
|
|
|
92
95
|
Note:
|
|
93
|
-
*
|
|
96
|
+
* Gadget applications only support installing dependencies with Yarn 1 (https://classic.yarnpkg.com/lang/en/).
|
|
94
97
|
* Since file changes are immediately reflected in Gadget, avoid the following while `ggt sync` is running:
|
|
95
98
|
* Deleting all your files
|
|
96
99
|
* Moving all your files to a different directory
|
|
@@ -115,7 +118,7 @@ EXAMPLES
|
|
|
115
118
|
$ ggt sync --app https://my-app.gadget.app/edit
|
|
116
119
|
```
|
|
117
120
|
|
|
118
|
-
_See code: [src/commands/sync.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.
|
|
121
|
+
_See code: [src/commands/sync.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.2/src/commands/sync.ts)_
|
|
119
122
|
|
|
120
123
|
### `ggt help [COMMAND]`
|
|
121
124
|
|
|
@@ -129,7 +132,7 @@ ARGUMENTS
|
|
|
129
132
|
COMMAND The command to show help for.
|
|
130
133
|
```
|
|
131
134
|
|
|
132
|
-
_See code: [src/commands/help.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.
|
|
135
|
+
_See code: [src/commands/help.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.2/src/commands/help.ts)_
|
|
133
136
|
|
|
134
137
|
### `ggt login`
|
|
135
138
|
|
|
@@ -145,7 +148,7 @@ EXAMPLES
|
|
|
145
148
|
Hello, Jane Doe (jane@example.com)
|
|
146
149
|
```
|
|
147
150
|
|
|
148
|
-
_See code: [src/commands/login.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.
|
|
151
|
+
_See code: [src/commands/login.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.2/src/commands/login.ts)_
|
|
149
152
|
|
|
150
153
|
### `ggt logout`
|
|
151
154
|
|
|
@@ -160,7 +163,7 @@ EXAMPLES
|
|
|
160
163
|
Goodbye
|
|
161
164
|
```
|
|
162
165
|
|
|
163
|
-
_See code: [src/commands/logout.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.
|
|
166
|
+
_See code: [src/commands/logout.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.2/src/commands/logout.ts)_
|
|
164
167
|
|
|
165
168
|
### `ggt whoami`
|
|
166
169
|
|
|
@@ -175,7 +178,7 @@ EXAMPLES
|
|
|
175
178
|
You are logged in as Jane Doe (jane@example.com)
|
|
176
179
|
```
|
|
177
180
|
|
|
178
|
-
_See code: [src/commands/whoami.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.
|
|
181
|
+
_See code: [src/commands/whoami.ts](https://github.com/gadget-inc/ggt/blob/v0.0.0-alpha.2/src/commands/whoami.ts)_
|
|
179
182
|
|
|
180
183
|
<!-- commandsstop -->
|
|
181
184
|
|
package/bin/dev
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
|
|
5
5
|
process.env.NODE_ENV = "development";
|
|
6
|
-
process.env.GGT_ENV
|
|
6
|
+
process.env.GGT_ENV ??= "development";
|
|
7
7
|
|
|
8
8
|
// store files in the project's tmp directory
|
|
9
9
|
// https://github.com/oclif/core/blob/main/src/config/config.ts#L171
|
package/dist/commands/sync.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export default class Sync extends BaseCommand {
|
|
|
19
19
|
default: string;
|
|
20
20
|
}[];
|
|
21
21
|
static flags: {
|
|
22
|
+
force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
22
23
|
"file-push-delay": OptionFlag<number>;
|
|
23
24
|
"file-stability-threshold": OptionFlag<number>;
|
|
24
25
|
"file-poll-interval": OptionFlag<number>;
|
package/dist/commands/sync.js
CHANGED
|
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
7
7
|
const chokidar_1 = require("chokidar");
|
|
8
|
+
const execa_1 = tslib_1.__importDefault(require("execa"));
|
|
8
9
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
9
10
|
const inquirer_1 = require("inquirer");
|
|
10
11
|
const lodash_1 = require("lodash");
|
|
@@ -14,7 +15,9 @@ const p_queue_1 = tslib_1.__importDefault(require("p-queue"));
|
|
|
14
15
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
15
16
|
const ts_dedent_1 = tslib_1.__importDefault(require("ts-dedent"));
|
|
16
17
|
const util_1 = require("util");
|
|
18
|
+
const which_1 = tslib_1.__importDefault(require("which"));
|
|
17
19
|
const base_command_1 = require("../lib/base-command");
|
|
20
|
+
const errors_1 = require("../lib/errors");
|
|
18
21
|
const fs_utils_1 = require("../lib/fs-utils");
|
|
19
22
|
const sleep_1 = require("../lib/sleep");
|
|
20
23
|
class Sync extends base_command_1.BaseCommand {
|
|
@@ -142,24 +145,25 @@ class Sync extends base_command_1.BaseCommand {
|
|
|
142
145
|
awaitWriteFinish: { pollInterval: flags["file-poll-interval"], stabilityThreshold: flags["file-stability-threshold"] },
|
|
143
146
|
});
|
|
144
147
|
this.debug("starting");
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
this.metadata = await fs_extra_1.default.readJson(this.absolute(".ggt", "sync.json"));
|
|
148
|
+
if (!which_1.default.sync("yarn", { nothrow: true })) {
|
|
149
|
+
throw new errors_1.YarnNotFoundError();
|
|
148
150
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
await fs_extra_1.default.ensureDir(this.dir);
|
|
152
|
+
if (!(await (0, fs_utils_1.isEmptyDir)(this.dir))) {
|
|
153
|
+
try {
|
|
154
|
+
this.metadata = await fs_extra_1.default.readJson(this.absolute(".ggt", "sync.json"));
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (!flags.force) {
|
|
158
|
+
throw new errors_1.InvalidSyncFileError(error, this.dir, this.app);
|
|
159
|
+
}
|
|
155
160
|
}
|
|
156
|
-
await d.close();
|
|
157
161
|
}
|
|
158
162
|
const { remoteFilesVersion } = await this.client.queryUnwrap({ query: exports.REMOTE_FILES_VERSION_QUERY });
|
|
159
163
|
const hasRemoteChanges = BigInt(remoteFilesVersion) > BigInt(this.metadata.lastWritten.filesVersion);
|
|
160
164
|
const getChangedFiles = async () => {
|
|
161
165
|
const files = new Map();
|
|
162
|
-
for await (const filepath of (0, fs_utils_1.walkDir)(this.dir, { ignorer: this.ignorer
|
|
166
|
+
for await (const filepath of (0, fs_utils_1.walkDir)(this.dir, { ignorer: this.ignorer })) {
|
|
163
167
|
const stats = await fs_extra_1.default.stat(filepath);
|
|
164
168
|
if (stats.mtime.getTime() > this.metadata.lastWritten.mtime) {
|
|
165
169
|
files.set(this.absolute(filepath), stats);
|
|
@@ -280,6 +284,8 @@ class Sync extends base_command_1.BaseCommand {
|
|
|
280
284
|
await fs_extra_1.default.ensureDir(path_1.default.dirname(filepath), { mode: 0o755 });
|
|
281
285
|
if (!file.path.endsWith("/"))
|
|
282
286
|
await fs_extra_1.default.writeFile(filepath, this.encoder.encode(file.content), { mode: file.mode });
|
|
287
|
+
if (filepath == this.absolute("yarn.lock"))
|
|
288
|
+
await (0, execa_1.default)("yarn", ["install"], { cwd: this.dir });
|
|
283
289
|
}
|
|
284
290
|
else {
|
|
285
291
|
await fs_extra_1.default.remove(filepath);
|
|
@@ -434,7 +440,7 @@ Object.defineProperty(Sync, "description", {
|
|
|
434
440
|
* node_modules
|
|
435
441
|
|
|
436
442
|
Note:
|
|
437
|
-
*
|
|
443
|
+
* Gadget applications only support installing dependencies with Yarn 1 (https://classic.yarnpkg.com/lang/en/).
|
|
438
444
|
* Since file changes are immediately reflected in Gadget, avoid the following while \`ggt sync\` is running:
|
|
439
445
|
* Deleting all your files
|
|
440
446
|
* Moving all your files to a different directory
|
|
@@ -457,6 +463,10 @@ Object.defineProperty(Sync, "flags", {
|
|
|
457
463
|
configurable: true,
|
|
458
464
|
writable: true,
|
|
459
465
|
value: {
|
|
466
|
+
force: core_1.Flags.boolean({
|
|
467
|
+
summary: "Sync even if we can't determine the state of your local files relative to your remote ones.",
|
|
468
|
+
default: false,
|
|
469
|
+
}),
|
|
460
470
|
"file-push-delay": core_1.Flags.integer({
|
|
461
471
|
summary: "Delay in milliseconds before pushing files to your app.",
|
|
462
472
|
helpGroup: "file",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { Flags } from \"@oclif/core\";\nimport type { OptionFlag } from \"@oclif/core/lib/interfaces\";\nimport assert from \"assert\";\nimport { FSWatcher } from \"chokidar\";\nimport type { Stats } from \"fs-extra\";\nimport fs from \"fs-extra\";\nimport { prompt } from \"inquirer\";\nimport type { DebouncedFunc } from \"lodash\";\nimport { debounce } from \"lodash\";\nimport normalizePath from \"normalize-path\";\nimport pMap from \"p-map\";\nimport PQueue from \"p-queue\";\nimport path from \"path\";\nimport dedent from \"ts-dedent\";\nimport { TextDecoder, TextEncoder } from \"util\";\nimport { BaseCommand } from \"../lib/base-command\";\nimport type { Query } from \"../lib/client\";\nimport { ignoreEnoent, Ignorer, walkDir } from \"../lib/fs-utils\";\nimport { sleepUntil } from \"../lib/sleep\";\nimport type {\n FileSyncChangedEventInput,\n FileSyncDeletedEventInput,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n} from \"../__generated__/graphql\";\n\nexport default class Sync extends BaseCommand {\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 --app <name> [DIRECTORY]\";\n\n static override description = dedent`\n Sync provides the ability to sync your Gadget application's source code to and from your local\n filesystem. While \\`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 (https://code.visualstudio.com/)\n * Storing your source code in a Git repository like GitHub (https://github.com/)\n\n Sync includes the concept of a \\`.ignore\\` file. This file can contain a list of files and\n directories that won't be sent to Gadget when syncing.\n\n The following files and directories are always ignored:\n * .gadget\n * .ggt\n * .git\n * node_modules\n\n Note:\n * Sync does not support node_modules, so you will have to run \\`npm install\\` yourself.\n * Since file changes are immediately reflected in Gadget, avoid the following while \\`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 {\n name: \"directory\",\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 \"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 }) as OptionFlag<number>,\n \"file-stability-threshold\": Flags.integer({\n name: \"file-stability-threshold\",\n summary: \"Time in milliseconds a file's size must remain the same.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 500,\n hidden: true,\n }) as OptionFlag<number>,\n \"file-poll-interval\": Flags.integer({\n name: \"file-poll-interval\",\n description: \"Interval in milliseconds between polling a file's size.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 100,\n hidden: true,\n }) as OptionFlag<number>,\n };\n\n static override examples = [\n dedent`\n $ ggt sync --app my-app ~/gadget/my-app\n Ready\n Received\n ← routes/GET.js\n ← user/signUp/signIn.js\n Sent\n → routes/GET.js\n ^C Stopping... (press Ctrl+C again to force)\n Done\n `,\n dedent`\n # These are equivalent\n $ ggt sync -A my-app\n $ ggt sync --app my-app\n $ ggt sync --app my-app.gadget.app\n $ ggt sync --app https://my-app.gadget.app\n $ ggt sync --app https://my-app.gadget.app/edit\n `,\n ];\n\n override readonly requireApp = true;\n\n status = SyncStatus.STARTING;\n\n dir!: string;\n\n recentWrites = new Set();\n\n encoder = new TextEncoder();\n\n decoder = new TextDecoder();\n\n filePushDelay!: number;\n\n queue = new PQueue({ concurrency: 1 });\n\n ignorer!: Ignorer;\n\n watcher!: FSWatcher;\n\n metadata = {\n lastWritten: {\n filesVersion: \"0\",\n mtime: 0,\n },\n };\n\n publish!: DebouncedFunc<() => void>;\n\n stop!: (error?: unknown) => Promise<void>;\n\n relative(to: string): string {\n return path.relative(this.dir, to);\n }\n\n absolute(...pathSegments: string[]): string {\n return path.resolve(this.dir, ...pathSegments);\n }\n\n normalize(filepath: string): string {\n return normalizePath(path.isAbsolute(filepath) ? this.relative(filepath) : filepath);\n }\n\n logPaths(filepaths: string[], { limit = 10, sep = \"-\" } = {}): void {\n let logged = 0;\n for (const filepath of filepaths) {\n this.log(`${sep} ${this.normalize(filepath)}`);\n if (++logged == limit && !this.debugEnabled) break;\n }\n\n if (filepaths.length > logged) {\n this.log(`… ${filepaths.length - logged} more`);\n }\n }\n\n override async init(): Promise<void> {\n await super.init();\n const { args, flags } = await this.parse(Sync);\n\n this.dir = path.resolve(args[\"directory\"] as string);\n\n this.filePushDelay = flags[\"file-push-delay\"];\n\n // local files that should never be published\n const ignored = [\"node_modules/\", \".gadget/\", \".ggt/\", \".git/\"];\n\n this.ignorer = new Ignorer(this.dir, ignored);\n\n this.watcher = new FSWatcher({\n ignored,\n // don't emit an event for every watched file on boot\n ignoreInitial: true,\n // make sure stats are always present on add/change events\n alwaysStat: true,\n // wait for the entire file to be written before emitting add/change events\n awaitWriteFinish: { pollInterval: flags[\"file-poll-interval\"], stabilityThreshold: flags[\"file-stability-threshold\"] },\n });\n\n this.debug(\"starting\");\n await fs.ensureDir(this.dir);\n\n try {\n this.metadata = await fs.readJson(this.absolute(\".ggt\", \"sync.json\"));\n } catch (error) {\n // use defaults if the metadata file doesn't exist\n ignoreEnoent(error);\n\n const d = await fs.opendir(this.dir);\n if ((await d.read()) != null) {\n this.warn(\"Could not find .ggt/sync.json in a non empty directory\");\n }\n await d.close();\n }\n\n const { remoteFilesVersion } = await this.client.queryUnwrap({ query: REMOTE_FILES_VERSION_QUERY });\n const hasRemoteChanges = BigInt(remoteFilesVersion) > BigInt(this.metadata.lastWritten.filesVersion);\n\n const getChangedFiles = async (): Promise<Map<string, Stats>> => {\n const files = new Map();\n for await (const filepath of walkDir(this.dir, { ignorer: this.ignorer, maxFiles: 100 })) {\n const stats = await fs.stat(filepath);\n if (stats.mtime.getTime() > this.metadata.lastWritten.mtime) {\n files.set(this.absolute(filepath), stats);\n }\n }\n return files;\n };\n\n const changedFiles = await getChangedFiles();\n const hasLocalChanges = changedFiles.size > 0;\n if (hasLocalChanges) {\n this.log(\"Local files have changed since the last sync\");\n this.logPaths(Array.from(changedFiles.keys()), { limit: changedFiles.size });\n this.log();\n }\n\n this.debug(\"init %o\", { metadata: this.metadata, remoteFilesVersion, hasRemoteChanges, hasLocalChanges });\n\n let action: Action | undefined;\n if (hasLocalChanges) {\n ({ action } = await 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 switch (action) {\n case Action.MERGE: {\n // get all the changed files again in case more changed\n const files = await getChangedFiles();\n\n // we purposefully don't set the returned remoteFilesVersion here because we haven't processed the in-between versions yet\n await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: {\n input: {\n expectedRemoteFilesVersion: remoteFilesVersion,\n changed: await pMap(files, async ([filepath, stats]) => {\n if (stats.mtime.getTime() > this.metadata.lastWritten.mtime) {\n this.metadata.lastWritten.mtime = stats.mtime.getTime();\n }\n\n return {\n path: this.normalize(filepath),\n mode: stats.mode,\n content: await fs.readFile(filepath, \"utf-8\"),\n };\n }),\n deleted: [],\n },\n },\n });\n break;\n }\n case Action.RESET: {\n await pMap(changedFiles, ([filepath]) => fs.remove(filepath));\n this.metadata.lastWritten.filesVersion = \"0\";\n break;\n }\n case Action.CANCEL: {\n process.exit(0);\n }\n }\n\n this.debug(\"started\");\n }\n\n async run(): Promise<void> {\n let error: unknown;\n\n this.stop = async (e?: unknown) => {\n if (this.status != SyncStatus.RUNNING) return;\n\n error = e;\n this.debug(\"stopping\");\n this.status = SyncStatus.STOPPING;\n\n try {\n unsubscribe();\n this.watcher.removeAllListeners();\n this.publish.flush();\n await this.queue.onIdle();\n } finally {\n await fs.outputJSON(this.absolute(\".ggt\", \"sync.json\"), this.metadata, { spaces: 2 });\n await Promise.allSettled([this.watcher.close(), this.client.dispose()]);\n\n this.debug(\"stopped\");\n this.status = SyncStatus.STOPPED;\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(\" Stopping... (press Ctrl+C again to force)\");\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(\"SIGINT\", () => {\n this.log(\" Exiting immediately. Note that files may not have finished syncing.\");\n process.exit(1);\n });\n }, 100).unref();\n\n void this.stop();\n });\n }\n\n const unsubscribe = this.client.subscribeUnwrap(\n {\n query: REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION,\n variables: () => ({ localFilesVersion: this.metadata.lastWritten.filesVersion }),\n },\n {\n error: (error) => void this.stop(error),\n next: ({ remoteFileSyncEvents }) => {\n if (!remoteFileSyncEvents.changed.length && !remoteFileSyncEvents.deleted.length) {\n return;\n }\n\n const { remoteFilesVersion, changed, deleted } = remoteFileSyncEvents;\n const remoteFiles = new Map([...deleted, ...changed].map((e) => [e.path, e]));\n\n void this.queue\n .add(async () => {\n this.log(\"Received\");\n this.logPaths(Array.from(remoteFiles.keys()), { sep: \"←\" });\n\n await pMap(\n remoteFiles,\n async ([relativePath, file]) => {\n const filepath = this.absolute(relativePath);\n this.recentWrites.add(filepath);\n\n if (\"content\" in file) {\n await fs.ensureDir(path.dirname(filepath), { mode: 0o755 });\n if (!file.path.endsWith(\"/\")) await fs.writeFile(filepath, this.encoder.encode(file.content), { mode: file.mode });\n } else {\n await fs.remove(filepath);\n }\n\n if (filepath == this.ignorer.filepath) {\n this.ignorer.reload();\n }\n },\n { stopOnError: false }\n );\n\n this.metadata.lastWritten.filesVersion = remoteFilesVersion;\n })\n .catch(this.stop);\n },\n }\n );\n\n const localFilesBuffer = new Map<string, { mode: number; mtime: number } | false>();\n\n this.publish = debounce(() => {\n const localFiles = new Map(localFilesBuffer.entries());\n localFilesBuffer.clear();\n\n void this.queue\n .add(async () => {\n const changed: FileSyncChangedEventInput[] = [];\n const deleted: FileSyncDeletedEventInput[] = [];\n\n await pMap(\n localFiles,\n async ([filepath, file]) => {\n if (file) {\n try {\n changed.push({\n path: this.normalize(filepath),\n mode: file.mode,\n content: this.decoder.decode(await fs.readFile(filepath)),\n });\n } catch (error) {\n // A file could have been changed and then deleted before we process the change event, so the readFile above will raise\n // an ENOENT. This is normal operation, so just ignore this event.\n ignoreEnoent(error);\n }\n } else {\n deleted.push({ path: this.normalize(filepath) });\n }\n },\n { stopOnError: false }\n );\n\n if (changed.length > 0 || deleted.length > 0) {\n this.log(\"Sent\");\n this.logPaths(Array.from(localFiles.keys()), { sep: \"→\" });\n\n const data = await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: { input: { expectedRemoteFilesVersion: this.metadata.lastWritten.filesVersion, changed, deleted } },\n });\n\n const { remoteFilesVersion } = data.publishFileSyncEvents;\n this.debug(\"remote files version after publishing %s\", remoteFilesVersion);\n\n if (BigInt(remoteFilesVersion) > BigInt(this.metadata.lastWritten.filesVersion)) {\n this.metadata.lastWritten.filesVersion = remoteFilesVersion;\n }\n }\n })\n .catch(this.stop);\n }, this.filePushDelay);\n\n this.watcher\n .add(`${this.dir}/**/*`)\n .on(\"error\", (error) => void this.stop(error))\n .on(\"all\", (event, filepath, stats) => {\n const relativePath = this.relative(filepath);\n\n if (event === \"addDir\") {\n this.debug(\"skipping event caused by added directory %s\", relativePath);\n return;\n }\n\n if (stats?.isSymbolicLink?.()) {\n this.debug(\"skipping event caused by symlink %s\", relativePath);\n return;\n }\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\", relativePath);\n return;\n }\n\n // we only update the lastWritten.mtime if the file is not ignored, because if we restart and the lastWritten.mtime is set to an\n // ignored 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.metadata.lastWritten.mtime) {\n this.metadata.lastWritten.mtime = stats.mtime.getTime();\n }\n\n if (this.recentWrites.delete(filepath)) {\n this.debug(\"skipping event caused by recent write %s\", relativePath);\n return;\n }\n\n this.debug(\"file changed %s\", relativePath);\n\n switch (event) {\n case \"add\":\n case \"change\":\n assert(stats, \"missing stats on add/change event\");\n localFilesBuffer.set(filepath, { mode: stats.mode, mtime: stats.mtime.getTime() });\n break;\n case \"unlink\":\n case \"unlinkDir\":\n localFilesBuffer.set(filepath, false);\n break;\n }\n\n this.publish();\n });\n\n this.log(\"Ready\");\n this.status = SyncStatus.RUNNING;\n\n await sleepUntil(() => this.status == SyncStatus.STOPPED, { timeout: Infinity });\n\n if (error) {\n this.notify({ subtitle: \"Uh oh!\", message: \"An error occurred while syncing files\" });\n throw error;\n } else {\n this.log(\"Done\");\n }\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) {\n remoteFilesVersion\n changed {\n path\n mode\n content\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"]}
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { Flags } from \"@oclif/core\";\nimport type { OptionFlag } from \"@oclif/core/lib/interfaces\";\nimport assert from \"assert\";\nimport { FSWatcher } from \"chokidar\";\nimport execa from \"execa\";\nimport type { Stats } from \"fs-extra\";\nimport fs from \"fs-extra\";\nimport { prompt } from \"inquirer\";\nimport type { DebouncedFunc } from \"lodash\";\nimport { debounce } from \"lodash\";\nimport normalizePath from \"normalize-path\";\nimport pMap from \"p-map\";\nimport PQueue from \"p-queue\";\nimport path from \"path\";\nimport dedent from \"ts-dedent\";\nimport { TextDecoder, TextEncoder } from \"util\";\nimport which from \"which\";\nimport { BaseCommand } from \"../lib/base-command\";\nimport type { Query } from \"../lib/client\";\nimport { InvalidSyncFileError, YarnNotFoundError } from \"../lib/errors\";\nimport { ignoreEnoent, Ignorer, isEmptyDir, walkDir } from \"../lib/fs-utils\";\nimport { sleepUntil } from \"../lib/sleep\";\nimport type {\n FileSyncChangedEventInput,\n FileSyncDeletedEventInput,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n} from \"../__generated__/graphql\";\n\nexport default class Sync extends BaseCommand {\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 --app <name> [DIRECTORY]\";\n\n static override description = dedent`\n Sync provides the ability to sync your Gadget application's source code to and from your local\n filesystem. While \\`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 (https://code.visualstudio.com/)\n * Storing your source code in a Git repository like GitHub (https://github.com/)\n\n Sync includes the concept of a \\`.ignore\\` file. This file can contain a list of files and\n directories that won't be sent to Gadget when syncing.\n\n The following files and directories are always ignored:\n * .gadget\n * .ggt\n * .git\n * node_modules\n\n Note:\n * Gadget applications only support installing dependencies with Yarn 1 (https://classic.yarnpkg.com/lang/en/).\n * Since file changes are immediately reflected in Gadget, avoid the following while \\`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 {\n name: \"directory\",\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 force: Flags.boolean({\n summary: \"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 }) as OptionFlag<number>,\n \"file-stability-threshold\": Flags.integer({\n name: \"file-stability-threshold\",\n summary: \"Time in milliseconds a file's size must remain the same.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 500,\n hidden: true,\n }) as OptionFlag<number>,\n \"file-poll-interval\": Flags.integer({\n name: \"file-poll-interval\",\n description: \"Interval in milliseconds between polling a file's size.\",\n helpGroup: \"file\",\n helpValue: \"ms\",\n default: 100,\n hidden: true,\n }) as OptionFlag<number>,\n };\n\n static override examples = [\n dedent`\n $ ggt sync --app my-app ~/gadget/my-app\n Ready\n Received\n ← routes/GET.js\n ← user/signUp/signIn.js\n Sent\n → routes/GET.js\n ^C Stopping... (press Ctrl+C again to force)\n Done\n `,\n dedent`\n # These are equivalent\n $ ggt sync -A my-app\n $ ggt sync --app my-app\n $ ggt sync --app my-app.gadget.app\n $ ggt sync --app https://my-app.gadget.app\n $ ggt sync --app https://my-app.gadget.app/edit\n `,\n ];\n\n override readonly requireApp = true;\n\n status = SyncStatus.STARTING;\n\n dir!: string;\n\n recentWrites = new Set();\n\n encoder = new TextEncoder();\n\n decoder = new TextDecoder();\n\n filePushDelay!: number;\n\n queue = new PQueue({ concurrency: 1 });\n\n ignorer!: Ignorer;\n\n watcher!: FSWatcher;\n\n metadata = {\n lastWritten: {\n filesVersion: \"0\",\n mtime: 0,\n },\n };\n\n publish!: DebouncedFunc<() => void>;\n\n stop!: (error?: unknown) => Promise<void>;\n\n relative(to: string): string {\n return path.relative(this.dir, to);\n }\n\n absolute(...pathSegments: string[]): string {\n return path.resolve(this.dir, ...pathSegments);\n }\n\n normalize(filepath: string): string {\n return normalizePath(path.isAbsolute(filepath) ? this.relative(filepath) : filepath);\n }\n\n logPaths(filepaths: string[], { limit = 10, sep = \"-\" } = {}): void {\n let logged = 0;\n for (const filepath of filepaths) {\n this.log(`${sep} ${this.normalize(filepath)}`);\n if (++logged == limit && !this.debugEnabled) break;\n }\n\n if (filepaths.length > logged) {\n this.log(`… ${filepaths.length - logged} more`);\n }\n }\n\n override async init(): Promise<void> {\n await super.init();\n const { args, flags } = await this.parse(Sync);\n\n this.dir = path.resolve(args[\"directory\"] as string);\n\n this.filePushDelay = flags[\"file-push-delay\"];\n\n // local files that should never be published\n const ignored = [\"node_modules/\", \".gadget/\", \".ggt/\", \".git/\"];\n\n this.ignorer = new Ignorer(this.dir, ignored);\n\n this.watcher = new FSWatcher({\n ignored,\n // don't emit an event for every watched file on boot\n ignoreInitial: true,\n // make sure stats are always present on add/change events\n alwaysStat: true,\n // wait for the entire file to be written before emitting add/change events\n awaitWriteFinish: { pollInterval: flags[\"file-poll-interval\"], stabilityThreshold: flags[\"file-stability-threshold\"] },\n });\n\n this.debug(\"starting\");\n\n if (!which.sync(\"yarn\", { nothrow: true })) {\n throw new YarnNotFoundError();\n }\n\n await fs.ensureDir(this.dir);\n\n if (!(await isEmptyDir(this.dir))) {\n try {\n this.metadata = await fs.readJson(this.absolute(\".ggt\", \"sync.json\"));\n } catch (error) {\n if (!flags.force) {\n throw new InvalidSyncFileError(error, this.dir, this.app);\n }\n }\n }\n\n const { remoteFilesVersion } = await this.client.queryUnwrap({ query: REMOTE_FILES_VERSION_QUERY });\n const hasRemoteChanges = BigInt(remoteFilesVersion) > BigInt(this.metadata.lastWritten.filesVersion);\n\n const getChangedFiles = async (): Promise<Map<string, Stats>> => {\n const files = new Map();\n for await (const filepath of walkDir(this.dir, { ignorer: this.ignorer })) {\n const stats = await fs.stat(filepath);\n if (stats.mtime.getTime() > this.metadata.lastWritten.mtime) {\n files.set(this.absolute(filepath), stats);\n }\n }\n return files;\n };\n\n const changedFiles = await getChangedFiles();\n const hasLocalChanges = changedFiles.size > 0;\n if (hasLocalChanges) {\n this.log(\"Local files have changed since the last sync\");\n this.logPaths(Array.from(changedFiles.keys()), { limit: changedFiles.size });\n this.log();\n }\n\n this.debug(\"init %o\", { metadata: this.metadata, remoteFilesVersion, hasRemoteChanges, hasLocalChanges });\n\n let action: Action | undefined;\n if (hasLocalChanges) {\n ({ action } = await 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 switch (action) {\n case Action.MERGE: {\n // get all the changed files again in case more changed\n const files = await getChangedFiles();\n\n // we purposefully don't set the returned remoteFilesVersion here because we haven't processed the in-between versions yet\n await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: {\n input: {\n expectedRemoteFilesVersion: remoteFilesVersion,\n changed: await pMap(files, async ([filepath, stats]) => {\n if (stats.mtime.getTime() > this.metadata.lastWritten.mtime) {\n this.metadata.lastWritten.mtime = stats.mtime.getTime();\n }\n\n return {\n path: this.normalize(filepath),\n mode: stats.mode,\n content: await fs.readFile(filepath, \"utf-8\"),\n };\n }),\n deleted: [],\n },\n },\n });\n break;\n }\n case Action.RESET: {\n await pMap(changedFiles, ([filepath]) => fs.remove(filepath));\n this.metadata.lastWritten.filesVersion = \"0\";\n break;\n }\n case Action.CANCEL: {\n process.exit(0);\n }\n }\n\n this.debug(\"started\");\n }\n\n async run(): Promise<void> {\n let error: unknown;\n\n this.stop = async (e?: unknown) => {\n if (this.status != SyncStatus.RUNNING) return;\n\n error = e;\n this.debug(\"stopping\");\n this.status = SyncStatus.STOPPING;\n\n try {\n unsubscribe();\n this.watcher.removeAllListeners();\n this.publish.flush();\n await this.queue.onIdle();\n } finally {\n await fs.outputJSON(this.absolute(\".ggt\", \"sync.json\"), this.metadata, { spaces: 2 });\n await Promise.allSettled([this.watcher.close(), this.client.dispose()]);\n\n this.debug(\"stopped\");\n this.status = SyncStatus.STOPPED;\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(\" Stopping... (press Ctrl+C again to force)\");\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(\"SIGINT\", () => {\n this.log(\" Exiting immediately. Note that files may not have finished syncing.\");\n process.exit(1);\n });\n }, 100).unref();\n\n void this.stop();\n });\n }\n\n const unsubscribe = this.client.subscribeUnwrap(\n {\n query: REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION,\n variables: () => ({ localFilesVersion: this.metadata.lastWritten.filesVersion }),\n },\n {\n error: (error) => void this.stop(error),\n next: ({ remoteFileSyncEvents }) => {\n if (!remoteFileSyncEvents.changed.length && !remoteFileSyncEvents.deleted.length) {\n return;\n }\n\n const { remoteFilesVersion, changed, deleted } = remoteFileSyncEvents;\n const remoteFiles = new Map([...deleted, ...changed].map((e) => [e.path, e]));\n\n void this.queue\n .add(async () => {\n this.log(\"Received\");\n this.logPaths(Array.from(remoteFiles.keys()), { sep: \"←\" });\n\n await pMap(\n remoteFiles,\n async ([relativePath, file]) => {\n const filepath = this.absolute(relativePath);\n this.recentWrites.add(filepath);\n\n if (\"content\" in file) {\n await fs.ensureDir(path.dirname(filepath), { mode: 0o755 });\n if (!file.path.endsWith(\"/\")) await fs.writeFile(filepath, this.encoder.encode(file.content), { mode: file.mode });\n if (filepath == this.absolute(\"yarn.lock\")) await execa(\"yarn\", [\"install\"], { cwd: this.dir });\n } else {\n await fs.remove(filepath);\n }\n\n if (filepath == this.ignorer.filepath) {\n this.ignorer.reload();\n }\n },\n { stopOnError: false }\n );\n\n this.metadata.lastWritten.filesVersion = remoteFilesVersion;\n })\n .catch(this.stop);\n },\n }\n );\n\n const localFilesBuffer = new Map<string, { mode: number; mtime: number } | false>();\n\n this.publish = debounce(() => {\n const localFiles = new Map(localFilesBuffer.entries());\n localFilesBuffer.clear();\n\n void this.queue\n .add(async () => {\n const changed: FileSyncChangedEventInput[] = [];\n const deleted: FileSyncDeletedEventInput[] = [];\n\n await pMap(\n localFiles,\n async ([filepath, file]) => {\n if (file) {\n try {\n changed.push({\n path: this.normalize(filepath),\n mode: file.mode,\n content: this.decoder.decode(await fs.readFile(filepath)),\n });\n } catch (error) {\n // A file could have been changed and then deleted before we process the change event, so the readFile above will raise\n // an ENOENT. This is normal operation, so just ignore this event.\n ignoreEnoent(error);\n }\n } else {\n deleted.push({ path: this.normalize(filepath) });\n }\n },\n { stopOnError: false }\n );\n\n if (changed.length > 0 || deleted.length > 0) {\n this.log(\"Sent\");\n this.logPaths(Array.from(localFiles.keys()), { sep: \"→\" });\n\n const data = await this.client.queryUnwrap({\n query: PUBLISH_FILE_SYNC_EVENTS_MUTATION,\n variables: { input: { expectedRemoteFilesVersion: this.metadata.lastWritten.filesVersion, changed, deleted } },\n });\n\n const { remoteFilesVersion } = data.publishFileSyncEvents;\n this.debug(\"remote files version after publishing %s\", remoteFilesVersion);\n\n if (BigInt(remoteFilesVersion) > BigInt(this.metadata.lastWritten.filesVersion)) {\n this.metadata.lastWritten.filesVersion = remoteFilesVersion;\n }\n }\n })\n .catch(this.stop);\n }, this.filePushDelay);\n\n this.watcher\n .add(`${this.dir}/**/*`)\n .on(\"error\", (error) => void this.stop(error))\n .on(\"all\", (event, filepath, stats) => {\n const relativePath = this.relative(filepath);\n\n if (event === \"addDir\") {\n this.debug(\"skipping event caused by added directory %s\", relativePath);\n return;\n }\n\n if (stats?.isSymbolicLink?.()) {\n this.debug(\"skipping event caused by symlink %s\", relativePath);\n return;\n }\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\", relativePath);\n return;\n }\n\n // we only update the lastWritten.mtime if the file is not ignored, because if we restart and the lastWritten.mtime is set to an\n // ignored 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.metadata.lastWritten.mtime) {\n this.metadata.lastWritten.mtime = stats.mtime.getTime();\n }\n\n if (this.recentWrites.delete(filepath)) {\n this.debug(\"skipping event caused by recent write %s\", relativePath);\n return;\n }\n\n this.debug(\"file changed %s\", relativePath);\n\n switch (event) {\n case \"add\":\n case \"change\":\n assert(stats, \"missing stats on add/change event\");\n localFilesBuffer.set(filepath, { mode: stats.mode, mtime: stats.mtime.getTime() });\n break;\n case \"unlink\":\n case \"unlinkDir\":\n localFilesBuffer.set(filepath, false);\n break;\n }\n\n this.publish();\n });\n\n this.log(\"Ready\");\n this.status = SyncStatus.RUNNING;\n\n await sleepUntil(() => this.status == SyncStatus.STOPPED, { timeout: Infinity });\n\n if (error) {\n this.notify({ subtitle: \"Uh oh!\", message: \"An error occurred while syncing files\" });\n throw error;\n } else {\n this.log(\"Done\");\n }\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) {\n remoteFilesVersion\n changed {\n path\n mode\n content\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"]}
|
|
@@ -24,6 +24,14 @@ export declare abstract class BaseCommand extends Command {
|
|
|
24
24
|
* Indicates whether the command is being run with the `-D/--debug` flag.
|
|
25
25
|
*/
|
|
26
26
|
debugEnabled: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The selected application.
|
|
29
|
+
*
|
|
30
|
+
* Will be `undefined` if the user is not logged in or if the user has not selected an app.
|
|
31
|
+
*
|
|
32
|
+
* @see {@linkcode requireApp requireApp}
|
|
33
|
+
*/
|
|
34
|
+
app: string;
|
|
27
35
|
/**
|
|
28
36
|
* Determines whether the command requires the user to be logged in or not.
|
|
29
37
|
* If true and the user is not logged in, the user will be prompted to login before the command is run.
|
package/dist/lib/base-command.js
CHANGED
|
@@ -31,6 +31,19 @@ class BaseCommand extends core_1.Command {
|
|
|
31
31
|
writable: true,
|
|
32
32
|
value: false
|
|
33
33
|
});
|
|
34
|
+
/**
|
|
35
|
+
* The selected application.
|
|
36
|
+
*
|
|
37
|
+
* Will be `undefined` if the user is not logged in or if the user has not selected an app.
|
|
38
|
+
*
|
|
39
|
+
* @see {@linkcode requireApp requireApp}
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(this, "app", {
|
|
42
|
+
enumerable: true,
|
|
43
|
+
configurable: true,
|
|
44
|
+
writable: true,
|
|
45
|
+
value: void 0
|
|
46
|
+
});
|
|
34
47
|
/**
|
|
35
48
|
* Determines whether the command requires the user to be logged in or not.
|
|
36
49
|
* If true and the user is not logged in, the user will be prompted to login before the command is run.
|
|
@@ -117,7 +130,7 @@ class BaseCommand extends core_1.Command {
|
|
|
117
130
|
async init() {
|
|
118
131
|
await super.init();
|
|
119
132
|
const { flags, argv } = await this.parse({ flags: BaseCommand.globalFlags, strict: false });
|
|
120
|
-
// remove global flags from argv
|
|
133
|
+
// remove global flags from argv so that when the implementation calls parse, it doesn't get confused by them
|
|
121
134
|
this.argv = argv;
|
|
122
135
|
if (flags.debug) {
|
|
123
136
|
this.debugEnabled = true;
|
|
@@ -149,6 +162,7 @@ class BaseCommand extends core_1.Command {
|
|
|
149
162
|
choices: await this.getApps().then((apps) => apps.map((app) => app.slug)),
|
|
150
163
|
}));
|
|
151
164
|
}
|
|
165
|
+
this.app = app;
|
|
152
166
|
this.client = new client_1.Client(app, {
|
|
153
167
|
ws: {
|
|
154
168
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-command.js","sourceRoot":"","sources":["../../src/lib/base-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Config } from \"@oclif/core\";\nimport { Command, Flags } from \"@oclif/core\";\nimport { ExitError } from \"@oclif/core/lib/errors\";\nimport { CLIError } from \"@oclif/errors\";\nimport Debug from \"debug\";\nimport fs from \"fs-extra\";\nimport getPort from \"get-port\";\nimport type { Got } from \"got\";\nimport got, { HTTPError } from \"got\";\nimport type { Server } from \"http\";\nimport { createServer } from \"http\";\nimport { prompt } from \"inquirer\";\nimport type { Notification } from \"node-notifier\";\nimport { notify } from \"node-notifier\";\nimport type WindowsBalloon from \"node-notifier/notifiers/balloon\";\nimport type Growl from \"node-notifier/notifiers/growl\";\nimport type NotificationCenter from \"node-notifier/notifiers/notificationcenter\";\nimport type NotifySend from \"node-notifier/notifiers/notifysend\";\nimport type WindowsToaster from \"node-notifier/notifiers/toaster\";\nimport open from \"open\";\nimport path from \"path\";\nimport { Client } from \"./client\";\nimport { Env } from \"./env\";\nimport { BaseError, UnexpectedError as UnknownError } from \"./errors\";\nimport { ignoreEnoent } from \"./fs-utils\";\nimport type { App, User } from \"./types\";\n\nexport const ENDPOINT = Env.productionLike ? \"https://app.gadget.dev\" : \"https://app.ggt.dev:3000\";\n\nexport abstract class BaseCommand extends Command {\n /**\n * Determines how high the command is listed in the README. The lower the number, the higher the command is listed. Equal numbers are\n * sorted alphabetically.\n */\n static priority = Infinity;\n\n static override globalFlags = {\n app: Flags.string({\n char: \"A\",\n summary: \"The Gadget application this command applies to.\",\n helpGroup: \"global\",\n helpValue: \"name\",\n parse: (value) => {\n const app = /^(https:\\/\\/)?(?<app>[\\w-]+)(\\..*)?/.exec(value)?.groups?.[\"app\"];\n if (!app) throw new CLIError(\"Flag '-A, --app=<name>' is invalid\");\n return Promise.resolve(app);\n },\n }),\n debug: Flags.boolean({\n char: \"D\",\n summary: \"Whether to output debug information.\",\n helpGroup: \"global\",\n default: false,\n }),\n };\n\n /**\n * Indicates whether the command is being run with the `-D/--debug` flag.\n */\n debugEnabled = false;\n\n /**\n * Determines whether the command requires the user to be logged in or not.\n * If true and the user is not logged in, the user will be prompted to login before the command is run.\n */\n readonly requireUser: boolean = false;\n\n /**\n * Determines whether the command requires a Gadget app to be selected or not.\n * If true and an app hasn't been selected, the user will be prompted to select an app before the command is run.\n *\n * Implies {@linkcode requireUser requireUser = true}.\n */\n readonly requireApp: boolean = false;\n\n /**\n * The HTTP client to use for all HTTP requests.\n *\n * If a request is made to Gadget, the session token will be added to the request's headers.\n */\n readonly http: Got;\n\n /**\n * The GraphQL client to use for all Gadget API requests.\n *\n * Will be `undefined` if the user is not logged in or if the user has not selected an app.\n *\n * @see {@linkcode requireApp requireApp}\n */\n client!: Client;\n\n private _session?: string;\n\n constructor(argv: string[], config: Config) {\n super(argv, config);\n\n this.http = got.extend({\n hooks: {\n beforeRequest: [\n (options) => {\n options.headers[\"user-agent\"] = this.config.userAgent;\n if (options.url.origin === ENDPOINT && this.session) {\n options.headers = { ...options.headers, cookie: `session=${encodeURIComponent(this.session)};` };\n }\n },\n ],\n },\n });\n }\n\n get session(): string | undefined {\n try {\n return (this._session ??= fs.readFileSync(path.join(this.config.configDir, \"session.txt\"), \"utf-8\"));\n } catch (error) {\n ignoreEnoent(error);\n return undefined;\n }\n }\n\n set session(value: string | undefined) {\n this._session = value;\n if (value) {\n fs.outputFileSync(path.join(this.config.configDir, \"session.txt\"), value);\n } else {\n fs.removeSync(path.join(this.config.configDir, \"session.txt\"));\n }\n }\n\n override async init(): Promise<void> {\n await super.init();\n const { flags, argv } = await this.parse({ flags: BaseCommand.globalFlags, strict: false });\n\n // remove global flags from argv\n this.argv = argv;\n\n if (flags.debug) {\n this.debugEnabled = true;\n Debug.enable(`${this.config.bin}:*`);\n }\n\n if (!this.requireUser && !this.requireApp) {\n return;\n }\n\n if (!(await this.getCurrentUser())) {\n const { login } = await prompt<{ login: boolean }>({\n type: \"confirm\",\n name: \"login\",\n message: \"You must be logged in to use this command. Would you like to log in?\",\n });\n\n if (!login) {\n return this.exit(0);\n }\n\n await this.login();\n }\n\n if (!this.requireApp) {\n return;\n }\n\n let app = flags.app;\n if (!app) {\n ({ app } = await prompt<{ app: string }>({\n type: \"list\",\n name: \"app\",\n message: \"Please select the app to use with this command.\",\n choices: await this.getApps().then((apps) => apps.map((app) => app.slug)),\n }));\n }\n\n this.client = new Client(app, {\n ws: {\n headers: {\n \"user-agent\": this.config.userAgent,\n cookie: `session=${encodeURIComponent(this.session as string)};`,\n },\n },\n });\n }\n\n /**\n * Sends a native OS notification to the user.\n *\n * @see {@link https://www.npmjs.com/package/node-notifier node-notifier}\n */\n notify(\n notification:\n | Notification\n | NotificationCenter.Notification\n | NotifySend.Notification\n | WindowsToaster.Notification\n | WindowsBalloon.Notification\n | Growl.Notification\n ): void {\n notify(\n {\n title: \"Gadget\",\n contentImage: path.join(this.config.root, \"assets\", \"favicon-128@4x.png\"),\n icon: path.join(this.config.root, \"assets\", \"favicon-128@4x.png\"),\n sound: true,\n timeout: false,\n ...notification,\n },\n (error) => {\n if (error) this.warn(error);\n }\n );\n }\n\n /**\n * Opens the Gadget login page in the user's default browser and waits for the user to login.\n */\n async login(): Promise<void> {\n let server: Server | undefined;\n\n try {\n const port = await getPort();\n const receiveSession = new Promise<void>((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n server = createServer(async (req, res) => {\n const redirectTo = new URL(`${ENDPOINT}/auth/cli`);\n\n try {\n if (!req.url) throw new Error(\"missing url\");\n const incomingUrl = new URL(req.url, `http://localhost:${port}`);\n\n const session = incomingUrl.searchParams.get(\"session\");\n if (!session) throw new Error(\"missing session\");\n\n this.session = session;\n\n const user = await this.getCurrentUser();\n if (!user) throw new Error(\"missing current user\");\n\n if (user.name) {\n this.log(`Hello, ${user.name} (${user.email})`);\n } else {\n this.log(`Hello, ${user.email}`);\n }\n\n redirectTo.searchParams.set(\"success\", \"true\");\n resolve();\n } catch (error) {\n this.session = undefined;\n redirectTo.searchParams.set(\"success\", \"false\");\n reject(error);\n } finally {\n res.writeHead(303, { Location: redirectTo.toString() });\n res.end();\n }\n });\n\n server.listen(port);\n });\n\n const url = new URL(`${ENDPOINT}/auth/login`);\n url.searchParams.set(\"returnTo\", `${ENDPOINT}/auth/cli/callback?port=${port}`);\n await open(url.toString());\n\n this.log(\"Your browser has been opened. Please log in to your account.\");\n\n await receiveSession;\n } finally {\n server?.close();\n }\n }\n\n /**\n * @returns Whether the user was logged in or not.\n */\n logout(): boolean {\n if (!this.session) return false;\n\n this.session = undefined;\n return true;\n }\n\n /**\n * @returns The current user, or undefined if the user is not logged in.\n */\n async getCurrentUser(): Promise<User | undefined> {\n if (!this.session) return undefined;\n\n try {\n return await this.http(`${ENDPOINT}/auth/api/current-user`).json<User>();\n } catch (error) {\n if (error instanceof HTTPError && error.response.statusCode === 401) {\n this.logout();\n return undefined;\n }\n throw error;\n }\n }\n\n /**\n * @returns A list of Gadget apps that the user has access to.\n */\n async getApps(): Promise<App[]> {\n if (!this.session) return [];\n\n return await this.http(`${ENDPOINT}/auth/api/apps`).json<App[]>();\n }\n\n /**\n * Overrides the default `catch` behavior so we can control how errors are printed to the user. This is called automatically by oclif when\n * an error is thrown during the `init` or `run` methods.\n */\n override catch(cause: Error & { exitCode?: number }): never {\n const error = cause instanceof BaseError ? cause : new UnknownError(cause);\n console.error(error.render(this.config));\n\n // The original implementation of `catch` re-throws the error so that it's caught and printed by oclif's `handle` method. We still want\n // to end up in oclif's `handle` method, but we don't want it to print the error again so we throw an ExitError instead. This will cause\n // `handle` to not print the error, but still exit with the correct exit code.\n //\n // catch: https://github.com/oclif/core/blob/12e31ff2288606e583e03bf774a3244f3136cd10/src/command.ts#L261\n // handle: https://github.com/oclif/core/blob/12e31ff2288606e583e03bf774a3244f3136cd10/src/errors/handle.ts#L15\n throw new ExitError(process.exitCode ?? cause.exitCode ?? 1);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base-command.js","sourceRoot":"","sources":["../../src/lib/base-command.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Config } from \"@oclif/core\";\nimport { Command, Flags } from \"@oclif/core\";\nimport { ExitError } from \"@oclif/core/lib/errors\";\nimport { CLIError } from \"@oclif/errors\";\nimport Debug from \"debug\";\nimport fs from \"fs-extra\";\nimport getPort from \"get-port\";\nimport type { Got } from \"got\";\nimport got, { HTTPError } from \"got\";\nimport type { Server } from \"http\";\nimport { createServer } from \"http\";\nimport { prompt } from \"inquirer\";\nimport type { Notification } from \"node-notifier\";\nimport { notify } from \"node-notifier\";\nimport type WindowsBalloon from \"node-notifier/notifiers/balloon\";\nimport type Growl from \"node-notifier/notifiers/growl\";\nimport type NotificationCenter from \"node-notifier/notifiers/notificationcenter\";\nimport type NotifySend from \"node-notifier/notifiers/notifysend\";\nimport type WindowsToaster from \"node-notifier/notifiers/toaster\";\nimport open from \"open\";\nimport path from \"path\";\nimport { Client } from \"./client\";\nimport { Env } from \"./env\";\nimport { BaseError, UnexpectedError as UnknownError } from \"./errors\";\nimport { ignoreEnoent } from \"./fs-utils\";\nimport type { App, User } from \"./types\";\n\nexport const ENDPOINT = Env.productionLike ? \"https://app.gadget.dev\" : \"https://app.ggt.dev:3000\";\n\nexport abstract class BaseCommand extends Command {\n /**\n * Determines how high the command is listed in the README. The lower the number, the higher the command is listed. Equal numbers are\n * sorted alphabetically.\n */\n static priority = Infinity;\n\n static override globalFlags = {\n app: Flags.string({\n char: \"A\",\n summary: \"The Gadget application this command applies to.\",\n helpGroup: \"global\",\n helpValue: \"name\",\n parse: (value) => {\n const app = /^(https:\\/\\/)?(?<app>[\\w-]+)(\\..*)?/.exec(value)?.groups?.[\"app\"];\n if (!app) throw new CLIError(\"Flag '-A, --app=<name>' is invalid\");\n return Promise.resolve(app);\n },\n }),\n debug: Flags.boolean({\n char: \"D\",\n summary: \"Whether to output debug information.\",\n helpGroup: \"global\",\n default: false,\n }),\n };\n\n /**\n * Indicates whether the command is being run with the `-D/--debug` flag.\n */\n debugEnabled = false;\n\n /**\n * The selected application.\n *\n * Will be `undefined` if the user is not logged in or if the user has not selected an app.\n *\n * @see {@linkcode requireApp requireApp}\n */\n app!: string;\n\n /**\n * Determines whether the command requires the user to be logged in or not.\n * If true and the user is not logged in, the user will be prompted to login before the command is run.\n */\n readonly requireUser: boolean = false;\n\n /**\n * Determines whether the command requires a Gadget app to be selected or not.\n * If true and an app hasn't been selected, the user will be prompted to select an app before the command is run.\n *\n * Implies {@linkcode requireUser requireUser = true}.\n */\n readonly requireApp: boolean = false;\n\n /**\n * The HTTP client to use for all HTTP requests.\n *\n * If a request is made to Gadget, the session token will be added to the request's headers.\n */\n readonly http: Got;\n\n /**\n * The GraphQL client to use for all Gadget API requests.\n *\n * Will be `undefined` if the user is not logged in or if the user has not selected an app.\n *\n * @see {@linkcode requireApp requireApp}\n */\n client!: Client;\n\n private _session?: string;\n\n constructor(argv: string[], config: Config) {\n super(argv, config);\n\n this.http = got.extend({\n hooks: {\n beforeRequest: [\n (options) => {\n options.headers[\"user-agent\"] = this.config.userAgent;\n if (options.url.origin === ENDPOINT && this.session) {\n options.headers = { ...options.headers, cookie: `session=${encodeURIComponent(this.session)};` };\n }\n },\n ],\n },\n });\n }\n\n get session(): string | undefined {\n try {\n return (this._session ??= fs.readFileSync(path.join(this.config.configDir, \"session.txt\"), \"utf-8\"));\n } catch (error) {\n ignoreEnoent(error);\n return undefined;\n }\n }\n\n set session(value: string | undefined) {\n this._session = value;\n if (value) {\n fs.outputFileSync(path.join(this.config.configDir, \"session.txt\"), value);\n } else {\n fs.removeSync(path.join(this.config.configDir, \"session.txt\"));\n }\n }\n\n override async init(): Promise<void> {\n await super.init();\n const { flags, argv } = await this.parse({ flags: BaseCommand.globalFlags, strict: false });\n\n // remove global flags from argv so that when the implementation calls parse, it doesn't get confused by them\n this.argv = argv;\n\n if (flags.debug) {\n this.debugEnabled = true;\n Debug.enable(`${this.config.bin}:*`);\n }\n\n if (!this.requireUser && !this.requireApp) {\n return;\n }\n\n if (!(await this.getCurrentUser())) {\n const { login } = await prompt<{ login: boolean }>({\n type: \"confirm\",\n name: \"login\",\n message: \"You must be logged in to use this command. Would you like to log in?\",\n });\n\n if (!login) {\n return this.exit(0);\n }\n\n await this.login();\n }\n\n if (!this.requireApp) {\n return;\n }\n\n let app = flags.app;\n if (!app) {\n ({ app } = await prompt<{ app: string }>({\n type: \"list\",\n name: \"app\",\n message: \"Please select the app to use with this command.\",\n choices: await this.getApps().then((apps) => apps.map((app) => app.slug)),\n }));\n }\n\n this.app = app;\n\n this.client = new Client(app, {\n ws: {\n headers: {\n \"user-agent\": this.config.userAgent,\n cookie: `session=${encodeURIComponent(this.session as string)};`,\n },\n },\n });\n }\n\n /**\n * Sends a native OS notification to the user.\n *\n * @see {@link https://www.npmjs.com/package/node-notifier node-notifier}\n */\n notify(\n notification:\n | Notification\n | NotificationCenter.Notification\n | NotifySend.Notification\n | WindowsToaster.Notification\n | WindowsBalloon.Notification\n | Growl.Notification\n ): void {\n notify(\n {\n title: \"Gadget\",\n contentImage: path.join(this.config.root, \"assets\", \"favicon-128@4x.png\"),\n icon: path.join(this.config.root, \"assets\", \"favicon-128@4x.png\"),\n sound: true,\n timeout: false,\n ...notification,\n },\n (error) => {\n if (error) this.warn(error);\n }\n );\n }\n\n /**\n * Opens the Gadget login page in the user's default browser and waits for the user to login.\n */\n async login(): Promise<void> {\n let server: Server | undefined;\n\n try {\n const port = await getPort();\n const receiveSession = new Promise<void>((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n server = createServer(async (req, res) => {\n const redirectTo = new URL(`${ENDPOINT}/auth/cli`);\n\n try {\n if (!req.url) throw new Error(\"missing url\");\n const incomingUrl = new URL(req.url, `http://localhost:${port}`);\n\n const session = incomingUrl.searchParams.get(\"session\");\n if (!session) throw new Error(\"missing session\");\n\n this.session = session;\n\n const user = await this.getCurrentUser();\n if (!user) throw new Error(\"missing current user\");\n\n if (user.name) {\n this.log(`Hello, ${user.name} (${user.email})`);\n } else {\n this.log(`Hello, ${user.email}`);\n }\n\n redirectTo.searchParams.set(\"success\", \"true\");\n resolve();\n } catch (error) {\n this.session = undefined;\n redirectTo.searchParams.set(\"success\", \"false\");\n reject(error);\n } finally {\n res.writeHead(303, { Location: redirectTo.toString() });\n res.end();\n }\n });\n\n server.listen(port);\n });\n\n const url = new URL(`${ENDPOINT}/auth/login`);\n url.searchParams.set(\"returnTo\", `${ENDPOINT}/auth/cli/callback?port=${port}`);\n await open(url.toString());\n\n this.log(\"Your browser has been opened. Please log in to your account.\");\n\n await receiveSession;\n } finally {\n server?.close();\n }\n }\n\n /**\n * @returns Whether the user was logged in or not.\n */\n logout(): boolean {\n if (!this.session) return false;\n\n this.session = undefined;\n return true;\n }\n\n /**\n * @returns The current user, or undefined if the user is not logged in.\n */\n async getCurrentUser(): Promise<User | undefined> {\n if (!this.session) return undefined;\n\n try {\n return await this.http(`${ENDPOINT}/auth/api/current-user`).json<User>();\n } catch (error) {\n if (error instanceof HTTPError && error.response.statusCode === 401) {\n this.logout();\n return undefined;\n }\n throw error;\n }\n }\n\n /**\n * @returns A list of Gadget apps that the user has access to.\n */\n async getApps(): Promise<App[]> {\n if (!this.session) return [];\n\n return await this.http(`${ENDPOINT}/auth/api/apps`).json<App[]>();\n }\n\n /**\n * Overrides the default `catch` behavior so we can control how errors are printed to the user. This is called automatically by oclif when\n * an error is thrown during the `init` or `run` methods.\n */\n override catch(cause: Error & { exitCode?: number }): never {\n const error = cause instanceof BaseError ? cause : new UnknownError(cause);\n console.error(error.render(this.config));\n\n // The original implementation of `catch` re-throws the error so that it's caught and printed by oclif's `handle` method. We still want\n // to end up in oclif's `handle` method, but we don't want it to print the error again so we throw an ExitError instead. This will cause\n // `handle` to not print the error, but still exit with the correct exit code.\n //\n // catch: https://github.com/oclif/core/blob/12e31ff2288606e583e03bf774a3244f3136cd10/src/command.ts#L261\n // handle: https://github.com/oclif/core/blob/12e31ff2288606e583e03bf774a3244f3136cd10/src/errors/handle.ts#L15\n throw new ExitError(process.exitCode ?? cause.exitCode ?? 1);\n }\n}\n"]}
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -65,10 +65,16 @@ export declare class ClientError extends BaseError {
|
|
|
65
65
|
body(_: Config): string;
|
|
66
66
|
protected issueOptions(config: Config): newGithubIssueUrl.Options;
|
|
67
67
|
}
|
|
68
|
-
export declare class
|
|
68
|
+
export declare class YarnNotFoundError extends BaseError {
|
|
69
|
+
isBug: IsBug;
|
|
70
|
+
constructor();
|
|
71
|
+
protected body(_: Config): string;
|
|
72
|
+
}
|
|
73
|
+
export declare class InvalidSyncFileError extends BaseError {
|
|
74
|
+
readonly cause: unknown;
|
|
69
75
|
readonly dir: string;
|
|
70
|
-
readonly
|
|
76
|
+
readonly app: string;
|
|
71
77
|
isBug: IsBug;
|
|
72
|
-
constructor(dir: string,
|
|
73
|
-
body(
|
|
78
|
+
constructor(cause: unknown, dir: string, app: string);
|
|
79
|
+
protected body(config: Config): string;
|
|
74
80
|
}
|
package/dist/lib/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.InvalidSyncFileError = exports.YarnNotFoundError = exports.ClientError = exports.UnexpectedError = exports.IsBug = exports.serializeError = exports.BaseError = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const clean_stack_1 = tslib_1.__importDefault(require("clean-stack"));
|
|
6
6
|
const source_1 = require("got/dist/source");
|
|
@@ -276,38 +276,74 @@ class ClientError extends BaseError {
|
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
exports.ClientError = ClientError;
|
|
279
|
-
class
|
|
280
|
-
constructor(
|
|
281
|
-
super("
|
|
279
|
+
class YarnNotFoundError extends BaseError {
|
|
280
|
+
constructor() {
|
|
281
|
+
super("GGT_CLI_YARN_NOT_FOUND", "Yarn not found");
|
|
282
|
+
Object.defineProperty(this, "isBug", {
|
|
283
|
+
enumerable: true,
|
|
284
|
+
configurable: true,
|
|
285
|
+
writable: true,
|
|
286
|
+
value: IsBug.NO
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
body(_) {
|
|
290
|
+
return (0, ts_dedent_1.default) `
|
|
291
|
+
Yarn is required to sync your application.
|
|
292
|
+
|
|
293
|
+
Please install Yarn by running:
|
|
294
|
+
|
|
295
|
+
$ npm install --global yarn
|
|
296
|
+
|
|
297
|
+
For more information, see: https://classic.yarnpkg.com/en/docs/install
|
|
298
|
+
`;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
exports.YarnNotFoundError = YarnNotFoundError;
|
|
302
|
+
class InvalidSyncFileError extends BaseError {
|
|
303
|
+
constructor(cause, dir, app) {
|
|
304
|
+
super("GGT_CLI_INVALID_SYNC_FILE", "The .ggt/sync.json file was invalid or not found");
|
|
305
|
+
Object.defineProperty(this, "cause", {
|
|
306
|
+
enumerable: true,
|
|
307
|
+
configurable: true,
|
|
308
|
+
writable: true,
|
|
309
|
+
value: cause
|
|
310
|
+
});
|
|
282
311
|
Object.defineProperty(this, "dir", {
|
|
283
312
|
enumerable: true,
|
|
284
313
|
configurable: true,
|
|
285
314
|
writable: true,
|
|
286
315
|
value: dir
|
|
287
316
|
});
|
|
288
|
-
Object.defineProperty(this, "
|
|
317
|
+
Object.defineProperty(this, "app", {
|
|
289
318
|
enumerable: true,
|
|
290
319
|
configurable: true,
|
|
291
320
|
writable: true,
|
|
292
|
-
value:
|
|
321
|
+
value: app
|
|
293
322
|
});
|
|
294
323
|
Object.defineProperty(this, "isBug", {
|
|
295
324
|
enumerable: true,
|
|
296
325
|
configurable: true,
|
|
297
326
|
writable: true,
|
|
298
|
-
value: IsBug.
|
|
327
|
+
value: IsBug.MAYBE
|
|
299
328
|
});
|
|
300
329
|
}
|
|
301
|
-
body(
|
|
330
|
+
body(config) {
|
|
302
331
|
return (0, ts_dedent_1.default) `
|
|
303
|
-
|
|
332
|
+
We failed to read the Gadget metadata file in this directory:
|
|
333
|
+
|
|
304
334
|
${this.dir}
|
|
305
335
|
|
|
306
|
-
|
|
307
|
-
|
|
336
|
+
If you're running \`ggt sync\` for the first time, we recommend using an empty directory such as \`~/gadget/${this.app}\`.
|
|
337
|
+
|
|
338
|
+
Otherwise, if you're sure you want to sync the contents of \`${this.dir}\` to Gadget, you can run the command again with the \`--force\` flag:
|
|
339
|
+
|
|
340
|
+
$ ${config.bin} ${process.argv.slice(2).join(" ")} --force
|
|
341
|
+
|
|
342
|
+
You will be prompted to either merge your local files with your remote ones or reset your local files to your remote ones.
|
|
343
|
+
`;
|
|
308
344
|
}
|
|
309
345
|
}
|
|
310
|
-
exports.
|
|
346
|
+
exports.InvalidSyncFileError = InvalidSyncFileError;
|
|
311
347
|
function isCloseEvent(e) {
|
|
312
348
|
return (0, lodash_1.has)(e, "type") && (0, lodash_1.has)(e, "code") && (0, lodash_1.has)(e, "reason") && (0, lodash_1.has)(e, "wasClean");
|
|
313
349
|
}
|
package/dist/lib/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Config } from \"@oclif/core\";\nimport cleanStack from \"clean-stack\";\nimport { HTTPError } from \"got/dist/source\";\nimport { GraphQLError } from \"graphql\";\nimport { has, isError, uniqBy } from \"lodash\";\nimport newGithubIssueUrl from \"new-github-issue-url\";\nimport { serializeError as baseSerializeError } from \"serialize-error\";\nimport dedent from \"ts-dedent\";\nimport type { SetOptional, Writable } from \"type-fest\";\nimport { inspect } from \"util\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport type { Payload } from \"./client\";\n\n/**\n * Base class for all errors.\n *\n * Inspired by gadget's GadgetError and oclif's PrettyPrintableError.\n */\nexport abstract class BaseError extends Error {\n /**\n * A GGT_CLI_SOMETHING human/machine readable unique identifier for this error.\n */\n code: string;\n\n /**\n * The underlying *thing* that caused this error.\n */\n override cause?: any;\n\n /**\n * Assume the stack trace exists.\n */\n override stack!: string;\n\n /**\n * Indicates whether this error is considered a bug or not.\n */\n abstract isBug: IsBug;\n\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n }\n\n /**\n * Turns this error into a user-friendly message that explains what went wrong and how to fix it. A good write up of what an error should\n * look like can be found here: {@link https://clig.dev/#errors}\n */\n render(config: Config): string {\n return dedent`\n ${this.header(config)}\n\n ${this.body(config)}\n\n ${this.footer(config)}\n `;\n }\n\n protected header(_: Config): string {\n return `${this.code}: ${this.message}`;\n }\n\n protected footer(config: Config): string {\n switch (this.isBug) {\n case IsBug.NO:\n return \"\";\n case IsBug.MAYBE:\n return dedent`\n If you think this is a bug, please submit an issue using the link below.\n\n ${newGithubIssueUrl(this.issueOptions(config))}\n `;\n case IsBug.YES:\n return dedent`\n This is a bug :(\n\n Visit the link below to see if someone has already reported this issue.\n https://github.com/gadget-inc/ggt/issues?q=is%3Aissue+is%3Aopen+label%3Abug+${this.code}\n\n If nobody has, you can submit one using the link below.\n ---\n ${newGithubIssueUrl(this.issueOptions(config))}\n `;\n }\n }\n\n protected issueOptions(config: Config): newGithubIssueUrl.Options {\n const options = {\n repoUrl: \"https://github.com/gadget-inc/ggt\",\n title: `[BUG ${this.code}]: `,\n labels: [\"bug\"],\n body: dedent`\n ### Description\n [Please describe what you were doing when this error occurred]\n\n ### Command\n \\`\\`\\`sh-session\n ${config.bin} ${process.argv.slice(2).join(\" \")}\n \\`\\`\\`\n\n ### Environment\n \\`\\`\\`\n version: ${config.version}\n platform: ${config.platform}\n arch: ${config.arch}\n shell: ${config.shell}\n timestamp: ${new Date().toISOString()}\n \\`\\`\\`\n\n ### Stack Trace\n \\`\\`\\`\n ${cleanStack(this.stack)}\n \\`\\`\\`\n `,\n };\n\n if (this.cause) {\n options.body += dedent`\n\n ### Cause\n \\`\\`\\`json\n ${JSON.stringify(isError(this.cause) ? serializeError(this.cause) : this.cause, null, 2)}\n \\`\\`\\`\n `;\n }\n\n return options;\n }\n\n protected abstract body(_: Config): string;\n}\n\n/**\n * Universal Error object to json blob serializer.\n * Wraps `serialize-error` with some handy stuff, like special support for Got HTTP errors\n */\nexport function serializeError(error: Error | string | unknown): Record<string, any> {\n let serialized = baseSerializeError(error);\n if (typeof serialized == \"string\") {\n serialized = { message: serialized };\n }\n\n if (error instanceof HTTPError && error.name === \"RequestError\") {\n delete serialized[\"timings\"];\n serialized[\"options\"] = { method: error.options.method, url: error.options.url.toJSON() };\n serialized[\"responseBody\"] = inspect(error.response?.body);\n }\n\n return serialized;\n}\n\nexport enum IsBug {\n NO,\n MAYBE,\n YES,\n}\n\n/**\n * Our \"catch all\" error. If this error is thrown, we almost certainly have a bug.\n *\n * Whenever possible, we should use a more specific error so that we can provide more useful information.\n */\nexport class UnexpectedError extends BaseError {\n isBug = IsBug.YES;\n\n constructor(override cause: Error) {\n super(\"GGT_CLI_UNEXPECTED_ERROR\", \"An unexpected error occurred\");\n }\n\n protected body(_: Config): string {\n return cleanStack(this.cause.stack ?? this.stack);\n }\n}\n\nexport class ClientError extends BaseError {\n isBug = IsBug.MAYBE;\n\n constructor(readonly payload: Payload<any, any>, override cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent) {\n super(\"GGT_CLI_CLIENT_ERROR\", \"An error occurred while communicating with Gadget\");\n\n // ErrorEvent and CloseEvent aren't serializable, so we reconstruct them into an object. We discard the `target` property because it's large and not that useful\n if (isErrorEvent(cause)) {\n this.cause = {\n type: cause.type,\n message: cause.message,\n error: serializeError(cause.error),\n } as any;\n } else if (isCloseEvent(cause)) {\n this.cause = {\n type: cause.type,\n code: cause.code,\n reason: cause.reason,\n wasClean: cause.wasClean,\n } as any;\n }\n }\n\n override body(_: Config): string {\n if (isGraphQLErrors(this.cause)) {\n if (this.cause.length > 1) {\n let output = \"Gadget responded with multiple errors:\";\n for (const error of uniqBy(this.cause, \"message\")) {\n output += `\\n * ${error.message}`;\n }\n return output;\n } else {\n return dedent`\n Gadget responded with an unexpected error.\n\n ${this.cause[0]?.message}\n `;\n }\n }\n\n if (isCloseEvent(this.cause)) {\n return \"The connection to Gadget closed unexpectedly.\";\n }\n\n if (isErrorEvent(this.cause)) {\n return dedent`\n The connection to Gadget received an unexpected error.\n\n ${this.cause.message}\n `;\n }\n\n if (isError(this.cause)) {\n return dedent`\n An unexpected error occurred.\n\n ${this.cause.message}\n `;\n }\n\n return this.cause;\n }\n\n protected override issueOptions(config: Config): newGithubIssueUrl.Options {\n const options = super.issueOptions(config) as Writable<newGithubIssueUrl.Options>;\n options.body += dedent`\n\n ### GraphQL\n\n #### Query\n \\`\\`\\`graphql\n ${this.payload.query}\n \\`\\`\\`\n `;\n\n // mutations can have large/sensitive payloads, so we don't include them by default\n if (!this.payload.query.trimStart().startsWith(\"mutation\")) {\n options.body += dedent`\n\n #### Variables\n \\`\\`\\`json\n ${JSON.stringify(this.payload.variables, null, 2)}\n \\`\\`\\`\n `;\n }\n\n return options;\n }\n}\n\nexport class WalkedTooManyFilesError extends BaseError {\n isBug = IsBug.NO;\n\n constructor(readonly dir: string, readonly maxFiles: number) {\n super(\"GGT_CLI_TOO_MANY_FILES\", \"Found too many files while scanning directory\");\n }\n\n override body(_: Config): string {\n return dedent`\n The following directory has over ${this.maxFiles} non-ignored files inside of it.\n ${this.dir}\n\n Consider adding more entries to your \\`.ignore\\` file.\n `;\n }\n}\n\nfunction isCloseEvent(e: any): e is SetOptional<CloseEvent, \"target\"> {\n return has(e, \"type\") && has(e, \"code\") && has(e, \"reason\") && has(e, \"wasClean\");\n}\n\nfunction isErrorEvent(e: any): e is SetOptional<ErrorEvent, \"target\"> {\n return has(e, \"type\") && has(e, \"message\") && has(e, \"error\");\n}\n\nfunction isGraphQLErrors(e: any): e is readonly GraphQLError[] {\n return Array.isArray(e) && e.every((e) => e instanceof GraphQLError);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Config } from \"@oclif/core\";\nimport cleanStack from \"clean-stack\";\nimport { HTTPError } from \"got/dist/source\";\nimport { GraphQLError } from \"graphql\";\nimport { has, isError, uniqBy } from \"lodash\";\nimport newGithubIssueUrl from \"new-github-issue-url\";\nimport { serializeError as baseSerializeError } from \"serialize-error\";\nimport dedent from \"ts-dedent\";\nimport type { SetOptional, Writable } from \"type-fest\";\nimport { inspect } from \"util\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport type { Payload } from \"./client\";\n\n/**\n * Base class for all errors.\n *\n * Inspired by gadget's GadgetError and oclif's PrettyPrintableError.\n */\nexport abstract class BaseError extends Error {\n /**\n * A GGT_CLI_SOMETHING human/machine readable unique identifier for this error.\n */\n code: string;\n\n /**\n * The underlying *thing* that caused this error.\n */\n override cause?: any;\n\n /**\n * Assume the stack trace exists.\n */\n override stack!: string;\n\n /**\n * Indicates whether this error is considered a bug or not.\n */\n abstract isBug: IsBug;\n\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n }\n\n /**\n * Turns this error into a user-friendly message that explains what went wrong and how to fix it. A good write up of what an error should\n * look like can be found here: {@link https://clig.dev/#errors}\n */\n render(config: Config): string {\n return dedent`\n ${this.header(config)}\n\n ${this.body(config)}\n\n ${this.footer(config)}\n `;\n }\n\n protected header(_: Config): string {\n return `${this.code}: ${this.message}`;\n }\n\n protected footer(config: Config): string {\n switch (this.isBug) {\n case IsBug.NO:\n return \"\";\n case IsBug.MAYBE:\n return dedent`\n If you think this is a bug, please submit an issue using the link below.\n\n ${newGithubIssueUrl(this.issueOptions(config))}\n `;\n case IsBug.YES:\n return dedent`\n This is a bug :(\n\n Visit the link below to see if someone has already reported this issue.\n https://github.com/gadget-inc/ggt/issues?q=is%3Aissue+is%3Aopen+label%3Abug+${this.code}\n\n If nobody has, you can submit one using the link below.\n ---\n ${newGithubIssueUrl(this.issueOptions(config))}\n `;\n }\n }\n\n protected issueOptions(config: Config): newGithubIssueUrl.Options {\n const options = {\n repoUrl: \"https://github.com/gadget-inc/ggt\",\n title: `[BUG ${this.code}]: `,\n labels: [\"bug\"],\n body: dedent`\n ### Description\n [Please describe what you were doing when this error occurred]\n\n ### Command\n \\`\\`\\`sh-session\n ${config.bin} ${process.argv.slice(2).join(\" \")}\n \\`\\`\\`\n\n ### Environment\n \\`\\`\\`\n version: ${config.version}\n platform: ${config.platform}\n arch: ${config.arch}\n shell: ${config.shell}\n timestamp: ${new Date().toISOString()}\n \\`\\`\\`\n\n ### Stack Trace\n \\`\\`\\`\n ${cleanStack(this.stack)}\n \\`\\`\\`\n `,\n };\n\n if (this.cause) {\n options.body += dedent`\n\n ### Cause\n \\`\\`\\`json\n ${JSON.stringify(isError(this.cause) ? serializeError(this.cause) : this.cause, null, 2)}\n \\`\\`\\`\n `;\n }\n\n return options;\n }\n\n protected abstract body(_: Config): string;\n}\n\n/**\n * Universal Error object to json blob serializer.\n * Wraps `serialize-error` with some handy stuff, like special support for Got HTTP errors\n */\nexport function serializeError(error: Error | string | unknown): Record<string, any> {\n let serialized = baseSerializeError(error);\n if (typeof serialized == \"string\") {\n serialized = { message: serialized };\n }\n\n if (error instanceof HTTPError && error.name === \"RequestError\") {\n delete serialized[\"timings\"];\n serialized[\"options\"] = { method: error.options.method, url: error.options.url.toJSON() };\n serialized[\"responseBody\"] = inspect(error.response?.body);\n }\n\n return serialized;\n}\n\nexport enum IsBug {\n NO,\n MAYBE,\n YES,\n}\n\n/**\n * Our \"catch all\" error. If this error is thrown, we almost certainly have a bug.\n *\n * Whenever possible, we should use a more specific error so that we can provide more useful information.\n */\nexport class UnexpectedError extends BaseError {\n isBug = IsBug.YES;\n\n constructor(override cause: Error) {\n super(\"GGT_CLI_UNEXPECTED_ERROR\", \"An unexpected error occurred\");\n }\n\n protected body(_: Config): string {\n return cleanStack(this.cause.stack ?? this.stack);\n }\n}\n\nexport class ClientError extends BaseError {\n isBug = IsBug.MAYBE;\n\n constructor(readonly payload: Payload<any, any>, override cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent) {\n super(\"GGT_CLI_CLIENT_ERROR\", \"An error occurred while communicating with Gadget\");\n\n // ErrorEvent and CloseEvent aren't serializable, so we reconstruct them into an object. We discard the `target` property because it's large and not that useful\n if (isErrorEvent(cause)) {\n this.cause = {\n type: cause.type,\n message: cause.message,\n error: serializeError(cause.error),\n } as any;\n } else if (isCloseEvent(cause)) {\n this.cause = {\n type: cause.type,\n code: cause.code,\n reason: cause.reason,\n wasClean: cause.wasClean,\n } as any;\n }\n }\n\n override body(_: Config): string {\n if (isGraphQLErrors(this.cause)) {\n if (this.cause.length > 1) {\n let output = \"Gadget responded with multiple errors:\";\n for (const error of uniqBy(this.cause, \"message\")) {\n output += `\\n * ${error.message}`;\n }\n return output;\n } else {\n return dedent`\n Gadget responded with an unexpected error.\n\n ${this.cause[0]?.message}\n `;\n }\n }\n\n if (isCloseEvent(this.cause)) {\n return \"The connection to Gadget closed unexpectedly.\";\n }\n\n if (isErrorEvent(this.cause)) {\n return dedent`\n The connection to Gadget received an unexpected error.\n\n ${this.cause.message}\n `;\n }\n\n if (isError(this.cause)) {\n return dedent`\n An unexpected error occurred.\n\n ${this.cause.message}\n `;\n }\n\n return this.cause;\n }\n\n protected override issueOptions(config: Config): newGithubIssueUrl.Options {\n const options = super.issueOptions(config) as Writable<newGithubIssueUrl.Options>;\n options.body += dedent`\n\n ### GraphQL\n\n #### Query\n \\`\\`\\`graphql\n ${this.payload.query}\n \\`\\`\\`\n `;\n\n // mutations can have large/sensitive payloads, so we don't include them by default\n if (!this.payload.query.trimStart().startsWith(\"mutation\")) {\n options.body += dedent`\n\n #### Variables\n \\`\\`\\`json\n ${JSON.stringify(this.payload.variables, null, 2)}\n \\`\\`\\`\n `;\n }\n\n return options;\n }\n}\n\nexport class YarnNotFoundError extends BaseError {\n isBug = IsBug.NO;\n\n constructor() {\n super(\"GGT_CLI_YARN_NOT_FOUND\", \"Yarn not found\");\n }\n\n protected body(_: Config): string {\n return dedent`\n Yarn is required to sync your application.\n\n Please install Yarn by running:\n\n $ npm install --global yarn\n\n For more information, see: https://classic.yarnpkg.com/en/docs/install\n `;\n }\n}\n\nexport class InvalidSyncFileError extends BaseError {\n isBug = IsBug.MAYBE;\n\n constructor(override readonly cause: unknown, readonly dir: string, readonly app: string) {\n super(\"GGT_CLI_INVALID_SYNC_FILE\", \"The .ggt/sync.json file was invalid or not found\");\n }\n\n protected body(config: Config): string {\n return dedent`\n We failed to read the Gadget metadata file in this directory:\n\n ${this.dir}\n\n If you're running \\`ggt sync\\` for the first time, we recommend using an empty directory such as \\`~/gadget/${this.app}\\`.\n\n Otherwise, if you're sure you want to sync the contents of \\`${\n this.dir\n }\\` to Gadget, you can run the command again with the \\`--force\\` flag:\n\n $ ${config.bin} ${process.argv.slice(2).join(\" \")} --force\n\n You will be prompted to either merge your local files with your remote ones or reset your local files to your remote ones.\n `;\n }\n}\n\nfunction isCloseEvent(e: any): e is SetOptional<CloseEvent, \"target\"> {\n return has(e, \"type\") && has(e, \"code\") && has(e, \"reason\") && has(e, \"wasClean\");\n}\n\nfunction isErrorEvent(e: any): e is SetOptional<ErrorEvent, \"target\"> {\n return has(e, \"type\") && has(e, \"message\") && has(e, \"error\");\n}\n\nfunction isGraphQLErrors(e: any): e is readonly GraphQLError[] {\n return Array.isArray(e) && e.every((e) => e instanceof GraphQLError);\n}\n"]}
|
package/dist/lib/fs-utils.d.ts
CHANGED
|
@@ -10,9 +10,8 @@ export declare class Ignorer {
|
|
|
10
10
|
export interface WalkDirOptions {
|
|
11
11
|
ignorer?: Ignorer;
|
|
12
12
|
maxFiles?: number;
|
|
13
|
-
_fileCount?: number;
|
|
14
|
-
_rootDir?: string;
|
|
15
13
|
}
|
|
16
14
|
export declare function walkDir(dir: string, options?: WalkDirOptions): AsyncGenerator<string>;
|
|
17
15
|
export declare function walkDirSync(dir: string, options?: WalkDirOptions): Generator<string>;
|
|
16
|
+
export declare function isEmptyDir(dir: string): Promise<boolean>;
|
|
18
17
|
export declare function ignoreEnoent(error: any): void;
|
package/dist/lib/fs-utils.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ignoreEnoent = exports.walkDirSync = exports.walkDir = exports.Ignorer = void 0;
|
|
3
|
+
exports.ignoreEnoent = exports.isEmptyDir = exports.walkDirSync = exports.walkDir = exports.Ignorer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
6
6
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
7
7
|
const ignore_1 = tslib_1.__importDefault(require("ignore"));
|
|
8
8
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
9
|
-
const errors_1 = require("./errors");
|
|
10
9
|
const debug = (0, debug_1.default)("ggt:fs-utils");
|
|
11
10
|
class Ignorer {
|
|
12
11
|
constructor(_rootDir, _alwaysIgnore) {
|
|
@@ -58,19 +57,12 @@ exports.Ignorer = Ignorer;
|
|
|
58
57
|
async function* walkDir(dir, options = {}) {
|
|
59
58
|
if (options.ignorer?.ignores(dir))
|
|
60
59
|
return;
|
|
61
|
-
if (options._rootDir == null)
|
|
62
|
-
options._rootDir = dir;
|
|
63
|
-
if (options._fileCount == null)
|
|
64
|
-
options._fileCount = 0;
|
|
65
60
|
for await (const entry of await fs_extra_1.default.opendir(dir)) {
|
|
66
61
|
const filepath = path_1.default.join(dir, entry.name);
|
|
67
62
|
if (entry.isDirectory()) {
|
|
68
63
|
yield* walkDir(filepath, options);
|
|
69
64
|
}
|
|
70
65
|
else if (entry.isFile() && !options.ignorer?.ignores(filepath)) {
|
|
71
|
-
if (options.maxFiles != null && ++options._fileCount >= options.maxFiles) {
|
|
72
|
-
throw new errors_1.WalkedTooManyFilesError(options._rootDir, options.maxFiles);
|
|
73
|
-
}
|
|
74
66
|
yield filepath;
|
|
75
67
|
}
|
|
76
68
|
}
|
|
@@ -79,24 +71,22 @@ exports.walkDir = walkDir;
|
|
|
79
71
|
function* walkDirSync(dir, options = {}) {
|
|
80
72
|
if (options.ignorer?.ignores(dir))
|
|
81
73
|
return;
|
|
82
|
-
if (options._rootDir == null)
|
|
83
|
-
options._rootDir = dir;
|
|
84
|
-
if (options._fileCount == null)
|
|
85
|
-
options._fileCount = 0;
|
|
86
74
|
for (const entry of fs_extra_1.default.readdirSync(dir, { withFileTypes: true })) {
|
|
87
75
|
const filepath = path_1.default.join(dir, entry.name);
|
|
88
76
|
if (entry.isDirectory()) {
|
|
89
77
|
yield* walkDirSync(filepath, options);
|
|
90
78
|
}
|
|
91
79
|
else if (entry.isFile() && !options.ignorer?.ignores(filepath)) {
|
|
92
|
-
if (options.maxFiles != null && ++options._fileCount >= options.maxFiles) {
|
|
93
|
-
throw new errors_1.WalkedTooManyFilesError(options._rootDir, options.maxFiles);
|
|
94
|
-
}
|
|
95
80
|
yield filepath;
|
|
96
81
|
}
|
|
97
82
|
}
|
|
98
83
|
}
|
|
99
84
|
exports.walkDirSync = walkDirSync;
|
|
85
|
+
async function isEmptyDir(dir) {
|
|
86
|
+
const files = await fs_extra_1.default.readdir(dir);
|
|
87
|
+
return files.length === 0;
|
|
88
|
+
}
|
|
89
|
+
exports.isEmptyDir = isEmptyDir;
|
|
100
90
|
function ignoreEnoent(error) {
|
|
101
91
|
if (error.code === "ENOENT") {
|
|
102
92
|
debug("ignoring ENOENT error %s", error.path);
|
package/dist/lib/fs-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../src/lib/fs-utils.ts"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAC1B,gEAA0B;AAE1B,4DAA4B;AAC5B,wDAAwB;
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../src/lib/fs-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import Debug from \"debug\";\nimport fs from \"fs-extra\";\nimport type { Ignore } from \"ignore\";\nimport ignore from \"ignore\";\nimport path from \"path\";\n\nconst debug = Debug(\"ggt:fs-utils\");\n\nexport class Ignorer {\n readonly filepath = path.join(this._rootDir, \".ignore\");\n\n private _ignorer!: Ignore;\n\n constructor(private readonly _rootDir: string, private readonly _alwaysIgnore: string[]) {\n this.reload();\n }\n\n ignores(filepath: string): boolean {\n const relative = path.relative(this._rootDir, filepath);\n if (relative == \"\") return false;\n return this._ignorer.ignores(relative);\n }\n\n reload(): void {\n this._ignorer = ignore();\n this._ignorer.add(this._alwaysIgnore);\n\n try {\n this._ignorer.add(fs.readFileSync(this.filepath, \"utf-8\"));\n debug(\"reloaded ignore rules from %s\", this.filepath);\n } catch (error) {\n ignoreEnoent(error);\n }\n }\n}\n\nexport interface WalkDirOptions {\n ignorer?: Ignorer;\n maxFiles?: number;\n}\n\nexport async function* walkDir(dir: string, options: WalkDirOptions = {}): AsyncGenerator<string> {\n if (options.ignorer?.ignores(dir)) return;\n\n for await (const entry of await fs.opendir(dir)) {\n const filepath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n yield* walkDir(filepath, options);\n } else if (entry.isFile() && !options.ignorer?.ignores(filepath)) {\n yield filepath;\n }\n }\n}\n\nexport function* walkDirSync(dir: string, options: WalkDirOptions = {}): Generator<string> {\n if (options.ignorer?.ignores(dir)) return;\n\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const filepath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n yield* walkDirSync(filepath, options);\n } else if (entry.isFile() && !options.ignorer?.ignores(filepath)) {\n yield filepath;\n }\n }\n}\n\nexport async function isEmptyDir(dir: string): Promise<boolean> {\n const files = await fs.readdir(dir);\n return files.length === 0;\n}\n\nexport function ignoreEnoent(error: any): void {\n if (error.code === \"ENOENT\") {\n debug(\"ignoring ENOENT error %s\", error.path);\n return;\n }\n throw error;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gadgetinc/ggt",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.2",
|
|
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",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"chokidar": "^3.5.3",
|
|
38
38
|
"clean-stack": "^3.0.1",
|
|
39
39
|
"debug": "^4.3.4",
|
|
40
|
+
"execa": "^5.1.1",
|
|
40
41
|
"fs-extra": "^10.1.0",
|
|
41
42
|
"get-port": "^5.1.1",
|
|
42
43
|
"got": "^11.8.5",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"patch-package": "^6.4.7",
|
|
55
56
|
"serialize-error": "^8.1.0",
|
|
56
57
|
"ts-dedent": "^2.2.0",
|
|
58
|
+
"which": "^2.0.2",
|
|
57
59
|
"ws": "^8.8.1"
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
@@ -71,6 +73,7 @@
|
|
|
71
73
|
"@types/node": "^18.6.3",
|
|
72
74
|
"@types/node-notifier": "^8.0.2",
|
|
73
75
|
"@types/normalize-path": "^3.0.0",
|
|
76
|
+
"@types/which": "^2.0.1",
|
|
74
77
|
"@types/ws": "^8.5.3",
|
|
75
78
|
"@typescript-eslint/eslint-plugin": "^5.32.0",
|
|
76
79
|
"@typescript-eslint/parser": "^5.32.0",
|