@gadgetinc/ggt 1.0.1 → 1.0.3

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 (100) hide show
  1. package/README.md +192 -128
  2. package/lib/__generated__/graphql.js.map +1 -1
  3. package/lib/commands/add.js +385 -0
  4. package/lib/commands/add.js.map +1 -0
  5. package/lib/commands/deploy.js +20 -102
  6. package/lib/commands/deploy.js.map +1 -1
  7. package/lib/commands/dev.js +43 -114
  8. package/lib/commands/dev.js.map +1 -1
  9. package/lib/commands/list.js +3 -6
  10. package/lib/commands/list.js.map +1 -1
  11. package/lib/commands/login.js +2 -5
  12. package/lib/commands/login.js.map +1 -1
  13. package/lib/commands/logout.js +2 -5
  14. package/lib/commands/logout.js.map +1 -1
  15. package/lib/commands/open.js +45 -86
  16. package/lib/commands/open.js.map +1 -1
  17. package/lib/commands/pull.js +19 -76
  18. package/lib/commands/pull.js.map +1 -1
  19. package/lib/commands/push.js +19 -76
  20. package/lib/commands/push.js.map +1 -1
  21. package/lib/commands/root.js +4 -3
  22. package/lib/commands/root.js.map +1 -1
  23. package/lib/commands/status.js +3 -8
  24. package/lib/commands/status.js.map +1 -1
  25. package/lib/commands/version.js +6 -5
  26. package/lib/commands/version.js.map +1 -1
  27. package/lib/commands/whoami.js +2 -5
  28. package/lib/commands/whoami.js.map +1 -1
  29. package/lib/ggt.js.map +1 -1
  30. package/lib/main.js.map +1 -1
  31. package/lib/services/app/api/api.js.map +1 -1
  32. package/lib/services/app/api/operation.js +11 -0
  33. package/lib/services/app/api/operation.js.map +1 -1
  34. package/lib/services/app/app.js +21 -2
  35. package/lib/services/app/app.js.map +1 -1
  36. package/lib/services/app/arg.js.map +1 -1
  37. package/lib/services/app/client.js +1 -5
  38. package/lib/services/app/client.js.map +1 -1
  39. package/lib/services/app/edit/edit.js.map +1 -1
  40. package/lib/services/app/edit/operation.js +52 -0
  41. package/lib/services/app/edit/operation.js.map +1 -1
  42. package/lib/services/app/error.js.map +1 -1
  43. package/lib/services/command/arg.js +3 -1
  44. package/lib/services/command/arg.js.map +1 -1
  45. package/lib/services/command/command.js +1 -0
  46. package/lib/services/command/command.js.map +1 -1
  47. package/lib/services/command/context.js.map +1 -1
  48. package/lib/services/config/config.js.map +1 -1
  49. package/lib/services/config/env.js.map +1 -1
  50. package/lib/services/config/package-json.js.map +1 -1
  51. package/lib/services/filesync/changes.js.map +1 -1
  52. package/lib/services/filesync/conflicts.js.map +1 -1
  53. package/lib/services/filesync/directory.js.map +1 -1
  54. package/lib/services/filesync/error.js +1 -0
  55. package/lib/services/filesync/error.js.map +1 -1
  56. package/lib/services/filesync/file.js.map +1 -1
  57. package/lib/services/filesync/filesync.js +179 -174
  58. package/lib/services/filesync/filesync.js.map +1 -1
  59. package/lib/services/filesync/hashes.js.map +1 -1
  60. package/lib/services/filesync/strategy.js.map +1 -1
  61. package/lib/services/filesync/sync-json.js.map +1 -1
  62. package/lib/services/http/auth.js.map +1 -1
  63. package/lib/services/http/http.js.map +1 -1
  64. package/lib/services/output/confirm.js.map +1 -1
  65. package/lib/services/output/footer.js.map +1 -1
  66. package/lib/services/output/log/field.js.map +1 -1
  67. package/lib/services/output/log/format/format.js.map +1 -1
  68. package/lib/services/output/log/format/json.js.map +1 -1
  69. package/lib/services/output/log/format/pretty.js.map +1 -1
  70. package/lib/services/output/log/level.js.map +1 -1
  71. package/lib/services/output/log/logger.js.map +1 -1
  72. package/lib/services/output/log/structured.js.map +1 -1
  73. package/lib/services/output/notify.js.map +1 -1
  74. package/lib/services/output/output.js.map +1 -1
  75. package/lib/services/output/print.js.map +1 -1
  76. package/lib/services/output/problems.js.map +1 -1
  77. package/lib/services/output/prompt.js.map +1 -1
  78. package/lib/services/output/report.js.map +1 -1
  79. package/lib/services/output/select.js.map +1 -1
  80. package/lib/services/output/spinner.js.map +1 -1
  81. package/lib/services/output/sprint.js.map +1 -1
  82. package/lib/services/output/symbols.js.map +1 -1
  83. package/lib/services/output/table.js.map +1 -1
  84. package/lib/services/output/timestamp.js.map +1 -1
  85. package/lib/services/output/update.js.map +1 -1
  86. package/lib/services/user/session.js.map +1 -1
  87. package/lib/services/user/user.js.map +1 -1
  88. package/lib/services/util/assert.js.map +1 -1
  89. package/lib/services/util/boolean.js.map +1 -1
  90. package/lib/services/util/collection.js.map +1 -1
  91. package/lib/services/util/function.js.map +1 -1
  92. package/lib/services/util/is.js.map +1 -1
  93. package/lib/services/util/json.js.map +1 -1
  94. package/lib/services/util/number.js.map +1 -1
  95. package/lib/services/util/object.js.map +1 -1
  96. package/lib/services/util/paths.js.map +1 -1
  97. package/lib/services/util/promise.js.map +1 -1
  98. package/lib/services/util/types.js.map +1 -1
  99. package/npm-shrinkwrap.json +2071 -1684
  100. package/package.json +30 -30
@@ -0,0 +1,385 @@
1
+ /* eslint-disable no-case-declarations */ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ import chalk from "chalk";
3
+ import terminalLink from "terminal-link";
4
+ import { getGlobalActions, getModels } from "../services/app/app.js";
5
+ import { CREATE_ACTION_MUTATION, CREATE_MODEL_FIELDS_MUTATION, CREATE_MODEL_MUTATION, CREATE_ROUTE_MUTATION } from "../services/app/edit/operation.js";
6
+ import { ClientError } from "../services/app/error.js";
7
+ import { ArgError } from "../services/command/arg.js";
8
+ import { UnknownDirectoryError } from "../services/filesync/error.js";
9
+ import { FileSync } from "../services/filesync/filesync.js";
10
+ import { SyncJson, SyncJsonArgs, loadSyncJsonDirectory } from "../services/filesync/sync-json.js";
11
+ import { println } from "../services/output/print.js";
12
+ import { GGTError, IsBug } from "../services/output/report.js";
13
+ import { select } from "../services/output/select.js";
14
+ import { sprint } from "../services/output/sprint.js";
15
+ import { symbol } from "../services/output/symbols.js";
16
+ import { ts } from "../services/output/timestamp.js";
17
+ import { uniq } from "../services/util/collection.js";
18
+ import { isGraphQLErrors } from "../services/util/is.js";
19
+ export class AddClientError extends GGTError {
20
+ render() {
21
+ return `${chalk.redBright(symbol.cross)} Failed to add:\n ` + this.message;
22
+ }
23
+ constructor(error){
24
+ let template = "";
25
+ if (isGraphQLErrors(error.cause)) {
26
+ const errors = uniq(error.cause.map((x)=>x.message));
27
+ template = sprint` • ${errors.map((e)=>e.split("\n").join("\n‎ • ")).join("\n")}`; // Why in gods name do I have to put an empty character for the tab to work?
28
+ } else {
29
+ template = sprint`${error.cause}`;
30
+ }
31
+ super(template);
32
+ _define_property(this, "isBug", IsBug.NO);
33
+ }
34
+ }
35
+ export const args = {
36
+ ...SyncJsonArgs
37
+ };
38
+ export const usage = ()=>{
39
+ return sprint`
40
+ Adds models, fields, actions and routes to your app.
41
+
42
+ This command first performs a sync to ensure that your local and environment directories match, changes are tracked since last sync.
43
+ If any conflicts are detected, they must be resolved before adding models, fields, actions or routes.
44
+
45
+ {gray Usage}
46
+ ggt add model <model_name> [field_name:field_type ...]
47
+
48
+ ggt add action [CONTEXT]/<action_name>
49
+ CONTEXT:Specifies the kind of action. Use "model" for model actions otherwise use "action".
50
+
51
+ ggt add route <HTTP_METHOD> <route_path>
52
+
53
+ ggt add field <model_path>/<field_name>:<field_type>
54
+
55
+ {gray Options}
56
+ -e, --env <env_name> Selects the environment to add to. Default set on ".gadget/sync.json"
57
+
58
+ {gray Examples}
59
+ Add a new model 'post' with out fields:
60
+ {cyanBright $ ggt add model modelA}
61
+
62
+ Add a new model 'post' with 2 new 'string' type fields 'title' and 'body':
63
+ {cyanBright $ ggt add model post title:string body:string}
64
+
65
+ Add new action 'publish' to the 'post' model:
66
+ {cyanBright ggt add action model/post/publish}
67
+
68
+ Add a new action 'audit'
69
+ {cyanBright ggt add action action/audit}
70
+
71
+ Add a new route 'howdy'
72
+ {cyanBright ggt add route GET howdy}
73
+
74
+ Add a new 'boolean' type field 'published' to an existing model
75
+ {cyanBright ggt add field post/published:boolean}
76
+ `;
77
+ };
78
+ export const command = async (ctx)=>{
79
+ const directory = await loadSyncJsonDirectory(process.cwd());
80
+ const syncJson = await SyncJson.load(ctx, {
81
+ directory
82
+ });
83
+ if (!syncJson) {
84
+ throw new UnknownDirectoryError(ctx, {
85
+ directory
86
+ });
87
+ }
88
+ const filesync = new FileSync(syncJson);
89
+ const hashes = await filesync.hashes(ctx, true);
90
+ if (!hashes.inSync) {
91
+ await filesync.merge(ctx, {
92
+ hashes,
93
+ printEnvironmentChangesOptions: {
94
+ limit: 5
95
+ },
96
+ printLocalChangesOptions: {
97
+ limit: 5
98
+ },
99
+ quietly: true
100
+ });
101
+ }
102
+ println({
103
+ ensureEmptyLineAbove: true
104
+ })`${chalk.greenBright(symbol.tick)} Sync completed ${ts()}`;
105
+ const actionType = ctx.args._[0];
106
+ if (!actionType) {
107
+ println(usage(ctx));
108
+ return;
109
+ }
110
+ switch(actionType){
111
+ case "model":
112
+ await modelSubCommand(ctx, filesync);
113
+ break;
114
+ case "action":
115
+ await actionSubCommand(ctx, filesync);
116
+ break;
117
+ case "route":
118
+ await routeSubCommand(ctx, filesync);
119
+ break;
120
+ case "field":
121
+ await fieldSubCommand(ctx, filesync);
122
+ break;
123
+ default:
124
+ println(usage(ctx));
125
+ return;
126
+ }
127
+ };
128
+ const addActionType = [
129
+ "model",
130
+ "action",
131
+ "route",
132
+ "field"
133
+ ];
134
+ const parseFieldValues = (fields)=>{
135
+ const problems = [];
136
+ const modelFields = [];
137
+ fields.forEach((field)=>{
138
+ const matches = field.match(/^(.*):+(.*)$/);
139
+ if (!matches || matches.length !== 3 || !matches[1] || !matches[2]) {
140
+ problems.push(sprint`${field} is not a valid field definition`);
141
+ } else {
142
+ modelFields.push({
143
+ name: matches[1].replace(/:+/g, ""),
144
+ fieldType: matches[2]
145
+ });
146
+ }
147
+ });
148
+ return [
149
+ modelFields,
150
+ problems
151
+ ];
152
+ };
153
+ const modelSubCommand = async (ctx, filesync)=>{
154
+ const syncJson = filesync.syncJson;
155
+ const modelApiIdentifier = ctx.args._[1];
156
+ if (!modelApiIdentifier) {
157
+ throw new ArgError(sprint`Failed to add model, missing model path
158
+
159
+ {gray Usage}
160
+ {cyanBright ggt add model <model_name> [field_name:field_type ...]}`);
161
+ }
162
+ const modelFieldsList = [];
163
+ if (ctx.args._.length > 2) {
164
+ const [modelFields, problems] = parseFieldValues(ctx.args._.slice(2));
165
+ if (problems.length > 0) {
166
+ throw new ArgError(sprint`
167
+ Failed to add model:
168
+ • ${problems.join("\n • ")}
169
+
170
+ {gray Usage}
171
+ {cyanBright ggt add model ${modelApiIdentifier} [field_name:field_type ...]}`);
172
+ }
173
+ modelFieldsList.push(...modelFields);
174
+ }
175
+ let result;
176
+ try {
177
+ result = (await syncJson.edit.mutate({
178
+ mutation: CREATE_MODEL_MUTATION,
179
+ variables: {
180
+ path: modelApiIdentifier,
181
+ fields: modelFieldsList.map((fields)=>({
182
+ name: fields.name,
183
+ fieldType: fields.fieldType
184
+ }))
185
+ }
186
+ })).createModel;
187
+ } catch (error) {
188
+ if (error instanceof ClientError) {
189
+ throw new AddClientError(error);
190
+ } else {
191
+ throw error;
192
+ }
193
+ }
194
+ println({
195
+ ensureEmptyLineAbove: true
196
+ })`${chalk.gray("New model created in environment.")}`;
197
+ await filesync.writeToLocalFilesystem(ctx, {
198
+ filesVersion: result.remoteFilesVersion,
199
+ files: result.changed,
200
+ delete: []
201
+ });
202
+ const modelPrintout = terminalLink.isSupported ? terminalLink(modelApiIdentifier, `https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/model/${modelApiIdentifier}/schema`) : modelApiIdentifier;
203
+ println({
204
+ ensureEmptyLineAbove: true
205
+ })`${chalk.greenBright(symbol.tick)} Model ${chalk.cyanBright(modelPrintout)} added successfully.`;
206
+ };
207
+ const actionSubCommand = async (ctx, filesync)=>{
208
+ const syncJson = filesync.syncJson;
209
+ const path = ctx.args._[1];
210
+ if (!path) {
211
+ throw new ArgError(sprint`Failed to add action, missing action path
212
+
213
+ {gray Usage}
214
+ {cyanBright ggt add action [CONTEXT]/<action_name>
215
+ CONTEXT:Specifies the kind of action. Use "model" for model actions otherwise use "action".}`);
216
+ }
217
+ const models = await getModels(ctx);
218
+ const globalActions = await getGlobalActions(ctx);
219
+ const splitPath = path.split("/");
220
+ let overrideContextAction;
221
+ const parsedPaths = splitPath.length > 1 ? splitPath.slice(0, splitPath.length - 1) : splitPath;
222
+ const parsedAction = splitPath[splitPath.length - 1];
223
+ const conflictingModel = models.find((model)=>{
224
+ const modelName = parsedPaths[parsedPaths.length - 1];
225
+ return model.apiIdentifier.toUpperCase() === modelName?.toUpperCase() && model.namespace?.join("/") === parsedPaths.slice(0, parsedPaths.length - 1).join("/");
226
+ });
227
+ const conflictingActionNamespace = globalActions.find((action)=>{
228
+ return action.namespace?.join("/") === parsedPaths.join("/");
229
+ });
230
+ if (conflictingModel && conflictingActionNamespace) {
231
+ const joinedParsedPaths = parsedPaths.join("/");
232
+ overrideContextAction = await select({
233
+ choices: Object.values([
234
+ "models",
235
+ "actions"
236
+ ]),
237
+ formatChoice: (choice)=>{
238
+ switch(choice){
239
+ case "models":
240
+ {
241
+ return `As a Model action in ${chalk.gray(`models/${joinedParsedPaths}/${parsedAction}.js`)}`;
242
+ }
243
+ case "actions":
244
+ {
245
+ return `As an Action in ${chalk.gray(`actions/${joinedParsedPaths}/${parsedAction}.js`)}`;
246
+ }
247
+ }
248
+ }
249
+ })`
250
+ {bold Namespace Conflict:} The action '${parsedAction}.js' cannot be automatically added due to a namespace conflict.
251
+
252
+ How would you like to proceed?:
253
+ `;
254
+ println({
255
+ ensureEmptyLineAbove: true
256
+ })`${chalk.yellowBright(symbol.info)} You can override the context of the action by specifying the context in the path. For example: {gray ggt add action ${overrideContextAction}/${path}}`;
257
+ }
258
+ try {
259
+ const result = (await syncJson.edit.mutate({
260
+ mutation: CREATE_ACTION_MUTATION,
261
+ variables: {
262
+ path: overrideContextAction ? `${overrideContextAction}/` + path : path
263
+ }
264
+ })).createAction;
265
+ await filesync.writeToLocalFilesystem(ctx, {
266
+ filesVersion: result.remoteFilesVersion,
267
+ files: result.changed,
268
+ delete: []
269
+ });
270
+ } catch (error) {
271
+ if (error instanceof ClientError) {
272
+ throw new AddClientError(error);
273
+ } else {
274
+ throw error;
275
+ }
276
+ }
277
+ println({
278
+ ensureEmptyLineAbove: true
279
+ })`
280
+ Action {cyanBright ${path}} added successfully.
281
+ `;
282
+ };
283
+ const routeSubCommand = async (ctx, filesync)=>{
284
+ const syncJson = filesync.syncJson;
285
+ const routeMethod = ctx.args._[1];
286
+ const routePath = ctx.args._[2];
287
+ if (!routeMethod) {
288
+ throw new ArgError(sprint`Failed to add route, missing route method
289
+
290
+ {gray Usage}
291
+ {cyanBright ggt add route <HTTP_METHOD> <route_path>}`);
292
+ }
293
+ if (!routePath) {
294
+ throw new ArgError(sprint`Failed to add route, missing route path
295
+
296
+ {gray Usage}
297
+ {cyanBright ggt add route ${routeMethod} <route_path>}`);
298
+ }
299
+ try {
300
+ const result = (await syncJson.edit.mutate({
301
+ mutation: CREATE_ROUTE_MUTATION,
302
+ variables: {
303
+ method: routeMethod,
304
+ path: routePath
305
+ }
306
+ })).createRoute;
307
+ await filesync.writeToLocalFilesystem(ctx, {
308
+ filesVersion: result.remoteFilesVersion,
309
+ files: result.changed,
310
+ delete: []
311
+ });
312
+ } catch (error) {
313
+ if (error instanceof ClientError) {
314
+ throw new AddClientError(error);
315
+ } else {
316
+ throw error;
317
+ }
318
+ }
319
+ println({
320
+ ensureEmptyLineAbove: true
321
+ })`
322
+ Route {cyanBright ${routePath}} added successfully.
323
+ `;
324
+ };
325
+ const fieldSubCommand = async (ctx, filesync)=>{
326
+ const syncJson = filesync.syncJson;
327
+ const splitPathAndField = ctx.args._[1]?.split("/");
328
+ if (!splitPathAndField) {
329
+ throw new ArgError(sprint`Failed to add field, invalid field path definition
330
+
331
+ {gray Usage}
332
+ {cyanBright ggt add field <model_path>/<field_name>:<field_type>}`);
333
+ }
334
+ const modelFieldsList = [];
335
+ if (splitPathAndField[1]) {
336
+ const [modelFields, problems] = parseFieldValues([
337
+ splitPathAndField[1]
338
+ ]);
339
+ if (problems.length > 0) {
340
+ throw new ArgError(sprint`
341
+ Failed to add field:
342
+ • ${problems.join("\n •")}
343
+
344
+ {gray Usage}
345
+ {cyanBright ggt add field ${splitPathAndField[0]}/<field_name>:<field_type>}`);
346
+ }
347
+ modelFieldsList.push(...modelFields);
348
+ } else {
349
+ throw new ArgError(sprint`Failed to add field, invalid field definition
350
+
351
+ {gray Usage}
352
+ {cyanBright ggt add field ${splitPathAndField[0]}/<field_name>:<field_type>}`);
353
+ }
354
+ try {
355
+ const result = (await syncJson.edit.mutate({
356
+ mutation: CREATE_MODEL_FIELDS_MUTATION,
357
+ variables: {
358
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
359
+ path: splitPathAndField[0],
360
+ fields: modelFieldsList.map((field)=>({
361
+ name: field.name,
362
+ fieldType: field.fieldType
363
+ }))
364
+ }
365
+ })).createModelFields;
366
+ await filesync.writeToLocalFilesystem(ctx, {
367
+ filesVersion: result.remoteFilesVersion,
368
+ files: result.changed,
369
+ delete: []
370
+ });
371
+ } catch (error) {
372
+ if (error instanceof ClientError) {
373
+ throw new AddClientError(error);
374
+ } else {
375
+ throw error;
376
+ }
377
+ }
378
+ println({
379
+ ensureEmptyLineAbove: true
380
+ })`
381
+ Field {cyanBright ${modelFieldsList[0]?.name}} added successfully.
382
+ `;
383
+ };
384
+
385
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/add.ts"],"sourcesContent":["/* eslint-disable no-case-declarations */\nimport chalk from \"chalk\";\nimport terminalLink from \"terminal-link\";\nimport { getGlobalActions, getModels } from \"../services/app/app.js\";\nimport {\n CREATE_ACTION_MUTATION,\n CREATE_MODEL_FIELDS_MUTATION,\n CREATE_MODEL_MUTATION,\n CREATE_ROUTE_MUTATION,\n} from \"../services/app/edit/operation.js\";\nimport { ClientError } from \"../services/app/error.js\";\nimport { ArgError } from \"../services/command/arg.js\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport type { Context } from \"../services/command/context.js\";\nimport { UnknownDirectoryError } from \"../services/filesync/error.js\";\nimport { FileSync } from \"../services/filesync/filesync.js\";\nimport { SyncJson, SyncJsonArgs, loadSyncJsonDirectory } from \"../services/filesync/sync-json.js\";\nimport { println } from \"../services/output/print.js\";\nimport { GGTError, IsBug } from \"../services/output/report.js\";\nimport { select } from \"../services/output/select.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { symbol } from \"../services/output/symbols.js\";\nimport { ts } from \"../services/output/timestamp.js\";\nimport { uniq } from \"../services/util/collection.js\";\nimport { isGraphQLErrors } from \"../services/util/is.js\";\nimport type { DevArgs } from \"./dev.js\";\n\nexport class AddClientError extends GGTError {\n isBug = IsBug.NO;\n\n constructor(error: ClientError) {\n let template = \"\";\n\n if (isGraphQLErrors(error.cause)) {\n const errors = uniq(error.cause.map((x) => x.message));\n\n template = sprint` • ${errors.map((e) => e.split(\"\\n\").join(\"\\n‎ • \")).join(\"\\n\")}`; // Why in gods name do I have to put an empty character for the tab to work?\n } else {\n template = sprint`${error.cause}`;\n }\n\n super(template);\n }\n\n protected override render(): string {\n return `${chalk.redBright(symbol.cross)} Failed to add:\\n ` + this.message;\n }\n}\n\nexport type AddArgs = typeof args;\n\nexport const args = {\n ...SyncJsonArgs,\n};\n\nexport const usage: Usage = () => {\n return sprint`\n Adds models, fields, actions and routes to your app.\n\n This command first performs a sync to ensure that your local and environment directories match, changes are tracked since last sync. \n If any conflicts are detected, they must be resolved before adding models, fields, actions or routes.\n\n {gray Usage}\n ggt add model <model_name> [field_name:field_type ...]\n\n ggt add action [CONTEXT]/<action_name>\n CONTEXT:Specifies the kind of action. Use \"model\" for model actions otherwise use \"action\".\n\n ggt add route <HTTP_METHOD> <route_path>\n\n ggt add field <model_path>/<field_name>:<field_type>\n\n {gray Options}\n -e, --env <env_name> Selects the environment to add to. Default set on \".gadget/sync.json\"\n \n {gray Examples}\n Add a new model 'post' with out fields:\n {cyanBright $ ggt add model modelA}\n\n Add a new model 'post' with 2 new 'string' type fields 'title' and 'body':\n {cyanBright $ ggt add model post title:string body:string}\n\n Add new action 'publish' to the 'post' model:\n {cyanBright ggt add action model/post/publish}\n\n Add a new action 'audit'\n {cyanBright ggt add action action/audit}\n\n Add a new route 'howdy'\n {cyanBright ggt add route GET howdy}\n\n Add a new 'boolean' type field 'published' to an existing model\n {cyanBright ggt add field post/published:boolean}\n `;\n};\n\nexport const command: Command<AddArgs> = async (ctx) => {\n const directory = await loadSyncJsonDirectory(process.cwd());\n const syncJson = await SyncJson.load(ctx, { directory });\n if (!syncJson) {\n throw new UnknownDirectoryError(ctx, { directory });\n }\n\n const filesync = new FileSync(syncJson);\n const hashes = await filesync.hashes(ctx, true);\n\n if (!hashes.inSync) {\n await filesync.merge(ctx as unknown as Context<DevArgs>, {\n hashes,\n printEnvironmentChangesOptions: {\n limit: 5,\n },\n printLocalChangesOptions: {\n limit: 5,\n },\n quietly: true,\n });\n }\n\n println({ ensureEmptyLineAbove: true })`${chalk.greenBright(symbol.tick)} Sync completed ${ts()}`;\n\n const actionType = ctx.args._[0] as AddActionType | undefined;\n if (!actionType) {\n println(usage(ctx));\n return;\n }\n\n switch (actionType) {\n case \"model\":\n await modelSubCommand(ctx, filesync);\n break;\n case \"action\":\n await actionSubCommand(ctx, filesync);\n break;\n case \"route\":\n await routeSubCommand(ctx, filesync);\n break;\n case \"field\":\n await fieldSubCommand(ctx, filesync);\n break;\n default:\n println(usage(ctx));\n return;\n }\n};\n\nconst addActionType = [\"model\", \"action\", \"route\", \"field\"] as const;\n\ntype AddActionType = (typeof addActionType)[number];\n\nconst parseFieldValues = (fields: string[]): [{ name: string; fieldType: string }[], problems: string[]] => {\n const problems: string[] = [];\n const modelFields: { name: string; fieldType: string }[] = [];\n\n fields.forEach((field) => {\n const matches = field.match(/^(.*):+(.*)$/);\n if (!matches || matches.length !== 3 || !matches[1] || !matches[2]) {\n problems.push(sprint`${field} is not a valid field definition`);\n } else {\n modelFields.push({ name: matches[1].replace(/:+/g, \"\"), fieldType: matches[2] });\n }\n });\n\n return [modelFields, problems];\n};\n\nconst modelSubCommand = async (ctx: Context<AddArgs>, filesync: FileSync): Promise<void> => {\n const syncJson = filesync.syncJson;\n const modelApiIdentifier = ctx.args._[1];\n\n if (!modelApiIdentifier) {\n throw new ArgError(sprint`Failed to add model, missing model path\n\n {gray Usage}\n {cyanBright ggt add model <model_name> [field_name:field_type ...]}`);\n }\n\n const modelFieldsList: { name: string; fieldType: string }[] = [];\n if (ctx.args._.length > 2) {\n const [modelFields, problems] = parseFieldValues(ctx.args._.slice(2));\n\n if (problems.length > 0) {\n throw new ArgError(sprint`\n Failed to add model:\n • ${problems.join(\"\\n • \")}\n \n {gray Usage}\n {cyanBright ggt add model ${modelApiIdentifier} [field_name:field_type ...]}`);\n }\n\n modelFieldsList.push(...modelFields);\n }\n\n let result;\n\n try {\n result = (\n await syncJson.edit.mutate({\n mutation: CREATE_MODEL_MUTATION,\n variables: {\n path: modelApiIdentifier,\n fields: modelFieldsList.map((fields) => ({\n name: fields.name,\n fieldType: fields.fieldType,\n })),\n },\n })\n ).createModel;\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n println({ ensureEmptyLineAbove: true })`${chalk.gray(\"New model created in environment.\")}`;\n\n await filesync.writeToLocalFilesystem(ctx, {\n filesVersion: result.remoteFilesVersion,\n files: result.changed,\n delete: [],\n });\n\n const modelPrintout = terminalLink.isSupported\n ? terminalLink(modelApiIdentifier, `https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/model/${modelApiIdentifier}/schema`)\n : modelApiIdentifier;\n println({ ensureEmptyLineAbove: true })`${chalk.greenBright(symbol.tick)} Model ${chalk.cyanBright(modelPrintout)} added successfully.`;\n};\n\nconst actionSubCommand = async (ctx: Context<AddArgs>, filesync: FileSync): Promise<void> => {\n const syncJson = filesync.syncJson;\n const path = ctx.args._[1];\n\n if (!path) {\n throw new ArgError(sprint`Failed to add action, missing action path\n\n {gray Usage}\n {cyanBright ggt add action [CONTEXT]/<action_name>\n CONTEXT:Specifies the kind of action. Use \"model\" for model actions otherwise use \"action\".}`);\n }\n\n const models = await getModels(ctx);\n const globalActions = await getGlobalActions(ctx);\n const splitPath = path.split(\"/\");\n\n let overrideContextAction: \"models\" | \"actions\" | undefined;\n\n const parsedPaths = splitPath.length > 1 ? splitPath.slice(0, splitPath.length - 1) : splitPath;\n const parsedAction = splitPath[splitPath.length - 1];\n\n const conflictingModel = models.find((model) => {\n const modelName = parsedPaths[parsedPaths.length - 1];\n\n return (\n model.apiIdentifier.toUpperCase() === modelName?.toUpperCase() &&\n model.namespace?.join(\"/\") === parsedPaths.slice(0, parsedPaths.length - 1).join(\"/\")\n );\n });\n\n const conflictingActionNamespace = globalActions.find((action) => {\n return action.namespace?.join(\"/\") === parsedPaths.join(\"/\");\n });\n\n if (conflictingModel && conflictingActionNamespace) {\n const joinedParsedPaths = parsedPaths.join(\"/\");\n overrideContextAction = await select({\n choices: Object.values([\"models\", \"actions\"]),\n formatChoice: (choice) => {\n switch (choice) {\n case \"models\": {\n return `As a Model action in ${chalk.gray(`models/${joinedParsedPaths}/${parsedAction}.js`)}`;\n }\n case \"actions\": {\n return `As an Action in ${chalk.gray(`actions/${joinedParsedPaths}/${parsedAction}.js`)}`;\n }\n }\n },\n })`\n {bold Namespace Conflict:} The action '${parsedAction}.js' cannot be automatically added due to a namespace conflict.\n\n How would you like to proceed?:\n `;\n\n println({\n ensureEmptyLineAbove: true,\n })`${chalk.yellowBright(symbol.info)} You can override the context of the action by specifying the context in the path. For example: {gray ggt add action ${overrideContextAction}/${path}}`;\n }\n\n try {\n const result = (\n await syncJson.edit.mutate({\n mutation: CREATE_ACTION_MUTATION,\n variables: { path: overrideContextAction ? `${overrideContextAction}/` + path : path },\n })\n ).createAction;\n\n await filesync.writeToLocalFilesystem(ctx, {\n filesVersion: result.remoteFilesVersion,\n files: result.changed,\n delete: [],\n });\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n println({ ensureEmptyLineAbove: true })`\n Action {cyanBright ${path}} added successfully.\n `;\n};\n\nconst routeSubCommand = async (ctx: Context<AddArgs>, filesync: FileSync): Promise<void> => {\n const syncJson = filesync.syncJson;\n const routeMethod = ctx.args._[1];\n const routePath = ctx.args._[2];\n\n if (!routeMethod) {\n throw new ArgError(sprint`Failed to add route, missing route method\n\n {gray Usage}\n {cyanBright ggt add route <HTTP_METHOD> <route_path>}`);\n }\n\n if (!routePath) {\n throw new ArgError(sprint`Failed to add route, missing route path\n\n {gray Usage}\n {cyanBright ggt add route ${routeMethod} <route_path>}`);\n }\n\n try {\n const result = (\n await syncJson.edit.mutate({\n mutation: CREATE_ROUTE_MUTATION,\n variables: { method: routeMethod, path: routePath },\n })\n ).createRoute;\n\n await filesync.writeToLocalFilesystem(ctx, {\n filesVersion: result.remoteFilesVersion,\n files: result.changed,\n delete: [],\n });\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n println({ ensureEmptyLineAbove: true })`\n Route {cyanBright ${routePath}} added successfully.\n `;\n};\n\nconst fieldSubCommand = async (ctx: Context<AddArgs>, filesync: FileSync): Promise<void> => {\n const syncJson = filesync.syncJson;\n\n const splitPathAndField = ctx.args._[1]?.split(\"/\");\n\n if (!splitPathAndField) {\n throw new ArgError(sprint`Failed to add field, invalid field path definition\n \n {gray Usage}\n {cyanBright ggt add field <model_path>/<field_name>:<field_type>}`);\n }\n\n const modelFieldsList: { name: string; fieldType: string }[] = [];\n\n if (splitPathAndField[1]) {\n const [modelFields, problems] = parseFieldValues([splitPathAndField[1]]);\n\n if (problems.length > 0) {\n throw new ArgError(sprint`\n Failed to add field:\n • ${problems.join(\"\\n •\")}\n \n {gray Usage}\n {cyanBright ggt add field ${splitPathAndField[0]}/<field_name>:<field_type>}`);\n }\n\n modelFieldsList.push(...modelFields);\n } else {\n throw new ArgError(sprint`Failed to add field, invalid field definition\n \n {gray Usage}\n {cyanBright ggt add field ${splitPathAndField[0]}/<field_name>:<field_type>}`);\n }\n\n try {\n const result = (\n await syncJson.edit.mutate({\n mutation: CREATE_MODEL_FIELDS_MUTATION,\n variables: {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n path: splitPathAndField[0]!,\n fields: modelFieldsList.map((field) => ({\n name: field.name,\n fieldType: field.fieldType,\n })),\n },\n })\n ).createModelFields;\n\n await filesync.writeToLocalFilesystem(ctx, {\n filesVersion: result.remoteFilesVersion,\n files: result.changed,\n delete: [],\n });\n } catch (error) {\n if (error instanceof ClientError) {\n throw new AddClientError(error);\n } else {\n throw error;\n }\n }\n\n println({ ensureEmptyLineAbove: true })`\n Field {cyanBright ${modelFieldsList[0]?.name}} added successfully.\n `;\n};\n"],"names":["chalk","terminalLink","getGlobalActions","getModels","CREATE_ACTION_MUTATION","CREATE_MODEL_FIELDS_MUTATION","CREATE_MODEL_MUTATION","CREATE_ROUTE_MUTATION","ClientError","ArgError","UnknownDirectoryError","FileSync","SyncJson","SyncJsonArgs","loadSyncJsonDirectory","println","GGTError","IsBug","select","sprint","symbol","ts","uniq","isGraphQLErrors","AddClientError","render","redBright","cross","message","constructor","error","template","cause","errors","map","x","e","split","join","isBug","NO","args","usage","command","ctx","directory","process","cwd","syncJson","load","filesync","hashes","inSync","merge","printEnvironmentChangesOptions","limit","printLocalChangesOptions","quietly","ensureEmptyLineAbove","greenBright","tick","actionType","_","modelSubCommand","actionSubCommand","routeSubCommand","fieldSubCommand","addActionType","parseFieldValues","fields","problems","modelFields","forEach","field","matches","match","length","push","name","replace","fieldType","modelApiIdentifier","modelFieldsList","slice","result","edit","mutate","mutation","variables","path","createModel","gray","writeToLocalFilesystem","filesVersion","remoteFilesVersion","files","changed","delete","modelPrintout","isSupported","app","primaryDomain","env","cyanBright","models","globalActions","splitPath","overrideContextAction","parsedPaths","parsedAction","conflictingModel","find","model","modelName","apiIdentifier","toUpperCase","namespace","conflictingActionNamespace","action","joinedParsedPaths","choices","Object","values","formatChoice","choice","yellowBright","info","createAction","routeMethod","routePath","method","createRoute","splitPathAndField","createModelFields"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -33,111 +33,29 @@ export const args = {
33
33
  type: Boolean
34
34
  }
35
35
  };
36
- export const usage = (ctx)=>{
37
- if (ctx.args["-h"]) {
38
- return sprint`
39
- Deploy an environment to production.
40
-
41
- Your local files must match your environment's files
42
- before you can deploy. Changes are tracked from
43
- the last "ggt dev", "ggt push", or "ggt pull" run locally.
44
-
45
- {bold USAGE}
46
- ggt deploy
47
-
48
- {bold EXAMPLES}
49
- $ ggt deploy
50
- $ ggt deploy --from=staging
51
- $ ggt deploy --from=staging --force
52
- $ ggt deploy --from=staging --force --allow-problems
53
-
54
- {bold FLAGS}
55
- -a, --app=<name> The application to deploy
56
- -e, --from=<env> The environment to deploy from
57
- --force Discard changes to your environment's filesystem
58
- --allow-problems Deploy regardless of any problems the environment has
59
- --allow-charges Deploy even if doing so will add charges to your account
60
-
61
- Run "ggt deploy --help" for more information.
62
- `;
63
- }
36
+ export const usage = (_ctx)=>{
64
37
  return sprint`
65
- Deploy an environment to production.
66
-
67
- Your local files must match your environment's files
68
- before you can deploy. Changes are tracked from
69
- the last "ggt dev", "ggt push", or "ggt pull" run locally.
70
-
71
- If your local files don't match your environment's files, you will
72
- be prompted to push your local files before you can deploy.
73
-
74
- If your environment has un-pulled changes, and "--force" is not
75
- passed, you will be prompted to {underline discard them} or abort the deploy.
76
-
77
- {bold USAGE}
78
-
79
- ggt deploy [--app=<name>] [--from=<env>] [--force]
80
- [--allow-problems] [--allow-charges]
81
-
82
- {bold EXAMPLES}
83
-
84
- $ ggt deploy
85
- $ ggt deploy --from=staging
86
- $ ggt deploy --from=staging --force
87
- $ ggt deploy --from=staging --force --allow-problems
88
- $ ggt deploy --from=staging --force --allow-problems --allow-charges
89
-
90
- {bold FLAGS}
91
-
92
- -a, --app, --application=<name>
93
- The application to deploy.
94
-
95
- Defaults to the application within the ".gadget/sync.json"
96
- file in the current directory or any parent directories.
97
-
98
- -e, --env, --environment, --from=<name>
99
- The environment to deploy from.
100
-
101
- Defaults to the environment within the ".gadget/sync.json"
102
- file in the current directory or any parent directories.
103
-
104
- -f, --force
105
- Discard any changes made to your environment's filesystem
106
- since the last "ggt dev", "ggt push", or "ggt pull".
107
-
108
- Defaults to false.
109
-
110
- --allow-problems, --allow-issues
111
- Deploy your environment to production regardless of any problems
112
- it may have.
113
-
114
- These problems may include:
115
- • Gelly syntax errors
116
- • TypeScript errors
117
- • Models with missing fields
118
-
119
- Defaults to false.
120
-
121
- --allow-charges
122
- Allows "ggt deploy" to continue when deploying your environment
123
- to production will add charges to your account.
124
-
125
- Defaults to false.
126
-
127
- --allow-unknown-directory
128
- Allows "ggt deploy" to continue when the current directory, nor
129
- any parent directories, contain a ".gadget/sync.json" file
130
- within it.
131
-
132
- Defaults to false.
133
-
134
- --allow-different-app
135
- Allows "ggt deploy" to continue with a different "--app" than the
136
- one found within the ".gadget/sync.json" file.
38
+ Deploys your app to production.
137
39
 
138
- Defaults to false.
40
+ This command first performs a sync to ensure that your local and environment directories
41
+ match, changes are tracked since last sync. If any conflicts are detected, they must be
42
+ resolved before deployment.
139
43
 
140
- Run "ggt deploy -h" for less information.
44
+ {gray Usage}
45
+ $ ggt deploy [options]
46
+
47
+ {gray Options}
48
+ -a, --app <app_name> Selects a specific app to deploy. Default set on ".gadget/sync.json"
49
+ --from, -e, --env <env_name> Selects a specific environment to sync and deploy from. Default set on ".gadget/sync.json"
50
+ --force Deploys by discarding any changes made to the environment directory since last sync
51
+ --allow-different-directory Deploys from any local directory with existing files, even if the ".gadget/sync.json" file is missing
52
+ --allow-different-app Deploys a different app using the --app command, instead of the one specified in the “.gadget/sync.json” file
53
+ --allow-problems Deploys despite any existing issues found in the app (gelly errors, typescript errors etc.)
54
+ --allow-charges Deploys even if it results in additional charges to your plan
55
+
56
+ {gray Examples}
57
+ Deploys code from the staging environment of a myBlog
58
+ {cyanBright $ ggt deploy -a myBlog -from staging}
141
59
  `;
142
60
  };
143
61
  export const command = async (ctx)=>{