@gadgetinc/ggt 0.1.18 → 0.2.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.
- package/README.md +6 -6
- package/bin/dev.js +24 -0
- package/bin/run.js +11 -0
- package/lib/__generated__/graphql.js +6 -9
- package/lib/__generated__/graphql.js.map +1 -1
- package/lib/commands/help.js +21 -36
- package/lib/commands/help.js.map +1 -1
- package/lib/commands/list.js +29 -55
- package/lib/commands/list.js.map +1 -1
- package/lib/commands/login.js +13 -29
- package/lib/commands/login.js.map +1 -1
- package/lib/commands/logout.js +17 -34
- package/lib/commands/logout.js.map +1 -1
- package/lib/commands/sync.js +501 -463
- package/lib/commands/sync.js.map +1 -1
- package/lib/commands/whoami.js +17 -34
- package/lib/commands/whoami.js.map +1 -1
- package/lib/index.js +2 -5
- package/lib/index.js.map +1 -1
- package/lib/utils/base-command.js +105 -146
- package/lib/utils/base-command.js.map +1 -1
- package/lib/utils/client.js +104 -113
- package/lib/utils/client.js.map +1 -1
- package/lib/utils/context.js +63 -119
- package/lib/utils/context.js.map +1 -1
- package/lib/utils/errors.js +161 -242
- package/lib/utils/errors.js.map +1 -1
- package/lib/utils/flags.js +23 -26
- package/lib/utils/flags.js.map +1 -1
- package/lib/utils/fs-utils.js +50 -73
- package/lib/utils/fs-utils.js.map +1 -1
- package/lib/utils/help.js +19 -26
- package/lib/utils/help.js.map +1 -1
- package/lib/utils/promise.js +32 -78
- package/lib/utils/promise.js.map +1 -1
- package/lib/utils/sleep.js +6 -11
- package/lib/utils/sleep.js.map +1 -1
- package/npm-shrinkwrap.json +7848 -7077
- package/oclif.manifest.json +1 -21
- package/package.json +49 -49
- package/bin/dev +0 -20
- package/bin/run +0 -7
- package/lib/__generated__/graphql.d.ts +0 -294
- package/lib/commands/help.d.ts +0 -14
- package/lib/commands/list.d.ts +0 -18
- package/lib/commands/login.d.ts +0 -7
- package/lib/commands/logout.d.ts +0 -7
- package/lib/commands/sync.d.ts +0 -146
- package/lib/commands/whoami.d.ts +0 -7
- package/lib/index.d.ts +0 -1
- package/lib/utils/base-command.d.ts +0 -64
- package/lib/utils/client.d.ts +0 -42
- package/lib/utils/context.d.ts +0 -57
- package/lib/utils/errors.d.ts +0 -100
- package/lib/utils/flags.d.ts +0 -1
- package/lib/utils/fs-utils.d.ts +0 -21
- package/lib/utils/help.d.ts +0 -19
- package/lib/utils/promise.d.ts +0 -35
- package/lib/utils/sleep.d.ts +0 -5
package/lib/utils/client.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const context_1 = require("./context");
|
|
11
|
-
const errors_1 = require("./errors");
|
|
12
|
-
const debug = (0, debug_1.default)("ggt:client");
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import Debug from "debug";
|
|
4
|
+
import { createClient } from "graphql-ws";
|
|
5
|
+
import _ from "lodash";
|
|
6
|
+
import WebSocket from "ws";
|
|
7
|
+
import { context } from "./context.js";
|
|
8
|
+
import { ClientError } from "./errors.js";
|
|
9
|
+
const debug = Debug("ggt:client");
|
|
13
10
|
var ConnectionStatus;
|
|
14
|
-
(function
|
|
11
|
+
(function(ConnectionStatus) {
|
|
15
12
|
ConnectionStatus[ConnectionStatus["CONNECTED"] = 0] = "CONNECTED";
|
|
16
13
|
ConnectionStatus[ConnectionStatus["DISCONNECTED"] = 1] = "DISCONNECTED";
|
|
17
14
|
ConnectionStatus[ConnectionStatus["RECONNECTING"] = 2] = "RECONNECTING";
|
|
@@ -21,110 +18,33 @@ var ConnectionStatus;
|
|
|
21
18
|
*
|
|
22
19
|
* NOTE: In order to use the Client, the user must be logged in and an app must have been selected (`context.app` and
|
|
23
20
|
* `context.session` must be set).
|
|
24
|
-
*/
|
|
25
|
-
class Client {
|
|
26
|
-
constructor() {
|
|
27
|
-
// assume the client is going to connect
|
|
28
|
-
Object.defineProperty(this, "status", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: ConnectionStatus.CONNECTED
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(this, "_client", {
|
|
35
|
-
enumerable: true,
|
|
36
|
-
configurable: true,
|
|
37
|
-
writable: true,
|
|
38
|
-
value: void 0
|
|
39
|
-
});
|
|
40
|
-
(0, assert_1.default)(context_1.context.app, "context.app must be set before instantiating the Client");
|
|
41
|
-
this._client = (0, graphql_ws_1.createClient)({
|
|
42
|
-
url: `wss://${context_1.context.app.slug}.${context_1.context.domains.app}/edit/api/graphql-ws`,
|
|
43
|
-
shouldRetry: () => true,
|
|
44
|
-
webSocketImpl: class extends ws_1.default {
|
|
45
|
-
constructor(address, protocols, wsOptions) {
|
|
46
|
-
(0, assert_1.default)(context_1.context.session, "context.session must be set before instantiating the Client");
|
|
47
|
-
super(address, protocols, {
|
|
48
|
-
...wsOptions,
|
|
49
|
-
headers: {
|
|
50
|
-
...wsOptions?.headers,
|
|
51
|
-
"user-agent": context_1.context.config.userAgent,
|
|
52
|
-
cookie: `session=${encodeURIComponent(context_1.context.session)};`,
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
on: {
|
|
58
|
-
connecting: () => {
|
|
59
|
-
switch (this.status) {
|
|
60
|
-
case ConnectionStatus.DISCONNECTED:
|
|
61
|
-
this.status = ConnectionStatus.RECONNECTING;
|
|
62
|
-
debug("reconnecting...");
|
|
63
|
-
break;
|
|
64
|
-
case ConnectionStatus.RECONNECTING:
|
|
65
|
-
debug("retrying...");
|
|
66
|
-
break;
|
|
67
|
-
default:
|
|
68
|
-
debug("connecting...");
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
connected: () => {
|
|
73
|
-
if (this.status === ConnectionStatus.RECONNECTING) {
|
|
74
|
-
debug("reconnected");
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
debug("connected");
|
|
78
|
-
}
|
|
79
|
-
// let the other on connected listeners see what status we're in
|
|
80
|
-
setImmediate(() => (this.status = ConnectionStatus.CONNECTED));
|
|
81
|
-
},
|
|
82
|
-
closed: (e) => {
|
|
83
|
-
const event = e;
|
|
84
|
-
if (event.wasClean) {
|
|
85
|
-
debug("connection closed");
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
if (this.status === ConnectionStatus.CONNECTED) {
|
|
89
|
-
this.status = ConnectionStatus.DISCONNECTED;
|
|
90
|
-
debug("disconnected");
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
error: (error) => {
|
|
94
|
-
if (this.status == ConnectionStatus.RECONNECTING) {
|
|
95
|
-
debug("failed to reconnect %o", { error });
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
debug("connection error %o", { error });
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
}
|
|
21
|
+
*/ export class Client {
|
|
104
22
|
subscribe(payload, sink) {
|
|
105
23
|
let subscribePayload;
|
|
106
24
|
let removeConnectedListener;
|
|
107
|
-
if (
|
|
25
|
+
if (_.isFunction(payload.variables)) {
|
|
108
26
|
// the caller wants us to re-evaluate the variables every time graphql-ws re-subscribes after reconnecting
|
|
109
|
-
subscribePayload = {
|
|
110
|
-
|
|
27
|
+
subscribePayload = {
|
|
28
|
+
...payload,
|
|
29
|
+
variables: payload.variables()
|
|
30
|
+
};
|
|
31
|
+
removeConnectedListener = this._client.on("connected", ()=>{
|
|
111
32
|
if (this.status == ConnectionStatus.RECONNECTING) {
|
|
112
33
|
// subscribePayload.variables is supposed to be readonly (it's not) and payload.variables may have been re-assigned (it won't)
|
|
113
34
|
subscribePayload.variables = payload.variables();
|
|
114
35
|
debug("re-sending %s%s%O", subscribePayload.query.split(/\s+/g, 1)[0], subscribePayload.query, subscribePayload.variables);
|
|
115
36
|
}
|
|
116
37
|
});
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
38
|
+
} else {
|
|
119
39
|
subscribePayload = payload;
|
|
120
40
|
}
|
|
121
41
|
debug("sending %s%s%O", subscribePayload.query.split(/\s+/g, 1)[0], subscribePayload.query, subscribePayload.variables);
|
|
122
42
|
const unsubscribe = this._client.subscribe(subscribePayload, {
|
|
123
|
-
next: (result)
|
|
124
|
-
error: (error)
|
|
125
|
-
complete: ()
|
|
43
|
+
next: (result)=>sink.next(result),
|
|
44
|
+
error: (error)=>sink.error(new ClientError(subscribePayload, error)),
|
|
45
|
+
complete: ()=>sink.complete?.()
|
|
126
46
|
});
|
|
127
|
-
return ()
|
|
47
|
+
return ()=>{
|
|
128
48
|
removeConnectedListener?.();
|
|
129
49
|
unsubscribe();
|
|
130
50
|
};
|
|
@@ -132,38 +52,109 @@ class Client {
|
|
|
132
52
|
subscribeUnwrap(payload, sink) {
|
|
133
53
|
const unsubscribe = this.subscribe(payload, {
|
|
134
54
|
...sink,
|
|
135
|
-
next: (result)
|
|
55
|
+
next: (result)=>{
|
|
136
56
|
if (result.errors) {
|
|
137
57
|
unsubscribe();
|
|
138
|
-
sink.error(new
|
|
58
|
+
sink.error(new ClientError(payload, result.errors));
|
|
139
59
|
return;
|
|
140
60
|
}
|
|
141
61
|
if (!result.data) {
|
|
142
|
-
sink.error(new
|
|
62
|
+
sink.error(new ClientError(payload, "We received a response without data"));
|
|
143
63
|
unsubscribe();
|
|
144
64
|
return;
|
|
145
65
|
}
|
|
146
66
|
sink.next(result.data);
|
|
147
|
-
}
|
|
67
|
+
}
|
|
148
68
|
});
|
|
149
69
|
return unsubscribe;
|
|
150
70
|
}
|
|
151
71
|
query(payload) {
|
|
152
|
-
return new Promise((resolve, reject)
|
|
153
|
-
this.subscribe(payload, {
|
|
72
|
+
return new Promise((resolve, reject)=>{
|
|
73
|
+
this.subscribe(payload, {
|
|
74
|
+
next: resolve,
|
|
75
|
+
error: reject
|
|
76
|
+
});
|
|
154
77
|
});
|
|
155
78
|
}
|
|
156
79
|
async queryUnwrap(payload) {
|
|
157
80
|
const result = await this.query(payload);
|
|
158
|
-
if (result.errors)
|
|
159
|
-
|
|
160
|
-
if (!result.data)
|
|
161
|
-
throw new errors_1.ClientError(payload, "We received a response without data");
|
|
81
|
+
if (result.errors) throw new ClientError(payload, result.errors);
|
|
82
|
+
if (!result.data) throw new ClientError(payload, "We received a response without data");
|
|
162
83
|
return result.data;
|
|
163
84
|
}
|
|
164
85
|
async dispose() {
|
|
165
86
|
await this._client.dispose();
|
|
166
87
|
}
|
|
88
|
+
constructor(){
|
|
89
|
+
// assume the client is going to connect
|
|
90
|
+
_define_property(this, "status", ConnectionStatus.CONNECTED);
|
|
91
|
+
_define_property(this, "_client", void 0);
|
|
92
|
+
assert(context.app, "context.app must be set before instantiating the Client");
|
|
93
|
+
this._client = createClient({
|
|
94
|
+
url: `wss://${context.app.slug}.${context.domains.app}/edit/api/graphql-ws`,
|
|
95
|
+
shouldRetry: ()=>true,
|
|
96
|
+
webSocketImpl: class extends WebSocket {
|
|
97
|
+
constructor(address, protocols, wsOptions){
|
|
98
|
+
assert(context.session, "context.session must be set before instantiating the Client");
|
|
99
|
+
super(address, protocols, {
|
|
100
|
+
...wsOptions,
|
|
101
|
+
headers: {
|
|
102
|
+
...wsOptions?.headers,
|
|
103
|
+
"user-agent": context.config.userAgent,
|
|
104
|
+
cookie: `session=${encodeURIComponent(context.session)};`
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
on: {
|
|
110
|
+
connecting: ()=>{
|
|
111
|
+
switch(this.status){
|
|
112
|
+
case ConnectionStatus.DISCONNECTED:
|
|
113
|
+
this.status = ConnectionStatus.RECONNECTING;
|
|
114
|
+
debug("reconnecting...");
|
|
115
|
+
break;
|
|
116
|
+
case ConnectionStatus.RECONNECTING:
|
|
117
|
+
debug("retrying...");
|
|
118
|
+
break;
|
|
119
|
+
default:
|
|
120
|
+
debug("connecting...");
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
connected: ()=>{
|
|
125
|
+
if (this.status === ConnectionStatus.RECONNECTING) {
|
|
126
|
+
debug("reconnected");
|
|
127
|
+
} else {
|
|
128
|
+
debug("connected");
|
|
129
|
+
}
|
|
130
|
+
// let the other on connected listeners see what status we're in
|
|
131
|
+
setImmediate(()=>this.status = ConnectionStatus.CONNECTED);
|
|
132
|
+
},
|
|
133
|
+
closed: (e)=>{
|
|
134
|
+
const event = e;
|
|
135
|
+
if (event.wasClean) {
|
|
136
|
+
debug("connection closed");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (this.status === ConnectionStatus.CONNECTED) {
|
|
140
|
+
this.status = ConnectionStatus.DISCONNECTED;
|
|
141
|
+
debug("disconnected");
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
error: (error)=>{
|
|
145
|
+
if (this.status == ConnectionStatus.RECONNECTING) {
|
|
146
|
+
debug("failed to reconnect %o", {
|
|
147
|
+
error
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
debug("connection error %o", {
|
|
151
|
+
error
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
167
158
|
}
|
|
168
|
-
|
|
159
|
+
|
|
169
160
|
//# sourceMappingURL=client.js.map
|
package/lib/utils/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"/","sources":["utils/client.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"assert\";\nimport Debug from \"debug\";\nimport type { GraphQLError } from \"graphql\";\nimport type { 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 { context } from \"./context\";\nimport { ClientError } from \"./errors\";\n\nconst debug = Debug(\"ggt:client\");\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: () => 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 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 },\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 may have been re-assigned (it won't)\n (subscribePayload as any).variables = (payload.variables as any)();\n debug(\"re-sending %s%s%O\", subscribePayload.query.split(/\\s+/g, 1)[0], subscribePayload.query, subscribePayload.variables);\n }\n });\n } else {\n subscribePayload = payload as SubscribePayload;\n }\n\n debug(\"sending %s%s%O\", subscribePayload.query.split(/\\s+/g, 1)[0], subscribePayload.query, subscribePayload.variables);\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/client.ts"],"sourcesContent":["import assert from \"assert\";\nimport Debug from \"debug\";\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\nconst debug = Debug(\"ggt:client\");\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: () => 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 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 },\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 may have been re-assigned (it won't)\n (subscribePayload as any).variables = (payload.variables as any)();\n debug(\"re-sending %s%s%O\", subscribePayload.query.split(/\\s+/g, 1)[0], subscribePayload.query, subscribePayload.variables);\n }\n });\n } else {\n subscribePayload = payload as SubscribePayload;\n }\n\n debug(\"sending %s%s%O\", subscribePayload.query.split(/\\s+/g, 1)[0], subscribePayload.query, subscribePayload.variables);\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?.(),\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","Debug","createClient","_","WebSocket","context","ClientError","debug","ConnectionStatus","CONNECTED","DISCONNECTED","RECONNECTING","Client","subscribe","payload","sink","subscribePayload","removeConnectedListener","isFunction","variables","_client","on","status","query","split","unsubscribe","next","result","error","complete","subscribeUnwrap","errors","data","Promise","resolve","reject","queryUnwrap","dispose","constructor","app","url","slug","domains","shouldRetry","webSocketImpl","address","protocols","wsOptions","session","headers","config","userAgent","cookie","encodeURIComponent","connecting","connected","setImmediate","closed","e","event","wasClean"],"mappings":"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"}
|
package/lib/utils/context.js
CHANGED
|
@@ -1,95 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
-
const fs_utils_1 = require("./fs-utils");
|
|
11
|
-
class Context {
|
|
12
|
-
constructor() {
|
|
13
|
-
/**
|
|
14
|
-
* A reference to oclif's {@linkcode Config}.
|
|
15
|
-
*
|
|
16
|
-
* By default, oclif's {@linkcode Config} is only available as an instance property on a Command, but we want to be
|
|
17
|
-
* able to access it from anywhere. To do this, we created this global variable that references the Config. It is set
|
|
18
|
-
* by the init function in the BaseCommand.
|
|
19
|
-
*/
|
|
20
|
-
Object.defineProperty(this, "config", {
|
|
21
|
-
enumerable: true,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
value: void 0
|
|
25
|
-
});
|
|
26
|
-
Object.defineProperty(this, "env", {
|
|
27
|
-
enumerable: true,
|
|
28
|
-
configurable: true,
|
|
29
|
-
writable: true,
|
|
30
|
-
value: new Env()
|
|
31
|
-
});
|
|
32
|
-
Object.defineProperty(this, "app", {
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
writable: true,
|
|
36
|
-
value: void 0
|
|
37
|
-
});
|
|
38
|
-
Object.defineProperty(this, "domains", {
|
|
39
|
-
enumerable: true,
|
|
40
|
-
configurable: true,
|
|
41
|
-
writable: true,
|
|
42
|
-
value: void 0
|
|
43
|
-
});
|
|
44
|
-
Object.defineProperty(this, "_session", {
|
|
45
|
-
enumerable: true,
|
|
46
|
-
configurable: true,
|
|
47
|
-
writable: true,
|
|
48
|
-
value: void 0
|
|
49
|
-
});
|
|
50
|
-
Object.defineProperty(this, "_user", {
|
|
51
|
-
enumerable: true,
|
|
52
|
-
configurable: true,
|
|
53
|
-
writable: true,
|
|
54
|
-
value: void 0
|
|
55
|
-
});
|
|
56
|
-
Object.defineProperty(this, "_availableApps", {
|
|
57
|
-
enumerable: true,
|
|
58
|
-
configurable: true,
|
|
59
|
-
writable: true,
|
|
60
|
-
value: []
|
|
61
|
-
});
|
|
62
|
-
Object.defineProperty(this, "_request", {
|
|
63
|
-
enumerable: true,
|
|
64
|
-
configurable: true,
|
|
65
|
-
writable: true,
|
|
66
|
-
value: got_1.default.extend({
|
|
67
|
-
hooks: {
|
|
68
|
-
beforeRequest: [
|
|
69
|
-
(options) => {
|
|
70
|
-
options.headers["user-agent"] = this.config.userAgent;
|
|
71
|
-
if (options.url.host === this.domains.services && this.session) {
|
|
72
|
-
options.headers["cookie"] = `session=${encodeURIComponent(this.session)};`;
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
},
|
|
77
|
-
})
|
|
78
|
-
});
|
|
79
|
-
this.domains = {
|
|
80
|
-
app: process.env["GGT_GADGET_APP_DOMAIN"] || (this.env.productionLike ? "gadget.app" : "ggt.pub"),
|
|
81
|
-
services: process.env["GGT_GADGET_SERVICES_DOMAIN"] || (this.env.productionLike ? "app.gadget.dev" : "app.ggt.dev"),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import { HTTPError, got } from "got";
|
|
5
|
+
import _ from "lodash";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { ignoreEnoent } from "./fs-utils.js";
|
|
8
|
+
export class Context {
|
|
84
9
|
get session() {
|
|
85
|
-
if (this._session)
|
|
86
|
-
return this._session;
|
|
10
|
+
if (this._session) return this._session;
|
|
87
11
|
try {
|
|
88
|
-
this._session =
|
|
12
|
+
this._session = fs.readFileSync(path.join(this.config.configDir, "session.txt"), "utf-8");
|
|
89
13
|
return this._session;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
(0, fs_utils_1.ignoreEnoent)(error);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
ignoreEnoent(error);
|
|
93
16
|
return undefined;
|
|
94
17
|
}
|
|
95
18
|
}
|
|
@@ -97,26 +20,21 @@ class Context {
|
|
|
97
20
|
this.clear();
|
|
98
21
|
this._session = value;
|
|
99
22
|
if (this._session) {
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
fs_extra_1.default.removeSync(path_1.default.join(this.config.configDir, "session.txt"));
|
|
23
|
+
fs.outputFileSync(path.join(this.config.configDir, "session.txt"), this._session);
|
|
24
|
+
} else {
|
|
25
|
+
fs.removeSync(path.join(this.config.configDir, "session.txt"));
|
|
104
26
|
}
|
|
105
27
|
}
|
|
106
28
|
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
return undefined;
|
|
112
|
-
if (this._user)
|
|
113
|
-
return this._user;
|
|
29
|
+
* @returns The current user, or undefined if the user is not logged in.
|
|
30
|
+
*/ async getUser() {
|
|
31
|
+
if (!this.session) return undefined;
|
|
32
|
+
if (this._user) return this._user;
|
|
114
33
|
try {
|
|
115
34
|
this._user = await this._request(`https://${this.domains.services}/auth/api/current-user`).json();
|
|
116
35
|
return this._user;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (error instanceof got_1.HTTPError && error.response.statusCode === 401) {
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error instanceof HTTPError && error.response.statusCode === 401) {
|
|
120
38
|
this.session = undefined;
|
|
121
39
|
return undefined;
|
|
122
40
|
}
|
|
@@ -124,23 +42,19 @@ class Context {
|
|
|
124
42
|
}
|
|
125
43
|
}
|
|
126
44
|
/**
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
return [];
|
|
132
|
-
if (this._availableApps.length > 0)
|
|
133
|
-
return this._availableApps;
|
|
45
|
+
* @returns The list of Gadget applications the current user has access to.
|
|
46
|
+
*/ async getAvailableApps() {
|
|
47
|
+
if (!this.session) return [];
|
|
48
|
+
if (this._availableApps.length > 0) return this._availableApps;
|
|
134
49
|
this._availableApps = await this._request(`https://${this.domains.services}/auth/api/apps`).json();
|
|
135
50
|
return this._availableApps;
|
|
136
51
|
}
|
|
137
52
|
async setApp(appOrSlug) {
|
|
138
|
-
if (
|
|
139
|
-
const app = await this.getAvailableApps().then((apps)
|
|
140
|
-
(
|
|
53
|
+
if (_.isString(appOrSlug)) {
|
|
54
|
+
const app = await this.getAvailableApps().then((apps)=>apps.find((app)=>app.slug == appOrSlug));
|
|
55
|
+
assert(app, `attempted to set app to "${appOrSlug}" but no app with that name or slug was found`);
|
|
141
56
|
this.app = app;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
57
|
+
} else {
|
|
144
58
|
this.app = appOrSlug;
|
|
145
59
|
}
|
|
146
60
|
}
|
|
@@ -150,12 +64,41 @@ class Context {
|
|
|
150
64
|
this.app = undefined;
|
|
151
65
|
this._availableApps = [];
|
|
152
66
|
}
|
|
67
|
+
constructor(){
|
|
68
|
+
/**
|
|
69
|
+
* A reference to oclif's {@linkcode Config}.
|
|
70
|
+
*
|
|
71
|
+
* By default, oclif's {@linkcode Config} is only available as an instance property on a Command, but we want to be
|
|
72
|
+
* able to access it from anywhere. To do this, we created this global variable that references the Config. It is set
|
|
73
|
+
* by the init function in the BaseCommand.
|
|
74
|
+
*/ _define_property(this, "config", void 0);
|
|
75
|
+
_define_property(this, "env", new Env());
|
|
76
|
+
_define_property(this, "app", void 0);
|
|
77
|
+
_define_property(this, "domains", void 0);
|
|
78
|
+
_define_property(this, "_session", void 0);
|
|
79
|
+
_define_property(this, "_user", void 0);
|
|
80
|
+
_define_property(this, "_availableApps", []);
|
|
81
|
+
_define_property(this, "_request", got.extend({
|
|
82
|
+
hooks: {
|
|
83
|
+
beforeRequest: [
|
|
84
|
+
(options)=>{
|
|
85
|
+
options.headers["user-agent"] = this.config.userAgent;
|
|
86
|
+
if (options.url instanceof URL && options.url.host === this.domains.services && this.session) {
|
|
87
|
+
options.headers["cookie"] = `session=${encodeURIComponent(this.session)};`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
this.domains = {
|
|
94
|
+
app: process.env["GGT_GADGET_APP_DOMAIN"] || (this.env.productionLike ? "gadget.app" : "ggt.pub"),
|
|
95
|
+
services: process.env["GGT_GADGET_SERVICES_DOMAIN"] || (this.env.productionLike ? "app.gadget.dev" : "app.ggt.dev")
|
|
96
|
+
};
|
|
97
|
+
}
|
|
153
98
|
}
|
|
154
|
-
exports.Context = Context;
|
|
155
99
|
/**
|
|
156
100
|
* Captures the name and nature of the environment
|
|
157
|
-
*/
|
|
158
|
-
class Env {
|
|
101
|
+
*/ class Env {
|
|
159
102
|
get value() {
|
|
160
103
|
return process.env["GGT_ENV"] || "production";
|
|
161
104
|
}
|
|
@@ -172,5 +115,6 @@ class Env {
|
|
|
172
115
|
return this.developmentLike || this.testLike;
|
|
173
116
|
}
|
|
174
117
|
}
|
|
175
|
-
|
|
118
|
+
export const context = new Context();
|
|
119
|
+
|
|
176
120
|
//# sourceMappingURL=context.js.map
|
package/lib/utils/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../../src/utils/context.ts"],"sourcesContent":["import type { Config } from \"@oclif/core\";\nimport assert from \"assert\";\nimport fs from \"fs-extra\";\nimport { HTTPError, got } from \"got\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { ignoreEnoent } from \"./fs-utils.js\";\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 env = new Env();\n\n app?: App;\n\n domains: {\n app: string;\n services: string;\n };\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 constructor() {\n this.domains = {\n app: process.env[\"GGT_GADGET_APP_DOMAIN\"] || (this.env.productionLike ? \"gadget.app\" : \"ggt.pub\"),\n services: process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] || (this.env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\"),\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 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) => apps.find((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 }\n}\n\n/**\n * Captures the name and nature of the environment\n */\nclass Env {\n get value(): string {\n return process.env[\"GGT_ENV\"] || \"production\";\n }\n\n get productionLike(): boolean {\n return this.value.startsWith(\"production\");\n }\n\n get developmentLike(): boolean {\n return this.value.startsWith(\"development\");\n }\n\n get testLike(): boolean {\n return this.value.startsWith(\"test\");\n }\n\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n }\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\nexport const context = new Context();\n"],"names":["assert","fs","HTTPError","got","_","path","ignoreEnoent","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","constructor","env","Env","extend","hooks","beforeRequest","options","headers","userAgent","url","URL","host","encodeURIComponent","process","productionLike","startsWith","developmentLike","testLike","developmentOrTestLike","context"],"mappings":"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"}
|