@gadgetinc/ggt 0.2.4 → 0.3.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 (70) hide show
  1. package/README.md +79 -91
  2. package/bin/dev.js +11 -19
  3. package/bin/run.js +1 -9
  4. package/lib/__generated__/graphql.js +2 -2
  5. package/lib/__generated__/graphql.js.map +1 -1
  6. package/lib/commands/index.js +9 -0
  7. package/lib/commands/index.js.map +1 -0
  8. package/lib/commands/list.js +34 -49
  9. package/lib/commands/list.js.map +1 -1
  10. package/lib/commands/login.js +74 -17
  11. package/lib/commands/login.js.map +1 -1
  12. package/lib/commands/logout.js +19 -23
  13. package/lib/commands/logout.js.map +1 -1
  14. package/lib/commands/root.js +85 -0
  15. package/lib/commands/root.js.map +1 -0
  16. package/lib/commands/sync.js +312 -678
  17. package/lib/commands/sync.js.map +1 -1
  18. package/lib/commands/whoami.js +23 -27
  19. package/lib/commands/whoami.js.map +1 -1
  20. package/lib/main.js +12 -0
  21. package/lib/main.js.map +1 -0
  22. package/lib/services/app.js +36 -0
  23. package/lib/services/app.js.map +1 -0
  24. package/lib/services/args.js +28 -0
  25. package/lib/services/args.js.map +1 -0
  26. package/lib/services/client.js +43 -76
  27. package/lib/services/client.js.map +1 -1
  28. package/lib/services/config.js +139 -0
  29. package/lib/services/config.js.map +1 -0
  30. package/lib/services/errors.js +64 -89
  31. package/lib/services/errors.js.map +1 -1
  32. package/lib/services/filesync.js +404 -0
  33. package/lib/services/filesync.js.map +1 -0
  34. package/lib/services/fs-utils.js +18 -91
  35. package/lib/services/fs-utils.js.map +1 -1
  36. package/lib/services/http.js +53 -0
  37. package/lib/services/http.js.map +1 -0
  38. package/lib/services/log.js +45 -0
  39. package/lib/services/log.js.map +1 -0
  40. package/lib/services/notify.js +30 -0
  41. package/lib/services/notify.js.map +1 -0
  42. package/lib/services/output.js +59 -0
  43. package/lib/services/output.js.map +1 -0
  44. package/lib/services/promise.js +8 -5
  45. package/lib/services/promise.js.map +1 -1
  46. package/lib/services/session.js +27 -0
  47. package/lib/services/session.js.map +1 -0
  48. package/lib/services/sleep.js +2 -5
  49. package/lib/services/sleep.js.map +1 -1
  50. package/lib/services/timeout.js +8 -0
  51. package/lib/services/timeout.js.map +1 -0
  52. package/lib/services/user.js +70 -0
  53. package/lib/services/user.js.map +1 -0
  54. package/lib/services/version.js +72 -0
  55. package/lib/services/version.js.map +1 -0
  56. package/npm-shrinkwrap.json +15703 -25760
  57. package/package.json +53 -60
  58. package/lib/commands/help.js +0 -28
  59. package/lib/commands/help.js.map +0 -1
  60. package/lib/index.js +0 -3
  61. package/lib/index.js.map +0 -1
  62. package/lib/services/base-command.js +0 -203
  63. package/lib/services/base-command.js.map +0 -1
  64. package/lib/services/context.js +0 -143
  65. package/lib/services/context.js.map +0 -1
  66. package/lib/services/flags.js +0 -57
  67. package/lib/services/flags.js.map +0 -1
  68. package/lib/services/help.js +0 -36
  69. package/lib/services/help.js.map +0 -1
  70. package/oclif.manifest.json +0 -244
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
1
  {
2
2
  "name": "@gadgetinc/ggt",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
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",
7
- "repository": "gadget-inc/ggt",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/gadget-inc/ggt.git"
10
+ },
8
11
  "license": "MIT",
9
12
  "author": "Gadget Authors",
10
13
  "type": "module",
11
- "main": "lib/index.js",
14
+ "main": "lib/main.js",
12
15
  "bin": {
13
- "ggt": "./bin/run.js"
16
+ "ggt": "bin/run.js"
14
17
  },
15
18
  "files": [
16
19
  "/assets",
17
20
  "/bin",
18
21
  "/lib",
19
22
  "/npm-shrinkwrap.json",
20
- "/oclif.manifest.json",
21
23
  "/package.json",
22
24
  "/README.md"
23
25
  ],
24
26
  "scripts": {
25
- "build": "npm run clean && swc src -d lib && oclif manifest",
26
- "clean": "rimraf lib tmp oclif.manifest.json",
27
- "generate-graphql": "graphql-codegen --config graphql-codegen.yml",
27
+ "build": "npm run clean && swc src -d lib",
28
+ "clean": "rimraf lib tmp",
29
+ "generate:graphql": "graphql-codegen --config graphql-codegen.yml",
30
+ "generate:readme": "FORCE_COLOR=0 node --loader @swc-node/register/esm --no-warnings ./scripts/generate-readme.ts",
28
31
  "lint": "concurrently --prefix none --group 'npm:lint:*(!fix)'",
29
32
  "lint:cspell": "cspell --no-progress --show-suggestions --show-context '**'",
30
33
  "lint:eslint": "eslint --max-warnings 0 .",
31
34
  "lint:fix": "eslint --fix . && prettier --write .",
32
35
  "lint:prettier": "prettier --check .",
33
36
  "lint:typescript": "tsc --project tsconfig.json",
34
- "publish": "npm run build && changeset publish",
35
- "readme": "patch-package && oclif readme && prettier --write README.md",
36
- "test": "cross-env NODE_OPTIONS=\"--no-warnings --loader ./node_modules/ts-node/esm.mjs\" vitest",
37
- "version": "changeset version && npm install --package-lock-only && npm run build && npm run readme"
37
+ "release": "npm run build && changeset publish",
38
+ "test": "cross-env NODE_OPTIONS=\"--loader @swc-node/register/esm --no-warnings\" vitest",
39
+ "version": "changeset version && npm install --package-lock-only && npm run generate:readme"
38
40
  },
39
41
  "dependencies": {
40
- "@oclif/core": "^2.15.0",
41
- "@oclif/errors": "^1.3.6",
42
- "@oclif/plugin-not-found": "^2.4.3",
43
- "@oclif/plugin-warn-if-update-available": "^2.1.1",
44
- "@sentry/node": "^7.73.0",
42
+ "@sentry/node": "^7.74.1",
45
43
  "@swc/helpers": "^0.5.3",
44
+ "arg": "^5.0.2",
45
+ "boxen": "^7.1.1",
46
46
  "chalk": "^5.3.0",
47
47
  "chalk-template": "^1.1.0",
48
48
  "clean-stack": "^5.2.0",
@@ -50,25 +50,32 @@
50
50
  "debug": "^4.3.4",
51
51
  "execa": "^8.0.1",
52
52
  "fast-levenshtein": "^3.0.0",
53
+ "find-up": "^6.3.0",
53
54
  "fs-extra": "^11.1.1",
54
55
  "get-port": "^7.0.0",
55
56
  "got": "^13.0.0",
56
57
  "graphql": "^16.8.1",
57
- "graphql-ws": "^5.14.1",
58
+ "graphql-ws": "^5.14.2",
58
59
  "ignore": "^5.2.4",
59
60
  "inquirer": "^9.2.11",
61
+ "is-wsl": "^3.1.0",
60
62
  "lodash": "^4.17.21",
63
+ "ms": "^2.1.3",
61
64
  "node-notifier": "^10.0.1",
65
+ "normalize-package-data": "^6.0.0",
62
66
  "normalize-path": "^3.0.0",
63
67
  "open": "^9.1.0",
64
68
  "p-map": "^6.0.0",
65
69
  "p-queue": "^7.4.1",
70
+ "p-retry": "^6.1.0",
66
71
  "pluralize": "^8.0.0",
72
+ "semver": "^7.5.4",
67
73
  "serialize-error": "^11.0.2",
68
74
  "ts-dedent": "^2.2.0",
69
75
  "watcher": "^2.3.0",
70
76
  "which": "^4.0.0",
71
- "ws": "^8.14.2"
77
+ "ws": "^8.14.2",
78
+ "zod": "^3.22.4"
72
79
  },
73
80
  "devDependencies": {
74
81
  "@changesets/cli": "^2.26.2",
@@ -76,59 +83,45 @@
76
83
  "@graphql-codegen/cli": "^5.0.0",
77
84
  "@graphql-codegen/typescript": "^4.0.0",
78
85
  "@graphql-codegen/typescript-operations": "^4.0.1",
79
- "@oclif/plugin-plugins": "^3.9.1",
80
- "@oclif/test": "^2.5.6",
86
+ "@swc-node/register": "^1.6.8",
81
87
  "@swc/cli": "^0.1.62",
82
- "@swc/core": "^1.3.82",
83
- "@types/debug": "^4.1.9",
84
- "@types/eslint": "^8.44.4",
85
- "@types/fast-levenshtein": "^0.0.2",
86
- "@types/fs-extra": "^11.0.2",
87
- "@types/inquirer": "^9.0.4",
88
- "@types/lodash": "^4.14.199",
89
- "@types/node": "^20.8.4",
90
- "@types/node-notifier": "^8.0.3",
91
- "@types/normalize-path": "^3.0.0",
92
- "@types/pluralize": "^0.0.31",
93
- "@types/which": "^3.0.0",
94
- "@types/ws": "^8.5.7",
95
- "@typescript-eslint/eslint-plugin": "^6.7.5",
96
- "@typescript-eslint/parser": "^6.7.5",
97
- "concurrently": "^8.2.1",
88
+ "@swc/core": "^1.3.94",
89
+ "@types/debug": "^4.1.10",
90
+ "@types/eslint": "^8.44.6",
91
+ "@types/fast-levenshtein": "^0.0.3",
92
+ "@types/fs-extra": "^11.0.3",
93
+ "@types/inquirer": "^9.0.6",
94
+ "@types/lodash": "^4.14.200",
95
+ "@types/ms": "^0.7.33",
96
+ "@types/node": "^20.8.7",
97
+ "@types/node-notifier": "^8.0.4",
98
+ "@types/normalize-path": "^3.0.1",
99
+ "@types/pluralize": "^0.0.32",
100
+ "@types/which": "^3.0.1",
101
+ "@types/ws": "^8.5.8",
102
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
103
+ "@typescript-eslint/parser": "^6.9.0",
104
+ "concurrently": "^8.2.2",
98
105
  "cross-env": "^7.0.3",
99
- "cspell": "^7.3.7",
100
- "eslint": "^8.51.0",
106
+ "cspell": "^7.3.8",
107
+ "eslint": "^8.52.0",
101
108
  "eslint-config-prettier": "^9.0.0",
102
- "eslint-plugin-import": "^2.28.1",
109
+ "eslint-import-resolver-typescript": "^3.6.1",
110
+ "eslint-plugin-import": "^2.29.0",
103
111
  "eslint-plugin-lodash": "^7.4.0",
104
- "nock": "^13.3.4",
105
- "oclif": "^3.17.2",
106
- "patch-package": "^8.0.0",
112
+ "nock": "^13.3.6",
107
113
  "prettier": "^3.0.3",
108
114
  "prettier-plugin-organize-imports": "^3.2.3",
109
115
  "prettier-plugin-packagejson": "^2.4.6",
116
+ "remark": "^15.0.1",
117
+ "remark-gfm": "^4.0.0",
118
+ "remark-toc": "^9.0.0",
110
119
  "rimraf": "^5.0.5",
111
- "ts-node": "^10.9.1",
112
- "type-fest": "^4.4.0",
120
+ "type-fest": "^4.5.0",
113
121
  "typescript": "^5.2.2",
114
122
  "vitest": "^0.34.6"
115
123
  },
116
124
  "engines": {
117
125
  "node": ">=16.0.0"
118
- },
119
- "oclif": {
120
- "bin": "ggt",
121
- "dirname": "gadget",
122
- "commands": "./lib/commands",
123
- "helpClass": "./lib/services/help",
124
- "topicSeparator": " ",
125
- "topics": {},
126
- "plugins": [
127
- "@oclif/plugin-not-found",
128
- "@oclif/plugin-warn-if-update-available"
129
- ],
130
- "warn-if-update-available": {
131
- "timeoutInDays": 1
132
- }
133
126
  }
134
127
  }
@@ -1,28 +0,0 @@
1
- import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
- import { Args } from "@oclif/core";
3
- import { BaseCommand } from "../services/base-command.js";
4
- import Help from "../services/help.js";
5
- class HelpCommand extends BaseCommand {
6
- async run() {
7
- const { argv } = await this.parse();
8
- const help = new Help(this.config, {
9
- all: true
10
- });
11
- await help.showHelp(argv);
12
- }
13
- }
14
- _define_property(HelpCommand, "strict", false);
15
- _define_property(HelpCommand, "summary", "Display help for ggt.");
16
- _define_property(HelpCommand, "args", {
17
- command: Args.string({
18
- required: false,
19
- description: "The command to show help for."
20
- })
21
- });
22
- /**
23
- * Copied from @oclif/plugin-help. Uses our own {@link Help} template class instead of the one from @oclif/core.
24
- *
25
- * @see https://github.com/oclif/plugin-help/blob/67b580570257b45e92d3a04d50bf2a432c59afe3/src/commands/help.ts
26
- */ export { HelpCommand as default };
27
-
28
- //# sourceMappingURL=help.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/help.ts"],"sourcesContent":["import { Args } from \"@oclif/core\";\nimport { BaseCommand } from \"../services/base-command.js\";\nimport Help from \"../services/help.js\";\n\n/**\n * Copied from @oclif/plugin-help. Uses our own {@link Help} template class instead of the one from @oclif/core.\n *\n * @see https://github.com/oclif/plugin-help/blob/67b580570257b45e92d3a04d50bf2a432c59afe3/src/commands/help.ts\n */\nexport default class HelpCommand extends BaseCommand<typeof HelpCommand> {\n static override strict = false;\n\n static override summary = \"Display help for ggt.\";\n\n static override args = {\n command: Args.string({\n required: false,\n description: \"The command to show help for.\",\n }),\n };\n\n async run(): Promise<void> {\n const { argv } = await this.parse();\n const help = new Help(this.config, { all: true });\n await help.showHelp(argv as string[]);\n }\n}\n"],"names":["Args","BaseCommand","Help","HelpCommand","run","argv","parse","help","config","all","showHelp","strict","summary","args","command","string","required","description"],"mappings":";AAAA,SAASA,IAAI,QAAQ,cAAc;AACnC,SAASC,WAAW,QAAQ,8BAA8B;AAC1D,OAAOC,UAAU,sBAAsB;AAOxB,MAAMC,oBAAoBF;IAYvC,MAAMG,MAAqB;QACzB,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAM,IAAI,CAACC,KAAK;QACjC,MAAMC,OAAO,IAAIL,KAAK,IAAI,CAACM,MAAM,EAAE;YAAEC,KAAK;QAAK;QAC/C,MAAMF,KAAKG,QAAQ,CAACL;IACtB;AACF;AAhBE,iBADmBF,aACHQ,UAAS;AAEzB,iBAHmBR,aAGHS,WAAU;AAE1B,iBALmBT,aAKHU,QAAO;IACrBC,SAASd,KAAKe,MAAM,CAAC;QACnBC,UAAU;QACVC,aAAa;IACf;AACF;AAfF;;;;CAIC,GACD,SAAqBd,yBAiBpB"}
package/lib/index.js DELETED
@@ -1,3 +0,0 @@
1
- export { run } from "@oclif/core";
2
-
3
- //# sourceMappingURL=index.js.map
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { run } from \"@oclif/core\";\n"],"names":["run"],"mappings":"AAAA,SAASA,GAAG,QAAQ,cAAc"}
@@ -1,203 +0,0 @@
1
- import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
- import { Command, Flags, settings } from "@oclif/core";
3
- import { CLIError as CLIError2 } from "@oclif/core/lib/errors/index.js";
4
- import { CLIError, ExitError } from "@oclif/errors";
5
- import { init as initSentry } from "@sentry/node";
6
- import chalkTemplate from "chalk-template";
7
- import Debug from "debug";
8
- import getPort from "get-port";
9
- import inquirer from "inquirer";
10
- import _ from "lodash";
11
- import notifier from "node-notifier";
12
- import http from "node:http";
13
- import path from "node:path";
14
- import open from "open";
15
- import { dedent } from "ts-dedent";
16
- import { context } from "./context.js";
17
- import { BaseError, UnexpectedError } from "./errors.js";
18
- /**
19
- * BaseCommand is the base class for all commands in the Gadget CLI.
20
- */ export class BaseCommand extends Command {
21
- /**
22
- * Indicates whether the command is being run with the `-D/--debug` flag.
23
- */ get debugEnabled() {
24
- return !!settings.debug;
25
- }
26
- async init() {
27
- context.config = this.config;
28
- initSentry({
29
- dsn: "https://0c26e0d8afd94e77a88ee1c3aa9e7065@o250689.ingest.sentry.io/6703266",
30
- release: context.config.version,
31
- enabled: context.env.productionLike && !_.includes([
32
- "0",
33
- "false",
34
- "no",
35
- "off"
36
- ], _.toLower(_.trim(process.env["GGT_SENTRY_ENABLED"])))
37
- });
38
- await super.init();
39
- if (this.requireUser && !await context.getUser()) {
40
- // we purposely log the user in before parsing flags in case one of the flags requires the user to be logged in
41
- // e.g. the `--app` flag verifies that the user has access to the app they are trying to use
42
- const { login } = await inquirer.prompt({
43
- type: "confirm",
44
- name: "login",
45
- message: "You must be logged in to use this command. Would you like to log in?"
46
- });
47
- if (!login) {
48
- this.exit(0);
49
- return;
50
- }
51
- await this.login();
52
- }
53
- const { flags, args } = await this.parse({
54
- flags: this.ctor.flags,
55
- baseFlags: super.ctor.baseFlags,
56
- args: this.ctor.args,
57
- strict: this.ctor.strict
58
- });
59
- this.flags = flags;
60
- this.args = args;
61
- if (flags.debug) {
62
- settings.debug = true;
63
- Debug.enable(`${this.config.bin}:*`);
64
- }
65
- context.addBreadcrumb({
66
- category: "command",
67
- message: "Initialized",
68
- data: {
69
- command: this.id,
70
- flags: this.flags,
71
- args: this.args
72
- }
73
- });
74
- }
75
- /**
76
- * Sends a native OS notification to the user.
77
- *
78
- * @see {@link https://www.npmjs.com/package/node-notifier node-notifier}
79
- */ notify(notification) {
80
- notifier.notify({
81
- title: "Gadget",
82
- contentImage: path.join(this.config.root, "assets", "favicon-128@4x.png"),
83
- icon: path.join(this.config.root, "assets", "favicon-128@4x.png"),
84
- sound: true,
85
- timeout: false,
86
- ...notification
87
- }, (error)=>{
88
- if (error) this.warn(error);
89
- });
90
- }
91
- /**
92
- * Opens the Gadget login page in the user's default browser and waits for the user to login.
93
- */ async login() {
94
- let server;
95
- try {
96
- const port = await getPort();
97
- const receiveSession = new Promise((resolve, reject)=>{
98
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
99
- server = http.createServer(async (req, res)=>{
100
- const redirectTo = new URL(`https://${context.domains.services}/auth/cli`);
101
- try {
102
- if (!req.url) throw new Error("missing url");
103
- const incomingUrl = new URL(req.url, `http://localhost:${port}`);
104
- const value = incomingUrl.searchParams.get("session");
105
- if (!value) throw new Error("missing session");
106
- context.session = value;
107
- const user = await context.getUser();
108
- if (!user) throw new Error("missing current user");
109
- if (user.name) {
110
- this.log(chalkTemplate`Hello, ${user.name} {gray (${user.email})}`);
111
- } else {
112
- this.log(`Hello, ${user.email}`);
113
- }
114
- this.log();
115
- redirectTo.searchParams.set("success", "true");
116
- resolve();
117
- } catch (error) {
118
- context.session = undefined;
119
- redirectTo.searchParams.set("success", "false");
120
- reject(error);
121
- } finally{
122
- res.writeHead(303, {
123
- Location: redirectTo.toString()
124
- });
125
- res.end();
126
- }
127
- });
128
- server.listen(port);
129
- });
130
- const url = new URL(`https://${context.domains.services}/auth/login`);
131
- url.searchParams.set("returnTo", `https://${context.domains.services}/auth/cli/callback?port=${port}`);
132
- await open(url.toString());
133
- this.log(dedent`
134
- We've opened Gadget's login page using your default browser.
135
-
136
- Please log in and then return to this terminal.\n
137
- `);
138
- await receiveSession;
139
- } finally{
140
- server?.close();
141
- }
142
- }
143
- /**
144
- * Overrides the default `catch` behavior so we can control how errors are printed to the user. This is called
145
- * automatically by oclif when an error is thrown during the `init` or `run` methods.
146
- */ async catch(cause) {
147
- if (cause instanceof CLIError || cause instanceof CLIError2) {
148
- // CLIErrors are user errors (invalid flag, arg, etc...) and already print nicely formatted error messages
149
- throw cause;
150
- }
151
- const error = cause instanceof BaseError ? cause : new UnexpectedError(cause);
152
- console.error(error.render());
153
- await error.capture();
154
- // The original implementation of `catch` re-throws the error so that it's caught and printed by oclif's `handle`
155
- // method. We still want to end up in oclif's `handle` method, but we don't want it to print the error again so we
156
- // throw an ExitError instead. This will cause `handle` to not print the error, but still exit with the correct exit
157
- // code.
158
- //
159
- // catch: https://github.com/oclif/core/blob/12e31ff2288606e583e03bf774a3244f3136cd10/src/command.ts#L261
160
- // handle: https://github.com/oclif/core/blob/12e31ff2288606e583e03bf774a3244f3136cd10/src/errors/handle.ts#L15
161
- throw new ExitError(1);
162
- }
163
- constructor(argv, config){
164
- super(argv, config);
165
- /**
166
- * Determines whether the command requires the user to be logged in or not.
167
- *
168
- * If true and the user is not logged in, the user will be prompted to login before the underlying command is
169
- * initialized and run.
170
- */ _define_property(this, "requireUser", false);
171
- /**
172
- * The parsed flags for the command.
173
- */ _define_property(this, "flags", void 0);
174
- /**
175
- * The parsed arguments for the command.
176
- */ _define_property(this, "args", void 0);
177
- // TODO: Remove this once the `@oclif/core` warnIfFlagDeprecated function checks base flags as well.
178
- // warnIfFlagDeprecated throws a null pointer because it assumes all parsed flags are in the flags object (which is not the case for global flags).
179
- // https://github.com/oclif/core/blob/11c5752cec838d08bb27cd55f0f1aa2390df3c5e/src/command.ts#L259
180
- this.ctor.flags = {
181
- ...this.ctor.flags,
182
- ...BaseCommand.baseFlags
183
- };
184
- }
185
- }
186
- /**
187
- * Determines how high the command is listed in the README. The lower the number, the higher the command is listed.
188
- * Equal numbers are sorted alphabetically.
189
- */ _define_property(BaseCommand, "priority", Infinity);
190
- /**
191
- * Flags that are available to all commands.
192
- *
193
- * Short form should be capitalized.
194
- */ _define_property(BaseCommand, "baseFlags", {
195
- debug: Flags.boolean({
196
- char: "D",
197
- summary: "Whether to output debug information.",
198
- helpGroup: "global",
199
- default: false
200
- })
201
- });
202
-
203
- //# sourceMappingURL=base-command.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/base-command.ts"],"sourcesContent":["import type { Config, Interfaces } from \"@oclif/core\";\nimport { Command, Flags, settings } from \"@oclif/core\";\nimport { CLIError as CLIError2 } from \"@oclif/core/lib/errors/index.js\";\nimport { CLIError, ExitError } from \"@oclif/errors\";\nimport { init as initSentry } from \"@sentry/node\";\nimport chalkTemplate from \"chalk-template\";\nimport Debug from \"debug\";\nimport getPort from \"get-port\";\nimport inquirer from \"inquirer\";\nimport _ from \"lodash\";\nimport type { Notification } from \"node-notifier\";\nimport notifier from \"node-notifier\";\nimport type WindowsBalloon from \"node-notifier/notifiers/balloon.js\";\nimport type Growl from \"node-notifier/notifiers/growl.js\";\nimport type NotificationCenter from \"node-notifier/notifiers/notificationcenter.js\";\nimport type NotifySend from \"node-notifier/notifiers/notifysend.js\";\nimport type WindowsToaster from \"node-notifier/notifiers/toaster.js\";\nimport type { Server } from \"node:http\";\nimport http from \"node:http\";\nimport path from \"node:path\";\nimport open from \"open\";\nimport { dedent } from \"ts-dedent\";\nimport { context } from \"./context.js\";\nimport { BaseError, UnexpectedError } from \"./errors.js\";\n\nexport type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)[\"baseFlags\"] & T[\"flags\"]>;\nexport type Args<T extends typeof Command> = Interfaces.InferredArgs<T[\"args\"]>;\n\n/**\n * BaseCommand is the base class for all commands in the Gadget CLI.\n */\nexport abstract class BaseCommand<T extends typeof Command> extends Command {\n /**\n * Determines how high the command is listed in the README. The lower the number, the higher the command is listed.\n * Equal numbers are sorted alphabetically.\n */\n static priority = Infinity;\n\n /**\n * Flags that are available to all commands.\n *\n * Short form should be capitalized.\n */\n static override baseFlags = {\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 * Determines whether the command requires the user to be logged in or not.\n *\n * If true and the user is not logged in, the user will be prompted to login before the underlying command is\n * initialized and run.\n */\n readonly requireUser: boolean = false;\n\n /**\n * The parsed flags for the command.\n */\n flags!: Flags<T>;\n\n /**\n * The parsed arguments for the command.\n */\n args!: Args<T>;\n\n constructor(argv: string[], config: Config) {\n super(argv, config);\n\n // TODO: Remove this once the `@oclif/core` warnIfFlagDeprecated function checks base flags as well.\n // warnIfFlagDeprecated throws a null pointer because it assumes all parsed flags are in the flags object (which is not the case for global flags).\n // https://github.com/oclif/core/blob/11c5752cec838d08bb27cd55f0f1aa2390df3c5e/src/command.ts#L259\n this.ctor.flags = { ...this.ctor.flags, ...BaseCommand.baseFlags };\n }\n\n /**\n * Indicates whether the command is being run with the `-D/--debug` flag.\n */\n get debugEnabled(): boolean {\n return !!settings.debug;\n }\n\n override async init(): Promise<void> {\n context.config = this.config;\n\n initSentry({\n dsn: \"https://0c26e0d8afd94e77a88ee1c3aa9e7065@o250689.ingest.sentry.io/6703266\",\n release: context.config.version,\n enabled: context.env.productionLike && !_.includes([\"0\", \"false\", \"no\", \"off\"], _.toLower(_.trim(process.env[\"GGT_SENTRY_ENABLED\"]))),\n });\n\n await super.init();\n\n if (this.requireUser && !(await context.getUser())) {\n // we purposely log the user in before parsing flags in case one of the flags requires the user to be logged in\n // e.g. the `--app` flag verifies that the user has access to the app they are trying to use\n const { login } = await inquirer.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 this.exit(0);\n return;\n }\n\n await this.login();\n }\n\n const { flags, args } = await this.parse({\n flags: this.ctor.flags,\n baseFlags: (super.ctor as typeof BaseCommand).baseFlags,\n args: this.ctor.args,\n strict: this.ctor.strict,\n });\n\n this.flags = flags as Flags<T>;\n this.args = args as Args<T>;\n\n if (flags.debug) {\n settings.debug = true;\n Debug.enable(`${this.config.bin}:*`);\n }\n\n context.addBreadcrumb({\n category: \"command\",\n message: \"Initialized\",\n data: {\n command: this.id,\n flags: this.flags,\n args: this.args,\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 notifier.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 = http.createServer(async (req, res) => {\n const redirectTo = new URL(`https://${context.domains.services}/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 value = incomingUrl.searchParams.get(\"session\");\n if (!value) throw new Error(\"missing session\");\n\n context.session = value;\n\n const user = await context.getUser();\n if (!user) throw new Error(\"missing current user\");\n\n if (user.name) {\n this.log(chalkTemplate`Hello, ${user.name} {gray (${user.email})}`);\n } else {\n this.log(`Hello, ${user.email}`);\n }\n this.log();\n\n redirectTo.searchParams.set(\"success\", \"true\");\n resolve();\n } catch (error) {\n context.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(`https://${context.domains.services}/auth/login`);\n url.searchParams.set(\"returnTo\", `https://${context.domains.services}/auth/cli/callback?port=${port}`);\n await open(url.toString());\n\n this.log(dedent`\n We've opened Gadget's login page using your default browser.\n\n Please log in and then return to this terminal.\\n\n `);\n\n await receiveSession;\n } finally {\n server?.close();\n }\n }\n\n /**\n * Overrides the default `catch` behavior so we can control how errors are printed to the user. This is called\n * automatically by oclif when an error is thrown during the `init` or `run` methods.\n */\n override async catch(cause: Error): Promise<never> {\n if (cause instanceof CLIError || cause instanceof CLIError2) {\n // CLIErrors are user errors (invalid flag, arg, etc...) and already print nicely formatted error messages\n throw cause;\n }\n\n const error = cause instanceof BaseError ? cause : new UnexpectedError(cause);\n console.error(error.render());\n await error.capture();\n\n // The original implementation of `catch` re-throws the error so that it's caught and printed by oclif's `handle`\n // method. We still want to end up in oclif's `handle` method, but we don't want it to print the error again so we\n // throw an ExitError instead. This will cause `handle` to not print the error, but still exit with the correct exit\n // 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(1);\n }\n}\n"],"names":["Command","Flags","settings","CLIError","CLIError2","ExitError","init","initSentry","chalkTemplate","Debug","getPort","inquirer","_","notifier","http","path","open","dedent","context","BaseError","UnexpectedError","BaseCommand","debugEnabled","debug","config","dsn","release","version","enabled","env","productionLike","includes","toLower","trim","process","requireUser","getUser","login","prompt","type","name","message","exit","flags","args","parse","ctor","baseFlags","strict","enable","bin","addBreadcrumb","category","data","command","id","notify","notification","title","contentImage","join","root","icon","sound","timeout","error","warn","server","port","receiveSession","Promise","resolve","reject","createServer","req","res","redirectTo","URL","domains","services","url","Error","incomingUrl","value","searchParams","get","session","user","log","email","set","undefined","writeHead","Location","toString","end","listen","close","catch","cause","console","render","capture","constructor","argv","priority","Infinity","boolean","char","summary","helpGroup","default"],"mappings":"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"}
@@ -1,143 +0,0 @@
1
- import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
- import { addBreadcrumb, setUser } from "@sentry/node";
3
- import assert from "assert";
4
- import Debug from "debug";
5
- import fs from "fs-extra";
6
- import { HTTPError, got } from "got";
7
- import _ from "lodash";
8
- import path from "path";
9
- import { ignoreEnoent } from "./fs-utils.js";
10
- const debug = Debug("ggt:context");
11
- export class Context {
12
- get session() {
13
- if (this._session) return this._session;
14
- try {
15
- this._session = fs.readFileSync(path.join(this.config.configDir, "session.txt"), "utf-8");
16
- return this._session;
17
- } catch (error) {
18
- ignoreEnoent(error);
19
- return undefined;
20
- }
21
- }
22
- set session(value) {
23
- this.clear();
24
- this._session = value;
25
- if (this._session) {
26
- fs.outputFileSync(path.join(this.config.configDir, "session.txt"), this._session);
27
- } else {
28
- fs.removeSync(path.join(this.config.configDir, "session.txt"));
29
- }
30
- }
31
- /**
32
- * @returns The current user, or undefined if the user is not logged in.
33
- */ async getUser() {
34
- if (!this.session) return undefined;
35
- if (this._user) return this._user;
36
- try {
37
- this._user = await this._request(`https://${this.domains.services}/auth/api/current-user`).json();
38
- setUser(this._user);
39
- return this._user;
40
- } catch (error) {
41
- if (error instanceof HTTPError && error.response.statusCode === 401) {
42
- this.session = undefined;
43
- return undefined;
44
- }
45
- throw error;
46
- }
47
- }
48
- /**
49
- * @returns The list of Gadget applications the current user has access to.
50
- */ async getAvailableApps() {
51
- if (!this.session) return [];
52
- if (this._availableApps.length > 0) return this._availableApps;
53
- this._availableApps = await this._request(`https://${this.domains.services}/auth/api/apps`).json();
54
- return this._availableApps;
55
- }
56
- async setApp(appOrSlug) {
57
- if (_.isString(appOrSlug)) {
58
- const app = await this.getAvailableApps().then((apps)=>_.find(apps, (app)=>app.slug == appOrSlug));
59
- assert(app, `attempted to set app to "${appOrSlug}" but no app with that name or slug was found`);
60
- this.app = app;
61
- } else {
62
- this.app = appOrSlug;
63
- }
64
- }
65
- clear() {
66
- this._session = undefined;
67
- this._user = undefined;
68
- this.app = undefined;
69
- this._availableApps = [];
70
- setUser(null);
71
- }
72
- addBreadcrumb(breadcrumb) {
73
- debug("breadcrumb %O", breadcrumb);
74
- // clone any objects in the data so that we get a snapshot of the object at the time the breadcrumb was added
75
- if (breadcrumb.data) {
76
- for (const [key, value] of Object.entries(breadcrumb.data)){
77
- if (_.isObjectLike(value)) {
78
- breadcrumb.data[key] = _.cloneDeep(value);
79
- }
80
- }
81
- }
82
- addBreadcrumb(breadcrumb);
83
- }
84
- constructor(){
85
- /**
86
- * A reference to oclif's {@linkcode Config}.
87
- *
88
- * By default, oclif's {@linkcode Config} is only available as an instance property on a Command, but we want to be
89
- * able to access it from anywhere. To do this, we created this global variable that references the Config. It is set
90
- * by the init function in the BaseCommand.
91
- */ _define_property(this, "config", void 0);
92
- /**
93
- * Captures the name and nature of the environment
94
- */ _define_property(this, "env", {
95
- get value () {
96
- return process.env["GGT_ENV"] ?? "production";
97
- },
98
- get productionLike () {
99
- return _.startsWith(this.value, "production");
100
- },
101
- get developmentLike () {
102
- return _.startsWith(this.value, "development");
103
- },
104
- get testLike () {
105
- return _.startsWith(this.value, "test");
106
- },
107
- get developmentOrTestLike () {
108
- return this.developmentLike || this.testLike;
109
- }
110
- });
111
- /**
112
- * Domains for various Gadget services.
113
- */ _define_property(this, "domains", {
114
- /**
115
- * The domain for the Gadget applications. This is where the user applications are hosted.
116
- */ app: process.env["GGT_GADGET_APP_DOMAIN"] ?? (this.env.productionLike ? "gadget.app" : "ggt.pub"),
117
- /**
118
- * The domain for the Gadget services. This is where the Gadget's API is hosted.
119
- */ services: process.env["GGT_GADGET_SERVICES_DOMAIN"] ?? (this.env.productionLike ? "app.gadget.dev" : "app.ggt.dev")
120
- });
121
- /**
122
- * The current Gadget application the CLI is operating on.
123
- */ _define_property(this, "app", void 0);
124
- _define_property(this, "_session", void 0);
125
- _define_property(this, "_user", void 0);
126
- _define_property(this, "_availableApps", []);
127
- _define_property(this, "_request", got.extend({
128
- hooks: {
129
- beforeRequest: [
130
- (options)=>{
131
- options.headers["user-agent"] = this.config.userAgent;
132
- if (options.url instanceof URL && options.url.host === this.domains.services && this.session) {
133
- options.headers["cookie"] = `session=${encodeURIComponent(this.session)};`;
134
- }
135
- }
136
- ]
137
- }
138
- }));
139
- }
140
- }
141
- export const context = new Context();
142
-
143
- //# sourceMappingURL=context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/context.ts"],"sourcesContent":["import type { Config } from \"@oclif/core\";\nimport { addBreadcrumb, setUser, type Breadcrumb as SentryBreadcrumb } from \"@sentry/node\";\nimport assert from \"assert\";\nimport Debug from \"debug\";\nimport fs from \"fs-extra\";\nimport { HTTPError, got } from \"got\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { ignoreEnoent } from \"./fs-utils.js\";\n\nconst debug = Debug(\"ggt:context\");\n\nexport class Context {\n /**\n * A reference to oclif's {@linkcode Config}.\n *\n * By default, oclif's {@linkcode Config} is only available as an instance property on a Command, but we want to be\n * able to access it from anywhere. To do this, we created this global variable that references the Config. It is set\n * by the init function in the BaseCommand.\n */\n config!: Config;\n\n /**\n * Captures the name and nature of the environment\n */\n env = {\n get value(): string {\n return process.env[\"GGT_ENV\"] ?? \"production\";\n },\n get productionLike(): boolean {\n return _.startsWith(this.value, \"production\");\n },\n get developmentLike(): boolean {\n return _.startsWith(this.value, \"development\");\n },\n get testLike(): boolean {\n return _.startsWith(this.value, \"test\");\n },\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n },\n };\n\n /**\n * Domains for various Gadget services.\n */\n domains = {\n /**\n * The domain for the Gadget applications. This is where the user applications are hosted.\n */\n app: process.env[\"GGT_GADGET_APP_DOMAIN\"] ?? (this.env.productionLike ? \"gadget.app\" : \"ggt.pub\"),\n\n /**\n * The domain for the Gadget services. This is where the Gadget's API is hosted.\n */\n services: process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] ?? (this.env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\"),\n };\n\n /**\n * The current Gadget application the CLI is operating on.\n */\n app?: App;\n\n private _session?: string;\n\n private _user?: User;\n\n private _availableApps: App[] = [];\n\n private _request = got.extend({\n hooks: {\n beforeRequest: [\n (options) => {\n options.headers[\"user-agent\"] = this.config.userAgent;\n if (options.url instanceof URL && options.url.host === this.domains.services && this.session) {\n options.headers[\"cookie\"] = `session=${encodeURIComponent(this.session)};`;\n }\n },\n ],\n },\n });\n\n get session(): string | undefined {\n if (this._session) return this._session;\n\n try {\n this._session = fs.readFileSync(path.join(this.config.configDir, \"session.txt\"), \"utf-8\");\n return this._session;\n } catch (error) {\n ignoreEnoent(error);\n return undefined;\n }\n }\n\n set session(value: string | undefined) {\n this.clear();\n this._session = value;\n if (this._session) {\n fs.outputFileSync(path.join(this.config.configDir, \"session.txt\"), this._session);\n } else {\n fs.removeSync(path.join(this.config.configDir, \"session.txt\"));\n }\n }\n\n /**\n * @returns The current user, or undefined if the user is not logged in.\n */\n async getUser(): Promise<User | undefined> {\n if (!this.session) return undefined;\n if (this._user) return this._user;\n\n try {\n this._user = await this._request(`https://${this.domains.services}/auth/api/current-user`).json<User>();\n setUser(this._user);\n return this._user;\n } catch (error) {\n if (error instanceof HTTPError && error.response.statusCode === 401) {\n this.session = undefined;\n return undefined;\n }\n throw error;\n }\n }\n\n /**\n * @returns The list of Gadget applications the current user has access to.\n */\n async getAvailableApps(): Promise<App[]> {\n if (!this.session) return [];\n if (this._availableApps.length > 0) return this._availableApps;\n\n this._availableApps = await this._request(`https://${this.domains.services}/auth/api/apps`).json<App[]>();\n return this._availableApps;\n }\n\n async setApp(appOrSlug?: App | string): Promise<void> {\n if (_.isString(appOrSlug)) {\n const app = await this.getAvailableApps().then((apps) => _.find(apps, (app) => app.slug == appOrSlug));\n assert(app, `attempted to set app to \"${appOrSlug}\" but no app with that name or slug was found`);\n this.app = app;\n } else {\n this.app = appOrSlug;\n }\n }\n\n clear(): void {\n this._session = undefined;\n this._user = undefined;\n this.app = undefined;\n this._availableApps = [];\n setUser(null);\n }\n\n addBreadcrumb(breadcrumb: Breadcrumb) {\n debug(\"breadcrumb %O\", breadcrumb);\n\n // clone any objects in the data so that we get a snapshot of the object at the time the breadcrumb was added\n if (breadcrumb.data) {\n for (const [key, value] of Object.entries(breadcrumb.data)) {\n if (_.isObjectLike(value)) {\n breadcrumb.data[key] = _.cloneDeep(value);\n }\n }\n }\n\n addBreadcrumb(breadcrumb);\n }\n}\n\nexport const context = new Context();\n\nexport interface Breadcrumb extends SentryBreadcrumb {\n category: \"command\" | \"client\" | \"sync\";\n message: Capitalize<string>;\n}\n\nexport interface User {\n id: string | number;\n email: string;\n name?: string;\n}\n\nexport interface App {\n id: string | number;\n slug: string;\n primaryDomain: string;\n hasSplitEnvironments: boolean;\n}\n"],"names":["addBreadcrumb","setUser","assert","Debug","fs","HTTPError","got","_","path","ignoreEnoent","debug","Context","session","_session","readFileSync","join","config","configDir","error","undefined","value","clear","outputFileSync","removeSync","getUser","_user","_request","domains","services","json","response","statusCode","getAvailableApps","_availableApps","length","setApp","appOrSlug","isString","app","then","apps","find","slug","breadcrumb","data","key","Object","entries","isObjectLike","cloneDeep","env","process","productionLike","startsWith","developmentLike","testLike","developmentOrTestLike","extend","hooks","beforeRequest","options","headers","userAgent","url","URL","host","encodeURIComponent","context"],"mappings":"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"}