@gadgetinc/ggt 0.0.0-alpha.0

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.
Files changed (50) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +177 -0
  3. package/assets/favicon-128@4x.png +0 -0
  4. package/bin/dev +20 -0
  5. package/bin/dev.cmd +3 -0
  6. package/bin/run +7 -0
  7. package/bin/run.cmd +3 -0
  8. package/dist/commands/help.d.ts +16 -0
  9. package/dist/commands/help.js +37 -0
  10. package/dist/commands/help.js.map +1 -0
  11. package/dist/commands/login.d.ts +7 -0
  12. package/dist/commands/login.js +36 -0
  13. package/dist/commands/login.js.map +1 -0
  14. package/dist/commands/logout.d.ts +7 -0
  15. package/dist/commands/logout.js +41 -0
  16. package/dist/commands/logout.js.map +1 -0
  17. package/dist/commands/sync.d.ts +64 -0
  18. package/dist/commands/sync.js +534 -0
  19. package/dist/commands/sync.js.map +1 -0
  20. package/dist/commands/whoami.d.ts +7 -0
  21. package/dist/commands/whoami.js +45 -0
  22. package/dist/commands/whoami.js.map +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +6 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/lib/base-command.d.ts +87 -0
  27. package/dist/lib/base-command.js +318 -0
  28. package/dist/lib/base-command.js.map +1 -0
  29. package/dist/lib/client.d.ts +39 -0
  30. package/dist/lib/client.js +155 -0
  31. package/dist/lib/client.js.map +1 -0
  32. package/dist/lib/env.d.ts +10 -0
  33. package/dist/lib/env.js +25 -0
  34. package/dist/lib/env.js.map +1 -0
  35. package/dist/lib/errors.d.ts +74 -0
  36. package/dist/lib/errors.js +320 -0
  37. package/dist/lib/errors.js.map +1 -0
  38. package/dist/lib/fs-utils.d.ts +18 -0
  39. package/dist/lib/fs-utils.js +108 -0
  40. package/dist/lib/fs-utils.js.map +1 -0
  41. package/dist/lib/help.d.ts +14 -0
  42. package/dist/lib/help.js +30 -0
  43. package/dist/lib/help.js.map +1 -0
  44. package/dist/lib/sleep.d.ts +5 -0
  45. package/dist/lib/sleep.js +23 -0
  46. package/dist/lib/sleep.js.map +1 -0
  47. package/dist/lib/types.d.ts +9 -0
  48. package/dist/lib/types.js +3 -0
  49. package/dist/lib/types.js.map +1 -0
  50. package/package.json +107 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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","sourcesContent":["import Debug from \"debug\";\nimport type { GraphQLError } from \"graphql\";\nimport type { ClientOptions, ExecutionResult, SubscribePayload } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport type { ClientRequestArgs } from \"http\";\nimport { isFunction, noop } from \"lodash\";\nimport type { JsonObject, SetOptional } from \"type-fest\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport WebSocket from \"ws\";\nimport { Env } from \"./env\";\nimport { ClientError } from \"./errors\";\n\nconst debug = Debug(\"ggt:client\");\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\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(app: string, options?: Partial<ClientOptions> & { ws?: Partial<WebSocket.ClientOptions> }) {\n this._client = createClient({\n url: `wss://${app}.${Env.productionLike ? \"gadget.app\" : \"ggt.pub:3000\"}/edit/api/graphql-ws`,\n shouldRetry: () => true,\n webSocketImpl: class extends WebSocket {\n constructor(address: string | URL, protocols?: string | string[], wsOptions?: WebSocket.ClientOptions | ClientRequestArgs) {\n super(address, protocols, { ...wsOptions, ...options?.ws });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n debug(\"reconnecting...\");\n break;\n case ConnectionStatus.RECONNECTING:\n debug(\"retrying...\");\n break;\n default:\n debug(\"connecting...\");\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n debug(\"reconnected\");\n } else {\n debug(\"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 debug(\"connection closed\");\n return;\n }\n\n if (this.status === ConnectionStatus.CONNECTED) {\n this.status = ConnectionStatus.DISCONNECTED;\n debug(\"disconnected\");\n }\n },\n error: (error) => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n debug(\"failed to reconnect %o\", { error });\n } else {\n debug(\"connection error %o\", { error });\n }\n },\n ...options?.on,\n },\n ...options,\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: () => void;\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 could been re-assigned (it won't)\n (subscribePayload as any).variables = (payload.variables as any)();\n debug(\"re-sending query %s\", subscribePayload.query);\n }\n });\n } else {\n subscribePayload = payload as SubscribePayload;\n }\n\n debug(\"sending query %s\", subscribePayload.query);\n const unsubscribe = this._client.subscribe(subscribePayload, {\n next: (result: ExecutionResult<Data, Extensions>) => sink.next(result),\n error: (error) => sink.error(new ClientError(subscribePayload, error as Error | GraphQLError[] | CloseEvent | ErrorEvent)),\n complete: () => sink.complete?.() ?? noop,\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"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Captures the name and nature of the environment
3
+ */
4
+ export declare class Env {
5
+ static get value(): string;
6
+ static get developmentLike(): boolean;
7
+ static get testLike(): boolean;
8
+ static get developmentOrTestLike(): boolean;
9
+ static get productionLike(): boolean;
10
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Env = void 0;
4
+ /**
5
+ * Captures the name and nature of the environment
6
+ */
7
+ class Env {
8
+ static get value() {
9
+ return process.env["GGT_ENV"] || "production";
10
+ }
11
+ static get developmentLike() {
12
+ return this.value.startsWith("development");
13
+ }
14
+ static get testLike() {
15
+ return this.value.startsWith("test");
16
+ }
17
+ static get developmentOrTestLike() {
18
+ return this.developmentLike || this.testLike;
19
+ }
20
+ static get productionLike() {
21
+ return this.value.startsWith("production");
22
+ }
23
+ }
24
+ exports.Env = Env;
25
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/lib/env.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,GAAG;IACd,MAAM,KAAK,KAAK;QACd,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,YAAY,CAAC;IAChD,CAAC;IAED,MAAM,KAAK,eAAe;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,KAAK,QAAQ;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,KAAK,qBAAqB;QAC9B,OAAO,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAC;IAC/C,CAAC;IAED,MAAM,KAAK,cAAc;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC;CACF;AApBD,kBAoBC","sourcesContent":["/**\n * Captures the name and nature of the environment\n */\nexport class Env {\n static get value(): string {\n return process.env[\"GGT_ENV\"] || \"production\";\n }\n\n static get developmentLike(): boolean {\n return this.value.startsWith(\"development\");\n }\n\n static get testLike(): boolean {\n return this.value.startsWith(\"test\");\n }\n\n static get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n }\n\n static get productionLike(): boolean {\n return this.value.startsWith(\"production\");\n }\n}\n"]}
@@ -0,0 +1,74 @@
1
+ import type { Config } from "@oclif/core";
2
+ import { GraphQLError } from "graphql";
3
+ import newGithubIssueUrl from "new-github-issue-url";
4
+ import type { CloseEvent, ErrorEvent } from "ws";
5
+ import type { Payload } from "./client";
6
+ /**
7
+ * Base class for all errors.
8
+ *
9
+ * Inspired by gadget's GadgetError and oclif's PrettyPrintableError.
10
+ */
11
+ export declare abstract class BaseError extends Error {
12
+ /**
13
+ * A GGT_CLI_SOMETHING human/machine readable unique identifier for this error.
14
+ */
15
+ code: string;
16
+ /**
17
+ * The underlying *thing* that caused this error.
18
+ */
19
+ cause?: any;
20
+ /**
21
+ * Assume the stack trace exists.
22
+ */
23
+ stack: string;
24
+ /**
25
+ * Indicates whether this error is considered a bug or not.
26
+ */
27
+ abstract isBug: IsBug;
28
+ constructor(code: string, message: string);
29
+ /**
30
+ * 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
31
+ * look like can be found here: {@link https://clig.dev/#errors}
32
+ */
33
+ render(config: Config): string;
34
+ protected header(_: Config): string;
35
+ protected footer(config: Config): string;
36
+ protected issueOptions(config: Config): newGithubIssueUrl.Options;
37
+ protected abstract body(_: Config): string;
38
+ }
39
+ /**
40
+ * Universal Error object to json blob serializer.
41
+ * Wraps `serialize-error` with some handy stuff, like special support for Got HTTP errors
42
+ */
43
+ export declare function serializeError(error: Error | string | unknown): Record<string, any>;
44
+ export declare enum IsBug {
45
+ NO = 0,
46
+ MAYBE = 1,
47
+ YES = 2
48
+ }
49
+ /**
50
+ * Our "catch all" error. If this error is thrown, we almost certainly have a bug.
51
+ *
52
+ * Whenever possible, we should use a more specific error so that we can provide more useful information.
53
+ */
54
+ export declare class UnexpectedError extends BaseError {
55
+ cause: Error;
56
+ isBug: IsBug;
57
+ constructor(cause: Error);
58
+ protected body(_: Config): string;
59
+ }
60
+ export declare class ClientError extends BaseError {
61
+ readonly payload: Payload<any, any>;
62
+ cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent;
63
+ isBug: IsBug;
64
+ constructor(payload: Payload<any, any>, cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent);
65
+ body(_: Config): string;
66
+ protected issueOptions(config: Config): newGithubIssueUrl.Options;
67
+ }
68
+ export declare class WalkedTooManyFilesError extends BaseError {
69
+ readonly dir: string;
70
+ readonly maxFiles: number;
71
+ isBug: IsBug;
72
+ constructor(dir: string, maxFiles: number);
73
+ body(_: Config): string;
74
+ }
@@ -0,0 +1,320 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WalkedTooManyFilesError = exports.ClientError = exports.UnexpectedError = exports.IsBug = exports.serializeError = exports.BaseError = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const clean_stack_1 = tslib_1.__importDefault(require("clean-stack"));
6
+ const source_1 = require("got/dist/source");
7
+ const graphql_1 = require("graphql");
8
+ const lodash_1 = require("lodash");
9
+ const new_github_issue_url_1 = tslib_1.__importDefault(require("new-github-issue-url"));
10
+ const serialize_error_1 = require("serialize-error");
11
+ const ts_dedent_1 = tslib_1.__importDefault(require("ts-dedent"));
12
+ const util_1 = require("util");
13
+ /**
14
+ * Base class for all errors.
15
+ *
16
+ * Inspired by gadget's GadgetError and oclif's PrettyPrintableError.
17
+ */
18
+ class BaseError extends Error {
19
+ constructor(code, message) {
20
+ super(message);
21
+ /**
22
+ * A GGT_CLI_SOMETHING human/machine readable unique identifier for this error.
23
+ */
24
+ Object.defineProperty(this, "code", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: void 0
29
+ });
30
+ /**
31
+ * The underlying *thing* that caused this error.
32
+ */
33
+ Object.defineProperty(this, "cause", {
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true,
37
+ value: void 0
38
+ });
39
+ /**
40
+ * Assume the stack trace exists.
41
+ */
42
+ Object.defineProperty(this, "stack", {
43
+ enumerable: true,
44
+ configurable: true,
45
+ writable: true,
46
+ value: void 0
47
+ });
48
+ this.code = code;
49
+ }
50
+ /**
51
+ * 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
52
+ * look like can be found here: {@link https://clig.dev/#errors}
53
+ */
54
+ render(config) {
55
+ return (0, ts_dedent_1.default) `
56
+ ${this.header(config)}
57
+
58
+ ${this.body(config)}
59
+
60
+ ${this.footer(config)}
61
+ `;
62
+ }
63
+ header(_) {
64
+ return `${this.code}: ${this.message}`;
65
+ }
66
+ footer(config) {
67
+ switch (this.isBug) {
68
+ case IsBug.NO:
69
+ return "";
70
+ case IsBug.MAYBE:
71
+ return (0, ts_dedent_1.default) `
72
+ If you think this is a bug, please submit an issue using the link below.
73
+
74
+ ${(0, new_github_issue_url_1.default)(this.issueOptions(config))}
75
+ `;
76
+ case IsBug.YES:
77
+ return (0, ts_dedent_1.default) `
78
+ This is a bug :(
79
+
80
+ Visit the link below to see if someone has already reported this issue.
81
+ https://github.com/gadget-inc/ggt/issues?q=is%3Aissue+is%3Aopen+label%3Abug+${this.code}
82
+
83
+ If nobody has, you can submit one using the link below.
84
+ ---
85
+ ${(0, new_github_issue_url_1.default)(this.issueOptions(config))}
86
+ `;
87
+ }
88
+ }
89
+ issueOptions(config) {
90
+ const options = {
91
+ repoUrl: "https://github.com/gadget-inc/ggt",
92
+ title: `[BUG ${this.code}]: `,
93
+ labels: ["bug"],
94
+ body: (0, ts_dedent_1.default) `
95
+ ### Description
96
+ [Please describe what you were doing when this error occurred]
97
+
98
+ ### Command
99
+ \`\`\`sh-session
100
+ ${config.bin} ${process.argv.slice(2).join(" ")}
101
+ \`\`\`
102
+
103
+ ### Environment
104
+ \`\`\`
105
+ version: ${config.version}
106
+ platform: ${config.platform}
107
+ arch: ${config.arch}
108
+ shell: ${config.shell}
109
+ timestamp: ${new Date().toISOString()}
110
+ \`\`\`
111
+
112
+ ### Stack Trace
113
+ \`\`\`
114
+ ${(0, clean_stack_1.default)(this.stack)}
115
+ \`\`\`
116
+ `,
117
+ };
118
+ if (this.cause) {
119
+ options.body += (0, ts_dedent_1.default) `
120
+
121
+ ### Cause
122
+ \`\`\`json
123
+ ${JSON.stringify((0, lodash_1.isError)(this.cause) ? serializeError(this.cause) : this.cause, null, 2)}
124
+ \`\`\`
125
+ `;
126
+ }
127
+ return options;
128
+ }
129
+ }
130
+ exports.BaseError = BaseError;
131
+ /**
132
+ * Universal Error object to json blob serializer.
133
+ * Wraps `serialize-error` with some handy stuff, like special support for Got HTTP errors
134
+ */
135
+ function serializeError(error) {
136
+ let serialized = (0, serialize_error_1.serializeError)(error);
137
+ if (typeof serialized == "string") {
138
+ serialized = { message: serialized };
139
+ }
140
+ if (error instanceof source_1.HTTPError && error.name === "RequestError") {
141
+ delete serialized["timings"];
142
+ serialized["options"] = { method: error.options.method, url: error.options.url.toJSON() };
143
+ serialized["responseBody"] = (0, util_1.inspect)(error.response?.body);
144
+ }
145
+ return serialized;
146
+ }
147
+ exports.serializeError = serializeError;
148
+ var IsBug;
149
+ (function (IsBug) {
150
+ IsBug[IsBug["NO"] = 0] = "NO";
151
+ IsBug[IsBug["MAYBE"] = 1] = "MAYBE";
152
+ IsBug[IsBug["YES"] = 2] = "YES";
153
+ })(IsBug = exports.IsBug || (exports.IsBug = {}));
154
+ /**
155
+ * Our "catch all" error. If this error is thrown, we almost certainly have a bug.
156
+ *
157
+ * Whenever possible, we should use a more specific error so that we can provide more useful information.
158
+ */
159
+ class UnexpectedError extends BaseError {
160
+ constructor(cause) {
161
+ super("GGT_CLI_UNEXPECTED_ERROR", "An unexpected error occurred");
162
+ Object.defineProperty(this, "cause", {
163
+ enumerable: true,
164
+ configurable: true,
165
+ writable: true,
166
+ value: cause
167
+ });
168
+ Object.defineProperty(this, "isBug", {
169
+ enumerable: true,
170
+ configurable: true,
171
+ writable: true,
172
+ value: IsBug.YES
173
+ });
174
+ }
175
+ body(_) {
176
+ return (0, clean_stack_1.default)(this.cause.stack ?? this.stack);
177
+ }
178
+ }
179
+ exports.UnexpectedError = UnexpectedError;
180
+ class ClientError extends BaseError {
181
+ constructor(payload, cause) {
182
+ super("GGT_CLI_CLIENT_ERROR", "An error occurred while communicating with Gadget");
183
+ Object.defineProperty(this, "payload", {
184
+ enumerable: true,
185
+ configurable: true,
186
+ writable: true,
187
+ value: payload
188
+ });
189
+ Object.defineProperty(this, "cause", {
190
+ enumerable: true,
191
+ configurable: true,
192
+ writable: true,
193
+ value: cause
194
+ });
195
+ Object.defineProperty(this, "isBug", {
196
+ enumerable: true,
197
+ configurable: true,
198
+ writable: true,
199
+ value: IsBug.MAYBE
200
+ });
201
+ // 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
202
+ if (isErrorEvent(cause)) {
203
+ this.cause = {
204
+ type: cause.type,
205
+ message: cause.message,
206
+ error: serializeError(cause.error),
207
+ };
208
+ }
209
+ else if (isCloseEvent(cause)) {
210
+ this.cause = {
211
+ type: cause.type,
212
+ code: cause.code,
213
+ reason: cause.reason,
214
+ wasClean: cause.wasClean,
215
+ };
216
+ }
217
+ }
218
+ body(_) {
219
+ if (isGraphQLErrors(this.cause)) {
220
+ if (this.cause.length > 1) {
221
+ let output = "Gadget responded with multiple errors:";
222
+ for (const error of (0, lodash_1.uniqBy)(this.cause, "message")) {
223
+ output += `\n * ${error.message}`;
224
+ }
225
+ return output;
226
+ }
227
+ else {
228
+ return (0, ts_dedent_1.default) `
229
+ Gadget responded with an unexpected error.
230
+
231
+ ${this.cause[0]?.message}
232
+ `;
233
+ }
234
+ }
235
+ if (isCloseEvent(this.cause)) {
236
+ return "The connection to Gadget closed unexpectedly.";
237
+ }
238
+ if (isErrorEvent(this.cause)) {
239
+ return (0, ts_dedent_1.default) `
240
+ The connection to Gadget received an unexpected error.
241
+
242
+ ${this.cause.message}
243
+ `;
244
+ }
245
+ if ((0, lodash_1.isError)(this.cause)) {
246
+ return (0, ts_dedent_1.default) `
247
+ An unexpected error occurred.
248
+
249
+ ${this.cause.message}
250
+ `;
251
+ }
252
+ return this.cause;
253
+ }
254
+ issueOptions(config) {
255
+ const options = super.issueOptions(config);
256
+ options.body += (0, ts_dedent_1.default) `
257
+
258
+ ### GraphQL
259
+
260
+ #### Query
261
+ \`\`\`graphql
262
+ ${this.payload.query}
263
+ \`\`\`
264
+ `;
265
+ // mutations can have large/sensitive payloads, so we don't include them by default
266
+ if (!this.payload.query.trimStart().startsWith("mutation")) {
267
+ options.body += (0, ts_dedent_1.default) `
268
+
269
+ #### Variables
270
+ \`\`\`json
271
+ ${JSON.stringify(this.payload.variables, null, 2)}
272
+ \`\`\`
273
+ `;
274
+ }
275
+ return options;
276
+ }
277
+ }
278
+ exports.ClientError = ClientError;
279
+ class WalkedTooManyFilesError extends BaseError {
280
+ constructor(dir, maxFiles) {
281
+ super("GGT_CLI_TOO_MANY_FILES", "Found too many files while scanning directory");
282
+ Object.defineProperty(this, "dir", {
283
+ enumerable: true,
284
+ configurable: true,
285
+ writable: true,
286
+ value: dir
287
+ });
288
+ Object.defineProperty(this, "maxFiles", {
289
+ enumerable: true,
290
+ configurable: true,
291
+ writable: true,
292
+ value: maxFiles
293
+ });
294
+ Object.defineProperty(this, "isBug", {
295
+ enumerable: true,
296
+ configurable: true,
297
+ writable: true,
298
+ value: IsBug.NO
299
+ });
300
+ }
301
+ body(_) {
302
+ return (0, ts_dedent_1.default) `
303
+ The following directory has over ${this.maxFiles} non-ignored files inside of it.
304
+ ${this.dir}
305
+
306
+ Consider adding more entries to your \`.ignore\` file.
307
+ `;
308
+ }
309
+ }
310
+ exports.WalkedTooManyFilesError = WalkedTooManyFilesError;
311
+ function isCloseEvent(e) {
312
+ 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
+ }
314
+ function isErrorEvent(e) {
315
+ return (0, lodash_1.has)(e, "type") && (0, lodash_1.has)(e, "message") && (0, lodash_1.has)(e, "error");
316
+ }
317
+ function isGraphQLErrors(e) {
318
+ return Array.isArray(e) && e.every((e) => e instanceof graphql_1.GraphQLError);
319
+ }
320
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,18 @@
1
+ export declare class Ignorer {
2
+ private readonly _rootDir;
3
+ private readonly _alwaysIgnore;
4
+ readonly filepath: string;
5
+ private _ignorer;
6
+ constructor(_rootDir: string, _alwaysIgnore: string[]);
7
+ ignores(filepath: string): boolean;
8
+ reload(): void;
9
+ }
10
+ export interface WalkDirOptions {
11
+ ignorer?: Ignorer;
12
+ maxFiles?: number;
13
+ _fileCount?: number;
14
+ _rootDir?: string;
15
+ }
16
+ export declare function walkDir(dir: string, options?: WalkDirOptions): AsyncGenerator<string>;
17
+ export declare function walkDirSync(dir: string, options?: WalkDirOptions): Generator<string>;
18
+ export declare function ignoreEnoent(error: any): void;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ignoreEnoent = exports.walkDirSync = exports.walkDir = exports.Ignorer = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const debug_1 = tslib_1.__importDefault(require("debug"));
6
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
7
+ const ignore_1 = tslib_1.__importDefault(require("ignore"));
8
+ const path_1 = tslib_1.__importDefault(require("path"));
9
+ const errors_1 = require("./errors");
10
+ const debug = (0, debug_1.default)("ggt:fs-utils");
11
+ class Ignorer {
12
+ constructor(_rootDir, _alwaysIgnore) {
13
+ Object.defineProperty(this, "_rootDir", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: _rootDir
18
+ });
19
+ Object.defineProperty(this, "_alwaysIgnore", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: _alwaysIgnore
24
+ });
25
+ Object.defineProperty(this, "filepath", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: path_1.default.join(this._rootDir, ".ignore")
30
+ });
31
+ Object.defineProperty(this, "_ignorer", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: void 0
36
+ });
37
+ this.reload();
38
+ }
39
+ ignores(filepath) {
40
+ const relative = path_1.default.relative(this._rootDir, filepath);
41
+ if (relative == "")
42
+ return false;
43
+ return this._ignorer.ignores(relative);
44
+ }
45
+ reload() {
46
+ this._ignorer = (0, ignore_1.default)();
47
+ this._ignorer.add(this._alwaysIgnore);
48
+ try {
49
+ this._ignorer.add(fs_extra_1.default.readFileSync(this.filepath, "utf-8"));
50
+ debug("reloaded ignore rules from %s", this.filepath);
51
+ }
52
+ catch (error) {
53
+ ignoreEnoent(error);
54
+ }
55
+ }
56
+ }
57
+ exports.Ignorer = Ignorer;
58
+ async function* walkDir(dir, options = {}) {
59
+ if (options.ignorer?.ignores(dir))
60
+ return;
61
+ if (options._rootDir == null)
62
+ options._rootDir = dir;
63
+ if (options._fileCount == null)
64
+ options._fileCount = 0;
65
+ for await (const entry of await fs_extra_1.default.opendir(dir)) {
66
+ const filepath = path_1.default.join(dir, entry.name);
67
+ if (entry.isDirectory()) {
68
+ yield* walkDir(filepath, options);
69
+ }
70
+ 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
+ yield filepath;
75
+ }
76
+ }
77
+ }
78
+ exports.walkDir = walkDir;
79
+ function* walkDirSync(dir, options = {}) {
80
+ if (options.ignorer?.ignores(dir))
81
+ return;
82
+ if (options._rootDir == null)
83
+ options._rootDir = dir;
84
+ if (options._fileCount == null)
85
+ options._fileCount = 0;
86
+ for (const entry of fs_extra_1.default.readdirSync(dir, { withFileTypes: true })) {
87
+ const filepath = path_1.default.join(dir, entry.name);
88
+ if (entry.isDirectory()) {
89
+ yield* walkDirSync(filepath, options);
90
+ }
91
+ 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
+ yield filepath;
96
+ }
97
+ }
98
+ }
99
+ exports.walkDirSync = walkDirSync;
100
+ function ignoreEnoent(error) {
101
+ if (error.code === "ENOENT") {
102
+ debug("ignoring ENOENT error %s", error.path);
103
+ return;
104
+ }
105
+ throw error;
106
+ }
107
+ exports.ignoreEnoent = ignoreEnoent;
108
+ //# sourceMappingURL=fs-utils.js.map
@@ -0,0 +1 @@
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\";\nimport { WalkedTooManyFilesError } from \"./errors\";\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 _fileCount?: number;\n _rootDir?: string;\n}\n\nexport async function* walkDir(dir: string, options: WalkDirOptions = {}): AsyncGenerator<string> {\n if (options.ignorer?.ignores(dir)) return;\n if (options._rootDir == null) options._rootDir = dir;\n if (options._fileCount == null) options._fileCount = 0;\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 if (options.maxFiles != null && ++options._fileCount >= options.maxFiles) {\n throw new WalkedTooManyFilesError(options._rootDir, options.maxFiles);\n }\n yield filepath;\n }\n }\n}\n\nexport function* walkDirSync(dir: string, options: WalkDirOptions = {}): Generator<string> {\n if (options.ignorer?.ignores(dir)) return;\n if (options._rootDir == null) options._rootDir = dir;\n if (options._fileCount == null) options._fileCount = 0;\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 if (options.maxFiles != null && ++options._fileCount >= options.maxFiles) {\n throw new WalkedTooManyFilesError(options._rootDir, options.maxFiles);\n }\n yield filepath;\n }\n }\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"]}
@@ -0,0 +1,14 @@
1
+ import { CommandHelp as OclifCommandHelp, Help as OclifHelp } from "@oclif/core";
2
+ export default class Help extends OclifHelp {
3
+ CommandHelpClass: typeof CommandHelp;
4
+ }
5
+ declare class CommandHelp extends OclifCommandHelp {
6
+ /**
7
+ * By default, oclif tries to format the description so that it fit's within the terminal window. However, if the description is already
8
+ * formatted with `dedent`, then the description gets mangled and the help output is not pretty.
9
+ *
10
+ * This overrides the default behavior to just use the description as-is if it already exists.
11
+ */
12
+ protected description(): string | undefined;
13
+ }
14
+ export {};