@gadgetinc/ggt 0.2.4 → 0.3.1

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 (72) 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 +319 -685
  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/config.js +139 -0
  27. package/lib/services/config.js.map +1 -0
  28. package/lib/services/edit-graphql.js +193 -0
  29. package/lib/services/edit-graphql.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 +15680 -25737
  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/client.js +0 -209
  65. package/lib/services/client.js.map +0 -1
  66. package/lib/services/context.js +0 -143
  67. package/lib/services/context.js.map +0 -1
  68. package/lib/services/flags.js +0 -57
  69. package/lib/services/flags.js.map +0 -1
  70. package/lib/services/help.js +0 -36
  71. package/lib/services/help.js.map +0 -1
  72. package/oclif.manifest.json +0 -244
@@ -1,209 +0,0 @@
1
- import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
- import assert from "assert";
3
- import { createClient } from "graphql-ws";
4
- import _ from "lodash";
5
- import WebSocket from "ws";
6
- import { context } from "./context.js";
7
- import { ClientError } from "./errors.js";
8
- var ConnectionStatus;
9
- (function(ConnectionStatus) {
10
- ConnectionStatus[ConnectionStatus["CONNECTED"] = 0] = "CONNECTED";
11
- ConnectionStatus[ConnectionStatus["DISCONNECTED"] = 1] = "DISCONNECTED";
12
- ConnectionStatus[ConnectionStatus["RECONNECTING"] = 2] = "RECONNECTING";
13
- })(ConnectionStatus || (ConnectionStatus = {}));
14
- /**
15
- * Client is a GraphQL client connected to a Gadget application's /edit/api/graphql-ws endpoint.
16
- *
17
- * NOTE: In order to use the Client, the user must be logged in and an app must have been selected (`context.app` and
18
- * `context.session` must be set).
19
- */ export class Client {
20
- subscribe(payload, sink) {
21
- let subscribePayload;
22
- let removeConnectedListener = _.noop.bind(_);
23
- if (_.isFunction(payload.variables)) {
24
- // the caller wants us to re-evaluate the variables every time graphql-ws re-subscribes after reconnecting
25
- subscribePayload = {
26
- ...payload,
27
- variables: payload.variables()
28
- };
29
- removeConnectedListener = this._client.on("connected", ()=>{
30
- if (this.status == ConnectionStatus.RECONNECTING) {
31
- // subscribePayload.variables is supposed to be readonly (it's not) and payload.variables may have been re-assigned (it won't)
32
- subscribePayload.variables = payload.variables();
33
- context.addBreadcrumb({
34
- category: "client",
35
- message: "Re-sending GraphQL query",
36
- data: {
37
- type: _.split(subscribePayload.query, " ", 1)[0],
38
- query: subscribePayload.query
39
- }
40
- });
41
- }
42
- });
43
- } else {
44
- subscribePayload = payload;
45
- }
46
- context.addBreadcrumb({
47
- category: "client",
48
- message: "Sending GraphQL query",
49
- data: {
50
- type: _.split(subscribePayload.query, " ", 1)[0],
51
- query: subscribePayload.query
52
- }
53
- });
54
- const unsubscribe = this._client.subscribe(subscribePayload, {
55
- next: (result)=>{
56
- sink.next(result);
57
- },
58
- error: (error)=>{
59
- sink.error(new ClientError(subscribePayload, error));
60
- },
61
- complete: ()=>{
62
- sink.complete?.();
63
- }
64
- });
65
- return ()=>{
66
- removeConnectedListener();
67
- unsubscribe();
68
- };
69
- }
70
- subscribeUnwrap(payload, sink) {
71
- const unsubscribe = this.subscribe(payload, {
72
- ...sink,
73
- next: (result)=>{
74
- if (result.errors) {
75
- unsubscribe();
76
- sink.error(new ClientError(payload, result.errors));
77
- return;
78
- }
79
- if (!result.data) {
80
- sink.error(new ClientError(payload, "We received a response without data"));
81
- unsubscribe();
82
- return;
83
- }
84
- sink.next(result.data);
85
- }
86
- });
87
- return unsubscribe;
88
- }
89
- query(payload) {
90
- return new Promise((resolve, reject)=>{
91
- this.subscribe(payload, {
92
- next: resolve,
93
- error: reject
94
- });
95
- });
96
- }
97
- async queryUnwrap(payload) {
98
- const result = await this.query(payload);
99
- if (result.errors) throw new ClientError(payload, result.errors);
100
- if (!result.data) throw new ClientError(payload, "We received a response without data");
101
- return result.data;
102
- }
103
- async dispose() {
104
- await this._client.dispose();
105
- }
106
- constructor(){
107
- // assume the client is going to connect
108
- _define_property(this, "status", ConnectionStatus.CONNECTED);
109
- _define_property(this, "_client", void 0);
110
- assert(context.app, "context.app must be set before instantiating the Client");
111
- this._client = createClient({
112
- url: `wss://${context.app.slug}.${context.domains.app}/edit/api/graphql-ws`,
113
- shouldRetry: _.constant(true),
114
- webSocketImpl: class extends WebSocket {
115
- constructor(address, protocols, wsOptions){
116
- assert(context.session, "context.session must be set before instantiating the Client");
117
- super(address, protocols, {
118
- ...wsOptions,
119
- headers: {
120
- ...wsOptions?.headers,
121
- "user-agent": context.config.userAgent,
122
- cookie: `session=${encodeURIComponent(context.session)};`
123
- }
124
- });
125
- }
126
- },
127
- on: {
128
- connecting: ()=>{
129
- switch(this.status){
130
- case ConnectionStatus.DISCONNECTED:
131
- this.status = ConnectionStatus.RECONNECTING;
132
- context.addBreadcrumb({
133
- category: "client",
134
- message: "Reconnecting"
135
- });
136
- break;
137
- case ConnectionStatus.RECONNECTING:
138
- context.addBreadcrumb({
139
- category: "client",
140
- message: "Retrying"
141
- });
142
- break;
143
- default:
144
- context.addBreadcrumb({
145
- category: "client",
146
- message: "Connecting"
147
- });
148
- break;
149
- }
150
- },
151
- connected: ()=>{
152
- if (this.status === ConnectionStatus.RECONNECTING) {
153
- context.addBreadcrumb({
154
- category: "client",
155
- message: "Reconnected"
156
- });
157
- } else {
158
- context.addBreadcrumb({
159
- category: "client",
160
- message: "Connected"
161
- });
162
- }
163
- // let the other on connected listeners see what status we're in
164
- setImmediate(()=>this.status = ConnectionStatus.CONNECTED);
165
- },
166
- closed: (e)=>{
167
- const event = e;
168
- if (event.wasClean) {
169
- context.addBreadcrumb({
170
- category: "client",
171
- message: "Connection Closed"
172
- });
173
- return;
174
- }
175
- if (this.status === ConnectionStatus.CONNECTED) {
176
- this.status = ConnectionStatus.DISCONNECTED;
177
- context.addBreadcrumb({
178
- category: "client",
179
- message: "Disconnected"
180
- });
181
- }
182
- },
183
- error: (error)=>{
184
- if (this.status == ConnectionStatus.RECONNECTING) {
185
- context.addBreadcrumb({
186
- category: "client",
187
- message: "Failed to reconnect",
188
- level: "error",
189
- data: {
190
- error
191
- }
192
- });
193
- } else {
194
- context.addBreadcrumb({
195
- category: "client",
196
- message: "Connection error",
197
- level: "error",
198
- data: {
199
- error
200
- }
201
- });
202
- }
203
- }
204
- }
205
- });
206
- }
207
- }
208
-
209
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/client.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { GraphQLError } from \"graphql\";\nimport type { ExecutionResult, SubscribePayload } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport type { ClientRequestArgs } from \"http\";\nimport _ from \"lodash\";\nimport type { JsonObject, SetOptional } from \"type-fest\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport WebSocket from \"ws\";\nimport { context } from \"./context.js\";\nimport { ClientError } from \"./errors.js\";\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\n\n/**\n * Client is a GraphQL client connected to a Gadget application's /edit/api/graphql-ws endpoint.\n *\n * NOTE: In order to use the Client, the user must be logged in and an app must have been selected (`context.app` and\n * `context.session` must be set).\n */\nexport class Client {\n // assume the client is going to connect\n status = ConnectionStatus.CONNECTED;\n\n private _client: ReturnType<typeof createClient>;\n\n constructor() {\n assert(context.app, \"context.app must be set before instantiating the Client\");\n\n this._client = createClient({\n url: `wss://${context.app.slug}.${context.domains.app}/edit/api/graphql-ws`,\n shouldRetry: _.constant(true),\n webSocketImpl: class extends WebSocket {\n constructor(address: string | URL, protocols?: string | string[], wsOptions?: WebSocket.ClientOptions | ClientRequestArgs) {\n assert(context.session, \"context.session must be set before instantiating the Client\");\n super(address, protocols, {\n ...wsOptions,\n headers: {\n ...wsOptions?.headers,\n \"user-agent\": context.config.userAgent,\n cookie: `session=${encodeURIComponent(context.session)};`,\n },\n });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n context.addBreadcrumb({ category: \"client\", message: \"Reconnecting\" });\n break;\n case ConnectionStatus.RECONNECTING:\n context.addBreadcrumb({ category: \"client\", message: \"Retrying\" });\n break;\n default:\n context.addBreadcrumb({ category: \"client\", message: \"Connecting\" });\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n context.addBreadcrumb({ category: \"client\", message: \"Reconnected\" });\n } else {\n context.addBreadcrumb({ category: \"client\", message: \"Connected\" });\n }\n\n // let the other on connected listeners see what status we're in\n setImmediate(() => (this.status = ConnectionStatus.CONNECTED));\n },\n closed: (e) => {\n const event = e as CloseEvent;\n if (event.wasClean) {\n context.addBreadcrumb({ category: \"client\", message: \"Connection Closed\" });\n return;\n }\n\n if (this.status === ConnectionStatus.CONNECTED) {\n this.status = ConnectionStatus.DISCONNECTED;\n context.addBreadcrumb({ category: \"client\", message: \"Disconnected\" });\n }\n },\n error: (error) => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n context.addBreadcrumb({ category: \"client\", message: \"Failed to reconnect\", level: \"error\", data: { error } });\n } else {\n context.addBreadcrumb({ category: \"client\", message: \"Connection error\", level: \"error\", data: { error } });\n }\n },\n },\n });\n }\n\n subscribe<Data extends JsonObject, Variables extends JsonObject, Extensions extends JsonObject = JsonObject>(\n payload: Payload<Data, Variables>,\n sink: SetOptional<Sink<Data, Extensions>, \"complete\">,\n ): () => void {\n let subscribePayload: SubscribePayload;\n let removeConnectedListener = _.noop.bind(_);\n\n if (_.isFunction(payload.variables)) {\n // the caller wants us to re-evaluate the variables every time graphql-ws re-subscribes after reconnecting\n subscribePayload = { ...payload, variables: payload.variables() };\n removeConnectedListener = this._client.on(\"connected\", () => {\n if (this.status == ConnectionStatus.RECONNECTING) {\n // subscribePayload.variables is supposed to be readonly (it's not) and payload.variables may have been re-assigned (it won't)\n (subscribePayload as any).variables = (payload.variables as any)();\n context.addBreadcrumb({\n category: \"client\",\n message: \"Re-sending GraphQL query\",\n data: {\n type: _.split(subscribePayload.query, \" \", 1)[0],\n query: subscribePayload.query,\n },\n });\n }\n });\n } else {\n subscribePayload = payload as SubscribePayload;\n }\n\n context.addBreadcrumb({\n category: \"client\",\n message: \"Sending GraphQL query\",\n data: {\n type: _.split(subscribePayload.query, \" \", 1)[0],\n query: subscribePayload.query,\n },\n });\n\n const unsubscribe = this._client.subscribe(subscribePayload, {\n next: (result: ExecutionResult<Data, Extensions>) => {\n sink.next(result);\n },\n error: (error) => {\n sink.error(new ClientError(subscribePayload, error as Error | GraphQLError[] | CloseEvent | ErrorEvent));\n },\n complete: () => {\n sink.complete?.();\n },\n });\n\n return () => {\n removeConnectedListener();\n unsubscribe();\n };\n }\n\n subscribeUnwrap<Data extends JsonObject, Variables extends JsonObject>(\n payload: Payload<Data, Variables>,\n sink: { next: (data: Data) => void; error: (error: ClientError) => void },\n ): () => void {\n const unsubscribe = this.subscribe(payload, {\n ...sink,\n next: (result) => {\n if (result.errors) {\n unsubscribe();\n sink.error(new ClientError(payload, result.errors));\n return;\n }\n\n if (!result.data) {\n sink.error(new ClientError(payload, \"We received a response without data\"));\n unsubscribe();\n return;\n }\n\n sink.next(result.data);\n },\n });\n\n return unsubscribe;\n }\n\n query<Data extends JsonObject, Variables extends JsonObject, Extensions extends JsonObject = JsonObject>(\n payload: Payload<Data, Variables>,\n ): Promise<ExecutionResult<Data, Extensions>> {\n return new Promise((resolve, reject) => {\n this.subscribe<Data, Variables, Extensions>(payload, { next: resolve, error: reject });\n });\n }\n\n async queryUnwrap<Data extends JsonObject, Variables extends JsonObject>(payload: Payload<Data, Variables>): Promise<Data> {\n const result = await this.query(payload);\n if (result.errors) throw new ClientError(payload, result.errors);\n if (!result.data) throw new ClientError(payload, \"We received a response without data\");\n return result.data;\n }\n\n async dispose(): Promise<void> {\n await this._client.dispose();\n }\n}\n\nexport type Query<\n Data extends JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n> = string & {\n __TData?: Data;\n __TVariables?: Variables;\n __TExtensions?: Extensions;\n};\n\nexport interface Payload<Data extends JsonObject, Variables extends JsonObject> {\n readonly query: Query<Data, Variables>;\n readonly variables?: Variables | (() => Variables) | null;\n}\n\nexport interface Sink<Data extends JsonObject, Extensions extends JsonObject> {\n next(value: ExecutionResult<Data, Extensions>): void;\n error(error: ClientError): void;\n complete(): void;\n}\n"],"names":["assert","createClient","_","WebSocket","context","ClientError","ConnectionStatus","CONNECTED","DISCONNECTED","RECONNECTING","Client","subscribe","payload","sink","subscribePayload","removeConnectedListener","noop","bind","isFunction","variables","_client","on","status","addBreadcrumb","category","message","data","type","split","query","unsubscribe","next","result","error","complete","subscribeUnwrap","errors","Promise","resolve","reject","queryUnwrap","dispose","constructor","app","url","slug","domains","shouldRetry","constant","webSocketImpl","address","protocols","wsOptions","session","headers","config","userAgent","cookie","encodeURIComponent","connecting","connected","setImmediate","closed","e","event","wasClean","level"],"mappings":"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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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"}
@@ -1,57 +0,0 @@
1
- import { Flags } from "@oclif/core";
2
- import levenshtein from "fast-levenshtein";
3
- import _ from "lodash";
4
- import { dedent } from "ts-dedent";
5
- import { context } from "./context.js";
6
- import { FlagError } from "./errors.js";
7
- export const app = Flags.custom({
8
- char: "a",
9
- name: "app",
10
- summary: "The Gadget application this command applies to.",
11
- helpValue: "<name>",
12
- parse: async (value)=>{
13
- const parsed = RegExp("^(https:\\/\\/)?(?<name>[\\w-]+)").exec(value)?.groups?.["name"];
14
- if (!parsed) throw new FlagError({
15
- char: "a",
16
- name: "app"
17
- }, dedent`
18
- The -a, --app flag must be the application's slug or URL
19
-
20
- Examples:
21
-
22
- --app my-app
23
- --app my-app.gadget.app
24
- --app https://my-app.gadget.app
25
- --app https://my-app.gadget.app/edit
26
- `);
27
- const slug = _.endsWith(parsed, "--development") ? parsed.slice(0, -"--development".length) : parsed;
28
- const availableApps = await context.getAvailableApps();
29
- const foundApp = _.find(availableApps, (a)=>a.slug == slug);
30
- if (foundApp) {
31
- return foundApp.slug;
32
- }
33
- const sortedApps = _.sortBy(availableApps, (app)=>levenshtein.get(app.slug, slug));
34
- throw new FlagError({
35
- char: "a",
36
- name: "app"
37
- }, availableApps.length > 0 ? dedent`
38
- Unknown application:
39
-
40
- ${value}
41
-
42
- Did you mean one of these?
43
-
44
- ${_.map(sortedApps.slice(0, 10), (app)=>`* ${app.slug}`).join("\n")}
45
- ` : dedent`
46
- Unknown application:
47
-
48
- ${value}
49
-
50
- It doesn't look like you have any applications.
51
-
52
- Visit https://gadget.new to create one!
53
- `);
54
- }
55
- });
56
-
57
- //# sourceMappingURL=flags.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/flags.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport levenshtein from \"fast-levenshtein\";\nimport _ from \"lodash\";\nimport { dedent } from \"ts-dedent\";\nimport { context } from \"./context.js\";\nimport { FlagError } from \"./errors.js\";\n\nexport const app = Flags.custom({\n char: \"a\",\n name: \"app\",\n summary: \"The Gadget application this command applies to.\",\n helpValue: \"<name>\",\n parse: async (value: string) => {\n const parsed = /^(https:\\/\\/)?(?<name>[\\w-]+)/.exec(value)?.groups?.[\"name\"];\n if (!parsed)\n throw new FlagError(\n { char: \"a\", name: \"app\" },\n dedent`\n The -a, --app flag must be the application's slug or URL\n\n Examples:\n\n --app my-app\n --app my-app.gadget.app\n --app https://my-app.gadget.app\n --app https://my-app.gadget.app/edit\n `,\n );\n\n const slug = _.endsWith(parsed, \"--development\") ? parsed.slice(0, -\"--development\".length) : parsed;\n\n const availableApps = await context.getAvailableApps();\n const foundApp = _.find(availableApps, (a) => a.slug == slug);\n if (foundApp) {\n return foundApp.slug;\n }\n\n const sortedApps = _.sortBy(availableApps, (app) => levenshtein.get(app.slug, slug));\n throw new FlagError(\n { char: \"a\", name: \"app\" },\n availableApps.length > 0\n ? dedent`\n Unknown application:\n\n ${value}\n\n Did you mean one of these?\n\n ${_.map(sortedApps.slice(0, 10), (app) => `* ${app.slug}`).join(\"\\n\")}\n `\n : dedent`\n Unknown application:\n\n ${value}\n\n It doesn't look like you have any applications.\n\n Visit https://gadget.new to create one!\n `,\n );\n },\n});\n"],"names":["Flags","levenshtein","_","dedent","context","FlagError","app","custom","char","name","summary","helpValue","parse","value","parsed","exec","groups","slug","endsWith","slice","length","availableApps","getAvailableApps","foundApp","find","a","sortedApps","sortBy","get","map","join"],"mappings":"AAAA,SAASA,KAAK,QAAQ,cAAc;AACpC,OAAOC,iBAAiB,mBAAmB;AAC3C,OAAOC,OAAO,SAAS;AACvB,SAASC,MAAM,QAAQ,YAAY;AACnC,SAASC,OAAO,QAAQ,eAAe;AACvC,SAASC,SAAS,QAAQ,cAAc;AAExC,OAAO,MAAMC,MAAMN,MAAMO,MAAM,CAAC;IAC9BC,MAAM;IACNC,MAAM;IACNC,SAAS;IACTC,WAAW;IACXC,OAAO,OAAOC;QACZ,MAAMC,SAAS,2CAAgCC,IAAI,CAACF,QAAQG,QAAQ,CAAC,OAAO;QAC5E,IAAI,CAACF,QACH,MAAM,IAAIT,UACR;YAAEG,MAAM;YAAKC,MAAM;QAAM,GACzBN,MAAM,CAAC;;;;;;;;;QASP,CAAC;QAGL,MAAMc,OAAOf,EAAEgB,QAAQ,CAACJ,QAAQ,mBAAmBA,OAAOK,KAAK,CAAC,GAAG,CAAC,gBAAgBC,MAAM,IAAIN;QAE9F,MAAMO,gBAAgB,MAAMjB,QAAQkB,gBAAgB;QACpD,MAAMC,WAAWrB,EAAEsB,IAAI,CAACH,eAAe,CAACI,IAAMA,EAAER,IAAI,IAAIA;QACxD,IAAIM,UAAU;YACZ,OAAOA,SAASN,IAAI;QACtB;QAEA,MAAMS,aAAaxB,EAAEyB,MAAM,CAACN,eAAe,CAACf,MAAQL,YAAY2B,GAAG,CAACtB,IAAIW,IAAI,EAAEA;QAC9E,MAAM,IAAIZ,UACR;YAAEG,MAAM;YAAKC,MAAM;QAAM,GACzBY,cAAcD,MAAM,GAAG,IACnBjB,MAAM,CAAC;;;gBAGD,EAAEU,MAAM;;;;gBAIR,EAAEX,EAAE2B,GAAG,CAACH,WAAWP,KAAK,CAAC,GAAG,KAAK,CAACb,MAAQ,CAAC,EAAE,EAAEA,IAAIW,IAAI,CAAC,CAAC,EAAEa,IAAI,CAAC,MAAM;YAC1E,CAAC,GACH3B,MAAM,CAAC;;;gBAGD,EAAEU,MAAM;;;;;YAKZ,CAAC;IAEX;AACF,GAAG"}
@@ -1,36 +0,0 @@
1
- import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
- import { CommandHelp as OclifCommandHelp, Help as OclifHelp } from "@oclif/core";
3
- import _ from "lodash";
4
- class Help extends OclifHelp {
5
- constructor(...args){
6
- super(...args);
7
- _define_property(this, "CommandHelpClass", CommandHelp);
8
- }
9
- }
10
- export { Help as default };
11
- class CommandHelp extends OclifCommandHelp {
12
- /**
13
- * By default, oclif tries to format the description so that it fit's within the terminal window. However, if the description is already
14
- * formatted with `dedent`, then the description gets mangled and the help output is not pretty.
15
- *
16
- * This overrides the default behavior to just use the description as-is if it already exists.
17
- */ description() {
18
- if (this.command.description) {
19
- return this.command.description;
20
- }
21
- return super.description();
22
- }
23
- /**
24
- * Same as above, but for examples.
25
- */ examples(examples) {
26
- if (_.isString(examples)) {
27
- return examples;
28
- }
29
- if (_.isArray(examples) && _.every(examples, _.isString)) {
30
- return examples.join("\n\n");
31
- }
32
- return super.examples(examples);
33
- }
34
- }
35
-
36
- //# sourceMappingURL=help.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/services/help.ts"],"sourcesContent":["import type { Command } from \"@oclif/core\";\nimport { CommandHelp as OclifCommandHelp, Help as OclifHelp } from \"@oclif/core\";\nimport _ from \"lodash\";\n\nexport default class Help extends OclifHelp {\n override CommandHelpClass = CommandHelp;\n}\n\nclass CommandHelp extends OclifCommandHelp {\n /**\n * By default, oclif tries to format the description so that it fit's within the terminal window. However, if the description is already\n * formatted with `dedent`, then the description gets mangled and the help output is not pretty.\n *\n * This overrides the default behavior to just use the description as-is if it already exists.\n */\n protected override description(): string | undefined {\n if (this.command.description) {\n return this.command.description;\n }\n return super.description();\n }\n\n /**\n * Same as above, but for examples.\n */\n protected override examples(examples: string | string[] | Command.Example[] | undefined): string | undefined {\n if (_.isString(examples)) {\n return examples;\n }\n if (_.isArray(examples) && _.every(examples, _.isString)) {\n return examples.join(\"\\n\\n\");\n }\n return super.examples(examples);\n }\n}\n"],"names":["CommandHelp","OclifCommandHelp","Help","OclifHelp","_","CommandHelpClass","description","command","examples","isString","isArray","every","join"],"mappings":";AACA,SAASA,eAAeC,gBAAgB,EAAEC,QAAQC,SAAS,QAAQ,cAAc;AACjF,OAAOC,OAAO,SAAS;AAER,MAAMF,aAAaC;;;QAChC,uBAASE,oBAAmBL;;AAC9B;AAFA,SAAqBE,kBAEpB;AAED,MAAMF,oBAAoBC;IACxB;;;;;GAKC,GACD,AAAmBK,cAAkC;QACnD,IAAI,IAAI,CAACC,OAAO,CAACD,WAAW,EAAE;YAC5B,OAAO,IAAI,CAACC,OAAO,CAACD,WAAW;QACjC;QACA,OAAO,KAAK,CAACA;IACf;IAEA;;GAEC,GACD,AAAmBE,SAASA,QAA2D,EAAsB;QAC3G,IAAIJ,EAAEK,QAAQ,CAACD,WAAW;YACxB,OAAOA;QACT;QACA,IAAIJ,EAAEM,OAAO,CAACF,aAAaJ,EAAEO,KAAK,CAACH,UAAUJ,EAAEK,QAAQ,GAAG;YACxD,OAAOD,SAASI,IAAI,CAAC;QACvB;QACA,OAAO,KAAK,CAACJ,SAASA;IACxB;AACF"}