@shopify/cli-kit 3.9.2 → 3.11.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 (95) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/api/admin.js +2 -6
  3. package/dist/api/admin.js.map +1 -1
  4. package/dist/api/graphql/index.d.ts +0 -5
  5. package/dist/api/graphql/index.js +0 -5
  6. package/dist/api/graphql/index.js.map +1 -1
  7. package/dist/api/identity.js +2 -2
  8. package/dist/api/identity.js.map +1 -1
  9. package/dist/api/partners.js +2 -10
  10. package/dist/api/partners.js.map +1 -1
  11. package/dist/array.d.ts +2 -0
  12. package/dist/array.js +6 -0
  13. package/dist/array.js.map +1 -1
  14. package/dist/common/result.d.ts +17 -0
  15. package/dist/common/result.js +31 -0
  16. package/dist/common/result.js.map +1 -0
  17. package/dist/constants.d.ts +5 -4
  18. package/dist/constants.js +6 -4
  19. package/dist/constants.js.map +1 -1
  20. package/dist/environment/fqdn.js +4 -4
  21. package/dist/environment/fqdn.js.map +1 -1
  22. package/dist/environment/local.d.ts +2 -0
  23. package/dist/environment/local.js +9 -0
  24. package/dist/environment/local.js.map +1 -1
  25. package/dist/environment/service.d.ts +2 -17
  26. package/dist/environment/service.js +5 -46
  27. package/dist/environment/service.js.map +1 -1
  28. package/dist/environment/spin-cache.d.ts +2 -0
  29. package/dist/environment/spin-cache.js +8 -0
  30. package/dist/environment/spin-cache.js.map +1 -0
  31. package/dist/environment/spin.d.ts +3 -0
  32. package/dist/environment/spin.js +19 -3
  33. package/dist/environment/spin.js.map +0 -1
  34. package/dist/error.d.ts +0 -1
  35. package/dist/error.js +0 -1
  36. package/dist/error.js.map +1 -1
  37. package/dist/http/fetch.d.ts +1 -2
  38. package/dist/http/fetch.js +2 -2
  39. package/dist/http/fetch.js.map +1 -1
  40. package/dist/http/graphql.d.ts +0 -2
  41. package/dist/http/graphql.js +1 -1
  42. package/dist/http/graphql.js.map +1 -1
  43. package/dist/http.d.ts +2 -3
  44. package/dist/http.js +5 -5
  45. package/dist/http.js.map +1 -1
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.js +1 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/log.d.ts +21 -0
  50. package/dist/log.js +155 -0
  51. package/dist/log.js.map +1 -0
  52. package/dist/node/cli.js +0 -12
  53. package/dist/node/cli.js.map +1 -1
  54. package/dist/node/error-handler.js +16 -0
  55. package/dist/node/error-handler.js.map +1 -1
  56. package/dist/node/hooks/init.js +2 -4
  57. package/dist/node/hooks/init.js.map +1 -1
  58. package/dist/node/node-package-manager.d.ts +2 -2
  59. package/dist/node/node-package-manager.js +9 -16
  60. package/dist/node/node-package-manager.js.map +1 -1
  61. package/dist/node/ruby.js +0 -10
  62. package/dist/node/ruby.js.map +1 -1
  63. package/dist/output.d.ts +9 -9
  64. package/dist/output.js +16 -100
  65. package/dist/output.js.map +1 -1
  66. package/dist/plugins.d.ts +25 -8
  67. package/dist/plugins.js +33 -11
  68. package/dist/plugins.js.map +1 -1
  69. package/dist/port.js +1 -1
  70. package/dist/port.js.map +1 -1
  71. package/dist/session/device-authorization.d.ts +32 -0
  72. package/dist/session/device-authorization.js +86 -0
  73. package/dist/session/device-authorization.js.map +1 -0
  74. package/dist/session/exchange.d.ts +11 -0
  75. package/dist/session/exchange.js +22 -2
  76. package/dist/session/exchange.js.map +1 -1
  77. package/dist/session/identity.js +5 -5
  78. package/dist/session/identity.js.map +1 -1
  79. package/dist/session/store.js +4 -4
  80. package/dist/session/store.js.map +1 -1
  81. package/dist/session.js +21 -7
  82. package/dist/session.js.map +1 -1
  83. package/dist/store.d.ts +19 -5
  84. package/dist/store.js +39 -13
  85. package/dist/store.js.map +1 -1
  86. package/dist/string.d.ts +5 -0
  87. package/dist/string.js +23 -0
  88. package/dist/string.js.map +1 -1
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/dist/ui.js +2 -1
  91. package/dist/ui.js.map +1 -1
  92. package/package.json +8 -1
  93. package/dist/api/graphql/functions/get_app_functions.d.ts +0 -1
  94. package/dist/api/graphql/functions/get_app_functions.js +0 -10
  95. package/dist/api/graphql/functions/get_app_functions.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/session/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAC/B,OAAO,EACL,OAAO,IAAI,kBAAkB,EAC7B,QAAQ,IAAI,mBAAmB,EAC/B,QAAQ,IAAI,mBAAmB,GAChC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAGjD,MAAM,UAAU,QAAQ;IACtB,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAA;IACzC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;QACrC,OAAO,sCAAsC,CAAA;KAC9C;SAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;QACjD,OAAO,sCAAsC,CAAA;KAC9C;SAAM;QACL,OAAO,sCAAsC,CAAA;KAC9C;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,QAAQ,GAAG,EAAE;QACX,KAAK,OAAO,CAAC,CAAC;YACZ,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,kEAAkE,CAAA;aAC1E;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,kEAAkE,CAAA;aAC1E;iBAAM;gBACL,OAAO,kEAAkE,CAAA;aAC1E;SACF;QACD,KAAK,UAAU,CAAC,CAAC;YACf,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAA;YACzC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,kEAAkE,CAAA;aAC1E;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,kEAAkE,CAAA;aAC1E;iBAAM;gBACL,OAAO,kEAAkE,CAAA;aAC1E;SACF;QACD,KAAK,qBAAqB,CAAC,CAAC;YAC1B,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,sCAAsC,CAAA;aAC9C;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,sCAAsC,CAAA;aAC9C;iBAAM;gBACL,OAAO,sCAAsC,CAAA;aAC9C;SACF;QACD;YACE,MAAM,IAAI,GAAG,CAAC,mCAAmC,GAAG,EAAE,CAAC,CAAA;KAC1D;AACH,CAAC","sourcesContent":["import {Bug} from '../error.js'\nimport {\n shopify as shopifyEnvironment,\n partners as partnersEnvironment,\n identity as identityEnvironment,\n} from '../environment/service.js'\nimport {Environment} from '../network/service.js'\nimport {API} from '../network/api.js'\n\nexport function clientId(): string {\n const environment = identityEnvironment()\n if (environment === Environment.Local) {\n return 'e5380e02-312a-7408-5718-e07017e9cf52'\n } else if (environment === Environment.Production) {\n return 'fbdb2649-e327-4907-8f67-908d24cfd7e3'\n } else {\n return 'e5380e02-312a-7408-5718-e07017e9cf52'\n }\n}\n\nexport function applicationId(api: API): string {\n switch (api) {\n case 'admin': {\n const environment = shopifyEnvironment()\n if (environment === Environment.Local) {\n return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52'\n } else if (environment === Environment.Production) {\n return '7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c'\n } else {\n return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52'\n }\n }\n case 'partners': {\n const environment = partnersEnvironment()\n if (environment === Environment.Local) {\n return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978'\n } else if (environment === Environment.Production) {\n return '271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6'\n } else {\n return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978'\n }\n }\n case 'storefront-renderer': {\n const environment = shopifyEnvironment()\n if (environment === Environment.Local) {\n return '46f603de-894f-488d-9471-5b721280ff49'\n } else if (environment === Environment.Production) {\n return 'ee139b3d-5861-4d45-b387-1bc3ada7811c'\n } else {\n return '46f603de-894f-488d-9471-5b721280ff49'\n }\n }\n default:\n throw new Bug(`Application id for API of type: ${api}`)\n }\n}\n"]}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/session/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAEjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,2BAA2B,CAAA;AAE5D,MAAM,UAAU,QAAQ;IACtB,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;IACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;QACrC,OAAO,sCAAsC,CAAA;KAC9C;SAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;QACjD,OAAO,sCAAsC,CAAA;KAC9C;SAAM;QACL,OAAO,sCAAsC,CAAA;KAC9C;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,QAAQ,GAAG,EAAE;QACX,KAAK,OAAO,CAAC,CAAC;YACZ,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,kEAAkE,CAAA;aAC1E;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,kEAAkE,CAAA;aAC1E;iBAAM;gBACL,OAAO,kEAAkE,CAAA;aAC1E;SACF;QACD,KAAK,UAAU,CAAC,CAAC;YACf,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,kEAAkE,CAAA;aAC1E;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,kEAAkE,CAAA;aAC1E;iBAAM;gBACL,OAAO,kEAAkE,CAAA;aAC1E;SACF;QACD,KAAK,qBAAqB,CAAC,CAAC;YAC1B,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,sCAAsC,CAAA;aAC9C;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,sCAAsC,CAAA;aAC9C;iBAAM;gBACL,OAAO,sCAAsC,CAAA;aAC9C;SACF;QACD;YACE,MAAM,IAAI,GAAG,CAAC,mCAAmC,GAAG,EAAE,CAAC,CAAA;KAC1D;AACH,CAAC","sourcesContent":["import {Bug} from '../error.js'\nimport {Environment} from '../network/service.js'\nimport {API} from '../network/api.js'\nimport {serviceEnvironment} from '../environment/service.js'\n\nexport function clientId(): string {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return 'e5380e02-312a-7408-5718-e07017e9cf52'\n } else if (environment === Environment.Production) {\n return 'fbdb2649-e327-4907-8f67-908d24cfd7e3'\n } else {\n return 'e5380e02-312a-7408-5718-e07017e9cf52'\n }\n}\n\nexport function applicationId(api: API): string {\n switch (api) {\n case 'admin': {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52'\n } else if (environment === Environment.Production) {\n return '7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c'\n } else {\n return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52'\n }\n }\n case 'partners': {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978'\n } else if (environment === Environment.Production) {\n return '271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6'\n } else {\n return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978'\n }\n }\n case 'storefront-renderer': {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return '46f603de-894f-488d-9471-5b721280ff49'\n } else if (environment === Environment.Production) {\n return 'ee139b3d-5861-4d45-b387-1bc3ada7811c'\n } else {\n return '46f603de-894f-488d-9471-5b721280ff49'\n }\n }\n default:\n throw new Bug(`Application id for API of type: ${api}`)\n }\n}\n"]}
@@ -2,8 +2,8 @@ import { SessionSchema } from './schema.js';
2
2
  import constants from '../constants.js';
3
3
  import { platformAndArch } from '../os.js';
4
4
  import { store as secureStore, fetch as secureFetch, remove as secureRemove } from '../secure-store.js';
5
- import { cliKitStore } from '../store.js';
6
5
  import { content, debug } from '../output.js';
6
+ import { getSession, removeSession, setSession } from '../store.js';
7
7
  /**
8
8
  * The identifier of the session in the secure store.
9
9
  */
@@ -19,7 +19,7 @@ export async function store(session) {
19
19
  await secureStore(identifier, jsonSession);
20
20
  }
21
21
  else {
22
- await cliKitStore().setSession(jsonSession);
22
+ await setSession(jsonSession);
23
23
  }
24
24
  }
25
25
  /**
@@ -36,7 +36,7 @@ export async function fetch() {
36
36
  content = await secureFetch(identifier);
37
37
  }
38
38
  else {
39
- content = cliKitStore().getSession();
39
+ content = await getSession();
40
40
  }
41
41
  if (!content) {
42
42
  return undefined;
@@ -59,7 +59,7 @@ export async function remove() {
59
59
  await secureRemove(identifier);
60
60
  }
61
61
  else {
62
- cliKitStore().removeSession();
62
+ await removeSession();
63
63
  }
64
64
  }
65
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,UAAU,CAAA;AACxC,OAAO,EAAC,KAAK,IAAI,WAAW,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,IAAI,YAAY,EAAC,MAAM,oBAAoB,CAAA;AACrG,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AACvC,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AAG3C;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAgB;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,WAAW,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;KAC5C;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,OAAO,CAAA;IACX,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAA;KACxC;SAAM;QACL,OAAO,GAAG,WAAW,EAAE,CAAC,UAAU,EAAE,CAAA;KACrC;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,SAAS,CAAA;KACjB;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IACrE,IAAI,aAAa,CAAC,OAAO,EAAE;QACzB,OAAO,aAAa,CAAC,IAAI,CAAA;KAC1B;SAAM;QACL,MAAM,MAAM,EAAE,CAAA;QACd,OAAO,SAAS,CAAA;KACjB;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;KAC/B;SAAM;QACL,WAAW,EAAE,CAAC,aAAa,EAAE,CAAA;KAC9B;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB;IACjC,IAAI;QACF,IAAI,eAAe,EAAE,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC5C,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;YACrD,OAAO,KAAK,CAAA;SACb;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChE,KAAK,CAAC,OAAO,CAAA,2BAA2B,CAAC,CAAA;QACzC,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,MAAM,EAAE;QACf,KAAK,CAAC,OAAO,CAAA,6BAA6B,CAAC,CAAA;QAC3C,OAAO,KAAK,CAAA;KACb;AACH,CAAC","sourcesContent":["import {SessionSchema} from './schema.js'\nimport constants from '../constants.js'\nimport {platformAndArch} from '../os.js'\nimport {store as secureStore, fetch as secureFetch, remove as secureRemove} from '../secure-store.js'\nimport {cliKitStore} from '../store.js'\nimport {content, debug} from '../output.js'\nimport type {Session} from './schema.js'\n\n/**\n * The identifier of the session in the secure store.\n */\nexport const identifier = 'session'\n\n/**\n * Serializes the session as a JSON and stores it securely in the system.\n * If the secure store is not available, the session is stored in the local config.\n * @param session {Session} the session to store.\n */\nexport async function store(session: Session) {\n const jsonSession = JSON.stringify(session)\n if (await secureStoreAvailable()) {\n await secureStore(identifier, jsonSession)\n } else {\n await cliKitStore().setSession(jsonSession)\n }\n}\n\n/**\n * Fetches the session from the secure store and returns it.\n * If the secure store is not available, the session is fetched from the local config.\n * If the format of the session is invalid, the method will discard it.\n * In the future might add some logic for supporting migrating the schema\n * of already-persisted sessions.\n * @returns {Promise<Session\\undefined>} Returns a promise that resolves with the session if it exists and is valid.\n */\nexport async function fetch(): Promise<Session | undefined> {\n let content\n if (await secureStoreAvailable()) {\n content = await secureFetch(identifier)\n } else {\n content = cliKitStore().getSession()\n }\n\n if (!content) {\n return undefined\n }\n const contentJson = JSON.parse(content)\n const parsedSession = await SessionSchema.safeParseAsync(contentJson)\n if (parsedSession.success) {\n return parsedSession.data\n } else {\n await remove()\n return undefined\n }\n}\n\n/**\n * Removes a session from the system.\n */\nexport async function remove() {\n if (await secureStoreAvailable()) {\n await secureRemove(identifier)\n } else {\n cliKitStore().removeSession()\n }\n}\n\n/**\n * Returns true if the secure store is available on the system.\n * Keytar it's not supported on some Linux environments or Windows.\n * More details: https://github.com/Shopify/shopify-cli-planning/issues/261\n * @returns a boolean indicating if the secure store is available.\n */\nasync function secureStoreAvailable(): Promise<boolean> {\n try {\n if (platformAndArch().platform === 'windows') {\n debug(content`Secure store not supported on Windows`)\n return false\n }\n const keytar = await import('keytar')\n await keytar.default.findCredentials(constants.keychain.service)\n debug(content`Secure store is available`)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (_error) {\n debug(content`Failed to load secure store`)\n return false\n }\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,UAAU,CAAA;AACxC,OAAO,EAAC,KAAK,IAAI,WAAW,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,IAAI,YAAY,EAAC,MAAM,oBAAoB,CAAA;AACrG,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAC,MAAM,aAAa,CAAA;AAGjE;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAgB;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,UAAU,CAAC,WAAW,CAAC,CAAA;KAC9B;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,OAAO,CAAA;IACX,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAA;KACxC;SAAM;QACL,OAAO,GAAG,MAAM,UAAU,EAAE,CAAA;KAC7B;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,SAAS,CAAA;KACjB;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IACrE,IAAI,aAAa,CAAC,OAAO,EAAE;QACzB,OAAO,aAAa,CAAC,IAAI,CAAA;KAC1B;SAAM;QACL,MAAM,MAAM,EAAE,CAAA;QACd,OAAO,SAAS,CAAA;KACjB;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;KAC/B;SAAM;QACL,MAAM,aAAa,EAAE,CAAA;KACtB;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB;IACjC,IAAI;QACF,IAAI,eAAe,EAAE,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC5C,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;YACrD,OAAO,KAAK,CAAA;SACb;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChE,KAAK,CAAC,OAAO,CAAA,2BAA2B,CAAC,CAAA;QACzC,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,MAAM,EAAE;QACf,KAAK,CAAC,OAAO,CAAA,6BAA6B,CAAC,CAAA;QAC3C,OAAO,KAAK,CAAA;KACb;AACH,CAAC","sourcesContent":["import {SessionSchema} from './schema.js'\nimport constants from '../constants.js'\nimport {platformAndArch} from '../os.js'\nimport {store as secureStore, fetch as secureFetch, remove as secureRemove} from '../secure-store.js'\nimport {content, debug} from '../output.js'\nimport {getSession, removeSession, setSession} from '../store.js'\nimport type {Session} from './schema.js'\n\n/**\n * The identifier of the session in the secure store.\n */\nexport const identifier = 'session'\n\n/**\n * Serializes the session as a JSON and stores it securely in the system.\n * If the secure store is not available, the session is stored in the local config.\n * @param session {Session} the session to store.\n */\nexport async function store(session: Session) {\n const jsonSession = JSON.stringify(session)\n if (await secureStoreAvailable()) {\n await secureStore(identifier, jsonSession)\n } else {\n await setSession(jsonSession)\n }\n}\n\n/**\n * Fetches the session from the secure store and returns it.\n * If the secure store is not available, the session is fetched from the local config.\n * If the format of the session is invalid, the method will discard it.\n * In the future might add some logic for supporting migrating the schema\n * of already-persisted sessions.\n * @returns {Promise<Session\\undefined>} Returns a promise that resolves with the session if it exists and is valid.\n */\nexport async function fetch(): Promise<Session | undefined> {\n let content\n if (await secureStoreAvailable()) {\n content = await secureFetch(identifier)\n } else {\n content = await getSession()\n }\n\n if (!content) {\n return undefined\n }\n const contentJson = JSON.parse(content)\n const parsedSession = await SessionSchema.safeParseAsync(contentJson)\n if (parsedSession.success) {\n return parsedSession.data\n } else {\n await remove()\n return undefined\n }\n}\n\n/**\n * Removes a session from the system.\n */\nexport async function remove() {\n if (await secureStoreAvailable()) {\n await secureRemove(identifier)\n } else {\n await removeSession()\n }\n}\n\n/**\n * Returns true if the secure store is available on the system.\n * Keytar it's not supported on some Linux environments or Windows.\n * More details: https://github.com/Shopify/shopify-cli-planning/issues/261\n * @returns a boolean indicating if the secure store is available.\n */\nasync function secureStoreAvailable(): Promise<boolean> {\n try {\n if (platformAndArch().platform === 'windows') {\n debug(content`Secure store not supported on Windows`)\n return false\n }\n const keytar = await import('keytar')\n await keytar.default.findCredentials(constants.keychain.service)\n debug(content`Secure store is available`)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (_error) {\n debug(content`Failed to load secure store`)\n return false\n }\n}\n"]}
package/dist/session.js CHANGED
@@ -14,7 +14,8 @@ import { normalizeStoreName } from './string.js';
14
14
  import * as output from './output.js';
15
15
  import { partners } from './api.js';
16
16
  import { RequestClientError } from './api/common.js';
17
- import { firstPartyDev } from './environment/local.js';
17
+ import { firstPartyDev, useDeviceAuth } from './environment/local.js';
18
+ import { pollForDeviceAuthorization, requestDeviceAuthorization } from './session/device-authorization.js';
18
19
  import { gql } from 'graphql-request';
19
20
  const NoSessionError = new Bug('No session found after ensuring authenticated');
20
21
  const MissingPartnerTokenError = new Bug('No partners token found after ensuring authenticated');
@@ -178,12 +179,25 @@ async function executeCompleteFlow(applications, identityFqdn) {
178
179
  debug(content `Authenticating as Shopify Employee...`);
179
180
  scopes.push('employee');
180
181
  }
181
- // Authorize user via browser
182
- debug(content `Authorizing through Identity's website...`);
183
- const code = await authorize(scopes);
184
- // Exchange code for identity token
185
- debug(content `Authorization code received. Exchanging it for a CLI token...`);
186
- const identityToken = await exchangeCodeForAccessToken(code);
182
+ let identityToken;
183
+ if (useDeviceAuth()) {
184
+ // Request a device code to authorize without a browser redirect.
185
+ debug(content `Requesting device authorization code...`);
186
+ const deviceAuth = await requestDeviceAuthorization(scopes);
187
+ if (!deviceAuth.deviceCode || !deviceAuth.verificationUriComplete)
188
+ throw new Error('Invalid device code response');
189
+ // Poll for the identity token
190
+ debug(content `Starting polling for the identity token...`);
191
+ identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval);
192
+ }
193
+ else {
194
+ // Authorize user via browser
195
+ debug(content `Authorizing through Identity's website...`);
196
+ const code = await authorize(scopes);
197
+ // Exchange code for identity token
198
+ debug(content `Authorization code received. Exchanging it for a CLI token...`);
199
+ identityToken = await exchangeCodeForAccessToken(code);
200
+ }
187
201
  // Exchange identity token for application tokens
188
202
  debug(content `CLI token received. Exchanging it for application tokens...`);
189
203
  const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store);
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAC,KAAK,EAAE,GAAG,EAAC,MAAM,YAAY,CAAA;AACrC,OAAO,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAC,gBAAgB,EAAE,SAAS,EAAC,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAC,QAAQ,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;AAChC,OAAO,EACL,kCAAkC,EAClC,0BAA0B,EAC1B,0BAA0B,EAE1B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AACjD,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAA;AAEhC,OAAO,EAAC,SAAS,EAAC,MAAM,wBAAwB,CAAA;AAEhD,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AACjD,OAAO,SAAS,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAC,QAAQ,EAAC,MAAM,UAAU,CAAA;AACjC,OAAO,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAC,GAAG,EAAC,MAAM,iBAAiB,CAAA;AAEnC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,+CAA+C,CAAC,CAAA;AAC/E,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,sDAAsD,CAAC,CAAA;AAChG,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,mDAAmD,CAAC,CAAA;AAC3F,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,wDAAwD,CAAC,CAAA;AAwDrG,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,EAAE;IACnD,OAAO,IAAI,KAAK,CACd,kDAAkD,EAClD,gEAAgE,CACjE,CAAA;AACH,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,SAAmB,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG;IACxF,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;IAClE,IAAI,QAAQ,EAAE;QACZ,OAAO,CAAC,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAA;KAChE;IACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,WAAW,EAAE,EAAC,MAAM,EAAC,EAAC,CAAC,CAAA;IACjE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;QACpB,MAAM,wBAAwB,CAAA;KAC/B;IACD,OAAO,MAAM,CAAC,QAAQ,CAAA;AACxB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,SAAmB,EAAE;IACvE,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,qBAAqB,EAAE,EAAC,MAAM,EAAC,EAAC,CAAC,CAAA;IAC3E,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACtB,MAAM,2BAA2B,CAAA;KAClC;IACD,OAAO,MAAM,CAAC,UAAU,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAAa,EAAE,SAAmB,EAAE;IACjF,KAAK,CAAC,OAAO,CAAA,sGAAsG,KAAK,CAAC,GAAG,CAC1H,KAAK,CACN;EACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,QAAQ,EAAE,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAC,EAAC,CAAC,CAAA;IAChF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;QACjB,MAAM,sBAAsB,CAAA;KAC7B;IACD,OAAO,MAAM,CAAC,KAAK,CAAA;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,YAA+B,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG;IAC1F,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IAEjC,IAAI,YAAY,CAAC,QAAQ,EAAE,SAAS,EAAE;QACpC,YAAY,CAAC,QAAQ,CAAC,SAAS,GAAG,kBAAkB,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;KACtF;IAED,MAAM,cAAc,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAA;IACxD,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAE,CAAA;IACzC,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAE7C,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;;EAElB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,gBAAgB,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,CAAA;IAEjF,IAAI,UAAU,GAAG,EAAE,CAAA;IAEnB,IAAI,gBAAgB,KAAK,iBAAiB,EAAE;QAC1C,KAAK,CAAC,OAAO,CAAA,4CAA4C,CAAC,CAAA;QAC1D,UAAU,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;KAC3D;SAAM,IAAI,gBAAgB,KAAK,eAAe,EAAE;QAC/C,KAAK,CAAC,OAAO,CAAA,+DAA+D,CAAC,CAAA;QAC7E,IAAI;YACF,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,CAAA;SAC3E;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,iBAAiB,EAAE;gBACtC,UAAU,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;aAC3D;iBAAM;gBACL,MAAM,KAAK,CAAA;aACZ;SACF;KACF;IAED,MAAM,eAAe,GAAY,EAAC,GAAG,cAAc,EAAE,GAAG,UAAU,EAAC,CAAA;IACnE,MAAM,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IACxC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,eAAe,EAAE,IAAI,CAAC,CAAA;IAEnE,uDAAuD;IACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;IAClE,IAAI,QAAQ,IAAI,YAAY,CAAC,WAAW,EAAE;QACxC,MAAM,CAAC,QAAQ,GAAG,CAAC,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAA;KAC3E;IACD,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE;QAChC,MAAM,2BAA2B,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;KACnD;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,aAAqB;IAC3D,IAAI;QACF,MAAM,QAAQ,CAAC,OAAO,CACpB,GAAG,CAAA;;;;;;;;OAQF,EACD,aAAa,CACd,CAAA;QACD,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,KAAK,YAAY,kBAAkB,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE;YACnE,OAAO,KAAK,CAAA;SACb;aAAM;YACL,OAAO,IAAI,CAAA;SACZ;KACF;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,aAAqB;IACrE,KAAK,CAAC,OAAO,CAAA,oDAAoD,CAAC,CAAA;IAClE,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC,EAAE;QAC7C,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;QACtE,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;QAC7C,MAAM,QAAQ,EAAE,CAAA;QAChB,MAAM,IAAI,CAAC,qCAAqC,CAAC,CAAA;QACjD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA,kCAAkC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAA;QAC5G,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA,qFAAqF,CAAC,CAAA;QAChH,MAAM,QAAQ,EAAE,CAAA;QAChB,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC,EAAE;YAC7C,MAAM,gCAAgC,EAAE,CAAA;SACzC;KACF;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,YAA+B,EAAE,YAAoB;IACtF,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAC7C,MAAM,cAAc,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC9C,IAAI,aAAa,EAAE,EAAE;QACnB,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;QACrD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;KACxB;IAED,6BAA6B;IAC7B,KAAK,CAAC,OAAO,CAAA,2CAA2C,CAAC,CAAA;IACzD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAA;IAEpC,mCAAmC;IACnC,KAAK,CAAC,OAAO,CAAA,+DAA+D,CAAC,CAAA;IAC7E,MAAM,aAAa,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,CAAA;IAE5D,iDAAiD;IACjD,KAAK,CAAC,OAAO,CAAA,6DAA6D,CAAC,CAAA;IAC3E,MAAM,MAAM,GAAG,MAAM,kCAAkC,CAAC,aAAa,EAAE,cAAc,EAAE,KAAK,CAAC,CAAA;IAE7F,MAAM,OAAO,GAAY;QACvB,CAAC,YAAY,CAAC,EAAE;YACd,QAAQ,EAAE,aAAa;YACvB,YAAY,EAAE,MAAM;SACrB;KACF,CAAA;IAED,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;IAE9B,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAAoB,EAAE,YAA+B,EAAE,IAAY;IAC9F,yBAAyB;IACzB,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAErD,qDAAqD;IACrD,MAAM,cAAc,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAA;IACtD,MAAM,iBAAiB,GAAG,MAAM,kCAAkC,CAChE,aAAa,EACb,cAAc,EACd,YAAY,CAAC,QAAQ,EAAE,SAAS,CACjC,CAAA;IAED,OAAO;QACL,CAAC,IAAI,CAAC,EAAE;YACN,QAAQ,EAAE,aAAa;YACvB,YAAY,EAAE,iBAAiB;SAChC;KACF,CAAA;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,YAA+B,EAAE,OAAgB,EAAE,IAAY;IACtF,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,cAAc,CAAA;KACrB;IACD,MAAM,MAAM,GAAiB,EAAE,CAAA;IAC/B,IAAI,YAAY,CAAC,QAAQ,EAAE;QACzB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QACpC,MAAM,SAAS,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,SAAS,IAAI,KAAK,EAAE,CAAA;QAC/D,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,WAAW,CAAA;QAC9D,IAAI,KAAK,EAAE;YACT,MAAM,CAAC,KAAK,GAAG,EAAC,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAC,CAAA;SACnE;KACF;IAED,IAAI,YAAY,CAAC,WAAW,EAAE;QAC5B,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;QACvC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAC/D;IAED,IAAI,YAAY,CAAC,qBAAqB,EAAE;QACtC,MAAM,KAAK,GAAG,aAAa,CAAC,qBAAqB,CAAC,CAAA;QAClD,MAAM,CAAC,UAAU,GAAG,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KACjE;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,gBAAgB;AAChB,SAAS,gBAAgB,CAAC,IAAuB;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAA;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,CAAA;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE,MAAM,IAAI,EAAE,CAAA;IAC3D,MAAM,eAAe,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC,CAAA;IAC7D,OAAO,gBAAgB,CAAC,eAAe,CAAC,CAAA;AAC1C,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAuB;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAA;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,CAAA;IACnD,MAAM,gBAAgB,GAAG,IAAI,CAAC,qBAAqB,EAAE,MAAM,IAAI,EAAE,CAAA;IACjE,OAAO;QACL,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC;QACrC,QAAQ,EAAE,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC;QAC7C,UAAU,EAAE,SAAS,CAAC,qBAAqB,EAAE,gBAAgB,CAAC;KAC/D,CAAA;AACH,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,WAAW,CAAC,MAAM,EAAE,CAAA;AAC7B,CAAC","sourcesContent":["import {applicationId} from './session/identity.js'\nimport {Abort, Bug} from './error.js'\nimport {validateSession} from './session/validate.js'\nimport {allDefaultScopes, apiScopes} from './session/scopes.js'\nimport {identity as identityFqdn} from './environment/fqdn.js'\nimport {open} from './system.js'\nimport {\n exchangeAccessForApplicationTokens,\n exchangeCodeForAccessToken,\n exchangeCustomPartnerToken,\n ExchangeScopes,\n refreshAccessToken,\n InvalidGrantError,\n} from './session/exchange.js'\n\nimport {content, token, debug} from './output.js'\nimport {keypress} from './ui.js'\n\nimport {authorize} from './session/authorize.js'\nimport {IdentityToken, Session} from './session/schema.js'\nimport * as secureStore from './session/store.js'\nimport constants from './constants.js'\nimport {normalizeStoreName} from './string.js'\nimport * as output from './output.js'\nimport {partners} from './api.js'\nimport {RequestClientError} from './api/common.js'\nimport {firstPartyDev} from './environment/local.js'\nimport {gql} from 'graphql-request'\n\nconst NoSessionError = new Bug('No session found after ensuring authenticated')\nconst MissingPartnerTokenError = new Bug('No partners token found after ensuring authenticated')\nconst MissingAdminTokenError = new Bug('No admin token found after ensuring authenticated')\nconst MissingStorefrontTokenError = new Bug('No storefront token found after ensuring authenticated')\n\n/**\n * A scope supported by the Shopify Admin API.\n */\ntype AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string\n\n/**\n * It represents the options to authenticate against the Shopify Admin API.\n */\ninterface AdminAPIOAuthOptions {\n /** Store to request permissions for */\n storeFqdn: string\n /** List of scopes to request permissions for */\n scopes: AdminAPIScope[]\n}\n\n/**\n * A scope supported by the Partners API.\n */\ntype PartnersAPIScope = 'cli' | string\ninterface PartnersAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: PartnersAPIScope[]\n}\n\n/**\n * A scope supported by the Storefront Renderer API.\n */\ntype StorefrontRendererScope = 'devtools' | string\ninterface StorefrontRendererAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: StorefrontRendererScope[]\n}\n\n/**\n * It represents the authentication requirements and\n * is the input necessary to trigger the authentication\n * flow.\n */\nexport interface OAuthApplications {\n adminApi?: AdminAPIOAuthOptions\n storefrontRendererApi?: StorefrontRendererAPIOAuthOptions\n partnersApi?: PartnersAPIOAuthOptions\n}\n\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\nexport interface OAuthSession {\n admin?: AdminSession\n partners?: string\n storefront?: string\n}\nexport const PartnerOrganizationNotFoundError = () => {\n return new Abort(\n `Couldn't find your Shopify Partners organization`,\n `Have you confirmed your accounts from the emails you received?`,\n )\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored\n * @param scopes {string[]} Optional array of extra scopes to authenticate with.\n * @returns {Promise<string>} The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(scopes: string[] = [], env = process.env): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${token.json(scopes)}\n`)\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken) {\n return (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}})\n if (!tokens.partners) {\n throw MissingPartnerTokenError\n }\n return tokens.partners\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n * @param scopes {string[]} Optional array of extra scopes to authenticate with.\n * @returns {Promise<string>} The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(scopes: string[] = []): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}})\n if (!tokens.storefront) {\n throw MissingStorefrontTokenError\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n * @param store {string} Store fqdn to request auth for\n * @param scopes {string[]} Optional array of extra scopes to authenticate with.\n * @returns {Promise<string>} The access token for the Admin API\n */\nexport async function ensureAuthenticatedAdmin(store: string, scopes: string[] = []): Promise<AdminSession> {\n debug(content`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${token.raw(\n store,\n )}:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}})\n if (!tokens.admin) {\n throw MissingAdminTokenError\n }\n return tokens.admin\n}\n\n/**\n * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.\n * @param applications {OAuthApplications} An object containing the applications we need to be authenticated with.\n * @returns {OAuthSession} An instance with the access tokens organized by application.\n */\nexport async function ensureAuthenticated(applications: OAuthApplications, env = process.env): Promise<OAuthSession> {\n const fqdn = await identityFqdn()\n\n if (applications.adminApi?.storeFqdn) {\n applications.adminApi.storeFqdn = normalizeStoreName(applications.adminApi.storeFqdn)\n }\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdnSession = currentSession[fqdn]!\n const scopes = getFlattenScopes(applications)\n\n debug(content`Validating existing session against the scopes:\n${token.json(scopes)}\nFor applications:\n${token.json(applications)}\n`)\n const validationResult = await validateSession(scopes, applications, fqdnSession)\n\n let newSession = {}\n\n if (validationResult === 'needs_full_auth') {\n debug(content`Initiating the full authentication flow...`)\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (validationResult === 'needs_refresh') {\n debug(content`The current session is valid but needs refresh. Refreshing...`)\n try {\n newSession = await refreshTokens(fqdnSession.identity, applications, fqdn)\n } catch (error) {\n if (error instanceof InvalidGrantError) {\n newSession = await executeCompleteFlow(applications, fqdn)\n } else {\n throw error\n }\n }\n }\n\n const completeSession: Session = {...currentSession, ...newSession}\n await secureStore.store(completeSession)\n const tokens = await tokensFor(applications, completeSession, fqdn)\n\n // Overwrite partners token if using a custom CLI Token\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken && applications.partnersApi) {\n tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n if (!envToken && tokens.partners) {\n await ensureUserHasPartnerAccount(tokens.partners)\n }\n\n return tokens\n}\n\nexport async function hasPartnerAccount(partnersToken: string): Promise<boolean> {\n try {\n await partners.request(\n gql`\n {\n organizations(first: 1) {\n nodes {\n id\n }\n }\n }\n `,\n partnersToken,\n )\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n if (error instanceof RequestClientError && error.statusCode === 404) {\n return false\n } else {\n return true\n }\n }\n}\n\n/**\n * If the user creates an account from the Identity website, the created\n * account won't get a Partner organization created. We need to detect that\n * and take the user to create a partner organization.\n * @param partnersToken {string} Partners token\n */\nexport async function ensureUserHasPartnerAccount(partnersToken: string) {\n debug(content`Verifying that the user has a Partner organization`)\n if (!(await hasPartnerAccount(partnersToken))) {\n output.info(`\\nA Shopify Partners organization is needed to proceed.`)\n output.info(`👉 Press any key to create one`)\n await keypress()\n await open(`https://partners.shopify.com/signup`)\n output.info(output.content`👉 Press any key when you have ${output.token.cyan('created the organization')}`)\n output.warn(output.content`Make sure you've confirmed your Shopify and the Partner organization from the email`)\n await keypress()\n if (!(await hasPartnerAccount(partnersToken))) {\n throw PartnerOrganizationNotFoundError()\n }\n }\n}\n\nasync function executeCompleteFlow(applications: OAuthApplications, identityFqdn: string): Promise<Session> {\n const scopes = getFlattenScopes(applications)\n const exchangeScopes = getExchangeScopes(applications)\n const store = applications.adminApi?.storeFqdn\n if (firstPartyDev()) {\n debug(content`Authenticating as Shopify Employee...`)\n scopes.push('employee')\n }\n\n // Authorize user via browser\n debug(content`Authorizing through Identity's website...`)\n const code = await authorize(scopes)\n\n // Exchange code for identity token\n debug(content`Authorization code received. Exchanging it for a CLI token...`)\n const identityToken = await exchangeCodeForAccessToken(code)\n\n // Exchange identity token for application tokens\n debug(content`CLI token received. Exchanging it for application tokens...`)\n const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store)\n\n const session: Session = {\n [identityFqdn]: {\n identity: identityToken,\n applications: result,\n },\n }\n\n output.completed('Logged in.')\n\n return session\n}\n\nasync function refreshTokens(token: IdentityToken, applications: OAuthApplications, fqdn: string): Promise<Session> {\n // Refresh Identity Token\n const identityToken = await refreshAccessToken(token)\n\n // Exchange new identity token for application tokens\n const exchangeScopes = getExchangeScopes(applications)\n const applicationTokens = await exchangeAccessForApplicationTokens(\n identityToken,\n exchangeScopes,\n applications.adminApi?.storeFqdn,\n )\n\n return {\n [fqdn]: {\n identity: identityToken,\n applications: applicationTokens,\n },\n }\n}\n\nasync function tokensFor(applications: OAuthApplications, session: Session, fqdn: string): Promise<OAuthSession> {\n const fqdnSession = session[fqdn]\n if (!fqdnSession) {\n throw NoSessionError\n }\n const tokens: OAuthSession = {}\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = fqdnSession.applications[realAppId]?.accessToken\n if (token) {\n tokens.admin = {token, storeFqdn: applications.adminApi.storeFqdn}\n }\n }\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n tokens.partners = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n tokens.storefront = fqdnSession.applications[appId]?.accessToken\n }\n return tokens\n}\n\n// Scope Helpers\nfunction getFlattenScopes(apps: OAuthApplications): string[] {\n const admin = apps.adminApi?.scopes || []\n const partner = apps.partnersApi?.scopes || []\n const storefront = apps.storefrontRendererApi?.scopes || []\n const requestedScopes = [...admin, ...partner, ...storefront]\n return allDefaultScopes(requestedScopes)\n}\n\nfunction getExchangeScopes(apps: OAuthApplications): ExchangeScopes {\n const adminScope = apps.adminApi?.scopes || []\n const partnerScope = apps.partnersApi?.scopes || []\n const storefrontScopes = apps.storefrontRendererApi?.scopes || []\n return {\n admin: apiScopes('admin', adminScope),\n partners: apiScopes('partners', partnerScope),\n storefront: apiScopes('storefront-renderer', storefrontScopes),\n }\n}\n\nexport function logout() {\n return secureStore.remove()\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {applicationId} from './session/identity.js'\nimport {Abort, Bug} from './error.js'\nimport {validateSession} from './session/validate.js'\nimport {allDefaultScopes, apiScopes} from './session/scopes.js'\nimport {identity as identityFqdn} from './environment/fqdn.js'\nimport {open} from './system.js'\nimport {\n exchangeAccessForApplicationTokens,\n exchangeCodeForAccessToken,\n exchangeCustomPartnerToken,\n ExchangeScopes,\n refreshAccessToken,\n InvalidGrantError,\n} from './session/exchange.js'\n\nimport {content, token, debug} from './output.js'\nimport {keypress} from './ui.js'\n\nimport {authorize} from './session/authorize.js'\nimport {IdentityToken, Session} from './session/schema.js'\nimport * as secureStore from './session/store.js'\nimport constants from './constants.js'\nimport {normalizeStoreName} from './string.js'\nimport * as output from './output.js'\nimport {partners} from './api.js'\nimport {RequestClientError} from './api/common.js'\nimport {firstPartyDev, useDeviceAuth} from './environment/local.js'\nimport {pollForDeviceAuthorization, requestDeviceAuthorization} from './session/device-authorization.js'\nimport {gql} from 'graphql-request'\n\nconst NoSessionError = new Bug('No session found after ensuring authenticated')\nconst MissingPartnerTokenError = new Bug('No partners token found after ensuring authenticated')\nconst MissingAdminTokenError = new Bug('No admin token found after ensuring authenticated')\nconst MissingStorefrontTokenError = new Bug('No storefront token found after ensuring authenticated')\n\n/**\n * A scope supported by the Shopify Admin API.\n */\ntype AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string\n\n/**\n * It represents the options to authenticate against the Shopify Admin API.\n */\ninterface AdminAPIOAuthOptions {\n /** Store to request permissions for */\n storeFqdn: string\n /** List of scopes to request permissions for */\n scopes: AdminAPIScope[]\n}\n\n/**\n * A scope supported by the Partners API.\n */\ntype PartnersAPIScope = 'cli' | string\ninterface PartnersAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: PartnersAPIScope[]\n}\n\n/**\n * A scope supported by the Storefront Renderer API.\n */\ntype StorefrontRendererScope = 'devtools' | string\ninterface StorefrontRendererAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: StorefrontRendererScope[]\n}\n\n/**\n * It represents the authentication requirements and\n * is the input necessary to trigger the authentication\n * flow.\n */\nexport interface OAuthApplications {\n adminApi?: AdminAPIOAuthOptions\n storefrontRendererApi?: StorefrontRendererAPIOAuthOptions\n partnersApi?: PartnersAPIOAuthOptions\n}\n\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\nexport interface OAuthSession {\n admin?: AdminSession\n partners?: string\n storefront?: string\n}\nexport const PartnerOrganizationNotFoundError = () => {\n return new Abort(\n `Couldn't find your Shopify Partners organization`,\n `Have you confirmed your accounts from the emails you received?`,\n )\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored\n * @param scopes {string[]} Optional array of extra scopes to authenticate with.\n * @returns {Promise<string>} The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(scopes: string[] = [], env = process.env): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${token.json(scopes)}\n`)\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken) {\n return (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}})\n if (!tokens.partners) {\n throw MissingPartnerTokenError\n }\n return tokens.partners\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n * @param scopes {string[]} Optional array of extra scopes to authenticate with.\n * @returns {Promise<string>} The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(scopes: string[] = []): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}})\n if (!tokens.storefront) {\n throw MissingStorefrontTokenError\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n * @param store {string} Store fqdn to request auth for\n * @param scopes {string[]} Optional array of extra scopes to authenticate with.\n * @returns {Promise<string>} The access token for the Admin API\n */\nexport async function ensureAuthenticatedAdmin(store: string, scopes: string[] = []): Promise<AdminSession> {\n debug(content`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${token.raw(\n store,\n )}:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}})\n if (!tokens.admin) {\n throw MissingAdminTokenError\n }\n return tokens.admin\n}\n\n/**\n * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.\n * @param applications {OAuthApplications} An object containing the applications we need to be authenticated with.\n * @returns {OAuthSession} An instance with the access tokens organized by application.\n */\nexport async function ensureAuthenticated(applications: OAuthApplications, env = process.env): Promise<OAuthSession> {\n const fqdn = await identityFqdn()\n\n if (applications.adminApi?.storeFqdn) {\n applications.adminApi.storeFqdn = normalizeStoreName(applications.adminApi.storeFqdn)\n }\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdnSession = currentSession[fqdn]!\n const scopes = getFlattenScopes(applications)\n\n debug(content`Validating existing session against the scopes:\n${token.json(scopes)}\nFor applications:\n${token.json(applications)}\n`)\n const validationResult = await validateSession(scopes, applications, fqdnSession)\n\n let newSession = {}\n\n if (validationResult === 'needs_full_auth') {\n debug(content`Initiating the full authentication flow...`)\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (validationResult === 'needs_refresh') {\n debug(content`The current session is valid but needs refresh. Refreshing...`)\n try {\n newSession = await refreshTokens(fqdnSession.identity, applications, fqdn)\n } catch (error) {\n if (error instanceof InvalidGrantError) {\n newSession = await executeCompleteFlow(applications, fqdn)\n } else {\n throw error\n }\n }\n }\n\n const completeSession: Session = {...currentSession, ...newSession}\n await secureStore.store(completeSession)\n const tokens = await tokensFor(applications, completeSession, fqdn)\n\n // Overwrite partners token if using a custom CLI Token\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken && applications.partnersApi) {\n tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n if (!envToken && tokens.partners) {\n await ensureUserHasPartnerAccount(tokens.partners)\n }\n\n return tokens\n}\n\nexport async function hasPartnerAccount(partnersToken: string): Promise<boolean> {\n try {\n await partners.request(\n gql`\n {\n organizations(first: 1) {\n nodes {\n id\n }\n }\n }\n `,\n partnersToken,\n )\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n if (error instanceof RequestClientError && error.statusCode === 404) {\n return false\n } else {\n return true\n }\n }\n}\n\n/**\n * If the user creates an account from the Identity website, the created\n * account won't get a Partner organization created. We need to detect that\n * and take the user to create a partner organization.\n * @param partnersToken {string} Partners token\n */\nexport async function ensureUserHasPartnerAccount(partnersToken: string) {\n debug(content`Verifying that the user has a Partner organization`)\n if (!(await hasPartnerAccount(partnersToken))) {\n output.info(`\\nA Shopify Partners organization is needed to proceed.`)\n output.info(`👉 Press any key to create one`)\n await keypress()\n await open(`https://partners.shopify.com/signup`)\n output.info(output.content`👉 Press any key when you have ${output.token.cyan('created the organization')}`)\n output.warn(output.content`Make sure you've confirmed your Shopify and the Partner organization from the email`)\n await keypress()\n if (!(await hasPartnerAccount(partnersToken))) {\n throw PartnerOrganizationNotFoundError()\n }\n }\n}\n\nasync function executeCompleteFlow(applications: OAuthApplications, identityFqdn: string): Promise<Session> {\n const scopes = getFlattenScopes(applications)\n const exchangeScopes = getExchangeScopes(applications)\n const store = applications.adminApi?.storeFqdn\n if (firstPartyDev()) {\n debug(content`Authenticating as Shopify Employee...`)\n scopes.push('employee')\n }\n\n let identityToken: IdentityToken\n if (useDeviceAuth()) {\n // Request a device code to authorize without a browser redirect.\n debug(content`Requesting device authorization code...`)\n const deviceAuth = await requestDeviceAuthorization(scopes)\n if (!deviceAuth.deviceCode || !deviceAuth.verificationUriComplete) throw new Error('Invalid device code response')\n\n // Poll for the identity token\n debug(content`Starting polling for the identity token...`)\n identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval)\n } else {\n // Authorize user via browser\n debug(content`Authorizing through Identity's website...`)\n const code = await authorize(scopes)\n\n // Exchange code for identity token\n debug(content`Authorization code received. Exchanging it for a CLI token...`)\n identityToken = await exchangeCodeForAccessToken(code)\n }\n\n // Exchange identity token for application tokens\n debug(content`CLI token received. Exchanging it for application tokens...`)\n const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store)\n\n const session: Session = {\n [identityFqdn]: {\n identity: identityToken,\n applications: result,\n },\n }\n\n output.completed('Logged in.')\n\n return session\n}\n\nasync function refreshTokens(token: IdentityToken, applications: OAuthApplications, fqdn: string): Promise<Session> {\n // Refresh Identity Token\n const identityToken = await refreshAccessToken(token)\n\n // Exchange new identity token for application tokens\n const exchangeScopes = getExchangeScopes(applications)\n const applicationTokens = await exchangeAccessForApplicationTokens(\n identityToken,\n exchangeScopes,\n applications.adminApi?.storeFqdn,\n )\n\n return {\n [fqdn]: {\n identity: identityToken,\n applications: applicationTokens,\n },\n }\n}\n\nasync function tokensFor(applications: OAuthApplications, session: Session, fqdn: string): Promise<OAuthSession> {\n const fqdnSession = session[fqdn]\n if (!fqdnSession) {\n throw NoSessionError\n }\n const tokens: OAuthSession = {}\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = fqdnSession.applications[realAppId]?.accessToken\n if (token) {\n tokens.admin = {token, storeFqdn: applications.adminApi.storeFqdn}\n }\n }\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n tokens.partners = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n tokens.storefront = fqdnSession.applications[appId]?.accessToken\n }\n return tokens\n}\n\n// Scope Helpers\nfunction getFlattenScopes(apps: OAuthApplications): string[] {\n const admin = apps.adminApi?.scopes || []\n const partner = apps.partnersApi?.scopes || []\n const storefront = apps.storefrontRendererApi?.scopes || []\n const requestedScopes = [...admin, ...partner, ...storefront]\n return allDefaultScopes(requestedScopes)\n}\n\nfunction getExchangeScopes(apps: OAuthApplications): ExchangeScopes {\n const adminScope = apps.adminApi?.scopes || []\n const partnerScope = apps.partnersApi?.scopes || []\n const storefrontScopes = apps.storefrontRendererApi?.scopes || []\n return {\n admin: apiScopes('admin', adminScope),\n partners: apiScopes('partners', partnerScope),\n storefront: apiScopes('storefront-renderer', storefrontScopes),\n }\n}\n\nexport function logout() {\n return secureStore.remove()\n}\n"]}
package/dist/store.d.ts CHANGED
@@ -12,8 +12,22 @@ interface ConfSchema {
12
12
  themeStore: string;
13
13
  session: string;
14
14
  }
15
- export declare function cliKitStore(): CLIKitStore;
16
- export declare function initializeCliKitStore(): Promise<void>;
15
+ export declare function cliKitStore(): Promise<CLIKitStore>;
16
+ export declare function getAppInfo(directory: string): Promise<CachedAppInfo | undefined>;
17
+ export declare function setAppInfo(options: {
18
+ directory: string;
19
+ appId?: string;
20
+ title?: string;
21
+ storeFqdn?: string;
22
+ orgId?: string;
23
+ updateURLs?: boolean;
24
+ }): Promise<void>;
25
+ export declare function clearAppInfo(directory: string): Promise<void>;
26
+ export declare function getThemeStore(): Promise<string | undefined>;
27
+ export declare function setThemeStore(themeStore: string): Promise<void>;
28
+ export declare function getSession(): Promise<string | undefined>;
29
+ export declare function setSession(session: string): Promise<void>;
30
+ export declare function removeSession(): Promise<void>;
17
31
  export declare class CLIKitStore extends Conf<ConfSchema> {
18
32
  getAppInfo(directory: string): CachedAppInfo | undefined;
19
33
  setAppInfo(options: {
@@ -25,10 +39,10 @@ export declare class CLIKitStore extends Conf<ConfSchema> {
25
39
  updateURLs?: boolean;
26
40
  }): void;
27
41
  clearAppInfo(directory: string): void;
28
- getTheme(): string | undefined;
29
- setTheme(store: string): void;
42
+ getThemeStore(): string | undefined;
43
+ setThemeStore(themeStore: string): void;
30
44
  getSession(): string | undefined;
31
- setSession(store: string): void;
45
+ setSession(session: string): void;
32
46
  removeSession(): void;
33
47
  }
34
48
  export {};
package/dist/store.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { content, token, debug } from './output.js';
2
2
  import constants from './constants.js';
3
- import { Abort } from './error.js';
4
3
  import Conf from 'conf';
5
4
  const migrations = {};
6
5
  const schema = {
@@ -23,13 +22,7 @@ const schema = {
23
22
  },
24
23
  };
25
24
  let _instance;
26
- export function cliKitStore() {
27
- if (!_instance) {
28
- throw new Abort("The CLIKitStore instance hasn't been initialized");
29
- }
30
- return _instance;
31
- }
32
- export async function initializeCliKitStore() {
25
+ export async function cliKitStore() {
33
26
  if (!_instance) {
34
27
  // eslint-disable-next-line require-atomic-updates
35
28
  _instance = new CLIKitStore({
@@ -39,6 +32,39 @@ export async function initializeCliKitStore() {
39
32
  projectVersion: await constants.versions.cliKit(),
40
33
  });
41
34
  }
35
+ return _instance;
36
+ }
37
+ export async function getAppInfo(directory) {
38
+ const store = await cliKitStore();
39
+ return store.getAppInfo(directory);
40
+ }
41
+ export async function setAppInfo(options) {
42
+ const store = await cliKitStore();
43
+ store.setAppInfo(options);
44
+ }
45
+ export async function clearAppInfo(directory) {
46
+ const store = await cliKitStore();
47
+ store.clearAppInfo(directory);
48
+ }
49
+ export async function getThemeStore() {
50
+ const store = await cliKitStore();
51
+ return store.getThemeStore();
52
+ }
53
+ export async function setThemeStore(themeStore) {
54
+ const store = await cliKitStore();
55
+ store.setThemeStore(themeStore);
56
+ }
57
+ export async function getSession() {
58
+ const store = await cliKitStore();
59
+ return store.getSession();
60
+ }
61
+ export async function setSession(session) {
62
+ const store = await cliKitStore();
63
+ store.setSession(session);
64
+ }
65
+ export async function removeSession() {
66
+ const store = await cliKitStore();
67
+ store.removeSession();
42
68
  }
43
69
  export class CLIKitStore extends Conf {
44
70
  getAppInfo(directory) {
@@ -75,21 +101,21 @@ export class CLIKitStore extends Conf {
75
101
  }
76
102
  this.set('appInfo', apps);
77
103
  }
78
- getTheme() {
104
+ getThemeStore() {
79
105
  debug(content `Getting theme store...`);
80
106
  return this.get('themeStore');
81
107
  }
82
- setTheme(store) {
108
+ setThemeStore(themeStore) {
83
109
  debug(content `Setting theme store...`);
84
- this.set('themeStore', store);
110
+ this.set('themeStore', themeStore);
85
111
  }
86
112
  getSession() {
87
113
  debug(content `Getting session store...`);
88
114
  return this.get('sessionStore');
89
115
  }
90
- setSession(store) {
116
+ setSession(session) {
91
117
  debug(content `Setting session store...`);
92
- this.set('sessionStore', store);
118
+ this.set('sessionStore', session);
93
119
  }
94
120
  removeSession() {
95
121
  debug(content `Removing session store...`);
package/dist/store.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {content, token, debug} from './output.js'\nimport constants from './constants.js'\nimport {Abort} from './error.js'\nimport Conf, {Schema} from 'conf'\n\nconst migrations = {}\n\nexport interface CachedAppInfo {\n directory: string\n appId?: string\n title?: string\n orgId?: string\n storeFqdn?: string\n updateURLs?: boolean\n}\n\ninterface ConfSchema {\n appInfo: CachedAppInfo[]\n themeStore: string\n session: string\n}\n\nconst schema = {\n appInfo: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n appId: {\n type: 'string',\n },\n orgId: {\n type: 'string',\n },\n storeFqdn: {\n type: 'string',\n },\n },\n },\n },\n} as unknown as Schema<ConfSchema>\n\nlet _instance: CLIKitStore | undefined\n\nexport function cliKitStore() {\n if (!_instance) {\n throw new Abort(\"The CLIKitStore instance hasn't been initialized\")\n }\n return _instance\n}\n\nexport async function initializeCliKitStore() {\n if (!_instance) {\n // eslint-disable-next-line require-atomic-updates\n _instance = new CLIKitStore({\n schema,\n migrations,\n projectName: 'shopify-cli-kit',\n projectVersion: await constants.versions.cliKit(),\n })\n }\n}\n\nexport class CLIKitStore extends Conf<ConfSchema> {\n getAppInfo(directory: string): CachedAppInfo | undefined {\n debug(content`Reading cached app information for directory ${token.path(directory)}...`)\n const apps = this.get('appInfo') ?? []\n return apps.find((app: CachedAppInfo) => app.directory === directory)\n }\n\n setAppInfo(options: {\n directory: string\n appId?: string\n title?: string\n storeFqdn?: string\n orgId?: string\n updateURLs?: boolean\n }): void {\n debug(content`Storing app information for directory ${token.path(options.directory)}:${token.json(options)}`)\n const apps = this.get('appInfo') ?? []\n const index = apps.findIndex((saved: CachedAppInfo) => saved.directory === options.directory)\n if (index === -1) {\n apps.push(options)\n } else {\n const app: CachedAppInfo = apps[index]!\n apps[index] = {\n directory: options.directory,\n appId: options.appId ?? app.appId,\n title: options.title ?? app.title,\n storeFqdn: options.storeFqdn ?? app.storeFqdn,\n orgId: options.orgId ?? app.orgId,\n updateURLs: options.updateURLs ?? app.updateURLs,\n }\n }\n this.set('appInfo', apps)\n }\n\n clearAppInfo(directory: string): void {\n debug(content`Clearning app information for directory ${token.path(directory)}...`)\n const apps = this.get('appInfo') ?? []\n const index = apps.findIndex((saved: CachedAppInfo) => saved.directory === directory)\n if (index !== -1) {\n apps.splice(index, 1)\n }\n this.set('appInfo', apps)\n }\n\n getTheme(): string | undefined {\n debug(content`Getting theme store...`)\n return this.get('themeStore')\n }\n\n setTheme(store: string): void {\n debug(content`Setting theme store...`)\n this.set('themeStore', store)\n }\n\n getSession(): string | undefined {\n debug(content`Getting session store...`)\n return this.get('sessionStore')\n }\n\n setSession(store: string): void {\n debug(content`Setting session store...`)\n this.set('sessionStore', store)\n }\n\n removeSession(): void {\n debug(content`Removing session store...`)\n this.set('sessionStore', '')\n }\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {content, token, debug} from './output.js'\nimport constants from './constants.js'\nimport Conf, {Schema} from 'conf'\n\nconst migrations = {}\n\nexport interface CachedAppInfo {\n directory: string\n appId?: string\n title?: string\n orgId?: string\n storeFqdn?: string\n updateURLs?: boolean\n}\n\ninterface ConfSchema {\n appInfo: CachedAppInfo[]\n themeStore: string\n session: string\n}\n\nconst schema = {\n appInfo: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n appId: {\n type: 'string',\n },\n orgId: {\n type: 'string',\n },\n storeFqdn: {\n type: 'string',\n },\n },\n },\n },\n} as unknown as Schema<ConfSchema>\n\nlet _instance: CLIKitStore | undefined\n\nexport async function cliKitStore() {\n if (!_instance) {\n // eslint-disable-next-line require-atomic-updates\n _instance = new CLIKitStore({\n schema,\n migrations,\n projectName: 'shopify-cli-kit',\n projectVersion: await constants.versions.cliKit(),\n })\n }\n return _instance\n}\n\nexport async function getAppInfo(directory: string): Promise<CachedAppInfo | undefined> {\n const store = await cliKitStore()\n return store.getAppInfo(directory)\n}\n\nexport async function setAppInfo(options: {\n directory: string\n appId?: string\n title?: string\n storeFqdn?: string\n orgId?: string\n updateURLs?: boolean\n}): Promise<void> {\n const store = await cliKitStore()\n store.setAppInfo(options)\n}\n\nexport async function clearAppInfo(directory: string): Promise<void> {\n const store = await cliKitStore()\n store.clearAppInfo(directory)\n}\n\nexport async function getThemeStore(): Promise<string | undefined> {\n const store = await cliKitStore()\n return store.getThemeStore()\n}\n\nexport async function setThemeStore(themeStore: string): Promise<void> {\n const store = await cliKitStore()\n store.setThemeStore(themeStore)\n}\n\nexport async function getSession(): Promise<string | undefined> {\n const store = await cliKitStore()\n return store.getSession()\n}\n\nexport async function setSession(session: string): Promise<void> {\n const store = await cliKitStore()\n store.setSession(session)\n}\n\nexport async function removeSession(): Promise<void> {\n const store = await cliKitStore()\n store.removeSession()\n}\n\nexport class CLIKitStore extends Conf<ConfSchema> {\n getAppInfo(directory: string): CachedAppInfo | undefined {\n debug(content`Reading cached app information for directory ${token.path(directory)}...`)\n const apps = this.get('appInfo') ?? []\n return apps.find((app: CachedAppInfo) => app.directory === directory)\n }\n\n setAppInfo(options: {\n directory: string\n appId?: string\n title?: string\n storeFqdn?: string\n orgId?: string\n updateURLs?: boolean\n }): void {\n debug(content`Storing app information for directory ${token.path(options.directory)}:${token.json(options)}`)\n const apps = this.get('appInfo') ?? []\n const index = apps.findIndex((saved: CachedAppInfo) => saved.directory === options.directory)\n if (index === -1) {\n apps.push(options)\n } else {\n const app: CachedAppInfo = apps[index]!\n apps[index] = {\n directory: options.directory,\n appId: options.appId ?? app.appId,\n title: options.title ?? app.title,\n storeFqdn: options.storeFqdn ?? app.storeFqdn,\n orgId: options.orgId ?? app.orgId,\n updateURLs: options.updateURLs ?? app.updateURLs,\n }\n }\n this.set('appInfo', apps)\n }\n\n clearAppInfo(directory: string): void {\n debug(content`Clearning app information for directory ${token.path(directory)}...`)\n const apps = this.get('appInfo') ?? []\n const index = apps.findIndex((saved: CachedAppInfo) => saved.directory === directory)\n if (index !== -1) {\n apps.splice(index, 1)\n }\n this.set('appInfo', apps)\n }\n\n getThemeStore(): string | undefined {\n debug(content`Getting theme store...`)\n return this.get('themeStore')\n }\n\n setThemeStore(themeStore: string): void {\n debug(content`Setting theme store...`)\n this.set('themeStore', themeStore)\n }\n\n getSession(): string | undefined {\n debug(content`Getting session store...`)\n return this.get('sessionStore')\n }\n\n setSession(session: string): void {\n debug(content`Setting session store...`)\n this.set('sessionStore', session)\n }\n\n removeSession(): void {\n debug(content`Removing session store...`)\n this.set('sessionStore', '')\n }\n}\n"]}
package/dist/string.d.ts CHANGED
@@ -25,3 +25,8 @@ export declare function normalizeStoreName(store: string): string;
25
25
  * Try to convert a string to an int, falling back to undefined if unable to
26
26
  */
27
27
  export declare function tryParseInt(maybeInt: string | undefined): number | undefined;
28
+ /**
29
+ * Given a series of rows inside an array, where each row is an array of strings (representing columns)
30
+ * Parse it into a single string with the columns aligned
31
+ */
32
+ export declare function linesToColumns(lines: string[][]): string;
package/dist/string.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { unstyled } from './output.js';
1
2
  import crypto from 'crypto';
2
3
  export { camelCase as camelize } from 'change-case';
3
4
  export { paramCase as hyphenize } from 'change-case';
@@ -53,4 +54,26 @@ export function tryParseInt(maybeInt) {
53
54
  }
54
55
  return asInt;
55
56
  }
57
+ /**
58
+ * Given a series of rows inside an array, where each row is an array of strings (representing columns)
59
+ * Parse it into a single string with the columns aligned
60
+ */
61
+ export function linesToColumns(lines) {
62
+ const widths = [];
63
+ for (let i = 0; lines[0] && i < lines[0].length; i++) {
64
+ const columnRows = lines.map((line) => line[i]);
65
+ widths.push(Math.max(...columnRows.map((row) => unstyled(row).length)));
66
+ }
67
+ const paddedLines = lines
68
+ .map((line) => {
69
+ return line
70
+ .map((col, index) => {
71
+ return `${col}${' '.repeat(widths[index] - unstyled(col).length)}`;
72
+ })
73
+ .join(' ')
74
+ .trimEnd();
75
+ })
76
+ .join('\n');
77
+ return paddedLines;
78
+ }
56
79
  //# sourceMappingURL=string.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAE3B,OAAO,EAAC,SAAS,IAAI,QAAQ,EAAC,MAAM,aAAa,CAAA;AACjD,OAAO,EAAC,SAAS,IAAI,SAAS,EAAC,MAAM,aAAa,CAAA;AAClD,OAAO,EAAC,SAAS,IAAI,UAAU,EAAC,MAAM,aAAa,CAAA;AACnD,OAAO,EAAC,YAAY,IAAI,WAAW,EAAC,MAAM,aAAa,CAAA;AAEvD,8BAA8B;AAC9B,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5D,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA;IAC3D,OAAO,EAAC,YAAY,EAAE,aAAa,EAAC,CAAA;AACtC,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAC3F,CAAC;AAED,SAAS,MAAM,CAAC,GAAW;IACzB,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACtE,OAAO,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3E,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,SAAS,gBAAgB,CAAA;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAA4B;IACtD,IAAI,KAAyB,CAAA;IAC7B,IAAI,QAAQ,KAAK,SAAS,EAAE;QAC1B,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QAC9B,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE;YAChB,KAAK,GAAG,SAAS,CAAA;SAClB;KACF;IACD,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import crypto from 'crypto'\n\nexport {camelCase as camelize} from 'change-case'\nexport {paramCase as hyphenize} from 'change-case'\nexport {snakeCase as underscore} from 'change-case'\nexport {constantCase as constantize} from 'change-case'\n\n/** Returns a random string */\nexport function randomHex(size: number): string {\n return crypto.randomBytes(size).toString('hex')\n}\n\nexport function generateRandomChallengePair() {\n const codeVerifier = base64URLEncode(crypto.randomBytes(32))\n const codeChallenge = base64URLEncode(sha256(codeVerifier))\n return {codeVerifier, codeChallenge}\n}\n\nfunction base64URLEncode(str: Buffer) {\n return str.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/[=]/g, '')\n}\n\nfunction sha256(str: string) {\n return crypto.createHash('sha256').update(str).digest()\n}\n\nexport function hashString(str: string): string {\n return crypto.createHash('sha1').update(str).digest('hex')\n}\n\n/**\n * Given a string, it returns it with the first letter capitalized.\n * @param string {string} String whose first letter will be caplitalized.\n * @returns The given string with its first letter capitalized.\n */\nexport function capitalize(string: string) {\n return string.substring(0, 1).toUpperCase() + string.substring(1)\n}\n\n/**\n * Given a store, returns a valid store fqdn removing protocol and adding .myshopify.com domain\n * @param store Original store name provided by the user\n * @returns a valid store fqdn\n */\nexport function normalizeStoreName(store: string) {\n const storeFqdn = store.replace(/^https?:\\/\\//, '').replace(/\\/$/, '')\n return storeFqdn.includes('.myshopify.com') || storeFqdn.includes('spin.dev')\n ? storeFqdn\n : `${storeFqdn}.myshopify.com`\n}\n\n/**\n * Try to convert a string to an int, falling back to undefined if unable to\n */\nexport function tryParseInt(maybeInt: string | undefined) {\n let asInt: number | undefined\n if (maybeInt !== undefined) {\n asInt = parseInt(maybeInt, 10)\n if (isNaN(asInt)) {\n asInt = undefined\n }\n }\n return asInt\n}\n"]}
1
+ {"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"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","sourcesContent":["import {unstyled} from './output.js'\nimport crypto from 'crypto'\n\nexport {camelCase as camelize} from 'change-case'\nexport {paramCase as hyphenize} from 'change-case'\nexport {snakeCase as underscore} from 'change-case'\nexport {constantCase as constantize} from 'change-case'\n\n/** Returns a random string */\nexport function randomHex(size: number): string {\n return crypto.randomBytes(size).toString('hex')\n}\n\nexport function generateRandomChallengePair() {\n const codeVerifier = base64URLEncode(crypto.randomBytes(32))\n const codeChallenge = base64URLEncode(sha256(codeVerifier))\n return {codeVerifier, codeChallenge}\n}\n\nfunction base64URLEncode(str: Buffer) {\n return str.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/[=]/g, '')\n}\n\nfunction sha256(str: string) {\n return crypto.createHash('sha256').update(str).digest()\n}\n\nexport function hashString(str: string): string {\n return crypto.createHash('sha1').update(str).digest('hex')\n}\n\n/**\n * Given a string, it returns it with the first letter capitalized.\n * @param string {string} String whose first letter will be caplitalized.\n * @returns The given string with its first letter capitalized.\n */\nexport function capitalize(string: string) {\n return string.substring(0, 1).toUpperCase() + string.substring(1)\n}\n\n/**\n * Given a store, returns a valid store fqdn removing protocol and adding .myshopify.com domain\n * @param store Original store name provided by the user\n * @returns a valid store fqdn\n */\nexport function normalizeStoreName(store: string) {\n const storeFqdn = store.replace(/^https?:\\/\\//, '').replace(/\\/$/, '')\n return storeFqdn.includes('.myshopify.com') || storeFqdn.includes('spin.dev')\n ? storeFqdn\n : `${storeFqdn}.myshopify.com`\n}\n\n/**\n * Try to convert a string to an int, falling back to undefined if unable to\n */\nexport function tryParseInt(maybeInt: string | undefined) {\n let asInt: number | undefined\n if (maybeInt !== undefined) {\n asInt = parseInt(maybeInt, 10)\n if (isNaN(asInt)) {\n asInt = undefined\n }\n }\n return asInt\n}\n\n/**\n * Given a series of rows inside an array, where each row is an array of strings (representing columns)\n * Parse it into a single string with the columns aligned\n */\nexport function linesToColumns(lines: string[][]): string {\n const widths: number[] = []\n for (let i = 0; lines[0] && i < lines[0].length; i++) {\n const columnRows = lines.map((line) => line[i]!)\n widths.push(Math.max(...columnRows.map((row) => unstyled(row).length)))\n }\n const paddedLines = lines\n .map((line) => {\n return line\n .map((col, index) => {\n return `${col}${' '.repeat(widths[index]! - unstyled(col).length)}`\n })\n .join(' ')\n .trimEnd()\n })\n .join('\\n')\n return paddedLines\n}\n"]}