@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
@@ -1,41 +1,49 @@
1
1
  import { getApps } from "../services/app/app.js";
2
- import { sprint } from "../services/output/sprint.js";
2
+ import { output } from "../services/output/output.js";
3
+ import { println } from "../services/output/print.js";
4
+ import { sprint, sprintln } from "../services/output/sprint.js";
5
+ import { printTable } from "../services/output/table.js";
3
6
  import { getUserOrLogin } from "../services/user/user.js";
4
7
  export const usage = ()=>sprint`
5
- List the apps available to the currently logged in user.
8
+ List your available applications.
6
9
 
7
10
  {bold USAGE}
8
11
  ggt list
9
12
 
10
- {bold EXAMPLE}
13
+ {bold EXAMPLES}
11
14
  $ ggt list
12
- Slug Domain
13
- ─────── ──────────────────
14
- my-app my-app.gadget.app
15
- example example.gadget.app
16
- test test.gadget.app
17
15
  `;
18
16
  export const command = async (ctx)=>{
19
17
  await getUserOrLogin(ctx);
20
18
  const apps = await getApps(ctx);
21
19
  if (apps.length === 0) {
22
- ctx.log.println`
20
+ println`
23
21
  It doesn't look like you have any applications.
24
22
 
25
23
  Visit https://gadget.new to create one!
26
24
  `;
27
25
  return;
28
26
  }
29
- let longestSlug = 0;
30
- let longestDomain = 0;
31
- for (const app of apps){
32
- longestSlug = Math.max(longestSlug, app.slug.length);
33
- longestDomain = Math.max(longestDomain, app.primaryDomain.length);
34
- }
35
- ctx.log.println`{bold Slug}${" ".repeat(longestSlug - 4)} {bold Domain}`;
36
- ctx.log.println`${"─".repeat(Math.max(longestSlug, 4))} ${"─".repeat(Math.max(longestDomain, 6))}`;
37
- for (const app of apps.sort((a, b)=>a.slug.localeCompare(b.slug))){
38
- ctx.log.println`${app.slug}${" ".repeat(longestSlug - app.slug.length)} ${app.primaryDomain}`;
27
+ if (output.isInteractive) {
28
+ printTable({
29
+ json: apps,
30
+ headers: [
31
+ "Name",
32
+ "Domain"
33
+ ],
34
+ rows: apps.map((app)=>[
35
+ app.slug,
36
+ app.primaryDomain
37
+ ])
38
+ });
39
+ } else {
40
+ let simpleOutput = "";
41
+ for (const app of apps){
42
+ simpleOutput += sprintln`${app.slug}\t${app.primaryDomain}`;
43
+ }
44
+ println({
45
+ json: apps
46
+ })(simpleOutput);
39
47
  }
40
48
  };
41
49
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/list.ts"],"sourcesContent":["import { getApps } from \"../services/app/app.js\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { getUserOrLogin } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n List the apps available to the currently logged in user.\n\n {bold USAGE}\n ggt list\n\n {bold EXAMPLE}\n $ ggt list\n Slug Domain\n ─────── ──────────────────\n my-app my-app.gadget.app\n example example.gadget.app\n test test.gadget.app\n`;\n\nexport const command: Command = async (ctx) => {\n await getUserOrLogin(ctx);\n\n const apps = await getApps(ctx);\n if (apps.length === 0) {\n ctx.log.println`\n It doesn't look like you have any applications.\n\n Visit https://gadget.new to create one!\n `;\n return;\n }\n\n let longestSlug = 0;\n let longestDomain = 0;\n\n for (const app of apps) {\n longestSlug = Math.max(longestSlug, app.slug.length);\n longestDomain = Math.max(longestDomain, app.primaryDomain.length);\n }\n\n ctx.log.println`{bold Slug}${\" \".repeat(longestSlug - 4)} {bold Domain}`;\n ctx.log.println`${\"─\".repeat(Math.max(longestSlug, 4))} ${\"─\".repeat(Math.max(longestDomain, 6))}`;\n for (const app of apps.sort((a, b) => a.slug.localeCompare(b.slug))) {\n ctx.log.println`${app.slug}${\" \".repeat(longestSlug - app.slug.length)} ${app.primaryDomain}`;\n }\n};\n"],"names":["getApps","sprint","getUserOrLogin","usage","command","ctx","apps","length","log","println","longestSlug","longestDomain","app","Math","max","slug","primaryDomain","repeat","sort","a","b","localeCompare"],"mappings":"AAAA,SAASA,OAAO,QAAQ,yBAAyB;AAEjD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,cAAc,QAAQ,2BAA2B;AAE1D,OAAO,MAAMC,QAAe,IAAMF,MAAM,CAAC;;;;;;;;;;;;;AAazC,CAAC,CAAC;AAEF,OAAO,MAAMG,UAAmB,OAAOC;IACrC,MAAMH,eAAeG;IAErB,MAAMC,OAAO,MAAMN,QAAQK;IAC3B,IAAIC,KAAKC,MAAM,KAAK,GAAG;QACrBF,IAAIG,GAAG,CAACC,OAAO,CAAC;;;;IAIhB,CAAC;QACD;IACF;IAEA,IAAIC,cAAc;IAClB,IAAIC,gBAAgB;IAEpB,KAAK,MAAMC,OAAON,KAAM;QACtBI,cAAcG,KAAKC,GAAG,CAACJ,aAAaE,IAAIG,IAAI,CAACR,MAAM;QACnDI,gBAAgBE,KAAKC,GAAG,CAACH,eAAeC,IAAII,aAAa,CAACT,MAAM;IAClE;IAEAF,IAAIG,GAAG,CAACC,OAAO,CAAC,WAAW,EAAE,IAAIQ,MAAM,CAACP,cAAc,GAAG,cAAc,CAAC;IACxEL,IAAIG,GAAG,CAACC,OAAO,CAAC,EAAE,IAAIQ,MAAM,CAACJ,KAAKC,GAAG,CAACJ,aAAa,IAAI,CAAC,EAAE,IAAIO,MAAM,CAACJ,KAAKC,GAAG,CAACH,eAAe,IAAI,CAAC;IAClG,KAAK,MAAMC,OAAON,KAAKY,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEJ,IAAI,CAACM,aAAa,CAACD,EAAEL,IAAI,GAAI;QACnEV,IAAIG,GAAG,CAACC,OAAO,CAAC,EAAEG,IAAIG,IAAI,CAAC,EAAE,IAAIE,MAAM,CAACP,cAAcE,IAAIG,IAAI,CAACR,MAAM,EAAE,CAAC,EAAEK,IAAII,aAAa,CAAC,CAAC;IAC/F;AACF,EAAE"}
1
+ {"version":3,"sources":["../../src/commands/list.ts"],"sourcesContent":["import { getApps } from \"../services/app/app.js\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport { output } from \"../services/output/output.js\";\nimport { println } from \"../services/output/print.js\";\nimport { sprint, sprintln } from \"../services/output/sprint.js\";\nimport { printTable } from \"../services/output/table.js\";\nimport { getUserOrLogin } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n List your available applications.\n\n {bold USAGE}\n ggt list\n\n {bold EXAMPLES}\n $ ggt list\n`;\n\nexport const command: Command = async (ctx) => {\n await getUserOrLogin(ctx);\n\n const apps = await getApps(ctx);\n if (apps.length === 0) {\n println`\n It doesn't look like you have any applications.\n\n Visit https://gadget.new to create one!\n `;\n return;\n }\n\n if (output.isInteractive) {\n printTable({\n json: apps,\n headers: [\"Name\", \"Domain\"],\n rows: apps.map((app) => [app.slug, app.primaryDomain]),\n });\n } else {\n let simpleOutput = \"\";\n for (const app of apps) {\n simpleOutput += sprintln`${app.slug}\\t${app.primaryDomain}`;\n }\n\n println({ json: apps })(simpleOutput);\n }\n};\n"],"names":["getApps","output","println","sprint","sprintln","printTable","getUserOrLogin","usage","command","ctx","apps","length","isInteractive","json","headers","rows","map","app","slug","primaryDomain","simpleOutput"],"mappings":"AAAA,SAASA,OAAO,QAAQ,yBAAyB;AAEjD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,EAAEC,QAAQ,QAAQ,+BAA+B;AAChE,SAASC,UAAU,QAAQ,8BAA8B;AACzD,SAASC,cAAc,QAAQ,2BAA2B;AAE1D,OAAO,MAAMC,QAAe,IAAMJ,MAAM,CAAC;;;;;;;;AAQzC,CAAC,CAAC;AAEF,OAAO,MAAMK,UAAmB,OAAOC;IACrC,MAAMH,eAAeG;IAErB,MAAMC,OAAO,MAAMV,QAAQS;IAC3B,IAAIC,KAAKC,MAAM,KAAK,GAAG;QACrBT,OAAO,CAAC;;;;IAIR,CAAC;QACD;IACF;IAEA,IAAID,OAAOW,aAAa,EAAE;QACxBP,WAAW;YACTQ,MAAMH;YACNI,SAAS;gBAAC;gBAAQ;aAAS;YAC3BC,MAAML,KAAKM,GAAG,CAAC,CAACC,MAAQ;oBAACA,IAAIC,IAAI;oBAAED,IAAIE,aAAa;iBAAC;QACvD;IACF,OAAO;QACL,IAAIC,eAAe;QACnB,KAAK,MAAMH,OAAOP,KAAM;YACtBU,gBAAgBhB,QAAQ,CAAC,EAAEa,IAAIC,IAAI,CAAC,EAAE,EAAED,IAAIE,aAAa,CAAC,CAAC;QAC7D;QAEAjB,QAAQ;YAAEW,MAAMH;QAAK,GAAGU;IAC1B;AACF,EAAE"}
@@ -3,6 +3,7 @@ import assert from "node:assert";
3
3
  import http from "node:http";
4
4
  import open from "open";
5
5
  import { config } from "../services/config/config.js";
6
+ import { println } from "../services/output/print.js";
6
7
  import { sprint } from "../services/output/sprint.js";
7
8
  import { writeSession } from "../services/user/session.js";
8
9
  import { getUser } from "../services/user/user.js";
@@ -12,13 +13,8 @@ export const usage = ()=>sprint`
12
13
  {bold USAGE}
13
14
  ggt login
14
15
 
15
- {bold EXAMPLE}
16
+ {bold EXAMPLES}
16
17
  $ ggt login
17
- We've opened Gadget's login page using your default browser.
18
-
19
- Please log in and then return to this terminal.
20
-
21
- Hello, Jane Doe (jane@example.com)
22
18
  `;
23
19
  export const login = async (ctx)=>{
24
20
  let server;
@@ -36,9 +32,13 @@ export const login = async (ctx)=>{
36
32
  const user = await getUser(ctx);
37
33
  assert(user, "missing user after successful login");
38
34
  if (user.name) {
39
- ctx.log.printlns`Hello, ${user.name} {gray (${user.email})}`;
35
+ println({
36
+ ensureEmptyLineAbove: true
37
+ })`Hello, ${user.name} {gray (${user.email})}`;
40
38
  } else {
41
- ctx.log.printlns`Hello, ${user.email}`;
39
+ println({
40
+ ensureEmptyLineAbove: true
41
+ })`Hello, ${user.email}`;
42
42
  }
43
43
  landingPage.searchParams.set("success", "true");
44
44
  resolve();
@@ -65,16 +65,20 @@ export const login = async (ctx)=>{
65
65
  url.searchParams.set("returnTo", `https://${config.domains.services}/auth/cli/callback?port=${port}`);
66
66
  try {
67
67
  await open(url.toString());
68
- ctx.log.printlns`
68
+ println({
69
+ ensureEmptyLineAbove: true
70
+ })`
69
71
  We've opened Gadget's login page using your default browser.
70
72
 
71
73
  Please log in and then return to this terminal.
72
- `;
74
+ `;
73
75
  } catch (error) {
74
76
  ctx.log.error("failed to open browser", {
75
77
  error
76
78
  });
77
- ctx.log.printlns`
79
+ println({
80
+ ensureEmptyLineAbove: true
81
+ })`
78
82
  Please open the following URL in your browser and log in:
79
83
 
80
84
  {gray ${url.toString()}}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/login.ts"],"sourcesContent":["import getPort from \"get-port\";\nimport assert from \"node:assert\";\nimport http, { type Server } from \"node:http\";\nimport open from \"open\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport { config } from \"../services/config/config.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { writeSession } from \"../services/user/session.js\";\nimport { getUser } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n Log in to your account.\n\n {bold USAGE}\n ggt login\n\n {bold EXAMPLE}\n $ ggt login\n We've opened Gadget's login page using your default browser.\n\n Please log in and then return to this terminal.\n\n Hello, Jane Doe (jane@example.com)\n`;\n\nexport const login: Command = async (ctx): Promise<void> => {\n let server: Server | undefined;\n\n try {\n const port = await getPort();\n const receiveSession = new Promise<void>((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n server = http.createServer(async (req, res) => {\n const landingPage = new URL(`https://${config.domains.services}/auth/cli`);\n\n try {\n assert(req.url, \"missing url\");\n const session = new URL(req.url, `http://localhost:${port}`).searchParams.get(\"session\");\n assert(session, \"missing session\");\n\n writeSession(session);\n\n const user = await getUser(ctx);\n assert(user, \"missing user after successful login\");\n\n if (user.name) {\n ctx.log.printlns`Hello, ${user.name} {gray (${user.email})}`;\n } else {\n ctx.log.printlns`Hello, ${user.email}`;\n }\n\n landingPage.searchParams.set(\"success\", \"true\");\n resolve();\n } catch (error) {\n writeSession(undefined);\n landingPage.searchParams.set(\"success\", \"false\");\n reject(error);\n } finally {\n res.writeHead(303, { Location: landingPage.toString() });\n res.end();\n }\n });\n\n ctx.log.info(\"starting login server\", { port });\n server.listen(port);\n });\n\n // open the login page in the user's default browser have it\n // redirect to the cli callback route. The cli callback route will\n // send the session to the server we just started.\n const url = new URL(`https://${config.domains.services}/auth/login`);\n url.searchParams.set(\"returnTo\", `https://${config.domains.services}/auth/cli/callback?port=${port}`);\n\n try {\n await open(url.toString());\n ctx.log.printlns`\n We've opened Gadget's login page using your default browser.\n\n Please log in and then return to this terminal.\n `;\n } catch (error) {\n ctx.log.error(\"failed to open browser\", { error });\n ctx.log.printlns`\n Please open the following URL in your browser and log in:\n\n {gray ${url.toString()}}\n\n Once logged in, return to this terminal.\n `;\n }\n\n await receiveSession;\n } finally {\n server?.close();\n }\n};\n\nexport const command = login;\n"],"names":["getPort","assert","http","open","config","sprint","writeSession","getUser","usage","login","ctx","server","port","receiveSession","Promise","resolve","reject","createServer","req","res","landingPage","URL","domains","services","url","session","searchParams","get","user","name","log","printlns","email","set","error","undefined","writeHead","Location","toString","end","info","listen","close","command"],"mappings":"AAAA,OAAOA,aAAa,WAAW;AAC/B,OAAOC,YAAY,cAAc;AACjC,OAAOC,UAA2B,YAAY;AAC9C,OAAOC,UAAU,OAAO;AAExB,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,YAAY,QAAQ,8BAA8B;AAC3D,SAASC,OAAO,QAAQ,2BAA2B;AAEnD,OAAO,MAAMC,QAAe,IAAMH,MAAM,CAAC;;;;;;;;;;;;;AAazC,CAAC,CAAC;AAEF,OAAO,MAAMI,QAAiB,OAAOC;IACnC,IAAIC;IAEJ,IAAI;QACF,MAAMC,OAAO,MAAMZ;QACnB,MAAMa,iBAAiB,IAAIC,QAAc,CAACC,SAASC;YACjD,kEAAkE;YAClEL,SAAST,KAAKe,YAAY,CAAC,OAAOC,KAAKC;gBACrC,MAAMC,cAAc,IAAIC,IAAI,CAAC,QAAQ,EAAEjB,OAAOkB,OAAO,CAACC,QAAQ,CAAC,SAAS,CAAC;gBAEzE,IAAI;oBACFtB,OAAOiB,IAAIM,GAAG,EAAE;oBAChB,MAAMC,UAAU,IAAIJ,IAAIH,IAAIM,GAAG,EAAE,CAAC,iBAAiB,EAAEZ,KAAK,CAAC,EAAEc,YAAY,CAACC,GAAG,CAAC;oBAC9E1B,OAAOwB,SAAS;oBAEhBnB,aAAamB;oBAEb,MAAMG,OAAO,MAAMrB,QAAQG;oBAC3BT,OAAO2B,MAAM;oBAEb,IAAIA,KAAKC,IAAI,EAAE;wBACbnB,IAAIoB,GAAG,CAACC,QAAQ,CAAC,OAAO,EAAEH,KAAKC,IAAI,CAAC,QAAQ,EAAED,KAAKI,KAAK,CAAC,EAAE,CAAC;oBAC9D,OAAO;wBACLtB,IAAIoB,GAAG,CAACC,QAAQ,CAAC,OAAO,EAAEH,KAAKI,KAAK,CAAC,CAAC;oBACxC;oBAEAZ,YAAYM,YAAY,CAACO,GAAG,CAAC,WAAW;oBACxClB;gBACF,EAAE,OAAOmB,OAAO;oBACd5B,aAAa6B;oBACbf,YAAYM,YAAY,CAACO,GAAG,CAAC,WAAW;oBACxCjB,OAAOkB;gBACT,SAAU;oBACRf,IAAIiB,SAAS,CAAC,KAAK;wBAAEC,UAAUjB,YAAYkB,QAAQ;oBAAG;oBACtDnB,IAAIoB,GAAG;gBACT;YACF;YAEA7B,IAAIoB,GAAG,CAACU,IAAI,CAAC,yBAAyB;gBAAE5B;YAAK;YAC7CD,OAAO8B,MAAM,CAAC7B;QAChB;QAEA,4DAA4D;QAC5D,kEAAkE;QAClE,kDAAkD;QAClD,MAAMY,MAAM,IAAIH,IAAI,CAAC,QAAQ,EAAEjB,OAAOkB,OAAO,CAACC,QAAQ,CAAC,WAAW,CAAC;QACnEC,IAAIE,YAAY,CAACO,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE7B,OAAOkB,OAAO,CAACC,QAAQ,CAAC,wBAAwB,EAAEX,KAAK,CAAC;QAEpG,IAAI;YACF,MAAMT,KAAKqB,IAAIc,QAAQ;YACvB5B,IAAIoB,GAAG,CAACC,QAAQ,CAAC;;;;IAInB,CAAC;QACD,EAAE,OAAOG,OAAO;YACdxB,IAAIoB,GAAG,CAACI,KAAK,CAAC,0BAA0B;gBAAEA;YAAM;YAChDxB,IAAIoB,GAAG,CAACC,QAAQ,CAAC;;;gBAGP,EAAEP,IAAIc,QAAQ,GAAG;;;MAG3B,CAAC;QACH;QAEA,MAAMzB;IACR,SAAU;QACRF,QAAQ+B;IACV;AACF,EAAE;AAEF,OAAO,MAAMC,UAAUlC,MAAM"}
1
+ {"version":3,"sources":["../../src/commands/login.ts"],"sourcesContent":["import getPort from \"get-port\";\nimport assert from \"node:assert\";\nimport http, { type Server } from \"node:http\";\nimport open from \"open\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport { config } from \"../services/config/config.js\";\nimport { println } from \"../services/output/print.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { writeSession } from \"../services/user/session.js\";\nimport { getUser } from \"../services/user/user.js\";\n\nexport const usage: Usage = () => sprint`\n Log in to your account.\n\n {bold USAGE}\n ggt login\n\n {bold EXAMPLES}\n $ ggt login\n`;\n\nexport const login: Command = async (ctx): Promise<void> => {\n let server: Server | undefined;\n\n try {\n const port = await getPort();\n const receiveSession = new Promise<void>((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n server = http.createServer(async (req, res) => {\n const landingPage = new URL(`https://${config.domains.services}/auth/cli`);\n\n try {\n assert(req.url, \"missing url\");\n const session = new URL(req.url, `http://localhost:${port}`).searchParams.get(\"session\");\n assert(session, \"missing session\");\n\n writeSession(session);\n\n const user = await getUser(ctx);\n assert(user, \"missing user after successful login\");\n\n if (user.name) {\n println({ ensureEmptyLineAbove: true })`Hello, ${user.name} {gray (${user.email})}`;\n } else {\n println({ ensureEmptyLineAbove: true })`Hello, ${user.email}`;\n }\n\n landingPage.searchParams.set(\"success\", \"true\");\n resolve();\n } catch (error) {\n writeSession(undefined);\n landingPage.searchParams.set(\"success\", \"false\");\n reject(error as Error);\n } finally {\n res.writeHead(303, { Location: landingPage.toString() });\n res.end();\n }\n });\n\n ctx.log.info(\"starting login server\", { port });\n server.listen(port);\n });\n\n // open the login page in the user's default browser have it\n // redirect to the cli callback route. The cli callback route will\n // send the session to the server we just started.\n const url = new URL(`https://${config.domains.services}/auth/login`);\n url.searchParams.set(\"returnTo\", `https://${config.domains.services}/auth/cli/callback?port=${port}`);\n\n try {\n await open(url.toString());\n println({ ensureEmptyLineAbove: true })`\n We've opened Gadget's login page using your default browser.\n\n Please log in and then return to this terminal.\n `;\n } catch (error) {\n ctx.log.error(\"failed to open browser\", { error });\n println({ ensureEmptyLineAbove: true })`\n Please open the following URL in your browser and log in:\n\n {gray ${url.toString()}}\n\n Once logged in, return to this terminal.\n `;\n }\n\n await receiveSession;\n } finally {\n server?.close();\n }\n};\n\nexport const command = login;\n"],"names":["getPort","assert","http","open","config","println","sprint","writeSession","getUser","usage","login","ctx","server","port","receiveSession","Promise","resolve","reject","createServer","req","res","landingPage","URL","domains","services","url","session","searchParams","get","user","name","ensureEmptyLineAbove","email","set","error","undefined","writeHead","Location","toString","end","log","info","listen","close","command"],"mappings":"AAAA,OAAOA,aAAa,WAAW;AAC/B,OAAOC,YAAY,cAAc;AACjC,OAAOC,UAA2B,YAAY;AAC9C,OAAOC,UAAU,OAAO;AAExB,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,YAAY,QAAQ,8BAA8B;AAC3D,SAASC,OAAO,QAAQ,2BAA2B;AAEnD,OAAO,MAAMC,QAAe,IAAMH,MAAM,CAAC;;;;;;;;AAQzC,CAAC,CAAC;AAEF,OAAO,MAAMI,QAAiB,OAAOC;IACnC,IAAIC;IAEJ,IAAI;QACF,MAAMC,OAAO,MAAMb;QACnB,MAAMc,iBAAiB,IAAIC,QAAc,CAACC,SAASC;YACjD,kEAAkE;YAClEL,SAASV,KAAKgB,YAAY,CAAC,OAAOC,KAAKC;gBACrC,MAAMC,cAAc,IAAIC,IAAI,CAAC,QAAQ,EAAElB,OAAOmB,OAAO,CAACC,QAAQ,CAAC,SAAS,CAAC;gBAEzE,IAAI;oBACFvB,OAAOkB,IAAIM,GAAG,EAAE;oBAChB,MAAMC,UAAU,IAAIJ,IAAIH,IAAIM,GAAG,EAAE,CAAC,iBAAiB,EAAEZ,KAAK,CAAC,EAAEc,YAAY,CAACC,GAAG,CAAC;oBAC9E3B,OAAOyB,SAAS;oBAEhBnB,aAAamB;oBAEb,MAAMG,OAAO,MAAMrB,QAAQG;oBAC3BV,OAAO4B,MAAM;oBAEb,IAAIA,KAAKC,IAAI,EAAE;wBACbzB,QAAQ;4BAAE0B,sBAAsB;wBAAK,EAAE,CAAC,OAAO,EAAEF,KAAKC,IAAI,CAAC,QAAQ,EAAED,KAAKG,KAAK,CAAC,EAAE,CAAC;oBACrF,OAAO;wBACL3B,QAAQ;4BAAE0B,sBAAsB;wBAAK,EAAE,CAAC,OAAO,EAAEF,KAAKG,KAAK,CAAC,CAAC;oBAC/D;oBAEAX,YAAYM,YAAY,CAACM,GAAG,CAAC,WAAW;oBACxCjB;gBACF,EAAE,OAAOkB,OAAO;oBACd3B,aAAa4B;oBACbd,YAAYM,YAAY,CAACM,GAAG,CAAC,WAAW;oBACxChB,OAAOiB;gBACT,SAAU;oBACRd,IAAIgB,SAAS,CAAC,KAAK;wBAAEC,UAAUhB,YAAYiB,QAAQ;oBAAG;oBACtDlB,IAAImB,GAAG;gBACT;YACF;YAEA5B,IAAI6B,GAAG,CAACC,IAAI,CAAC,yBAAyB;gBAAE5B;YAAK;YAC7CD,OAAO8B,MAAM,CAAC7B;QAChB;QAEA,4DAA4D;QAC5D,kEAAkE;QAClE,kDAAkD;QAClD,MAAMY,MAAM,IAAIH,IAAI,CAAC,QAAQ,EAAElB,OAAOmB,OAAO,CAACC,QAAQ,CAAC,WAAW,CAAC;QACnEC,IAAIE,YAAY,CAACM,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE7B,OAAOmB,OAAO,CAACC,QAAQ,CAAC,wBAAwB,EAAEX,KAAK,CAAC;QAEpG,IAAI;YACF,MAAMV,KAAKsB,IAAIa,QAAQ;YACvBjC,QAAQ;gBAAE0B,sBAAsB;YAAK,EAAE,CAAC;;;;MAIxC,CAAC;QACH,EAAE,OAAOG,OAAO;YACdvB,IAAI6B,GAAG,CAACN,KAAK,CAAC,0BAA0B;gBAAEA;YAAM;YAChD7B,QAAQ;gBAAE0B,sBAAsB;YAAK,EAAE,CAAC;;;gBAG9B,EAAEN,IAAIa,QAAQ,GAAG;;;MAG3B,CAAC;QACH;QAEA,MAAMxB;IACR,SAAU;QACRF,QAAQ+B;IACV;AACF,EAAE;AAEF,OAAO,MAAMC,UAAUlC,MAAM"}
@@ -1,3 +1,4 @@
1
+ import { println } from "../services/output/print.js";
1
2
  import { sprint } from "../services/output/sprint.js";
2
3
  import { readSession, writeSession } from "../services/user/session.js";
3
4
  export const usage = ()=>sprint`
@@ -6,17 +7,16 @@ export const usage = ()=>sprint`
6
7
  {bold USAGE}
7
8
  ggt logout
8
9
 
9
- {bold EXAMPLE}
10
+ {bold EXAMPLES}
10
11
  $ ggt logout
11
- Goodbye
12
12
  `;
13
- export const command = (ctx)=>{
13
+ export const command = (_ctx)=>{
14
14
  const token = readSession();
15
15
  if (token) {
16
16
  writeSession(undefined);
17
- ctx.log.println("Goodbye");
17
+ println("Goodbye");
18
18
  } else {
19
- ctx.log.println("You are not logged in");
19
+ println("You are not logged in");
20
20
  }
21
21
  };
22
22
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/logout.ts"],"sourcesContent":["import type { Command, Usage } from \"../services/command/command.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { readSession, writeSession } from \"../services/user/session.js\";\n\nexport const usage: Usage = () => sprint`\n Log out of your account.\n\n {bold USAGE}\n ggt logout\n\n {bold EXAMPLE}\n $ ggt logout\n Goodbye\n`;\n\nexport const command: Command = (ctx) => {\n const token = readSession();\n if (token) {\n writeSession(undefined);\n ctx.log.println(\"Goodbye\");\n } else {\n ctx.log.println(\"You are not logged in\");\n }\n};\n"],"names":["sprint","readSession","writeSession","usage","command","ctx","token","undefined","log","println"],"mappings":"AACA,SAASA,MAAM,QAAQ,+BAA+B;AACtD,SAASC,WAAW,EAAEC,YAAY,QAAQ,8BAA8B;AAExE,OAAO,MAAMC,QAAe,IAAMH,MAAM,CAAC;;;;;;;;;AASzC,CAAC,CAAC;AAEF,OAAO,MAAMI,UAAmB,CAACC;IAC/B,MAAMC,QAAQL;IACd,IAAIK,OAAO;QACTJ,aAAaK;QACbF,IAAIG,GAAG,CAACC,OAAO,CAAC;IAClB,OAAO;QACLJ,IAAIG,GAAG,CAACC,OAAO,CAAC;IAClB;AACF,EAAE"}
1
+ {"version":3,"sources":["../../src/commands/logout.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 { readSession, writeSession } from \"../services/user/session.js\";\n\nexport const usage: Usage = () => sprint`\n Log out of your account.\n\n {bold USAGE}\n ggt logout\n\n {bold EXAMPLES}\n $ ggt logout\n`;\n\nexport const command: Command = (_ctx) => {\n const token = readSession();\n if (token) {\n writeSession(undefined);\n println(\"Goodbye\");\n } else {\n println(\"You are not logged in\");\n }\n};\n"],"names":["println","sprint","readSession","writeSession","usage","command","_ctx","token","undefined"],"mappings":"AACA,SAASA,OAAO,QAAQ,8BAA8B;AACtD,SAASC,MAAM,QAAQ,+BAA+B;AACtD,SAASC,WAAW,EAAEC,YAAY,QAAQ,8BAA8B;AAExE,OAAO,MAAMC,QAAe,IAAMH,MAAM,CAAC;;;;;;;;AAQzC,CAAC,CAAC;AAEF,OAAO,MAAMI,UAAmB,CAACC;IAC/B,MAAMC,QAAQL;IACd,IAAIK,OAAO;QACTJ,aAAaK;QACbR,QAAQ;IACV,OAAO;QACLA,QAAQ;IACV;AACF,EAAE"}
@@ -0,0 +1,200 @@
1
+ import open from "open";
2
+ import { getModels } from "../services/app/app.js";
3
+ import { ArgError } from "../services/command/arg.js";
4
+ import { UnknownDirectoryError } from "../services/filesync/error.js";
5
+ import { SyncJson, SyncJsonArgs, loadSyncJsonDirectory } from "../services/filesync/sync-json.js";
6
+ import { println } from "../services/output/print.js";
7
+ import { select } from "../services/output/select.js";
8
+ import { sprint } from "../services/output/sprint.js";
9
+ import { sortBySimilar } from "../services/util/collection.js";
10
+ import { isNever } from "../services/util/is.js";
11
+ export const args = {
12
+ ...SyncJsonArgs,
13
+ "--show-all": {
14
+ type: Boolean
15
+ }
16
+ };
17
+ export const usage = (ctx)=>{
18
+ if (ctx.args["-h"]) {
19
+ return sprint`
20
+ Open a Gadget location in your browser.
21
+
22
+ {bold USAGE}
23
+ ggt open [LOCATION] [MODEL]
24
+
25
+ {bold EXAMPLES}
26
+ $ ggt open
27
+ $ ggt open logs
28
+ $ ggt open permissions
29
+ $ ggt open data modelA
30
+ $ ggt open schema modelA
31
+ $ ggt open data --show-all
32
+ $ ggt open schema --show-all
33
+
34
+ {bold ARGUMENTS}
35
+ LOCATION The location to open
36
+ MODEL The model to open
37
+
38
+ {bold FLAGS}
39
+ -a, --app=<name> The application to open
40
+ -e, --env=<env> The environment to open
41
+ --show-all Show all available models to open
42
+
43
+ Run "ggt open --help" for more information.
44
+ `;
45
+ }
46
+ return sprint`
47
+ Open a Gadget location in your browser.
48
+
49
+ {bold USAGE}
50
+
51
+ ggt open [LOCATION] [MODEL] [--show-all]
52
+ [--app=<name>] [--env=<name>]
53
+
54
+ {bold EXAMPLES}
55
+
56
+ $ ggt open
57
+ $ ggt open logs
58
+ $ ggt open permissions
59
+ $ ggt open data modelA
60
+ $ ggt open schema modelA
61
+ $ ggt open data --show-all
62
+ $ ggt open schema --show-all
63
+
64
+ {bold ARGUMENTS}
65
+
66
+ LOCATION
67
+ The location to open in the browser.
68
+
69
+ Can be one of the following:
70
+ logs The log viewer
71
+ permissions The permissions settings
72
+ data The data viewer for the chosen model
73
+ schema The schema viewer for the chosen model
74
+
75
+ Defaults to opening the editor.
76
+
77
+ MODEL
78
+ The model to open in the browser.
79
+
80
+ Only required for the "data" and "schema" locations.
81
+
82
+ {bold FLAGS}
83
+
84
+ -a, --app, --application=<name>
85
+ The application to open.
86
+
87
+ Defaults to the application within the ".gadget/sync.json"
88
+ file in the current directory or any parent directories.
89
+
90
+ -e, --env, --environment=<name>
91
+ The environment to open.
92
+
93
+ Defaults to the environment within the ".gadget/sync.json"
94
+ file in the current directory or any parent directories.
95
+
96
+ --show-all
97
+ Makes "ggt open" display available models to open rather than
98
+ exiting with an error if a model is not specified.
99
+
100
+ Defaults to false.
101
+
102
+ Run "ggt open -h" for less information.
103
+ `;
104
+ };
105
+ export const command = async (ctx)=>{
106
+ const directory = await loadSyncJsonDirectory(process.cwd());
107
+ const syncJson = await SyncJson.load(ctx, {
108
+ directory
109
+ });
110
+ if (!syncJson) {
111
+ throw new UnknownDirectoryError(ctx, {
112
+ directory
113
+ });
114
+ }
115
+ const location = ctx.args._[0];
116
+ if (!location) {
117
+ await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}`);
118
+ println`
119
+ Opened editor for environment {cyanBright ${syncJson.env.name}}.
120
+ `;
121
+ return;
122
+ }
123
+ if (!Locations.includes(location)) {
124
+ const [closest] = sortBySimilar(location, Locations);
125
+ throw new ArgError(sprint`
126
+ Unknown location {yellow ${location}}
127
+
128
+ Did you mean {blueBright ${closest}}?
129
+
130
+ Run "ggt open -h" for usage.
131
+ `);
132
+ }
133
+ switch(location){
134
+ case "logs":
135
+ {
136
+ await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/logs`);
137
+ println`
138
+ Opened log viewer for environment {cyanBright ${syncJson.env.name}}.
139
+ `;
140
+ break;
141
+ }
142
+ case "permissions":
143
+ {
144
+ await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/settings/permissions`);
145
+ println`
146
+ Opened permissions settings for environment {cyanBright ${syncJson.env.name}}.
147
+ `;
148
+ break;
149
+ }
150
+ case "data":
151
+ case "schema":
152
+ {
153
+ const view = ctx.args._[0];
154
+ const remoteModelApiIdentifiers = (await getModels(ctx)).map((e)=>e.apiIdentifier);
155
+ let modelApiIdentifier = ctx.args._[1];
156
+ if (!modelApiIdentifier) {
157
+ if (ctx.args["--show-all"]) {
158
+ modelApiIdentifier = await select({
159
+ choices: remoteModelApiIdentifiers
160
+ })("Which model do you wish to open?");
161
+ } else {
162
+ throw new ArgError(sprint`
163
+ "ggt open ${view}" requires a model to be specified.
164
+
165
+ Run with "--show-all" to choose from available models.
166
+
167
+ ggt open ${view} --show-all
168
+ `);
169
+ }
170
+ }
171
+ if (!remoteModelApiIdentifiers.includes(modelApiIdentifier)) {
172
+ const [closest] = sortBySimilar(modelApiIdentifier, remoteModelApiIdentifiers);
173
+ throw new ArgError(sprint`
174
+ Unknown model {yellow ${modelApiIdentifier}}
175
+
176
+ Did you mean {blueBright ${closest}}?
177
+
178
+ Run with "--show-all" to choose from available models.
179
+
180
+ ggt open ${view} --show-all
181
+ `);
182
+ }
183
+ await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/model/${modelApiIdentifier}/${view}`);
184
+ println`
185
+ Opened ${view} viewer for environment {cyanBright ${syncJson.env.name}} for model {cyanBright ${modelApiIdentifier}}.
186
+ `;
187
+ break;
188
+ }
189
+ default:
190
+ isNever(location);
191
+ }
192
+ };
193
+ const Locations = [
194
+ "logs",
195
+ "permissions",
196
+ "data",
197
+ "schema"
198
+ ];
199
+
200
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/open.ts"],"sourcesContent":["import open from \"open\";\nimport { getModels } from \"../services/app/app.js\";\nimport { ArgError } from \"../services/command/arg.js\";\nimport type { Command, Usage } from \"../services/command/command.js\";\nimport { UnknownDirectoryError } from \"../services/filesync/error.js\";\nimport { SyncJson, SyncJsonArgs, loadSyncJsonDirectory } from \"../services/filesync/sync-json.js\";\nimport { println } from \"../services/output/print.js\";\nimport { select } from \"../services/output/select.js\";\nimport { sprint } from \"../services/output/sprint.js\";\nimport { sortBySimilar } from \"../services/util/collection.js\";\nimport { isNever } from \"../services/util/is.js\";\n\nexport type OpenArgs = typeof args;\n\nexport const args = {\n ...SyncJsonArgs,\n \"--show-all\": { type: Boolean },\n};\n\nexport const usage: Usage = (ctx) => {\n if (ctx.args[\"-h\"]) {\n return sprint`\n Open a Gadget location in your browser.\n\n {bold USAGE}\n ggt open [LOCATION] [MODEL]\n\n {bold EXAMPLES}\n $ ggt open\n $ ggt open logs\n $ ggt open permissions\n $ ggt open data modelA\n $ ggt open schema modelA\n $ ggt open data --show-all\n $ ggt open schema --show-all\n\n {bold ARGUMENTS}\n LOCATION The location to open\n MODEL The model to open\n\n {bold FLAGS}\n -a, --app=<name> The application to open\n -e, --env=<env> The environment to open\n --show-all Show all available models to open\n\n Run \"ggt open --help\" for more information.\n `;\n }\n\n return sprint`\n Open a Gadget location in your browser.\n\n {bold USAGE}\n\n ggt open [LOCATION] [MODEL] [--show-all]\n [--app=<name>] [--env=<name>]\n\n {bold EXAMPLES}\n\n $ ggt open\n $ ggt open logs\n $ ggt open permissions\n $ ggt open data modelA\n $ ggt open schema modelA\n $ ggt open data --show-all\n $ ggt open schema --show-all\n\n {bold ARGUMENTS}\n\n LOCATION\n The location to open in the browser.\n\n Can be one of the following:\n logs The log viewer\n permissions The permissions settings\n data The data viewer for the chosen model\n schema The schema viewer for the chosen model\n\n Defaults to opening the editor.\n\n MODEL\n The model to open in the browser.\n\n Only required for the \"data\" and \"schema\" locations.\n\n {bold FLAGS}\n\n -a, --app, --application=<name>\n The application to open.\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 open.\n\n Defaults to the environment within the \".gadget/sync.json\"\n file in the current directory or any parent directories.\n\n --show-all\n Makes \"ggt open\" display available models to open rather than\n exiting with an error if a model is not specified.\n\n Defaults to false.\n\n Run \"ggt open -h\" for less information.\n `;\n};\n\nexport const command: Command<OpenArgs> = 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 location = ctx.args._[0] as Location | undefined;\n if (!location) {\n await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}`);\n println`\n Opened editor for environment {cyanBright ${syncJson.env.name}}.\n `;\n return;\n }\n\n if (!Locations.includes(location)) {\n const [closest] = sortBySimilar(location, Locations);\n throw new ArgError(sprint`\n Unknown location {yellow ${location}}\n\n Did you mean {blueBright ${closest}}?\n\n Run \"ggt open -h\" for usage.\n `);\n }\n\n switch (location) {\n case \"logs\": {\n await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/logs`);\n println`\n Opened log viewer for environment {cyanBright ${syncJson.env.name}}.\n `;\n break;\n }\n case \"permissions\": {\n await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/settings/permissions`);\n println`\n Opened permissions settings for environment {cyanBright ${syncJson.env.name}}.\n `;\n break;\n }\n case \"data\":\n case \"schema\": {\n const view = ctx.args._[0];\n const remoteModelApiIdentifiers = (await getModels(ctx)).map((e) => e.apiIdentifier);\n\n let modelApiIdentifier = ctx.args._[1];\n if (!modelApiIdentifier) {\n if (ctx.args[\"--show-all\"]) {\n modelApiIdentifier = await select({ choices: remoteModelApiIdentifiers })(\"Which model do you wish to open?\");\n } else {\n throw new ArgError(sprint`\n \"ggt open ${view}\" requires a model to be specified.\n\n Run with \"--show-all\" to choose from available models.\n\n ggt open ${view} --show-all\n `);\n }\n }\n\n if (!remoteModelApiIdentifiers.includes(modelApiIdentifier)) {\n const [closest] = sortBySimilar(modelApiIdentifier, remoteModelApiIdentifiers);\n throw new ArgError(sprint`\n Unknown model {yellow ${modelApiIdentifier}}\n\n Did you mean {blueBright ${closest}}?\n\n Run with \"--show-all\" to choose from available models.\n\n ggt open ${view} --show-all\n `);\n }\n\n await open(`https://${syncJson.app.primaryDomain}/edit/${syncJson.env.name}/model/${modelApiIdentifier}/${view}`);\n println`\n Opened ${view} viewer for environment {cyanBright ${syncJson.env.name}} for model {cyanBright ${modelApiIdentifier}}.\n `;\n break;\n }\n default:\n isNever(location);\n }\n};\n\nconst Locations = [\"logs\", \"permissions\", \"data\", \"schema\"] as const;\n\ntype Location = (typeof Locations)[number];\n"],"names":["open","getModels","ArgError","UnknownDirectoryError","SyncJson","SyncJsonArgs","loadSyncJsonDirectory","println","select","sprint","sortBySimilar","isNever","args","type","Boolean","usage","ctx","command","directory","process","cwd","syncJson","load","location","_","app","primaryDomain","env","name","Locations","includes","closest","view","remoteModelApiIdentifiers","map","e","apiIdentifier","modelApiIdentifier","choices"],"mappings":"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"}
@@ -0,0 +1,128 @@
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
+ Pull your environment's files to your local filesystem.
17
+ Changes are tracked from the last "ggt dev", "ggt push", or
18
+ "ggt pull" run locally.
19
+
20
+ {bold USAGE}
21
+ ggt pull
22
+
23
+ {bold EXAMPLES}
24
+ $ ggt pull
25
+ $ ggt pull --env=staging
26
+ $ ggt pull --env=staging --force
27
+
28
+ {bold FLAGS}
29
+ -a, --app=<name> The application to pull files from
30
+ -e, --env=<name> The environment to pull files from
31
+ --force Discard changes to your local filesystem
32
+
33
+ Run "ggt pull --help" for more information.
34
+ `;
35
+ }
36
+ return sprint`
37
+ Pull your environment's files to your local filesystem.
38
+ Changes are tracked from the last "ggt dev", "ggt push", or
39
+ "ggt pull" run locally.
40
+
41
+ If you have un-pushed changes, and "--force" is not passed,
42
+ you will be prompted to {underline discard them} or abort the pull.
43
+
44
+ {bold USAGE}
45
+
46
+ ggt pull [--app=<name>] [--env=<name>] [--force]
47
+ [--allow-unknown-directory] [--allow-different-app]
48
+
49
+ {bold EXAMPLES}
50
+
51
+ $ ggt pull
52
+ $ ggt pull --env=staging
53
+ $ ggt pull --env=staging --force
54
+ $ ggt pull --env=staging --force --allow-unknown-directory
55
+
56
+ {bold FLAGS}
57
+
58
+ -a, --app, --application=<name>
59
+ The application to pull files from.
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 pull files from.
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 local 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 pull" 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 pull" 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 pull -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 pull" does not take any positional arguments.
96
+
97
+ If you are trying to pull changes to a specific directory,
98
+ you must "cd" to that directory and then run "ggt push".
99
+
100
+ Run "ggt pull -h" for more information.
101
+ `);
102
+ }
103
+ const directory = await loadSyncJsonDirectory(process.cwd());
104
+ const syncJson = await SyncJson.loadOrInit(ctx, {
105
+ directory
106
+ });
107
+ const filesync = new FileSync(syncJson);
108
+ const hashes = await filesync.hashes(ctx);
109
+ if (hashes.environmentChangesToPull.size === 0) {
110
+ println({
111
+ ensureEmptyLineAbove: true
112
+ })`
113
+ Nothing to pull.
114
+ `;
115
+ return;
116
+ }
117
+ if (hashes.localChangesToPush.size > 0) {
118
+ // show them the local changes they will discard
119
+ await filesync.print(ctx, {
120
+ hashes
121
+ });
122
+ }
123
+ await filesync.pull(ctx, {
124
+ hashes
125
+ });
126
+ };
127
+
128
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/pull.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 PullArgs = 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 Pull your environment's files to your local filesystem.\n Changes are tracked from the last \"ggt dev\", \"ggt push\", or\n \"ggt pull\" run locally.\n\n {bold USAGE}\n ggt pull\n\n {bold EXAMPLES}\n $ ggt pull\n $ ggt pull --env=staging\n $ ggt pull --env=staging --force\n\n {bold FLAGS}\n -a, --app=<name> The application to pull files from\n -e, --env=<name> The environment to pull files from\n --force Discard changes to your local filesystem\n\n Run \"ggt pull --help\" for more information.\n `;\n }\n\n return sprint`\n Pull your environment's files to your local filesystem.\n Changes are tracked from the last \"ggt dev\", \"ggt push\", or\n \"ggt pull\" run locally.\n\n If you have un-pushed changes, and \"--force\" is not passed,\n you will be prompted to {underline discard them} or abort the pull.\n\n {bold USAGE}\n\n ggt pull [--app=<name>] [--env=<name>] [--force]\n [--allow-unknown-directory] [--allow-different-app]\n\n {bold EXAMPLES}\n\n $ ggt pull\n $ ggt pull --env=staging\n $ ggt pull --env=staging --force\n $ ggt pull --env=staging --force --allow-unknown-directory\n\n {bold FLAGS}\n\n -a, --app, --application=<name>\n The application to pull files from.\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 pull files from.\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 local 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 pull\" 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 pull\" 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 pull -h\" for less information.\n `;\n};\n\nexport const command: Command<PullArgs> = async (ctx) => {\n if (ctx.args._.length > 0) {\n throw new ArgError(sprint`\n \"ggt pull\" does not take any positional arguments.\n\n If you are trying to pull changes to a specific directory,\n you must \"cd\" to that directory and then run \"ggt push\".\n\n Run \"ggt pull -h\" for more information.\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.environmentChangesToPull.size === 0) {\n println({ ensureEmptyLineAbove: true })`\n Nothing to pull.\n `;\n return;\n }\n\n if (hashes.localChangesToPush.size > 0) {\n // show them the local changes they will discard\n await filesync.print(ctx, { hashes });\n }\n\n await filesync.pull(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","environmentChangesToPull","size","ensureEmptyLineAbove","localChangesToPush","print","pull"],"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,UAA6B,OAAOD;IAC/C,IAAIA,IAAIL,IAAI,CAACO,CAAC,CAACC,MAAM,GAAG,GAAG;QACzB,MAAM,IAAIf,SAASM,MAAM,CAAC;;;;;;;IAO1B,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,wBAAwB,CAACC,IAAI,KAAK,GAAG;QAC9CnB,QAAQ;YAAEoB,sBAAsB;QAAK,EAAE,CAAC;;IAExC,CAAC;QACD;IACF;IAEA,IAAIH,OAAOI,kBAAkB,CAACF,IAAI,GAAG,GAAG;QACtC,gDAAgD;QAChD,MAAMH,SAASM,KAAK,CAACf,KAAK;YAAEU;QAAO;IACrC;IAEA,MAAMD,SAASO,IAAI,CAAChB,KAAK;QAAEU;IAAO;AACpC,EAAE"}