@gadgetinc/ggt 0.4.10 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +165 -93
  2. package/lib/__generated__/graphql.js +66 -1
  3. package/lib/__generated__/graphql.js.map +1 -1
  4. package/lib/commands/deploy.js +328 -230
  5. package/lib/commands/deploy.js.map +1 -1
  6. package/lib/commands/dev.js +445 -0
  7. package/lib/commands/dev.js.map +1 -0
  8. package/lib/commands/list.js +27 -19
  9. package/lib/commands/list.js.map +1 -1
  10. package/lib/commands/login.js +15 -11
  11. package/lib/commands/login.js.map +1 -1
  12. package/lib/commands/logout.js +5 -5
  13. package/lib/commands/logout.js.map +1 -1
  14. package/lib/commands/open.js +200 -0
  15. package/lib/commands/open.js.map +1 -0
  16. package/lib/commands/pull.js +128 -0
  17. package/lib/commands/pull.js.map +1 -0
  18. package/lib/commands/push.js +126 -0
  19. package/lib/commands/push.js.map +1 -0
  20. package/lib/commands/root.js +46 -28
  21. package/lib/commands/root.js.map +1 -1
  22. package/lib/commands/status.js +61 -0
  23. package/lib/commands/status.js.map +1 -0
  24. package/lib/commands/version.js +6 -6
  25. package/lib/commands/version.js.map +1 -1
  26. package/lib/commands/whoami.js +6 -6
  27. package/lib/commands/whoami.js.map +1 -1
  28. package/lib/ggt.js +33 -8
  29. package/lib/ggt.js.map +1 -1
  30. package/lib/main.js +5 -0
  31. package/lib/main.js.map +1 -0
  32. package/lib/services/app/api/api.js +191 -0
  33. package/lib/services/app/api/api.js.map +1 -0
  34. package/lib/services/app/api/operation.js +12 -0
  35. package/lib/services/app/api/operation.js.map +1 -0
  36. package/lib/services/app/app.js +44 -10
  37. package/lib/services/app/app.js.map +1 -1
  38. package/lib/services/app/{edit/client.js → client.js} +29 -19
  39. package/lib/services/app/client.js.map +1 -0
  40. package/lib/services/app/edit/edit.js +67 -31
  41. package/lib/services/app/edit/edit.js.map +1 -1
  42. package/lib/services/app/edit/operation.js +4 -3
  43. package/lib/services/app/edit/operation.js.map +1 -1
  44. package/lib/services/app/{edit/error.js → error.js} +6 -6
  45. package/lib/services/app/error.js.map +1 -0
  46. package/lib/services/command/arg.js +4 -4
  47. package/lib/services/command/arg.js.map +1 -1
  48. package/lib/services/command/command.js +9 -7
  49. package/lib/services/command/command.js.map +1 -1
  50. package/lib/services/command/context.js +82 -20
  51. package/lib/services/command/context.js.map +1 -1
  52. package/lib/services/config/config.js +4 -7
  53. package/lib/services/config/config.js.map +1 -1
  54. package/lib/services/config/env.js +1 -1
  55. package/lib/services/config/env.js.map +1 -1
  56. package/lib/services/filesync/changes.js +76 -37
  57. package/lib/services/filesync/changes.js.map +1 -1
  58. package/lib/services/filesync/conflicts.js +10 -9
  59. package/lib/services/filesync/conflicts.js.map +1 -1
  60. package/lib/services/filesync/directory.js +16 -1
  61. package/lib/services/filesync/directory.js.map +1 -1
  62. package/lib/services/filesync/error.js +96 -27
  63. package/lib/services/filesync/error.js.map +1 -1
  64. package/lib/services/filesync/filesync.js +448 -490
  65. package/lib/services/filesync/filesync.js.map +1 -1
  66. package/lib/services/filesync/hashes.js +8 -5
  67. package/lib/services/filesync/hashes.js.map +1 -1
  68. package/lib/services/filesync/strategy.js +59 -0
  69. package/lib/services/filesync/strategy.js.map +1 -0
  70. package/lib/services/filesync/sync-json.js +475 -0
  71. package/lib/services/filesync/sync-json.js.map +1 -0
  72. package/lib/services/http/auth.js +30 -1
  73. package/lib/services/http/auth.js.map +1 -1
  74. package/lib/services/http/http.js +5 -0
  75. package/lib/services/http/http.js.map +1 -1
  76. package/lib/services/output/confirm.js +149 -0
  77. package/lib/services/output/confirm.js.map +1 -0
  78. package/lib/services/output/footer.js +22 -0
  79. package/lib/services/output/footer.js.map +1 -0
  80. package/lib/services/output/log/format/pretty.js +2 -1
  81. package/lib/services/output/log/format/pretty.js.map +1 -1
  82. package/lib/services/output/log/logger.js +13 -5
  83. package/lib/services/output/log/logger.js.map +1 -1
  84. package/lib/services/output/log/structured.js +2 -2
  85. package/lib/services/output/log/structured.js.map +1 -1
  86. package/lib/services/output/output.js +197 -0
  87. package/lib/services/output/output.js.map +1 -0
  88. package/lib/services/output/print.js +31 -0
  89. package/lib/services/output/print.js.map +1 -0
  90. package/lib/services/output/problems.js +84 -0
  91. package/lib/services/output/problems.js.map +1 -0
  92. package/lib/services/output/prompt.js +173 -40
  93. package/lib/services/output/prompt.js.map +1 -1
  94. package/lib/services/output/report.js +63 -19
  95. package/lib/services/output/report.js.map +1 -1
  96. package/lib/services/output/select.js +198 -0
  97. package/lib/services/output/select.js.map +1 -0
  98. package/lib/services/output/spinner.js +141 -0
  99. package/lib/services/output/spinner.js.map +1 -0
  100. package/lib/services/output/sprint.js +38 -15
  101. package/lib/services/output/sprint.js.map +1 -1
  102. package/lib/services/output/symbols.js +23 -0
  103. package/lib/services/output/symbols.js.map +1 -0
  104. package/lib/services/output/table.js +98 -0
  105. package/lib/services/output/table.js.map +1 -0
  106. package/lib/services/output/timestamp.js +12 -0
  107. package/lib/services/output/timestamp.js.map +1 -0
  108. package/lib/services/output/update.js +29 -9
  109. package/lib/services/output/update.js.map +1 -1
  110. package/lib/services/user/session.js +4 -0
  111. package/lib/services/user/session.js.map +1 -1
  112. package/lib/services/user/user.js +15 -10
  113. package/lib/services/user/user.js.map +1 -1
  114. package/lib/services/util/assert.js +11 -0
  115. package/lib/services/util/assert.js.map +1 -0
  116. package/lib/services/util/boolean.js +2 -2
  117. package/lib/services/util/boolean.js.map +1 -1
  118. package/lib/services/util/function.js +45 -7
  119. package/lib/services/util/function.js.map +1 -1
  120. package/lib/services/util/is.js +23 -2
  121. package/lib/services/util/is.js.map +1 -1
  122. package/lib/services/util/json.js +16 -13
  123. package/lib/services/util/json.js.map +1 -1
  124. package/lib/services/util/object.js +2 -2
  125. package/lib/services/util/object.js.map +1 -1
  126. package/lib/services/util/promise.js +5 -2
  127. package/lib/services/util/promise.js.map +1 -1
  128. package/lib/services/util/types.js.map +1 -1
  129. package/npm-shrinkwrap.json +3415 -2973
  130. package/package.json +47 -40
  131. package/bin/dev.cmd +0 -3
  132. package/bin/dev.js +0 -14
  133. package/bin/run.cmd +0 -3
  134. package/bin/run.js +0 -5
  135. package/lib/commands/sync.js +0 -284
  136. package/lib/commands/sync.js.map +0 -1
  137. package/lib/services/app/edit/client.js.map +0 -1
  138. package/lib/services/app/edit/error.js.map +0 -1
  139. package/lib/services/output/log/printer.js +0 -120
  140. package/lib/services/output/log/printer.js.map +0 -1
  141. package/lib/services/output/stream.js +0 -54
  142. package/lib/services/output/stream.js.map +0 -1
@@ -0,0 +1,126 @@
1
+ import { ArgError } from "../services/command/arg.js";
2
+ import { FileSync } from "../services/filesync/filesync.js";
3
+ import { SyncJson, SyncJsonArgs, loadSyncJsonDirectory } from "../services/filesync/sync-json.js";
4
+ import { println } from "../services/output/print.js";
5
+ import { sprint } from "../services/output/sprint.js";
6
+ export const args = {
7
+ ...SyncJsonArgs,
8
+ "--force": {
9
+ type: Boolean,
10
+ alias: "-f"
11
+ }
12
+ };
13
+ export const usage = (ctx)=>{
14
+ if (ctx.args["-h"]) {
15
+ return sprint`
16
+ Push your local files to your environment's filesystem.
17
+ Changes are tracked from the last "ggt dev", "ggt push", or
18
+ "ggt pull" run locally.
19
+
20
+ {bold USAGE}
21
+ ggt push
22
+
23
+ {bold EXAMPLES}
24
+ $ ggt push
25
+ $ ggt push --env=staging
26
+ $ ggt push --env=staging --force
27
+
28
+ {bold FLAGS}
29
+ -a, --app=<name> The application to push files to
30
+ -e, --env=<name> The environment to push files to
31
+ --force Discard changes to your environment's filesystem
32
+
33
+ Run "ggt push --help" for more information.
34
+ `;
35
+ }
36
+ return sprint`
37
+ Push your local files to your environment's filesystem.
38
+ Changes are tracked from the last "ggt dev", "ggt push", or
39
+ "ggt pull" run locally.
40
+
41
+ If your environment has un-pulled changes, and "--force" is not passed,
42
+ you will be prompted to {underline discard them} or abort the push.
43
+
44
+ {bold USAGE}
45
+
46
+ ggt push [--app=<name>] [--env=<name>] [--force]
47
+ [--allow-unknown-directory] [--allow-different-app]
48
+
49
+ {bold EXAMPLES}
50
+
51
+ $ ggt push
52
+ $ ggt push --env=staging
53
+ $ ggt push --env=staging --force
54
+ $ ggt push --env=staging --force --allow-unknown-directory
55
+
56
+ {bold FLAGS}
57
+
58
+ -a, --app, --application=<name>
59
+ The application to push files to.
60
+
61
+ Defaults to the application within the ".gadget/sync.json"
62
+ file in the current directory or any parent directories.
63
+
64
+ -e, --env, --environment=<name>
65
+ The environment to push files to.
66
+
67
+ Defaults to the environment within the ".gadget/sync.json"
68
+ file in the current directory or any parent directories.
69
+
70
+ -f, --force
71
+ Discard any changes made to your environment's filesystem
72
+ since the last "ggt dev", "ggt push", or "ggt pull".
73
+
74
+ Defaults to false.
75
+
76
+ --allow-unknown-directory
77
+ Allows "ggt push" to continue when the current directory, nor
78
+ any parent directories, contain a ".gadget/sync.json" file
79
+ within it.
80
+
81
+ Defaults to false.
82
+
83
+ --allow-different-app
84
+ Allows "ggt push" to continue with a different "--app" than the
85
+ one found within the ".gadget/sync.json" file.
86
+
87
+ Defaults to false.
88
+
89
+ Run "ggt push -h" for less information.
90
+ `;
91
+ };
92
+ export const command = async (ctx)=>{
93
+ if (ctx.args._.length > 0) {
94
+ throw new ArgError(sprint`
95
+ "ggt push" does not take any positional arguments.
96
+
97
+ If you are trying to push changes from a specific directory,
98
+ you must "cd" to that directory and then run "ggt push".
99
+ `);
100
+ }
101
+ const directory = await loadSyncJsonDirectory(process.cwd());
102
+ const syncJson = await SyncJson.loadOrInit(ctx, {
103
+ directory
104
+ });
105
+ const filesync = new FileSync(syncJson);
106
+ const hashes = await filesync.hashes(ctx);
107
+ if (hashes.localChangesToPush.size === 0) {
108
+ println({
109
+ ensureEmptyLineAbove: true
110
+ })`
111
+ Nothing to push.
112
+ `;
113
+ return;
114
+ }
115
+ if (hashes.environmentChangesToPull.size > 0 && !hashes.onlyDotGadgetFilesChanged) {
116
+ // show them the environment changes they will discard
117
+ await filesync.print(ctx, {
118
+ hashes
119
+ });
120
+ }
121
+ await filesync.push(ctx, {
122
+ hashes
123
+ });
124
+ };
125
+
126
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/push.ts"],"sourcesContent":["import { ArgError, type ArgsDefinition } from \"../services/command/arg.js\";\nimport type { Command, Usage } from \"../services/command/command.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 { sprint } from \"../services/output/sprint.js\";\n\nexport type PushArgs = typeof args;\n\nexport const args = {\n ...SyncJsonArgs,\n \"--force\": { type: Boolean, alias: \"-f\" },\n} satisfies ArgsDefinition;\n\nexport const usage: Usage = (ctx) => {\n if (ctx.args[\"-h\"]) {\n return sprint`\n Push your local files to your environment's filesystem.\n Changes are tracked from the last \"ggt dev\", \"ggt push\", or\n \"ggt pull\" run locally.\n\n {bold USAGE}\n ggt push\n\n {bold EXAMPLES}\n $ ggt push\n $ ggt push --env=staging\n $ ggt push --env=staging --force\n\n {bold FLAGS}\n -a, --app=<name> The application to push files to\n -e, --env=<name> The environment to push files to\n --force Discard changes to your environment's filesystem\n\n Run \"ggt push --help\" for more information.\n `;\n }\n\n return sprint`\n Push your local files to your environment's filesystem.\n Changes are tracked from the last \"ggt dev\", \"ggt push\", or\n \"ggt pull\" run locally.\n\n If your environment has un-pulled changes, and \"--force\" is not passed,\n you will be prompted to {underline discard them} or abort the push.\n\n {bold USAGE}\n\n ggt push [--app=<name>] [--env=<name>] [--force]\n [--allow-unknown-directory] [--allow-different-app]\n\n {bold EXAMPLES}\n\n $ ggt push\n $ ggt push --env=staging\n $ ggt push --env=staging --force\n $ ggt push --env=staging --force --allow-unknown-directory\n\n {bold FLAGS}\n\n -a, --app, --application=<name>\n The application to push files to.\n\n Defaults to the application within the \".gadget/sync.json\"\n file in the current directory or any parent directories.\n\n -e, --env, --environment=<name>\n The environment to push files to.\n\n Defaults to the environment within the \".gadget/sync.json\"\n file in the current directory or any parent directories.\n\n -f, --force\n Discard any changes made to your environment's filesystem\n since the last \"ggt dev\", \"ggt push\", or \"ggt pull\".\n\n Defaults to false.\n\n --allow-unknown-directory\n Allows \"ggt push\" to continue when the current directory, nor\n any parent directories, contain a \".gadget/sync.json\" file\n within it.\n\n Defaults to false.\n\n --allow-different-app\n Allows \"ggt push\" to continue with a different \"--app\" than the\n one found within the \".gadget/sync.json\" file.\n\n Defaults to false.\n\n Run \"ggt push -h\" for less information.\n `;\n};\n\nexport const command: Command<typeof args> = async (ctx) => {\n if (ctx.args._.length > 0) {\n throw new ArgError(sprint`\n \"ggt push\" does not take any positional arguments.\n\n If you are trying to push changes from a specific directory,\n you must \"cd\" to that directory and then run \"ggt push\".\n `);\n }\n\n const directory = await loadSyncJsonDirectory(process.cwd());\n const syncJson = await SyncJson.loadOrInit(ctx, { directory });\n const filesync = new FileSync(syncJson);\n const hashes = await filesync.hashes(ctx);\n\n if (hashes.localChangesToPush.size === 0) {\n println({ ensureEmptyLineAbove: true })`\n Nothing to push.\n `;\n return;\n }\n\n if (hashes.environmentChangesToPull.size > 0 && !hashes.onlyDotGadgetFilesChanged) {\n // show them the environment changes they will discard\n await filesync.print(ctx, { hashes });\n }\n\n await filesync.push(ctx, { hashes });\n};\n"],"names":["ArgError","FileSync","SyncJson","SyncJsonArgs","loadSyncJsonDirectory","println","sprint","args","type","Boolean","alias","usage","ctx","command","_","length","directory","process","cwd","syncJson","loadOrInit","filesync","hashes","localChangesToPush","size","ensureEmptyLineAbove","environmentChangesToPull","onlyDotGadgetFilesChanged","print","push"],"mappings":"AAAA,SAASA,QAAQ,QAA6B,6BAA6B;AAE3E,SAASC,QAAQ,QAAQ,mCAAmC;AAC5D,SAASC,QAAQ,EAAEC,YAAY,EAAEC,qBAAqB,QAAQ,oCAAoC;AAClG,SAASC,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AAItD,OAAO,MAAMC,OAAO;IAClB,GAAGJ,YAAY;IACf,WAAW;QAAEK,MAAMC;QAASC,OAAO;IAAK;AAC1C,EAA2B;AAE3B,OAAO,MAAMC,QAAe,CAACC;IAC3B,IAAIA,IAAIL,IAAI,CAAC,KAAK,EAAE;QAClB,OAAOD,MAAM,CAAC;;;;;;;;;;;;;;;;;;;IAmBd,CAAC;IACH;IAEA,OAAOA,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDd,CAAC;AACH,EAAE;AAEF,OAAO,MAAMO,UAAgC,OAAOD;IAClD,IAAIA,IAAIL,IAAI,CAACO,CAAC,CAACC,MAAM,GAAG,GAAG;QACzB,MAAM,IAAIf,SAASM,MAAM,CAAC;;;;;IAK1B,CAAC;IACH;IAEA,MAAMU,YAAY,MAAMZ,sBAAsBa,QAAQC,GAAG;IACzD,MAAMC,WAAW,MAAMjB,SAASkB,UAAU,CAACR,KAAK;QAAEI;IAAU;IAC5D,MAAMK,WAAW,IAAIpB,SAASkB;IAC9B,MAAMG,SAAS,MAAMD,SAASC,MAAM,CAACV;IAErC,IAAIU,OAAOC,kBAAkB,CAACC,IAAI,KAAK,GAAG;QACxCnB,QAAQ;YAAEoB,sBAAsB;QAAK,EAAE,CAAC;;IAExC,CAAC;QACD;IACF;IAEA,IAAIH,OAAOI,wBAAwB,CAACF,IAAI,GAAG,KAAK,CAACF,OAAOK,yBAAyB,EAAE;QACjF,sDAAsD;QACtD,MAAMN,SAASO,KAAK,CAAChB,KAAK;YAAEU;QAAO;IACrC;IAEA,MAAMD,SAASQ,IAAI,CAACjB,KAAK;QAAEU;IAAO;AACpC,EAAE"}
@@ -1,36 +1,18 @@
1
1
  import arg from "arg";
2
2
  import { Commands, importCommand, isAvailableCommand } from "../services/command/command.js";
3
3
  import { verbosityToLevel } from "../services/output/log/level.js";
4
+ import { println } from "../services/output/print.js";
4
5
  import { reportErrorAndExit } from "../services/output/report.js";
5
6
  import { sprint } from "../services/output/sprint.js";
6
7
  import { warnIfUpdateAvailable } from "../services/output/update.js";
7
8
  import { sortBySimilar } from "../services/util/collection.js";
8
9
  import { isNil } from "../services/util/is.js";
9
- export const usage = ()=>sprint`
10
- The command-line interface for Gadget
11
-
12
- {bold USAGE}
13
- ggt [COMMAND]
14
-
15
- {bold COMMANDS}
16
- sync Sync your Gadget application's source code
17
- list List your apps
18
- login Log in to your account
19
- logout Log out of your account
20
- whoami Print the currently logged in account
21
- version Print the version of ggt
22
-
23
- {bold FLAGS}
24
- -h, --help Print command's usage
25
- -v, --verbose Print verbose output
26
- --json Print output as JSON
27
-
28
- For more information on a specific command, use 'ggt [COMMAND] --help'
29
- `;
30
10
  export const args = {
11
+ "-h": {
12
+ type: Boolean
13
+ },
31
14
  "--help": {
32
- type: Boolean,
33
- alias: "-h"
15
+ type: Boolean
34
16
  },
35
17
  "--verbose": {
36
18
  type: arg.COUNT,
@@ -39,10 +21,41 @@ export const args = {
39
21
  "--debug"
40
22
  ]
41
23
  },
24
+ "--telemetry": {
25
+ type: Boolean
26
+ },
42
27
  "--json": {
43
28
  type: Boolean
44
29
  }
45
30
  };
31
+ export const usage = ()=>{
32
+ return sprint`
33
+ The command-line interface for Gadget.
34
+
35
+ {bold USAGE}
36
+ ggt [COMMAND]
37
+
38
+ {bold COMMANDS}
39
+ dev Start developing your application
40
+ deploy Deploy your environment to production
41
+ status Show your local and environment's file changes
42
+ push Push your local files to your environment
43
+ pull Pull your environment's files to your local computer
44
+ open Open a Gadget location in your browser
45
+ list List your available applications
46
+ login Log in to your account
47
+ logout Log out of your account
48
+ whoami Print the currently logged in account
49
+ version Print this version of ggt
50
+
51
+ {bold FLAGS}
52
+ -h, --help Print how to use a command
53
+ -v, --verbose Print more verbose output
54
+ --telemetry Enable telemetry
55
+
56
+ Run "ggt [COMMAND] -h" for more information about a specific command.
57
+ `;
58
+ };
46
59
  export const command = async (parent)=>{
47
60
  const ctx = parent.child({
48
61
  name: "root",
@@ -57,14 +70,18 @@ export const command = async (parent)=>{
57
70
  process.env["GGT_LOG_LEVEL"] = verbosityToLevel(ctx.args["--verbose"]).toString();
58
71
  }
59
72
  await warnIfUpdateAvailable(ctx);
60
- const cmd = ctx.args._.shift();
73
+ let cmd = ctx.args._.shift();
61
74
  if (isNil(cmd)) {
62
- ctx.log.println(usage());
75
+ println(usage(ctx));
63
76
  process.exit(0);
64
77
  }
78
+ if (cmd === "sync") {
79
+ ctx.log.debug('renaming "sync" to "dev" for backwards compatibility');
80
+ cmd = "dev";
81
+ }
65
82
  if (!isAvailableCommand(cmd)) {
66
83
  const [closest] = sortBySimilar(cmd, Commands);
67
- ctx.log.println`
84
+ println`
68
85
  Unknown command {yellow ${cmd}}
69
86
 
70
87
  Did you mean {blueBright ${closest}}?
@@ -74,12 +91,13 @@ export const command = async (parent)=>{
74
91
  process.exit(1);
75
92
  }
76
93
  const subcommand = await importCommand(cmd);
77
- if (ctx.args["--help"]) {
78
- ctx.log.println(subcommand.usage());
94
+ if (ctx.args["-h"] ?? ctx.args["--help"]) {
95
+ println(subcommand.usage(ctx));
79
96
  process.exit(0);
80
97
  }
81
98
  try {
82
99
  await subcommand.command(ctx.child({
100
+ command: cmd,
83
101
  name: cmd,
84
102
  parse: subcommand.args
85
103
  }));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/root.ts"],"sourcesContent":["import arg from \"arg\";\nimport type { EmptyObject } from \"type-fest\";\nimport type { ArgsDefinition } from \"../services/command/arg.js\";\nimport { Commands, importCommand, isAvailableCommand, type Command, type Usage } from \"../services/command/command.js\";\nimport { verbosityToLevel } from \"../services/output/log/level.js\";\nimport { reportErrorAndExit } from \"../services/output/report.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { warnIfUpdateAvailable } from \"../services/output/update.js\";\nimport { sortBySimilar } from \"../services/util/collection.js\";\nimport { isNil } from \"../services/util/is.js\";\n\nexport const usage: Usage = () => sprint`\n The command-line interface for Gadget\n\n {bold USAGE}\n ggt [COMMAND]\n\n {bold COMMANDS}\n sync Sync your Gadget application's source code\n list List your apps\n login Log in to your account\n logout Log out of your account\n whoami Print the currently logged in account\n version Print the version of ggt\n\n {bold FLAGS}\n -h, --help Print command's usage\n -v, --verbose Print verbose output\n --json Print output as JSON\n\n For more information on a specific command, use 'ggt [COMMAND] --help'\n`;\n\nexport const args = {\n \"--help\": { type: Boolean, alias: \"-h\" },\n \"--verbose\": { type: arg.COUNT, alias: [\"-v\", \"--debug\"] },\n \"--json\": { type: Boolean },\n} satisfies ArgsDefinition;\n\nexport type RootArgs = typeof args;\n\nexport const command: Command<EmptyObject, EmptyObject> = async (parent): Promise<void> => {\n const ctx = parent.child({\n name: \"root\",\n parse: args,\n argv: process.argv.slice(2),\n permissive: true,\n });\n\n if (ctx.args[\"--json\"]) {\n process.env[\"GGT_LOG_FORMAT\"] = \"json\";\n }\n\n if (ctx.args[\"--verbose\"]) {\n process.env[\"GGT_LOG_LEVEL\"] = verbosityToLevel(ctx.args[\"--verbose\"]).toString();\n }\n\n await warnIfUpdateAvailable(ctx);\n\n const cmd = ctx.args._.shift();\n if (isNil(cmd)) {\n ctx.log.println(usage());\n process.exit(0);\n }\n\n if (!isAvailableCommand(cmd)) {\n const [closest] = sortBySimilar(cmd, Commands);\n ctx.log.println`\n Unknown command {yellow ${cmd}}\n\n Did you mean {blueBright ${closest}}?\n\n Run {gray ggt --help} for usage\n `;\n process.exit(1);\n }\n\n const subcommand = await importCommand(cmd);\n\n if (ctx.args[\"--help\"]) {\n ctx.log.println(subcommand.usage());\n process.exit(0);\n }\n\n try {\n await subcommand.command(ctx.child({ name: cmd, parse: subcommand.args }));\n } catch (error) {\n await reportErrorAndExit(ctx, error);\n }\n};\n"],"names":["arg","Commands","importCommand","isAvailableCommand","verbosityToLevel","reportErrorAndExit","sprint","warnIfUpdateAvailable","sortBySimilar","isNil","usage","args","type","Boolean","alias","COUNT","command","parent","ctx","child","name","parse","argv","process","slice","permissive","env","toString","cmd","_","shift","log","println","exit","closest","subcommand","error"],"mappings":"AAAA,OAAOA,SAAS,MAAM;AAGtB,SAASC,QAAQ,EAAEC,aAAa,EAAEC,kBAAkB,QAAkC,iCAAiC;AACvH,SAASC,gBAAgB,QAAQ,kCAAkC;AACnE,SAASC,kBAAkB,QAAQ,+BAA+B;AAClE,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,qBAAqB,QAAQ,+BAA+B;AACrE,SAASC,aAAa,QAAQ,iCAAiC;AAC/D,SAASC,KAAK,QAAQ,yBAAyB;AAE/C,OAAO,MAAMC,QAAe,IAAMJ,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;AAoBzC,CAAC,CAAC;AAEF,OAAO,MAAMK,OAAO;IAClB,UAAU;QAAEC,MAAMC;QAASC,OAAO;IAAK;IACvC,aAAa;QAAEF,MAAMZ,IAAIe,KAAK;QAAED,OAAO;YAAC;YAAM;SAAU;IAAC;IACzD,UAAU;QAAEF,MAAMC;IAAQ;AAC5B,EAA2B;AAI3B,OAAO,MAAMG,UAA6C,OAAOC;IAC/D,MAAMC,MAAMD,OAAOE,KAAK,CAAC;QACvBC,MAAM;QACNC,OAAOV;QACPW,MAAMC,QAAQD,IAAI,CAACE,KAAK,CAAC;QACzBC,YAAY;IACd;IAEA,IAAIP,IAAIP,IAAI,CAAC,SAAS,EAAE;QACtBY,QAAQG,GAAG,CAAC,iBAAiB,GAAG;IAClC;IAEA,IAAIR,IAAIP,IAAI,CAAC,YAAY,EAAE;QACzBY,QAAQG,GAAG,CAAC,gBAAgB,GAAGtB,iBAAiBc,IAAIP,IAAI,CAAC,YAAY,EAAEgB,QAAQ;IACjF;IAEA,MAAMpB,sBAAsBW;IAE5B,MAAMU,MAAMV,IAAIP,IAAI,CAACkB,CAAC,CAACC,KAAK;IAC5B,IAAIrB,MAAMmB,MAAM;QACdV,IAAIa,GAAG,CAACC,OAAO,CAACtB;QAChBa,QAAQU,IAAI,CAAC;IACf;IAEA,IAAI,CAAC9B,mBAAmByB,MAAM;QAC5B,MAAM,CAACM,QAAQ,GAAG1B,cAAcoB,KAAK3B;QACrCiB,IAAIa,GAAG,CAACC,OAAO,CAAC;8BACU,EAAEJ,IAAI;;+BAEL,EAAEM,QAAQ;;;IAGrC,CAAC;QACDX,QAAQU,IAAI,CAAC;IACf;IAEA,MAAME,aAAa,MAAMjC,cAAc0B;IAEvC,IAAIV,IAAIP,IAAI,CAAC,SAAS,EAAE;QACtBO,IAAIa,GAAG,CAACC,OAAO,CAACG,WAAWzB,KAAK;QAChCa,QAAQU,IAAI,CAAC;IACf;IAEA,IAAI;QACF,MAAME,WAAWnB,OAAO,CAACE,IAAIC,KAAK,CAAC;YAAEC,MAAMQ;YAAKP,OAAOc,WAAWxB,IAAI;QAAC;IACzE,EAAE,OAAOyB,OAAO;QACd,MAAM/B,mBAAmBa,KAAKkB;IAChC;AACF,EAAE"}
1
+ {"version":3,"sources":["../../src/commands/root.ts"],"sourcesContent":["import arg from \"arg\";\nimport type { EmptyObject } from \"type-fest\";\nimport type { ArgsDefinition } from \"../services/command/arg.js\";\nimport { Commands, importCommand, isAvailableCommand, type Command, type Usage } from \"../services/command/command.js\";\nimport { verbosityToLevel } from \"../services/output/log/level.js\";\nimport { println } from \"../services/output/print.js\";\nimport { reportErrorAndExit } from \"../services/output/report.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { warnIfUpdateAvailable } from \"../services/output/update.js\";\nimport { sortBySimilar } from \"../services/util/collection.js\";\nimport { isNil } from \"../services/util/is.js\";\n\nexport type RootArgs = typeof args;\n\nexport const args = {\n \"-h\": { type: Boolean },\n \"--help\": { type: Boolean },\n \"--verbose\": { type: arg.COUNT, alias: [\"-v\", \"--debug\"] },\n \"--telemetry\": { type: Boolean },\n \"--json\": { type: Boolean },\n} satisfies ArgsDefinition;\n\nexport const usage: Usage = () => {\n return sprint`\n The command-line interface for Gadget.\n\n {bold USAGE}\n ggt [COMMAND]\n\n {bold COMMANDS}\n dev Start developing your application\n deploy Deploy your environment to production\n status Show your local and environment's file changes\n push Push your local files to your environment\n pull Pull your environment's files to your local computer\n open Open a Gadget location in your browser\n list List your available applications\n login Log in to your account\n logout Log out of your account\n whoami Print the currently logged in account\n version Print this version of ggt\n\n {bold FLAGS}\n -h, --help Print how to use a command\n -v, --verbose Print more verbose output\n --telemetry Enable telemetry\n\n Run \"ggt [COMMAND] -h\" for more information about a specific command.\n `;\n};\n\nexport const command: Command<EmptyObject, EmptyObject> = async (parent): Promise<void> => {\n const ctx = parent.child({\n name: \"root\",\n parse: args,\n argv: process.argv.slice(2),\n permissive: true,\n });\n\n if (ctx.args[\"--json\"]) {\n process.env[\"GGT_LOG_FORMAT\"] = \"json\";\n }\n\n if (ctx.args[\"--verbose\"]) {\n process.env[\"GGT_LOG_LEVEL\"] = verbosityToLevel(ctx.args[\"--verbose\"]).toString();\n }\n\n await warnIfUpdateAvailable(ctx);\n\n let cmd = ctx.args._.shift();\n if (isNil(cmd)) {\n println(usage(ctx));\n process.exit(0);\n }\n\n if (cmd === \"sync\") {\n ctx.log.debug('renaming \"sync\" to \"dev\" for backwards compatibility');\n cmd = \"dev\";\n }\n\n if (!isAvailableCommand(cmd)) {\n const [closest] = sortBySimilar(cmd, Commands);\n println`\n Unknown command {yellow ${cmd}}\n\n Did you mean {blueBright ${closest}}?\n\n Run {gray ggt --help} for usage\n `;\n process.exit(1);\n }\n\n const subcommand = await importCommand(cmd);\n\n if (ctx.args[\"-h\"] ?? ctx.args[\"--help\"]) {\n println(subcommand.usage(ctx));\n process.exit(0);\n }\n\n try {\n await subcommand.command(ctx.child({ command: cmd, name: cmd, parse: subcommand.args }));\n } catch (error) {\n await reportErrorAndExit(ctx, error);\n }\n};\n"],"names":["arg","Commands","importCommand","isAvailableCommand","verbosityToLevel","println","reportErrorAndExit","sprint","warnIfUpdateAvailable","sortBySimilar","isNil","args","type","Boolean","COUNT","alias","usage","command","parent","ctx","child","name","parse","argv","process","slice","permissive","env","toString","cmd","_","shift","exit","log","debug","closest","subcommand","error"],"mappings":"AAAA,OAAOA,SAAS,MAAM;AAGtB,SAASC,QAAQ,EAAEC,aAAa,EAAEC,kBAAkB,QAAkC,iCAAiC;AACvH,SAASC,gBAAgB,QAAQ,kCAAkC;AACnE,SAASC,OAAO,QAAQ,8BAA8B;AACtD,SAASC,kBAAkB,QAAQ,+BAA+B;AAClE,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,qBAAqB,QAAQ,+BAA+B;AACrE,SAASC,aAAa,QAAQ,iCAAiC;AAC/D,SAASC,KAAK,QAAQ,yBAAyB;AAI/C,OAAO,MAAMC,OAAO;IAClB,MAAM;QAAEC,MAAMC;IAAQ;IACtB,UAAU;QAAED,MAAMC;IAAQ;IAC1B,aAAa;QAAED,MAAMZ,IAAIc,KAAK;QAAEC,OAAO;YAAC;YAAM;SAAU;IAAC;IACzD,eAAe;QAAEH,MAAMC;IAAQ;IAC/B,UAAU;QAAED,MAAMC;IAAQ;AAC5B,EAA2B;AAE3B,OAAO,MAAMG,QAAe;IAC1B,OAAOT,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAyBd,CAAC;AACH,EAAE;AAEF,OAAO,MAAMU,UAA6C,OAAOC;IAC/D,MAAMC,MAAMD,OAAOE,KAAK,CAAC;QACvBC,MAAM;QACNC,OAAOX;QACPY,MAAMC,QAAQD,IAAI,CAACE,KAAK,CAAC;QACzBC,YAAY;IACd;IAEA,IAAIP,IAAIR,IAAI,CAAC,SAAS,EAAE;QACtBa,QAAQG,GAAG,CAAC,iBAAiB,GAAG;IAClC;IAEA,IAAIR,IAAIR,IAAI,CAAC,YAAY,EAAE;QACzBa,QAAQG,GAAG,CAAC,gBAAgB,GAAGvB,iBAAiBe,IAAIR,IAAI,CAAC,YAAY,EAAEiB,QAAQ;IACjF;IAEA,MAAMpB,sBAAsBW;IAE5B,IAAIU,MAAMV,IAAIR,IAAI,CAACmB,CAAC,CAACC,KAAK;IAC1B,IAAIrB,MAAMmB,MAAM;QACdxB,QAAQW,MAAMG;QACdK,QAAQQ,IAAI,CAAC;IACf;IAEA,IAAIH,QAAQ,QAAQ;QAClBV,IAAIc,GAAG,CAACC,KAAK,CAAC;QACdL,MAAM;IACR;IAEA,IAAI,CAAC1B,mBAAmB0B,MAAM;QAC5B,MAAM,CAACM,QAAQ,GAAG1B,cAAcoB,KAAK5B;QACrCI,OAAO,CAAC;8BACkB,EAAEwB,IAAI;;+BAEL,EAAEM,QAAQ;;;IAGrC,CAAC;QACDX,QAAQQ,IAAI,CAAC;IACf;IAEA,MAAMI,aAAa,MAAMlC,cAAc2B;IAEvC,IAAIV,IAAIR,IAAI,CAAC,KAAK,IAAIQ,IAAIR,IAAI,CAAC,SAAS,EAAE;QACxCN,QAAQ+B,WAAWpB,KAAK,CAACG;QACzBK,QAAQQ,IAAI,CAAC;IACf;IAEA,IAAI;QACF,MAAMI,WAAWnB,OAAO,CAACE,IAAIC,KAAK,CAAC;YAAEH,SAASY;YAAKR,MAAMQ;YAAKP,OAAOc,WAAWzB,IAAI;QAAC;IACvF,EAAE,OAAO0B,OAAO;QACd,MAAM/B,mBAAmBa,KAAKkB;IAChC;AACF,EAAE"}
@@ -0,0 +1,61 @@
1
+ import { ArgError } from "../services/command/arg.js";
2
+ import { getConflicts, printConflicts } from "../services/filesync/conflicts.js";
3
+ import { UnknownDirectoryError } from "../services/filesync/error.js";
4
+ import { FileSync } from "../services/filesync/filesync.js";
5
+ import { SyncJson, SyncJsonArgs, loadSyncJsonDirectory } from "../services/filesync/sync-json.js";
6
+ import { sprint } from "../services/output/sprint.js";
7
+ export const args = SyncJsonArgs;
8
+ export const usage = ()=>{
9
+ return sprint`
10
+ Show file changes since your last dev, push, or pull.
11
+
12
+ {bold USAGE}
13
+
14
+ ggt status
15
+
16
+ {bold EXAMPLES}
17
+
18
+ $ ggt status
19
+ `;
20
+ };
21
+ export const command = async (ctx)=>{
22
+ if (ctx.args._.length > 0) {
23
+ throw new ArgError(sprint`
24
+ "ggt status" does not take any positional arguments.
25
+
26
+ If you are trying to see the status of a specific directory,
27
+ you must "cd" to that directory and then run "ggt status".
28
+
29
+ Run "ggt status -h" for more information.
30
+ `);
31
+ }
32
+ const directory = await loadSyncJsonDirectory(process.cwd());
33
+ const syncJson = await SyncJson.load(ctx, {
34
+ directory
35
+ });
36
+ if (!syncJson) {
37
+ throw new UnknownDirectoryError(ctx, {
38
+ directory
39
+ });
40
+ }
41
+ syncJson.print();
42
+ const filesync = new FileSync(syncJson);
43
+ const hashes = await filesync.hashes(ctx);
44
+ await filesync.print(ctx, {
45
+ hashes
46
+ });
47
+ const conflicts = getConflicts({
48
+ localChanges: hashes.localChanges,
49
+ environmentChanges: hashes.environmentChanges
50
+ });
51
+ if (conflicts.size > 0) {
52
+ ctx.log.debug("conflicts detected", {
53
+ conflicts
54
+ });
55
+ printConflicts({
56
+ conflicts
57
+ });
58
+ }
59
+ };
60
+
61
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/status.ts"],"sourcesContent":["import { ArgError } from \"../services/command/arg.js\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport { getConflicts, printConflicts } from \"../services/filesync/conflicts.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 { sprint } from \"../services/output/sprint.js\";\n\nexport type StatusArgs = typeof args;\n\nexport const args = SyncJsonArgs;\n\nexport const usage: Usage = () => {\n return sprint`\n Show file changes since your last dev, push, or pull.\n\n {bold USAGE}\n\n ggt status\n\n {bold EXAMPLES}\n\n $ ggt status\n `;\n};\n\nexport const command: Command<StatusArgs> = async (ctx) => {\n if (ctx.args._.length > 0) {\n throw new ArgError(sprint`\n \"ggt status\" does not take any positional arguments.\n\n If you are trying to see the status of a specific directory,\n you must \"cd\" to that directory and then run \"ggt status\".\n\n Run \"ggt status -h\" for more information.\n `);\n }\n\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 syncJson.print();\n\n const filesync = new FileSync(syncJson);\n const hashes = await filesync.hashes(ctx);\n await filesync.print(ctx, { hashes });\n\n const conflicts = getConflicts({ localChanges: hashes.localChanges, environmentChanges: hashes.environmentChanges });\n if (conflicts.size > 0) {\n ctx.log.debug(\"conflicts detected\", { conflicts });\n printConflicts({ conflicts });\n }\n};\n"],"names":["ArgError","getConflicts","printConflicts","UnknownDirectoryError","FileSync","SyncJson","SyncJsonArgs","loadSyncJsonDirectory","sprint","args","usage","command","ctx","_","length","directory","process","cwd","syncJson","load","print","filesync","hashes","conflicts","localChanges","environmentChanges","size","log","debug"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,6BAA6B;AAEtD,SAASC,YAAY,EAAEC,cAAc,QAAQ,oCAAoC;AACjF,SAASC,qBAAqB,QAAQ,gCAAgC;AACtE,SAASC,QAAQ,QAAQ,mCAAmC;AAC5D,SAASC,QAAQ,EAAEC,YAAY,EAAEC,qBAAqB,QAAQ,oCAAoC;AAClG,SAASC,MAAM,QAAQ,+BAA+B;AAItD,OAAO,MAAMC,OAAOH,aAAa;AAEjC,OAAO,MAAMI,QAAe;IAC1B,OAAOF,MAAM,CAAC;;;;;;;;;;EAUd,CAAC;AACH,EAAE;AAEF,OAAO,MAAMG,UAA+B,OAAOC;IACjD,IAAIA,IAAIH,IAAI,CAACI,CAAC,CAACC,MAAM,GAAG,GAAG;QACzB,MAAM,IAAId,SAASQ,MAAM,CAAC;;;;;;;IAO1B,CAAC;IACH;IAEA,MAAMO,YAAY,MAAMR,sBAAsBS,QAAQC,GAAG;IACzD,MAAMC,WAAW,MAAMb,SAASc,IAAI,CAACP,KAAK;QAAEG;IAAU;IACtD,IAAI,CAACG,UAAU;QACb,MAAM,IAAIf,sBAAsBS,KAAK;YAAEG;QAAU;IACnD;IAEAG,SAASE,KAAK;IAEd,MAAMC,WAAW,IAAIjB,SAASc;IAC9B,MAAMI,SAAS,MAAMD,SAASC,MAAM,CAACV;IACrC,MAAMS,SAASD,KAAK,CAACR,KAAK;QAAEU;IAAO;IAEnC,MAAMC,YAAYtB,aAAa;QAAEuB,cAAcF,OAAOE,YAAY;QAAEC,oBAAoBH,OAAOG,kBAAkB;IAAC;IAClH,IAAIF,UAAUG,IAAI,GAAG,GAAG;QACtBd,IAAIe,GAAG,CAACC,KAAK,CAAC,sBAAsB;YAAEL;QAAU;QAChDrB,eAAe;YAAEqB;QAAU;IAC7B;AACF,EAAE"}
@@ -1,17 +1,17 @@
1
- import { config } from "../services/config/config.js";
1
+ import { packageJson } from "../services/config/package-json.js";
2
+ import { println } from "../services/output/print.js";
2
3
  import { sprint } from "../services/output/sprint.js";
3
4
  export const usage = ()=>sprint`
4
- Print the version of ggt
5
+ Print this version of ggt.
5
6
 
6
7
  {bold USAGE}
7
8
  ggt version
8
9
 
9
- {bold EXAMPLE}
10
+ {bold EXAMPLES}
10
11
  $ ggt version
11
- ${config.version}
12
12
  `;
13
- export const command = (ctx)=>{
14
- ctx.log.println(config.version);
13
+ export const command = (_ctx)=>{
14
+ println(packageJson.version);
15
15
  };
16
16
 
17
17
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/version.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { config } from \"../services/config/config.js\";\nimport { sprint } from \"../services/output/sprint.js\";\n\nexport const usage: Usage = () => sprint`\n Print the version of ggt\n\n {bold USAGE}\n ggt version\n\n {bold EXAMPLE}\n $ ggt version\n ${config.version}\n`;\n\nexport const command: Command = (ctx) => {\n ctx.log.println(config.version);\n};\n"],"names":["config","sprint","usage","version","command","ctx","log","println"],"mappings":"AACA,SAASA,MAAM,QAAQ,+BAA+B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AAEtD,OAAO,MAAMC,QAAe,IAAMD,MAAM,CAAC;;;;;;;;MAQnC,EAAED,OAAOG,OAAO,CAAC;AACvB,CAAC,CAAC;AAEF,OAAO,MAAMC,UAAmB,CAACC;IAC/BA,IAAIC,GAAG,CAACC,OAAO,CAACP,OAAOG,OAAO;AAChC,EAAE"}
1
+ {"version":3,"sources":["../../src/commands/version.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { packageJson } from \"../services/config/package-json.js\";\nimport { println } from \"../services/output/print.js\";\nimport { sprint } from \"../services/output/sprint.js\";\n\nexport const usage: Usage = () => sprint`\n Print this version of ggt.\n\n {bold USAGE}\n ggt version\n\n {bold EXAMPLES}\n $ ggt version\n`;\n\nexport const command: Command = (_ctx) => {\n println(packageJson.version);\n};\n"],"names":["packageJson","println","sprint","usage","command","_ctx","version"],"mappings":"AACA,SAASA,WAAW,QAAQ,qCAAqC;AACjE,SAASC,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AAEtD,OAAO,MAAMC,QAAe,IAAMD,MAAM,CAAC;;;;;;;;AAQzC,CAAC,CAAC;AAEF,OAAO,MAAME,UAAmB,CAACC;IAC/BJ,QAAQD,YAAYM,OAAO;AAC7B,EAAE"}
@@ -1,25 +1,25 @@
1
+ import { println } from "../services/output/print.js";
1
2
  import { sprint } from "../services/output/sprint.js";
2
3
  import { getUser } from "../services/user/user.js";
3
4
  export const usage = ()=>sprint`
4
- Show the name and email address of the currently logged in user
5
+ Show the name and email address of the currently logged in user.
5
6
 
6
7
  {bold USAGE}
7
8
  ggt whoami
8
9
 
9
- {bold EXAMPLE}
10
+ {bold EXAMPLES}
10
11
  $ ggt whoami
11
- You are logged in as Jane Doe (jane@example.com)
12
12
  `;
13
13
  export const command = async (ctx)=>{
14
14
  const user = await getUser(ctx);
15
15
  if (!user) {
16
- ctx.log.println`You are not logged in`;
16
+ println`You are not logged in`;
17
17
  return;
18
18
  }
19
19
  if (user.name) {
20
- ctx.log.println`You are logged in as ${user.name} {gray (${user.email})}`;
20
+ println`You are logged in as ${user.name} (${user.email})`;
21
21
  } else {
22
- ctx.log.println`You are logged in as ${user.email}`;
22
+ println`You are logged in as ${user.email}`;
23
23
  }
24
24
  };
25
25
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/whoami.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { getUser } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n Show the name and email address of the currently logged in user\n\n {bold USAGE}\n ggt whoami\n\n {bold EXAMPLE}\n $ ggt whoami\n You are logged in as Jane Doe (jane@example.com)\n`;\n\nexport const command: Command = async (ctx) => {\n const user = await getUser(ctx);\n if (!user) {\n ctx.log.println`You are not logged in`;\n return;\n }\n\n if (user.name) {\n ctx.log.println`You are logged in as ${user.name} {gray (${user.email})}`;\n } else {\n ctx.log.println`You are logged in as ${user.email}`;\n }\n};\n"],"names":["sprint","getUser","usage","command","ctx","user","log","println","name","email"],"mappings":"AACA,SAASA,MAAM,QAAQ,+BAA+B;AACtD,SAASC,OAAO,QAAQ,2BAA2B;AAEnD,OAAO,MAAMC,QAAe,IAAMF,MAAM,CAAC;;;;;;;;;AASzC,CAAC,CAAC;AAEF,OAAO,MAAMG,UAAmB,OAAOC;IACrC,MAAMC,OAAO,MAAMJ,QAAQG;IAC3B,IAAI,CAACC,MAAM;QACTD,IAAIE,GAAG,CAACC,OAAO,CAAC,qBAAqB,CAAC;QACtC;IACF;IAEA,IAAIF,KAAKG,IAAI,EAAE;QACbJ,IAAIE,GAAG,CAACC,OAAO,CAAC,qBAAqB,EAAEF,KAAKG,IAAI,CAAC,QAAQ,EAAEH,KAAKI,KAAK,CAAC,EAAE,CAAC;IAC3E,OAAO;QACLL,IAAIE,GAAG,CAACC,OAAO,CAAC,qBAAqB,EAAEF,KAAKI,KAAK,CAAC,CAAC;IACrD;AACF,EAAE"}
1
+ {"version":3,"sources":["../../src/commands/whoami.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { println } from \"../services/output/print.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { getUser } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n Show the name and email address of the currently logged in user.\n\n {bold USAGE}\n ggt whoami\n\n {bold EXAMPLES}\n $ ggt whoami\n`;\n\nexport const command: Command = async (ctx) => {\n const user = await getUser(ctx);\n if (!user) {\n println`You are not logged in`;\n return;\n }\n\n if (user.name) {\n println`You are logged in as ${user.name} (${user.email})`;\n } else {\n println`You are logged in as ${user.email}`;\n }\n};\n"],"names":["println","sprint","getUser","usage","command","ctx","user","name","email"],"mappings":"AACA,SAASA,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,OAAO,QAAQ,2BAA2B;AAEnD,OAAO,MAAMC,QAAe,IAAMF,MAAM,CAAC;;;;;;;;AAQzC,CAAC,CAAC;AAEF,OAAO,MAAMG,UAAmB,OAAOC;IACrC,MAAMC,OAAO,MAAMJ,QAAQG;IAC3B,IAAI,CAACC,MAAM;QACTN,OAAO,CAAC,qBAAqB,CAAC;QAC9B;IACF;IAEA,IAAIM,KAAKC,IAAI,EAAE;QACbP,OAAO,CAAC,qBAAqB,EAAEM,KAAKC,IAAI,CAAC,EAAE,EAAED,KAAKE,KAAK,CAAC,CAAC,CAAC;IAC5D,OAAO;QACLR,OAAO,CAAC,qBAAqB,EAAEM,KAAKE,KAAK,CAAC,CAAC;IAC7C;AACF,EAAE"}
package/lib/ggt.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import ms from "ms";
2
2
  import * as root from "./commands/root.js";
3
3
  import { Context } from "./services/command/context.js";
4
+ import { output } from "./services/output/output.js";
5
+ import { println } from "./services/output/print.js";
4
6
  import { installErrorHandlers, reportErrorAndExit } from "./services/output/report.js";
7
+ import { activeSpinner, spin } from "./services/output/spinner.js";
5
8
  import { installJsonExtensions } from "./services/util/json.js";
6
9
  export const ggt = async (ctx = Context.init({
7
10
  name: "ggt"
@@ -9,26 +12,48 @@ export const ggt = async (ctx = Context.init({
9
12
  installJsonExtensions();
10
13
  installErrorHandlers(ctx);
11
14
  try {
15
+ let stopping = false;
12
16
  for (const signal of [
13
17
  "SIGINT",
14
18
  "SIGTERM"
15
19
  ]){
16
- process.once(signal, ()=>{
20
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
21
+ process.on(signal, async ()=>{
22
+ if (stopping) {
23
+ return;
24
+ }
25
+ stopping = true;
17
26
  ctx.log.trace("received signal", {
18
27
  signal
19
28
  });
20
- ctx.log.println` Stopping... {gray Press Ctrl+C again to force}`;
21
- ctx.abort();
22
- // when ggt is run via npx, and the user presses ctrl+c, npx
23
- // sends sigint twice in quick succession. in order to prevent
24
- // the second sigint from triggering the force exit listener,
25
- // we wait a bit before registering it
26
29
  setTimeout(()=>{
30
+ // when ggt is run with npx, and the user presses ctrl+c, ggt
31
+ // receives SIGINT twice in quick succession. in order to
32
+ // prevent the second SIGINT from triggering the force exit
33
+ // listener, we wait a bit in this setTimeout before adding it
27
34
  process.once(signal, ()=>{
28
- ctx.log.println(" Exiting immediately");
35
+ println(" Exiting immediately");
29
36
  process.exit(1);
30
37
  });
31
38
  }, ms("100ms")).unref();
39
+ // ctrl+c was pressed, so we need to clear the line
40
+ output.writeStdout("\n");
41
+ // if there was any sticky text, it needs to be persisted now
42
+ activeSpinner?.clear();
43
+ output.persistFooter();
44
+ const spinner = spin({
45
+ successSymbol: "👋"
46
+ })`
47
+ Stopping {gray Press Ctrl+C again to force}
48
+ `;
49
+ try {
50
+ ctx.abort();
51
+ await ctx.done;
52
+ spinner.succeed("Goodbye!");
53
+ } catch (error) {
54
+ spinner.fail();
55
+ await reportErrorAndExit(ctx, error);
56
+ }
32
57
  });
33
58
  }
34
59
  await root.command(ctx);
package/lib/ggt.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ggt.ts"],"sourcesContent":["import ms from \"ms\";\nimport * as root from \"./commands/root.js\";\nimport { Context } from \"./services/command/context.js\";\nimport { installErrorHandlers, reportErrorAndExit } from \"./services/output/report.js\";\nimport { installJsonExtensions } from \"./services/util/json.js\";\n\nexport const ggt = async (ctx = Context.init({ name: \"ggt\" })): Promise<void> => {\n installJsonExtensions();\n installErrorHandlers(ctx);\n\n try {\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.once(signal, () => {\n ctx.log.trace(\"received signal\", { signal });\n ctx.log.println` Stopping... {gray Press Ctrl+C again to force}`;\n ctx.abort();\n\n // when ggt is run via npx, and the user presses ctrl+c, npx\n // sends sigint twice in quick succession. in order to prevent\n // the second sigint from triggering the force exit listener,\n // we wait a bit before registering it\n setTimeout(() => {\n process.once(signal, () => {\n ctx.log.println(\" Exiting immediately\");\n process.exit(1);\n });\n }, ms(\"100ms\")).unref();\n });\n }\n\n await root.command(ctx);\n } catch (error) {\n await reportErrorAndExit(ctx, error);\n }\n};\n"],"names":["ms","root","Context","installErrorHandlers","reportErrorAndExit","installJsonExtensions","ggt","ctx","init","name","signal","process","once","log","trace","println","abort","setTimeout","exit","unref","command","error"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,YAAYC,UAAU,qBAAqB;AAC3C,SAASC,OAAO,QAAQ,gCAAgC;AACxD,SAASC,oBAAoB,EAAEC,kBAAkB,QAAQ,8BAA8B;AACvF,SAASC,qBAAqB,QAAQ,0BAA0B;AAEhE,OAAO,MAAMC,MAAM,OAAOC,MAAML,QAAQM,IAAI,CAAC;IAAEC,MAAM;AAAM,EAAE;IAC3DJ;IACAF,qBAAqBI;IAErB,IAAI;QACF,KAAK,MAAMG,UAAU;YAAC;YAAU;SAAU,CAAW;YACnDC,QAAQC,IAAI,CAACF,QAAQ;gBACnBH,IAAIM,GAAG,CAACC,KAAK,CAAC,mBAAmB;oBAAEJ;gBAAO;gBAC1CH,IAAIM,GAAG,CAACE,OAAO,CAAC,+CAA+C,CAAC;gBAChER,IAAIS,KAAK;gBAET,4DAA4D;gBAC5D,8DAA8D;gBAC9D,6DAA6D;gBAC7D,sCAAsC;gBACtCC,WAAW;oBACTN,QAAQC,IAAI,CAACF,QAAQ;wBACnBH,IAAIM,GAAG,CAACE,OAAO,CAAC;wBAChBJ,QAAQO,IAAI,CAAC;oBACf;gBACF,GAAGlB,GAAG,UAAUmB,KAAK;YACvB;QACF;QAEA,MAAMlB,KAAKmB,OAAO,CAACb;IACrB,EAAE,OAAOc,OAAO;QACd,MAAMjB,mBAAmBG,KAAKc;IAChC;AACF,EAAE"}
1
+ {"version":3,"sources":["../src/ggt.ts"],"sourcesContent":["import ms from \"ms\";\nimport * as root from \"./commands/root.js\";\nimport { Context } from \"./services/command/context.js\";\nimport { output } from \"./services/output/output.js\";\nimport { println } from \"./services/output/print.js\";\nimport { installErrorHandlers, reportErrorAndExit } from \"./services/output/report.js\";\nimport { activeSpinner, spin } from \"./services/output/spinner.js\";\nimport { installJsonExtensions } from \"./services/util/json.js\";\n\nexport const ggt = async (ctx = Context.init({ name: \"ggt\" })): Promise<void> => {\n installJsonExtensions();\n installErrorHandlers(ctx);\n\n try {\n let stopping = false;\n\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n process.on(signal, async () => {\n if (stopping) {\n return;\n }\n\n stopping = true;\n ctx.log.trace(\"received signal\", { signal });\n\n setTimeout(() => {\n // when ggt is run with npx, and the user presses ctrl+c, ggt\n // receives SIGINT twice in quick succession. in order to\n // prevent the second SIGINT from triggering the force exit\n // listener, we wait a bit in this setTimeout before adding it\n process.once(signal, () => {\n println(\" Exiting immediately\");\n process.exit(1);\n });\n }, ms(\"100ms\")).unref();\n\n // ctrl+c was pressed, so we need to clear the line\n output.writeStdout(\"\\n\");\n\n // if there was any sticky text, it needs to be persisted now\n activeSpinner?.clear();\n output.persistFooter();\n\n const spinner = spin({ successSymbol: \"👋\" })`\n Stopping {gray Press Ctrl+C again to force}\n `;\n\n try {\n ctx.abort();\n await ctx.done;\n spinner.succeed(\"Goodbye!\");\n } catch (error) {\n spinner.fail();\n await reportErrorAndExit(ctx, error);\n }\n });\n }\n\n await root.command(ctx);\n } catch (error) {\n await reportErrorAndExit(ctx, error);\n }\n};\n"],"names":["ms","root","Context","output","println","installErrorHandlers","reportErrorAndExit","activeSpinner","spin","installJsonExtensions","ggt","ctx","init","name","stopping","signal","process","on","log","trace","setTimeout","once","exit","unref","writeStdout","clear","persistFooter","spinner","successSymbol","abort","done","succeed","error","fail","command"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,YAAYC,UAAU,qBAAqB;AAC3C,SAASC,OAAO,QAAQ,gCAAgC;AACxD,SAASC,MAAM,QAAQ,8BAA8B;AACrD,SAASC,OAAO,QAAQ,6BAA6B;AACrD,SAASC,oBAAoB,EAAEC,kBAAkB,QAAQ,8BAA8B;AACvF,SAASC,aAAa,EAAEC,IAAI,QAAQ,+BAA+B;AACnE,SAASC,qBAAqB,QAAQ,0BAA0B;AAEhE,OAAO,MAAMC,MAAM,OAAOC,MAAMT,QAAQU,IAAI,CAAC;IAAEC,MAAM;AAAM,EAAE;IAC3DJ;IACAJ,qBAAqBM;IAErB,IAAI;QACF,IAAIG,WAAW;QAEf,KAAK,MAAMC,UAAU;YAAC;YAAU;SAAU,CAAW;YACnD,kEAAkE;YAClEC,QAAQC,EAAE,CAACF,QAAQ;gBACjB,IAAID,UAAU;oBACZ;gBACF;gBAEAA,WAAW;gBACXH,IAAIO,GAAG,CAACC,KAAK,CAAC,mBAAmB;oBAAEJ;gBAAO;gBAE1CK,WAAW;oBACT,6DAA6D;oBAC7D,yDAAyD;oBACzD,2DAA2D;oBAC3D,8DAA8D;oBAC9DJ,QAAQK,IAAI,CAACN,QAAQ;wBACnBX,QAAQ;wBACRY,QAAQM,IAAI,CAAC;oBACf;gBACF,GAAGtB,GAAG,UAAUuB,KAAK;gBAErB,mDAAmD;gBACnDpB,OAAOqB,WAAW,CAAC;gBAEnB,6DAA6D;gBAC7DjB,eAAekB;gBACftB,OAAOuB,aAAa;gBAEpB,MAAMC,UAAUnB,KAAK;oBAAEoB,eAAe;gBAAK,EAAE,CAAC;;QAE9C,CAAC;gBAED,IAAI;oBACFjB,IAAIkB,KAAK;oBACT,MAAMlB,IAAImB,IAAI;oBACdH,QAAQI,OAAO,CAAC;gBAClB,EAAE,OAAOC,OAAO;oBACdL,QAAQM,IAAI;oBACZ,MAAM3B,mBAAmBK,KAAKqB;gBAChC;YACF;QACF;QAEA,MAAM/B,KAAKiC,OAAO,CAACvB;IACrB,EAAE,OAAOqB,OAAO;QACd,MAAM1B,mBAAmBK,KAAKqB;IAChC;AACF,EAAE"}
package/lib/main.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { ggt } from "./ggt.js";
3
+ await ggt();
4
+
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ggt } from \"./ggt.js\";\n\nawait ggt();\n"],"names":["ggt"],"mappings":";AAEA,SAASA,GAAG,QAAQ,WAAW;AAE/B,MAAMA"}