@gadgetinc/ggt 0.3.3 → 0.4.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.
- package/README.md +139 -76
- package/bin/dev.js +4 -7
- package/lib/__generated__/graphql.js.map +1 -1
- package/lib/commands/deploy.js +227 -0
- package/lib/commands/deploy.js.map +1 -0
- package/lib/commands/list.js +20 -16
- package/lib/commands/list.js.map +1 -1
- package/lib/commands/login.js +22 -20
- package/lib/commands/login.js.map +1 -1
- package/lib/commands/logout.js +13 -9
- package/lib/commands/logout.js.map +1 -1
- package/lib/commands/root.js +89 -56
- package/lib/commands/root.js.map +1 -1
- package/lib/commands/sync.js +253 -496
- package/lib/commands/sync.js.map +1 -1
- package/lib/commands/version.js +21 -0
- package/lib/commands/version.js.map +1 -0
- package/lib/commands/whoami.js +15 -11
- package/lib/commands/whoami.js.map +1 -1
- package/lib/main.js +4 -10
- package/lib/main.js.map +1 -1
- package/lib/services/{app.js → app/app.js} +8 -3
- package/lib/services/app/app.js.map +1 -0
- package/lib/services/app/arg.js +28 -0
- package/lib/services/app/arg.js.map +1 -0
- package/lib/services/app/edit-graphql.js +389 -0
- package/lib/services/app/edit-graphql.js.map +1 -0
- package/lib/services/command/arg.js +53 -0
- package/lib/services/command/arg.js.map +1 -0
- package/lib/services/command/command.js +27 -0
- package/lib/services/command/command.js.map +1 -0
- package/lib/services/command/context.js +60 -0
- package/lib/services/command/context.js.map +1 -0
- package/lib/services/{config.js → config/config.js} +29 -31
- package/lib/services/config/config.js.map +1 -0
- package/lib/services/config/env.js +22 -0
- package/lib/services/config/env.js.map +1 -0
- package/lib/services/config/package-json.js +9 -0
- package/lib/services/config/package-json.js.map +1 -0
- package/lib/services/filesync/changes.js +97 -0
- package/lib/services/filesync/changes.js.map +1 -0
- package/lib/services/filesync/conflicts.js +137 -0
- package/lib/services/filesync/conflicts.js.map +1 -0
- package/lib/services/filesync/directory.js +253 -0
- package/lib/services/filesync/directory.js.map +1 -0
- package/lib/services/filesync/error.js +67 -0
- package/lib/services/filesync/error.js.map +1 -0
- package/lib/services/filesync/file.js +3 -0
- package/lib/services/filesync/file.js.map +1 -0
- package/lib/services/filesync/filesync.js +675 -0
- package/lib/services/filesync/filesync.js.map +1 -0
- package/lib/services/filesync/hashes.js +150 -0
- package/lib/services/filesync/hashes.js.map +1 -0
- package/lib/services/http/auth.js +41 -0
- package/lib/services/http/auth.js.map +1 -0
- package/lib/services/http/http.js +64 -0
- package/lib/services/http/http.js.map +1 -0
- package/lib/services/output/log/field.js +3 -0
- package/lib/services/output/log/field.js.map +1 -0
- package/lib/services/output/log/format/format.js +8 -0
- package/lib/services/output/log/format/format.js.map +1 -0
- package/lib/services/output/log/format/json.js +45 -0
- package/lib/services/output/log/format/json.js.map +1 -0
- package/lib/services/output/log/format/pretty.js +147 -0
- package/lib/services/output/log/format/pretty.js.map +1 -0
- package/lib/services/output/log/level.js +41 -0
- package/lib/services/output/log/level.js.map +1 -0
- package/lib/services/output/log/logger.js +40 -0
- package/lib/services/output/log/logger.js.map +1 -0
- package/lib/services/output/log/printer.js +120 -0
- package/lib/services/output/log/printer.js.map +1 -0
- package/lib/services/output/log/structured.js +52 -0
- package/lib/services/output/log/structured.js.map +1 -0
- package/lib/services/{notify.js → output/notify.js} +7 -6
- package/lib/services/output/notify.js.map +1 -0
- package/lib/services/output/prompt.js +52 -0
- package/lib/services/output/prompt.js.map +1 -0
- package/lib/services/output/report.js +162 -0
- package/lib/services/output/report.js.map +1 -0
- package/lib/services/output/sprint.js +21 -0
- package/lib/services/output/sprint.js.map +1 -0
- package/lib/services/output/stream.js +54 -0
- package/lib/services/output/stream.js.map +1 -0
- package/lib/services/{version.js → output/update.js} +24 -16
- package/lib/services/output/update.js.map +1 -0
- package/lib/services/user/session.js +50 -0
- package/lib/services/user/session.js.map +1 -0
- package/lib/services/{user.js → user/user.js} +23 -14
- package/lib/services/user/user.js.map +1 -0
- package/lib/services/util/boolean.js +15 -0
- package/lib/services/util/boolean.js.map +1 -0
- package/lib/services/util/collection.js +38 -0
- package/lib/services/util/collection.js.map +1 -0
- package/lib/services/util/function.js +97 -0
- package/lib/services/util/function.js.map +1 -0
- package/lib/services/{is.js → util/is.js} +7 -0
- package/lib/services/util/is.js.map +1 -0
- package/lib/services/util/number.js +27 -0
- package/lib/services/util/number.js.map +1 -0
- package/lib/services/util/object.js +101 -0
- package/lib/services/util/object.js.map +1 -0
- package/lib/services/util/paths.js +36 -0
- package/lib/services/util/paths.js.map +1 -0
- package/lib/services/{promise.js → util/promise.js} +5 -7
- package/lib/services/util/promise.js.map +1 -0
- package/npm-shrinkwrap.json +2143 -1304
- package/package.json +50 -42
- package/lib/commands/index.js +0 -9
- package/lib/commands/index.js.map +0 -1
- package/lib/services/app.js.map +0 -1
- package/lib/services/args.js +0 -28
- package/lib/services/args.js.map +0 -1
- package/lib/services/collections.js +0 -17
- package/lib/services/collections.js.map +0 -1
- package/lib/services/config.js.map +0 -1
- package/lib/services/debounce.js +0 -21
- package/lib/services/debounce.js.map +0 -1
- package/lib/services/defaults.js +0 -8
- package/lib/services/defaults.js.map +0 -1
- package/lib/services/edit-graphql.js +0 -202
- package/lib/services/edit-graphql.js.map +0 -1
- package/lib/services/errors.js +0 -277
- package/lib/services/errors.js.map +0 -1
- package/lib/services/filesync.js +0 -404
- package/lib/services/filesync.js.map +0 -1
- package/lib/services/fs.js +0 -35
- package/lib/services/fs.js.map +0 -1
- package/lib/services/http.js +0 -53
- package/lib/services/http.js.map +0 -1
- package/lib/services/is.js.map +0 -1
- package/lib/services/log.js +0 -45
- package/lib/services/log.js.map +0 -1
- package/lib/services/noop.js +0 -4
- package/lib/services/noop.js.map +0 -1
- package/lib/services/notify.js.map +0 -1
- package/lib/services/output.js +0 -74
- package/lib/services/output.js.map +0 -1
- package/lib/services/promise.js.map +0 -1
- package/lib/services/prompt.js +0 -22
- package/lib/services/prompt.js.map +0 -1
- package/lib/services/session.js +0 -31
- package/lib/services/session.js.map +0 -1
- package/lib/services/sleep.js +0 -21
- package/lib/services/sleep.js.map +0 -1
- package/lib/services/timeout.js +0 -8
- package/lib/services/timeout.js.map +0 -1
- package/lib/services/user.js.map +0 -1
- package/lib/services/version.js.map +0 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import { createClient } from "graphql-ws";
|
|
3
|
+
import assert from "node:assert";
|
|
4
|
+
import PQueue from "p-queue";
|
|
5
|
+
import pluralize from "pluralize";
|
|
6
|
+
import WebSocket from "ws";
|
|
7
|
+
import { config } from "../config/config.js";
|
|
8
|
+
import { loadCookie } from "../http/auth.js";
|
|
9
|
+
import { http } from "../http/http.js";
|
|
10
|
+
import { createLogger } from "../output/log/logger.js";
|
|
11
|
+
import { CLIError, IsBug } from "../output/report.js";
|
|
12
|
+
import { sprint } from "../output/sprint.js";
|
|
13
|
+
import { uniq } from "../util/collection.js";
|
|
14
|
+
import { noop, unthunk } from "../util/function.js";
|
|
15
|
+
import { isCloseEvent, isError, isErrorEvent, isGraphQLErrors, isObject, isString } from "../util/is.js";
|
|
16
|
+
import { serializeError } from "../util/object.js";
|
|
17
|
+
var ConnectionStatus;
|
|
18
|
+
(function(ConnectionStatus) {
|
|
19
|
+
ConnectionStatus[ConnectionStatus["CONNECTED"] = 0] = "CONNECTED";
|
|
20
|
+
ConnectionStatus[ConnectionStatus["DISCONNECTED"] = 1] = "DISCONNECTED";
|
|
21
|
+
ConnectionStatus[ConnectionStatus["RECONNECTING"] = 2] = "RECONNECTING";
|
|
22
|
+
})(ConnectionStatus || (ConnectionStatus = {}));
|
|
23
|
+
const log = createLogger({
|
|
24
|
+
name: "edit-graphql"
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* EditGraphQL is a GraphQL client connected to a Gadget application's
|
|
28
|
+
* /edit/api/graphql-ws endpoint.
|
|
29
|
+
*/ export class EditGraphQL {
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to a GraphQL query.
|
|
32
|
+
*
|
|
33
|
+
* This method is typically used to subscribe to a GraphQL
|
|
34
|
+
* subscription. If you want to execute a GraphQL query or mutation,
|
|
35
|
+
* use {@link EditGraphQL.query} instead.
|
|
36
|
+
*
|
|
37
|
+
* @param payload The query and variables to send to the server.
|
|
38
|
+
* @param sink The callbacks to invoke when the server responds.
|
|
39
|
+
* @returns A function to unsubscribe from the subscription.
|
|
40
|
+
*/ subscribe({ onData, ...options }) {
|
|
41
|
+
const unsubscribe = this._subscribe({
|
|
42
|
+
...options,
|
|
43
|
+
onResult: async (result)=>{
|
|
44
|
+
if (result.errors) {
|
|
45
|
+
unsubscribe();
|
|
46
|
+
await options.onError(new EditGraphQLError(options.query, result.errors));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!result.data) {
|
|
50
|
+
unsubscribe();
|
|
51
|
+
await options.onError(new EditGraphQLError(options.query, "Received a GraphQL response without errors or data"));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
await onData(result.data);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return unsubscribe;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Execute a GraphQL query or mutation.
|
|
61
|
+
*
|
|
62
|
+
* @param payload The query and variables to send to the server.
|
|
63
|
+
* @returns The data returned by the server.
|
|
64
|
+
*/ async query({ query, variables }) {
|
|
65
|
+
const result = await this._query({
|
|
66
|
+
query,
|
|
67
|
+
variables
|
|
68
|
+
});
|
|
69
|
+
if (result.errors) {
|
|
70
|
+
throw new EditGraphQLError(query, result.errors);
|
|
71
|
+
}
|
|
72
|
+
if (!result.data) {
|
|
73
|
+
throw new EditGraphQLError(query, "We received a response without data");
|
|
74
|
+
}
|
|
75
|
+
return result.data;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Close the connection to the server.
|
|
79
|
+
*/ async dispose() {
|
|
80
|
+
await this._client.dispose();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Internal method to subscribe to a GraphQL query.
|
|
84
|
+
*
|
|
85
|
+
* This method is only exposed for testing and shouldn't be used
|
|
86
|
+
* directly.
|
|
87
|
+
*/ _subscribe({ query, variables, onResult, onError: optionsOnError, onComplete = noop }) {
|
|
88
|
+
let payload = {
|
|
89
|
+
query,
|
|
90
|
+
variables: unthunk(variables)
|
|
91
|
+
};
|
|
92
|
+
const [type, operation] = payload.query.split(/ |\(/, 2);
|
|
93
|
+
const removeConnectedListener = this._client.on("connected", ()=>{
|
|
94
|
+
if (this.status === 2) {
|
|
95
|
+
payload = {
|
|
96
|
+
query,
|
|
97
|
+
variables: unthunk(variables)
|
|
98
|
+
};
|
|
99
|
+
log.info("re-sending graphql query via ws", {
|
|
100
|
+
type,
|
|
101
|
+
operation
|
|
102
|
+
}, {
|
|
103
|
+
variables: payload.variables
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const queue = new PQueue({
|
|
108
|
+
concurrency: 1
|
|
109
|
+
});
|
|
110
|
+
const onError = (error)=>optionsOnError(new EditGraphQLError(query, error));
|
|
111
|
+
log.info("sending graphql query via ws", {
|
|
112
|
+
type,
|
|
113
|
+
operation
|
|
114
|
+
}, {
|
|
115
|
+
variables: payload.variables
|
|
116
|
+
});
|
|
117
|
+
const unsubscribe = this._client.subscribe(payload, {
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
119
|
+
next: (result)=>queue.add(()=>onResult(result)).catch(onError),
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
121
|
+
error: (error)=>queue.add(()=>onError(error)),
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
123
|
+
complete: ()=>queue.add(()=>onComplete()).catch(onError)
|
|
124
|
+
});
|
|
125
|
+
return ()=>{
|
|
126
|
+
removeConnectedListener();
|
|
127
|
+
unsubscribe();
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async _query(input) {
|
|
131
|
+
const cookie = loadCookie();
|
|
132
|
+
assert(cookie, "missing cookie when connecting to GraphQL API");
|
|
133
|
+
let subdomain = this.app.slug;
|
|
134
|
+
if (this.app.hasSplitEnvironments) {
|
|
135
|
+
subdomain += "--development";
|
|
136
|
+
}
|
|
137
|
+
const payload = {
|
|
138
|
+
...input,
|
|
139
|
+
variables: unthunk(input.variables)
|
|
140
|
+
};
|
|
141
|
+
const [type, operation] = payload.query.split(/ |\(/, 2);
|
|
142
|
+
log.info("sending graphql query via http", {
|
|
143
|
+
type,
|
|
144
|
+
operation
|
|
145
|
+
}, {
|
|
146
|
+
variables: payload.variables
|
|
147
|
+
});
|
|
148
|
+
try {
|
|
149
|
+
const json = await http({
|
|
150
|
+
method: "POST",
|
|
151
|
+
url: `https://${subdomain}.${config.domains.app}/edit/api/graphql`,
|
|
152
|
+
headers: {
|
|
153
|
+
cookie
|
|
154
|
+
},
|
|
155
|
+
json: payload,
|
|
156
|
+
responseType: "json",
|
|
157
|
+
resolveBodyOnly: true,
|
|
158
|
+
throwHttpErrors: false
|
|
159
|
+
});
|
|
160
|
+
if (!isObject(json) || !("data" in json) && !("errors" in json)) {
|
|
161
|
+
log.error("received invalid graphql response", {
|
|
162
|
+
error: json
|
|
163
|
+
});
|
|
164
|
+
throw json;
|
|
165
|
+
}
|
|
166
|
+
return json;
|
|
167
|
+
} catch (error) {
|
|
168
|
+
throw new EditGraphQLError(input.query, error);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
constructor(app){
|
|
172
|
+
_define_property(this, "app", void 0);
|
|
173
|
+
// assume the client is going to connect
|
|
174
|
+
_define_property(this, "status", void 0);
|
|
175
|
+
_define_property(this, "_client", void 0);
|
|
176
|
+
this.app = app;
|
|
177
|
+
this.status = 0;
|
|
178
|
+
let subdomain = this.app.slug;
|
|
179
|
+
if (this.app.hasSplitEnvironments) {
|
|
180
|
+
subdomain += "--development";
|
|
181
|
+
}
|
|
182
|
+
this._client = createClient({
|
|
183
|
+
url: `wss://${subdomain}.${config.domains.app}/edit/api/graphql-ws`,
|
|
184
|
+
shouldRetry: ()=>true,
|
|
185
|
+
webSocketImpl: class extends WebSocket {
|
|
186
|
+
constructor(address, protocols, wsOptions){
|
|
187
|
+
// this cookie should be available since we were given an app which requires a cookie to load
|
|
188
|
+
const cookie = loadCookie();
|
|
189
|
+
assert(cookie, "missing cookie when connecting to GraphQL API");
|
|
190
|
+
super(address, protocols, {
|
|
191
|
+
...wsOptions,
|
|
192
|
+
headers: {
|
|
193
|
+
...wsOptions?.headers,
|
|
194
|
+
"user-agent": config.versionFull,
|
|
195
|
+
cookie
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
on: {
|
|
201
|
+
connecting: ()=>{
|
|
202
|
+
switch(this.status){
|
|
203
|
+
case 1:
|
|
204
|
+
this.status = 2;
|
|
205
|
+
log.info("reconnecting");
|
|
206
|
+
break;
|
|
207
|
+
case 2:
|
|
208
|
+
log.info("retrying");
|
|
209
|
+
break;
|
|
210
|
+
default:
|
|
211
|
+
log.info("connecting");
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
connected: ()=>{
|
|
216
|
+
if (this.status === 2) {
|
|
217
|
+
log.info("reconnected");
|
|
218
|
+
} else {
|
|
219
|
+
log.info("connected");
|
|
220
|
+
}
|
|
221
|
+
// let the other on connected listeners see what status we're in
|
|
222
|
+
setImmediate(()=>this.status = 0);
|
|
223
|
+
},
|
|
224
|
+
closed: (e)=>{
|
|
225
|
+
const event = e;
|
|
226
|
+
if (event.wasClean) {
|
|
227
|
+
log.info("connection closed");
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (this.status === 0) {
|
|
231
|
+
this.status = 1;
|
|
232
|
+
log.info("disconnected");
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
error: (error)=>{
|
|
236
|
+
if (this.status === 2) {
|
|
237
|
+
log.error("failed to reconnect", {
|
|
238
|
+
error
|
|
239
|
+
});
|
|
240
|
+
} else {
|
|
241
|
+
log.error("connection error", {
|
|
242
|
+
error
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
export class EditGraphQLError extends CLIError {
|
|
251
|
+
render() {
|
|
252
|
+
let body = "";
|
|
253
|
+
switch(true){
|
|
254
|
+
case isGraphQLErrors(this.cause):
|
|
255
|
+
{
|
|
256
|
+
const errors = uniq(this.cause.map((x)=>x.message));
|
|
257
|
+
body = sprint`
|
|
258
|
+
Gadget responded with the following ${pluralize("error", errors.length, false)}:
|
|
259
|
+
|
|
260
|
+
• ${errors.join("\n • ")}
|
|
261
|
+
`;
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
case isCloseEvent(this.cause):
|
|
265
|
+
body = "The connection to Gadget closed unexpectedly.";
|
|
266
|
+
break;
|
|
267
|
+
case isErrorEvent(this.cause) || isError(this.cause):
|
|
268
|
+
body = this.cause.message;
|
|
269
|
+
break;
|
|
270
|
+
default:
|
|
271
|
+
body = this.cause;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
return this.message + "\n\n" + body;
|
|
275
|
+
}
|
|
276
|
+
constructor(query, cause){
|
|
277
|
+
super("An error occurred while communicating with Gadget");
|
|
278
|
+
_define_property(this, "query", void 0);
|
|
279
|
+
_define_property(this, "isBug", void 0);
|
|
280
|
+
_define_property(this, "cause", void 0);
|
|
281
|
+
this.query = query;
|
|
282
|
+
this.isBug = IsBug.MAYBE;
|
|
283
|
+
// ErrorEvent and CloseEvent aren't serializable, so we reconstruct
|
|
284
|
+
// them into an object. We discard the `target` property because
|
|
285
|
+
// it's large and not that useful
|
|
286
|
+
if (isErrorEvent(cause)) {
|
|
287
|
+
this.cause = {
|
|
288
|
+
type: cause.type,
|
|
289
|
+
message: cause.message,
|
|
290
|
+
error: serializeError(cause.error)
|
|
291
|
+
};
|
|
292
|
+
} else if (isCloseEvent(cause)) {
|
|
293
|
+
this.cause = {
|
|
294
|
+
type: cause.type,
|
|
295
|
+
code: cause.code,
|
|
296
|
+
reason: cause.reason,
|
|
297
|
+
wasClean: cause.wasClean
|
|
298
|
+
};
|
|
299
|
+
} else {
|
|
300
|
+
assert(isString(cause) || isError(cause) || isGraphQLErrors(cause), "cause must be a string, Error, GraphQLError[], CloseEvent, or ErrorEvent");
|
|
301
|
+
this.cause = cause;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
export const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = sprint(/* GraphQL */ `
|
|
306
|
+
subscription RemoteFileSyncEvents($localFilesVersion: String!) {
|
|
307
|
+
remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {
|
|
308
|
+
remoteFilesVersion
|
|
309
|
+
changed {
|
|
310
|
+
path
|
|
311
|
+
mode
|
|
312
|
+
content
|
|
313
|
+
encoding
|
|
314
|
+
}
|
|
315
|
+
deleted {
|
|
316
|
+
path
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
`);
|
|
321
|
+
export const REMOTE_FILES_VERSION_QUERY = sprint(/* GraphQL */ `
|
|
322
|
+
query RemoteFilesVersion {
|
|
323
|
+
remoteFilesVersion
|
|
324
|
+
}
|
|
325
|
+
`);
|
|
326
|
+
export const PUBLISH_FILE_SYNC_EVENTS_MUTATION = sprint(/* GraphQL */ `
|
|
327
|
+
mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {
|
|
328
|
+
publishFileSyncEvents(input: $input) {
|
|
329
|
+
remoteFilesVersion
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
`);
|
|
333
|
+
export const FILE_SYNC_FILES_QUERY = sprint(/* GraphQL */ `
|
|
334
|
+
query FileSyncFiles($paths: [String!]!, $filesVersion: String, $encoding: FileSyncEncoding) {
|
|
335
|
+
fileSyncFiles(paths: $paths, filesVersion: $filesVersion, encoding: $encoding) {
|
|
336
|
+
filesVersion
|
|
337
|
+
files {
|
|
338
|
+
path
|
|
339
|
+
mode
|
|
340
|
+
content
|
|
341
|
+
encoding
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
`);
|
|
346
|
+
export const FILE_SYNC_HASHES_QUERY = sprint(/* GraphQL */ `
|
|
347
|
+
query FileSyncHashes($filesVersion: String) {
|
|
348
|
+
fileSyncHashes(filesVersion: $filesVersion) {
|
|
349
|
+
filesVersion
|
|
350
|
+
hashes
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
`);
|
|
354
|
+
export const FILE_SYNC_COMPARISON_HASHES_QUERY = sprint(/* GraphQL */ `
|
|
355
|
+
query FileSyncComparisonHashes($filesVersion: String!) {
|
|
356
|
+
fileSyncComparisonHashes(filesVersion: $filesVersion) {
|
|
357
|
+
filesVersionHashes {
|
|
358
|
+
filesVersion
|
|
359
|
+
hashes
|
|
360
|
+
}
|
|
361
|
+
latestFilesVersionHashes {
|
|
362
|
+
filesVersion
|
|
363
|
+
hashes
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
`);
|
|
368
|
+
export const REMOTE_SERVER_CONTRACT_STATUS_SUBSCRIPTION = sprint(/* GraphQL */ `
|
|
369
|
+
subscription publishStatus($localFilesVersion: String!, $force: Boolean) {
|
|
370
|
+
publishStatus(localFilesVersion: $localFilesVersion, force: $force) {
|
|
371
|
+
remoteFilesVersion
|
|
372
|
+
progress
|
|
373
|
+
issues {
|
|
374
|
+
severity
|
|
375
|
+
message
|
|
376
|
+
node {
|
|
377
|
+
type
|
|
378
|
+
key
|
|
379
|
+
name
|
|
380
|
+
fieldType
|
|
381
|
+
parentKey
|
|
382
|
+
parentApiIdentifier
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
`);
|
|
388
|
+
|
|
389
|
+
//# sourceMappingURL=edit-graphql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/app/edit-graphql.ts"],"sourcesContent":["import type { GraphQLError } from \"graphql\";\nimport type { ExecutionResult } from \"graphql-ws\";\nimport { createClient } from \"graphql-ws\";\nimport assert from \"node:assert\";\nimport type { ClientRequestArgs } from \"node:http\";\nimport PQueue from \"p-queue\";\nimport pluralize from \"pluralize\";\nimport type { JsonObject, Promisable } from \"type-fest\";\nimport type { CloseEvent, ErrorEvent } from \"ws\";\nimport WebSocket from \"ws\";\nimport type {\n FileSyncComparisonHashesQuery,\n FileSyncComparisonHashesQueryVariables,\n FileSyncFilesQuery,\n FileSyncFilesQueryVariables,\n FileSyncHashesQuery,\n FileSyncHashesQueryVariables,\n PublishFileSyncEventsMutation,\n PublishFileSyncEventsMutationVariables,\n PublishStatusSubscription,\n PublishStatusSubscriptionVariables,\n RemoteFileSyncEventsSubscription,\n RemoteFileSyncEventsSubscriptionVariables,\n RemoteFilesVersionQuery,\n RemoteFilesVersionQueryVariables,\n} from \"../../__generated__/graphql.js\";\nimport { config } from \"../config/config.js\";\nimport { loadCookie } from \"../http/auth.js\";\nimport { http } from \"../http/http.js\";\nimport { createLogger } from \"../output/log/logger.js\";\nimport { CLIError, IsBug } from \"../output/report.js\";\nimport { sprint } from \"../output/sprint.js\";\nimport { uniq } from \"../util/collection.js\";\nimport { noop, unthunk, type Thunk } from \"../util/function.js\";\nimport { isCloseEvent, isError, isErrorEvent, isGraphQLErrors, isObject, isString } from \"../util/is.js\";\nimport { serializeError } from \"../util/object.js\";\nimport type { App } from \"./app.js\";\n\nenum ConnectionStatus {\n CONNECTED,\n DISCONNECTED,\n RECONNECTING,\n}\n\nconst log = createLogger({ name: \"edit-graphql\" });\n\n/**\n * EditGraphQL is a GraphQL client connected to a Gadget application's\n * /edit/api/graphql-ws endpoint.\n */\nexport class EditGraphQL {\n // assume the client is going to connect\n status = ConnectionStatus.CONNECTED;\n\n private _client: ReturnType<typeof createClient>;\n\n constructor(readonly app: App) {\n let subdomain = this.app.slug;\n if (this.app.hasSplitEnvironments) {\n subdomain += \"--development\";\n }\n\n this._client = createClient({\n url: `wss://${subdomain}.${config.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 // this cookie should be available since we were given an app which requires a cookie to load\n const cookie = loadCookie();\n assert(cookie, \"missing cookie when connecting to GraphQL API\");\n\n super(address, protocols, {\n ...wsOptions,\n headers: {\n ...wsOptions?.headers,\n \"user-agent\": config.versionFull,\n cookie,\n },\n });\n }\n },\n on: {\n connecting: () => {\n switch (this.status) {\n case ConnectionStatus.DISCONNECTED:\n this.status = ConnectionStatus.RECONNECTING;\n log.info(\"reconnecting\");\n break;\n case ConnectionStatus.RECONNECTING:\n log.info(\"retrying\");\n break;\n default:\n log.info(\"connecting\");\n break;\n }\n },\n connected: () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n log.info(\"reconnected\");\n } else {\n log.info(\"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 log.info(\"connection closed\");\n return;\n }\n\n if (this.status === ConnectionStatus.CONNECTED) {\n this.status = ConnectionStatus.DISCONNECTED;\n log.info(\"disconnected\");\n }\n },\n error: (error) => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n log.error(\"failed to reconnect\", { error });\n } else {\n log.error(\"connection error\", { error });\n }\n },\n },\n });\n }\n\n /**\n * Subscribe to a GraphQL query.\n *\n * This method is typically used to subscribe to a GraphQL\n * subscription. If you want to execute a GraphQL query or mutation,\n * use {@link EditGraphQL.query} instead.\n *\n * @param payload The query and variables to send to the server.\n * @param sink The callbacks to invoke when the server responds.\n * @returns A function to unsubscribe from the subscription.\n */\n subscribe<Query extends GraphQLQuery>({\n onData,\n ...options\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n onData: (data: Query[\"Data\"]) => Promisable<void>;\n onError: (error: EditGraphQLError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n }): () => void {\n const unsubscribe = this._subscribe({\n ...options,\n onResult: async (result) => {\n if (result.errors) {\n unsubscribe();\n await options.onError(new EditGraphQLError(options.query, result.errors));\n return;\n }\n\n if (!result.data) {\n unsubscribe();\n await options.onError(new EditGraphQLError(options.query, \"Received a GraphQL response without errors or data\"));\n return;\n }\n\n await onData(result.data);\n },\n });\n\n return unsubscribe;\n }\n\n /**\n * Execute a GraphQL query or mutation.\n *\n * @param payload The query and variables to send to the server.\n * @returns The data returned by the server.\n */\n async query<Query extends GraphQLQuery>({\n query,\n variables,\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n }): Promise<Query[\"Data\"]> {\n const result = await this._query({ query, variables });\n if (result.errors) {\n throw new EditGraphQLError(query, result.errors);\n }\n if (!result.data) {\n throw new EditGraphQLError(query, \"We received a response without data\");\n }\n return result.data;\n }\n\n /**\n * Close the connection to the server.\n */\n async dispose(): Promise<void> {\n await this._client.dispose();\n }\n\n /**\n * Internal method to subscribe to a GraphQL query.\n *\n * This method is only exposed for testing and shouldn't be used\n * directly.\n */\n _subscribe<Query extends GraphQLQuery>({\n query,\n variables,\n onResult,\n onError: optionsOnError,\n onComplete = noop,\n }: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n onResult: (result: ExecutionResult<Query[\"Data\"], Query[\"Extensions\"]>) => Promisable<void>;\n onError: (error: EditGraphQLError) => Promisable<void>;\n onComplete?: () => Promisable<void>;\n }): () => void {\n let payload = { query, variables: unthunk(variables) };\n const [type, operation] = payload.query.split(/ |\\(/, 2);\n\n const removeConnectedListener = this._client.on(\"connected\", () => {\n if (this.status === ConnectionStatus.RECONNECTING) {\n payload = { query, variables: unthunk(variables) };\n log.info(\"re-sending graphql query via ws\", { type, operation }, { variables: payload.variables });\n }\n });\n\n const queue = new PQueue({ concurrency: 1 });\n const onError = (error: unknown): Promisable<void> => optionsOnError(new EditGraphQLError(query, error));\n\n log.info(\"sending graphql query via ws\", { type, operation }, { variables: payload.variables });\n const unsubscribe = this._client.subscribe<Query[\"Data\"], Query[\"Extensions\"]>(payload, {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n next: (result) => queue.add(() => onResult(result)).catch(onError),\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n error: (error) => queue.add(() => onError(error)),\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n complete: () => queue.add(() => onComplete()).catch(onError),\n });\n\n return () => {\n removeConnectedListener();\n unsubscribe();\n };\n }\n\n private async _query<Query extends GraphQLQuery>(input: {\n query: Query;\n variables?: Thunk<Query[\"Variables\"]> | null;\n }): Promise<ExecutionResult<Query[\"Data\"], Query[\"Extensions\"]>> {\n const cookie = loadCookie();\n assert(cookie, \"missing cookie when connecting to GraphQL API\");\n\n let subdomain = this.app.slug;\n if (this.app.hasSplitEnvironments) {\n subdomain += \"--development\";\n }\n\n const payload = { ...input, variables: unthunk(input.variables) };\n const [type, operation] = payload.query.split(/ |\\(/, 2);\n log.info(\"sending graphql query via http\", { type, operation }, { variables: payload.variables });\n\n try {\n const json = await http({\n method: \"POST\",\n url: `https://${subdomain}.${config.domains.app}/edit/api/graphql`,\n headers: { cookie },\n json: payload,\n responseType: \"json\",\n resolveBodyOnly: true,\n throwHttpErrors: false,\n });\n\n if (!isObject(json) || (!(\"data\" in json) && !(\"errors\" in json))) {\n log.error(\"received invalid graphql response\", { error: json });\n throw json;\n }\n\n return json as Query[\"Result\"];\n } catch (error) {\n throw new EditGraphQLError(input.query, error);\n }\n }\n}\n\nexport class EditGraphQLError extends CLIError {\n isBug = IsBug.MAYBE;\n\n override cause: string | Error | readonly GraphQLError[] | CloseEvent | ErrorEvent;\n\n constructor(\n readonly query: GraphQLQuery,\n cause: unknown,\n ) {\n super(\"An error occurred while communicating with Gadget\");\n\n // ErrorEvent and CloseEvent aren't serializable, so we reconstruct\n // them into an object. We discard the `target` property because\n // it's large and not that useful\n if (isErrorEvent(cause)) {\n this.cause = {\n type: cause.type,\n message: cause.message,\n error: serializeError(cause.error),\n } as ErrorEvent;\n } else if (isCloseEvent(cause)) {\n this.cause = {\n type: cause.type,\n code: cause.code,\n reason: cause.reason,\n wasClean: cause.wasClean,\n } as CloseEvent;\n } else {\n assert(\n isString(cause) || isError(cause) || isGraphQLErrors(cause),\n \"cause must be a string, Error, GraphQLError[], CloseEvent, or ErrorEvent\",\n );\n this.cause = cause;\n }\n }\n\n override render(): string {\n let body = \"\";\n\n switch (true) {\n case isGraphQLErrors(this.cause): {\n const errors = uniq(this.cause.map((x) => x.message));\n body = sprint`\n Gadget responded with the following ${pluralize(\"error\", errors.length, false)}:\n\n • ${errors.join(\"\\n • \")}\n `;\n break;\n }\n case isCloseEvent(this.cause):\n body = \"The connection to Gadget closed unexpectedly.\";\n break;\n case isErrorEvent(this.cause) || isError(this.cause):\n body = this.cause.message;\n break;\n default:\n body = this.cause;\n break;\n }\n\n return this.message + \"\\n\\n\" + body;\n }\n}\n\n/**\n * A GraphQL query with its associated types.\n *\n * At runtime, this type is just a string.\n */\nexport type GraphQLQuery<\n Data extends JsonObject = JsonObject,\n Variables extends JsonObject = JsonObject,\n Extensions extends JsonObject = JsonObject,\n Result extends ExecutionResult<Data, Extensions> = ExecutionResult<Data, Extensions>,\n> = string & {\n Data: Data;\n Variables: Variables;\n Extensions: Extensions;\n Result: Result;\n};\n\nexport const REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = sprint(/* GraphQL */ `\n subscription RemoteFileSyncEvents($localFilesVersion: String!) {\n remoteFileSyncEvents(localFilesVersion: $localFilesVersion, encoding: base64) {\n remoteFilesVersion\n changed {\n path\n mode\n content\n encoding\n }\n deleted {\n path\n }\n }\n }\n`) as GraphQLQuery<RemoteFileSyncEventsSubscription, RemoteFileSyncEventsSubscriptionVariables>;\n\nexport type REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION = typeof REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION;\n\nexport const REMOTE_FILES_VERSION_QUERY = sprint(/* GraphQL */ `\n query RemoteFilesVersion {\n remoteFilesVersion\n }\n`) as GraphQLQuery<RemoteFilesVersionQuery, RemoteFilesVersionQueryVariables>;\n\nexport type REMOTE_FILES_VERSION_QUERY = typeof REMOTE_FILES_VERSION_QUERY;\n\nexport const PUBLISH_FILE_SYNC_EVENTS_MUTATION = sprint(/* GraphQL */ `\n mutation PublishFileSyncEvents($input: PublishFileSyncEventsInput!) {\n publishFileSyncEvents(input: $input) {\n remoteFilesVersion\n }\n }\n`) as GraphQLQuery<PublishFileSyncEventsMutation, PublishFileSyncEventsMutationVariables>;\n\nexport type PUBLISH_FILE_SYNC_EVENTS_MUTATION = typeof PUBLISH_FILE_SYNC_EVENTS_MUTATION;\n\nexport const FILE_SYNC_FILES_QUERY = sprint(/* GraphQL */ `\n query FileSyncFiles($paths: [String!]!, $filesVersion: String, $encoding: FileSyncEncoding) {\n fileSyncFiles(paths: $paths, filesVersion: $filesVersion, encoding: $encoding) {\n filesVersion\n files {\n path\n mode\n content\n encoding\n }\n }\n }\n`) as GraphQLQuery<FileSyncFilesQuery, FileSyncFilesQueryVariables>;\n\nexport type FILE_SYNC_FILES_QUERY = typeof FILE_SYNC_FILES_QUERY;\n\nexport const FILE_SYNC_HASHES_QUERY = sprint(/* GraphQL */ `\n query FileSyncHashes($filesVersion: String) {\n fileSyncHashes(filesVersion: $filesVersion) {\n filesVersion\n hashes\n }\n }\n`) as GraphQLQuery<FileSyncHashesQuery, FileSyncHashesQueryVariables>;\n\nexport type FILE_SYNC_HASHES_QUERY = typeof FILE_SYNC_HASHES_QUERY;\n\nexport const FILE_SYNC_COMPARISON_HASHES_QUERY = sprint(/* GraphQL */ `\n query FileSyncComparisonHashes($filesVersion: String!) {\n fileSyncComparisonHashes(filesVersion: $filesVersion) {\n filesVersionHashes {\n filesVersion\n hashes\n }\n latestFilesVersionHashes {\n filesVersion\n hashes\n }\n }\n }\n`) as GraphQLQuery<FileSyncComparisonHashesQuery, FileSyncComparisonHashesQueryVariables>;\n\nexport type FILE_SYNC_COMPARISON_HASHES_QUERY = typeof FILE_SYNC_COMPARISON_HASHES_QUERY;\n\nexport const REMOTE_SERVER_CONTRACT_STATUS_SUBSCRIPTION = sprint(/* GraphQL */ `\n subscription publishStatus($localFilesVersion: String!, $force: Boolean) {\n publishStatus(localFilesVersion: $localFilesVersion, force: $force) {\n remoteFilesVersion\n progress\n issues {\n severity\n message\n node {\n type\n key\n name\n fieldType\n parentKey\n parentApiIdentifier\n }\n }\n }\n }\n`) as GraphQLQuery<PublishStatusSubscription, PublishStatusSubscriptionVariables>;\n\nexport type REMOTE_SERVER_CONTRACT_STATUS_SUBSCRIPTION = typeof REMOTE_SERVER_CONTRACT_STATUS_SUBSCRIPTION;\n"],"names":["createClient","assert","PQueue","pluralize","WebSocket","config","loadCookie","http","createLogger","CLIError","IsBug","sprint","uniq","noop","unthunk","isCloseEvent","isError","isErrorEvent","isGraphQLErrors","isObject","isString","serializeError","ConnectionStatus","log","name","EditGraphQL","subscribe","onData","options","unsubscribe","_subscribe","onResult","result","errors","onError","EditGraphQLError","query","data","variables","_query","dispose","_client","optionsOnError","onComplete","payload","type","operation","split","removeConnectedListener","on","status","info","queue","concurrency","error","next","add","catch","complete","input","cookie","subdomain","app","slug","hasSplitEnvironments","json","method","url","domains","headers","responseType","resolveBodyOnly","throwHttpErrors","constructor","shouldRetry","webSocketImpl","address","protocols","wsOptions","versionFull","connecting","connected","setImmediate","closed","e","event","wasClean","render","body","cause","map","x","message","length","join","isBug","MAYBE","code","reason","REMOTE_FILE_SYNC_EVENTS_SUBSCRIPTION","REMOTE_FILES_VERSION_QUERY","PUBLISH_FILE_SYNC_EVENTS_MUTATION","FILE_SYNC_FILES_QUERY","FILE_SYNC_HASHES_QUERY","FILE_SYNC_COMPARISON_HASHES_QUERY","REMOTE_SERVER_CONTRACT_STATUS_SUBSCRIPTION"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import arg from "arg";
|
|
3
|
+
import { CLIError, IsBug, UnexpectedError } from "../output/report.js";
|
|
4
|
+
import { isNil } from "../util/is.js";
|
|
5
|
+
export const parseArgs = (args, options)=>{
|
|
6
|
+
const realSpec = {};
|
|
7
|
+
const defaultValues = {};
|
|
8
|
+
for (const [key, value] of Object.entries(args)){
|
|
9
|
+
if (!("type" in value)) {
|
|
10
|
+
realSpec[key] = value;
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
realSpec[key] = value.type;
|
|
14
|
+
defaultValues[key] = value.default;
|
|
15
|
+
if (value.alias) {
|
|
16
|
+
for (const alias of Array.isArray(value.alias) ? value.alias : [
|
|
17
|
+
value.alias
|
|
18
|
+
]){
|
|
19
|
+
realSpec[alias] = key;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const parsed = arg(realSpec, options);
|
|
25
|
+
for (const [key, value] of Object.entries(defaultValues)){
|
|
26
|
+
if (isNil(parsed[key])) {
|
|
27
|
+
parsed[key] = value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return parsed;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (error instanceof arg.ArgError) {
|
|
33
|
+
// convert arg.ArgError to CLIError
|
|
34
|
+
// eslint-disable-next-line no-ex-assign
|
|
35
|
+
error = new ArgError(error.message);
|
|
36
|
+
}
|
|
37
|
+
if (error instanceof CLIError) {
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
throw new UnexpectedError(error);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export class ArgError extends CLIError {
|
|
44
|
+
render() {
|
|
45
|
+
return this.message;
|
|
46
|
+
}
|
|
47
|
+
constructor(...args){
|
|
48
|
+
super(...args);
|
|
49
|
+
_define_property(this, "isBug", IsBug.NO);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=arg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/command/arg.ts"],"sourcesContent":["import arg from \"arg\";\nimport type { Simplify } from \"type-fest\";\nimport { CLIError, IsBug, UnexpectedError } from \"../output/report.js\";\nimport { isNil } from \"../util/is.js\";\n\nexport type ArgsSpec = Record<string, ArgDefinition>;\n\ntype ArgDefinition<Handler extends arg.Handler = arg.Handler> =\n | Handler\n | {\n type: Handler;\n alias?: string | string[];\n default?: ReturnType<Handler>;\n };\n\nexport const parseArgs = <Args extends ArgsSpec>(args: Args, options?: arg.Options): ArgsSpecResult<Args> => {\n const realSpec: arg.Spec = {};\n const defaultValues: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(args)) {\n if (!(\"type\" in value)) {\n realSpec[key] = value;\n continue;\n }\n\n realSpec[key] = value.type;\n defaultValues[key] = value.default;\n\n if (value.alias) {\n for (const alias of Array.isArray(value.alias) ? value.alias : [value.alias]) {\n realSpec[alias] = key;\n }\n }\n }\n\n try {\n const parsed = arg(realSpec, options);\n for (const [key, value] of Object.entries(defaultValues)) {\n if (isNil(parsed[key])) {\n parsed[key] = value as never;\n }\n }\n return parsed as ArgsSpecResult<Args>;\n } catch (error: unknown) {\n if (error instanceof arg.ArgError) {\n // convert arg.ArgError to CLIError\n // eslint-disable-next-line no-ex-assign\n error = new ArgError(error.message);\n }\n if (error instanceof CLIError) {\n throw error;\n }\n throw new UnexpectedError(error);\n }\n};\n\nexport class ArgError extends CLIError {\n isBug = IsBug.NO;\n\n protected override render(): string {\n return this.message;\n }\n}\n\nexport type ArgsSpecResult<Spec extends ArgsSpec, Args extends keyof Spec = keyof Spec> = Simplify<{\n [Arg in Args]: Spec[Arg] extends ArgDefinition<infer Handler>\n ? Spec[Arg] extends { default: unknown }\n ? NonNullable<ReturnType<Handler>>\n : ReturnType<Handler> | undefined\n : never;\n}> & { _: string[] };\n"],"names":["arg","CLIError","IsBug","UnexpectedError","isNil","parseArgs","args","options","realSpec","defaultValues","key","value","Object","entries","type","default","alias","Array","isArray","parsed","error","ArgError","message","render","isBug","NO"],"mappings":";AAAA,OAAOA,SAAS,MAAM;AAEtB,SAASC,QAAQ,EAAEC,KAAK,EAAEC,eAAe,QAAQ,sBAAsB;AACvE,SAASC,KAAK,QAAQ,gBAAgB;AAYtC,OAAO,MAAMC,YAAY,CAAwBC,MAAYC;IAC3D,MAAMC,WAAqB,CAAC;IAC5B,MAAMC,gBAAyC,CAAC;IAEhD,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACP,MAAO;QAC/C,IAAI,CAAE,CAAA,UAAUK,KAAI,GAAI;YACtBH,QAAQ,CAACE,IAAI,GAAGC;YAChB;QACF;QAEAH,QAAQ,CAACE,IAAI,GAAGC,MAAMG,IAAI;QAC1BL,aAAa,CAACC,IAAI,GAAGC,MAAMI,OAAO;QAElC,IAAIJ,MAAMK,KAAK,EAAE;YACf,KAAK,MAAMA,SAASC,MAAMC,OAAO,CAACP,MAAMK,KAAK,IAAIL,MAAMK,KAAK,GAAG;gBAACL,MAAMK,KAAK;aAAC,CAAE;gBAC5ER,QAAQ,CAACQ,MAAM,GAAGN;YACpB;QACF;IACF;IAEA,IAAI;QACF,MAAMS,SAASnB,IAAIQ,UAAUD;QAC7B,KAAK,MAAM,CAACG,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACJ,eAAgB;YACxD,IAAIL,MAAMe,MAAM,CAACT,IAAI,GAAG;gBACtBS,MAAM,CAACT,IAAI,GAAGC;YAChB;QACF;QACA,OAAOQ;IACT,EAAE,OAAOC,OAAgB;QACvB,IAAIA,iBAAiBpB,IAAIqB,QAAQ,EAAE;YACjC,mCAAmC;YACnC,wCAAwC;YACxCD,QAAQ,IAAIC,SAASD,MAAME,OAAO;QACpC;QACA,IAAIF,iBAAiBnB,UAAU;YAC7B,MAAMmB;QACR;QACA,MAAM,IAAIjB,gBAAgBiB;IAC5B;AACF,EAAE;AAEF,OAAO,MAAMC,iBAAiBpB;IAGTsB,SAAiB;QAClC,OAAO,IAAI,CAACD,OAAO;IACrB;;;QAJAE,uBAAAA,SAAQtB,MAAMuB,EAAE;;AAKlB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/consistent-type-imports */ import assert from "node:assert";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import { config } from "../config/config.js";
|
|
4
|
+
import { relativeToThisFile } from "../util/paths.js";
|
|
5
|
+
export const AvailableCommands = [
|
|
6
|
+
"sync",
|
|
7
|
+
"deploy",
|
|
8
|
+
"list",
|
|
9
|
+
"login",
|
|
10
|
+
"logout",
|
|
11
|
+
"whoami",
|
|
12
|
+
"version"
|
|
13
|
+
];
|
|
14
|
+
export const isAvailableCommand = (command)=>{
|
|
15
|
+
return AvailableCommands.includes(command);
|
|
16
|
+
};
|
|
17
|
+
export const importCommand = async (cmd)=>{
|
|
18
|
+
assert(isAvailableCommand(cmd), `invalid command: ${cmd}`);
|
|
19
|
+
let commandPath = relativeToThisFile(`../../commands/${cmd}.js`);
|
|
20
|
+
if (config.windows) {
|
|
21
|
+
// https://github.com/nodejs/node/issues/31710
|
|
22
|
+
commandPath = pathToFileURL(commandPath).toString();
|
|
23
|
+
}
|
|
24
|
+
return await import(commandPath);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/command/command.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/consistent-type-imports */\nimport assert from \"node:assert\";\nimport { pathToFileURL } from \"node:url\";\nimport type { Promisable } from \"type-fest\";\nimport type { rootArgs } from \"../../commands/root.js\";\nimport { config } from \"../config/config.js\";\nimport { relativeToThisFile } from \"../util/paths.js\";\nimport type { ArgsSpec } from \"./arg.js\";\nimport type { Context } from \"./context.js\";\n\nexport const AvailableCommands = [\"sync\", \"deploy\", \"list\", \"login\", \"logout\", \"whoami\", \"version\"] as const;\n\nexport type AvailableCommand = (typeof AvailableCommands)[number];\n\nexport const isAvailableCommand = (command: string): command is AvailableCommand => {\n return AvailableCommands.includes(command as AvailableCommand);\n};\n\nexport const importCommand = async (cmd: AvailableCommand): Promise<CommandSpec> => {\n assert(isAvailableCommand(cmd), `invalid command: ${cmd}`);\n let commandPath = relativeToThisFile(`../../commands/${cmd}.js`);\n if (config.windows) {\n // https://github.com/nodejs/node/issues/31710\n commandPath = pathToFileURL(commandPath).toString();\n }\n return (await import(commandPath)) as CommandSpec;\n};\n\nexport type CommandSpec<Args extends ArgsSpec = ArgsSpec, ParentArgsSpec extends ArgsSpec = typeof rootArgs> = {\n args?: Args;\n usage: () => string;\n command: (ctx: Context<Args, ParentArgsSpec>) => Promisable<void>;\n};\n\nexport type Command<Spec extends ArgsSpec = ArgsSpec, ParentSpec extends ArgsSpec = typeof rootArgs> = CommandSpec<\n Spec,\n ParentSpec\n>[\"command\"];\n\nexport type Usage = CommandSpec[\"usage\"];\n"],"names":["assert","pathToFileURL","config","relativeToThisFile","AvailableCommands","isAvailableCommand","command","includes","importCommand","cmd","commandPath","windows","toString"],"mappings":"AAAA,6DAA6D,GAC7D,OAAOA,YAAY,cAAc;AACjC,SAASC,aAAa,QAAQ,WAAW;AAGzC,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,kBAAkB,QAAQ,mBAAmB;AAItD,OAAO,MAAMC,oBAAoB;IAAC;IAAQ;IAAU;IAAQ;IAAS;IAAU;IAAU;CAAU,CAAU;AAI7G,OAAO,MAAMC,qBAAqB,CAACC;IACjC,OAAOF,kBAAkBG,QAAQ,CAACD;AACpC,EAAE;AAEF,OAAO,MAAME,gBAAgB,OAAOC;IAClCT,OAAOK,mBAAmBI,MAAM,CAAC,iBAAiB,EAAEA,IAAI,CAAC;IACzD,IAAIC,cAAcP,mBAAmB,CAAC,eAAe,EAAEM,IAAI,GAAG,CAAC;IAC/D,IAAIP,OAAOS,OAAO,EAAE;QAClB,8CAA8C;QAC9CD,cAAcT,cAAcS,aAAaE,QAAQ;IACnD;IACA,OAAQ,MAAM,MAAM,CAACF;AACvB,EAAE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { createLogger } from "../output/log/logger.js";
|
|
4
|
+
import { isFunction } from "../util/is.js";
|
|
5
|
+
import { parseArgs } from "./arg.js";
|
|
6
|
+
export class Context extends AbortController {
|
|
7
|
+
extend({ args = {}, logName }) {
|
|
8
|
+
const ctx = new Context(args, {
|
|
9
|
+
args: this.args,
|
|
10
|
+
logName
|
|
11
|
+
});
|
|
12
|
+
this.onAbort(()=>ctx.abort());
|
|
13
|
+
return ctx;
|
|
14
|
+
}
|
|
15
|
+
onAbort(callbackOrOptions, callback) {
|
|
16
|
+
let options = {
|
|
17
|
+
once: true
|
|
18
|
+
};
|
|
19
|
+
if (isFunction(callbackOrOptions)) {
|
|
20
|
+
callback = callbackOrOptions;
|
|
21
|
+
} else {
|
|
22
|
+
options = {
|
|
23
|
+
...options,
|
|
24
|
+
...callbackOrOptions
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
this.signal.addEventListener("abort", // eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
28
|
+
async ()=>{
|
|
29
|
+
try {
|
|
30
|
+
assert(callback, "callback must have been provided");
|
|
31
|
+
await callback(this.signal.reason);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
this.log.error("error during cancel", {
|
|
34
|
+
error
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}, options);
|
|
38
|
+
}
|
|
39
|
+
constructor(args, options){
|
|
40
|
+
super();
|
|
41
|
+
_define_property(this, "log", void 0);
|
|
42
|
+
_define_property(this, "args", void 0);
|
|
43
|
+
if (options?.args) {
|
|
44
|
+
assert(!options.argv, "argv and args cannot be used together");
|
|
45
|
+
options.argv = options.args._;
|
|
46
|
+
}
|
|
47
|
+
this.args = {
|
|
48
|
+
...options?.args,
|
|
49
|
+
...parseArgs(args, options)
|
|
50
|
+
};
|
|
51
|
+
this.log = createLogger({
|
|
52
|
+
name: options?.logName || "context",
|
|
53
|
+
fields: {
|
|
54
|
+
args: this.args
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/command/context.ts"],"sourcesContent":["import type arg from \"arg\";\nimport assert from \"node:assert\";\nimport type { rootArgs } from \"../../commands/root.js\";\nimport { createLogger, type Logger } from \"../output/log/logger.js\";\nimport type { AnyVoid } from \"../util/function.js\";\nimport { isFunction } from \"../util/is.js\";\nimport { parseArgs, type ArgsSpec, type ArgsSpecResult } from \"./arg.js\";\n\nexport class Context<\n Args extends ArgsSpec = ArgsSpec,\n ParentArgs extends ArgsSpec = typeof rootArgs,\n AllArgs extends ArgsSpec = Args & ParentArgs,\n> extends AbortController {\n readonly log: Logger;\n\n readonly args: ArgsSpecResult<AllArgs>;\n\n constructor(args: Args, options?: arg.Options & { args?: ArgsSpecResult<ParentArgs>; logName?: string }) {\n super();\n if (options?.args) {\n assert(!options.argv, \"argv and args cannot be used together\");\n options.argv = options.args._;\n }\n this.args = { ...options?.args, ...parseArgs(args, options) } as ArgsSpecResult<AllArgs>;\n this.log = createLogger({ name: options?.logName || \"context\", fields: { args: this.args } });\n }\n\n extend<ExtendedArgs extends ArgsSpec>({\n args = {} as ExtendedArgs,\n logName,\n }: {\n args?: ExtendedArgs;\n logName?: string;\n }): Context<ExtendedArgs, AllArgs> {\n const ctx = new Context(args, { args: this.args, logName });\n this.onAbort(() => ctx.abort());\n return ctx;\n }\n\n onAbort(callback: OnAbort): void;\n onAbort(options: { once?: boolean }, callback: OnAbort): void;\n onAbort(callbackOrOptions: { once?: boolean } | OnAbort, callback?: OnAbort): void {\n let options = { once: true };\n if (isFunction(callbackOrOptions)) {\n callback = callbackOrOptions;\n } else {\n options = { ...options, ...callbackOrOptions };\n }\n\n this.signal.addEventListener(\n \"abort\",\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => {\n try {\n assert(callback, \"callback must have been provided\");\n await callback(this.signal.reason);\n } catch (error: unknown) {\n this.log.error(\"error during cancel\", { error });\n }\n },\n options,\n );\n }\n}\n\nexport type OnAbort = (reason: unknown) => AnyVoid;\n"],"names":["assert","createLogger","isFunction","parseArgs","Context","AbortController","extend","args","logName","ctx","onAbort","abort","callbackOrOptions","callback","options","once","signal","addEventListener","reason","error","log","constructor","argv","_","name","fields"],"mappings":";AACA,OAAOA,YAAY,cAAc;AAEjC,SAASC,YAAY,QAAqB,0BAA0B;AAEpE,SAASC,UAAU,QAAQ,gBAAgB;AAC3C,SAASC,SAAS,QAA4C,WAAW;AAEzE,OAAO,MAAMC,gBAIHC;IAeRC,OAAsC,EACpCC,OAAO,CAAC,CAAiB,EACzBC,OAAO,EAIR,EAAkC;QACjC,MAAMC,MAAM,IAAIL,QAAQG,MAAM;YAAEA,MAAM,IAAI,CAACA,IAAI;YAAEC;QAAQ;QACzD,IAAI,CAACE,OAAO,CAAC,IAAMD,IAAIE,KAAK;QAC5B,OAAOF;IACT;IAIAC,QAAQE,iBAA+C,EAAEC,QAAkB,EAAQ;QACjF,IAAIC,UAAU;YAAEC,MAAM;QAAK;QAC3B,IAAIb,WAAWU,oBAAoB;YACjCC,WAAWD;QACb,OAAO;YACLE,UAAU;gBAAE,GAAGA,OAAO;gBAAE,GAAGF,iBAAiB;YAAC;QAC/C;QAEA,IAAI,CAACI,MAAM,CAACC,gBAAgB,CAC1B,SACA,kEAAkE;QAClE;YACE,IAAI;gBACFjB,OAAOa,UAAU;gBACjB,MAAMA,SAAS,IAAI,CAACG,MAAM,CAACE,MAAM;YACnC,EAAE,OAAOC,OAAgB;gBACvB,IAAI,CAACC,GAAG,CAACD,KAAK,CAAC,uBAAuB;oBAAEA;gBAAM;YAChD;QACF,GACAL;IAEJ;IA7CAO,YAAYd,IAAU,EAAEO,OAA+E,CAAE;QACvG,KAAK;QALP,uBAASM,OAAT,KAAA;QAEA,uBAASb,QAAT,KAAA;QAIE,IAAIO,SAASP,MAAM;YACjBP,OAAO,CAACc,QAAQQ,IAAI,EAAE;YACtBR,QAAQQ,IAAI,GAAGR,QAAQP,IAAI,CAACgB,CAAC;QAC/B;QACA,IAAI,CAAChB,IAAI,GAAG;YAAE,GAAGO,SAASP,IAAI;YAAE,GAAGJ,UAAUI,MAAMO,QAAQ;QAAC;QAC5D,IAAI,CAACM,GAAG,GAAGnB,aAAa;YAAEuB,MAAMV,SAASN,WAAW;YAAWiB,QAAQ;gBAAElB,MAAM,IAAI,CAACA,IAAI;YAAC;QAAE;IAC7F;AAsCF"}
|