@shopify/cli-kit 3.91.1 → 3.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/private/node/analytics/bounded-collections.d.ts +1 -3
- package/dist/private/node/analytics/bounded-collections.js.map +1 -1
- package/dist/private/node/analytics/error-categorizer.js.map +1 -1
- package/dist/private/node/analytics.js.map +1 -1
- package/dist/private/node/api/graphql.d.ts +1 -3
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/api/headers.d.ts +2 -6
- package/dist/private/node/api/headers.js +0 -1
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/api/rest.d.ts +2 -6
- package/dist/private/node/api/rest.js.map +1 -1
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/conf-store.d.ts +6 -6
- package/dist/private/node/conf-store.js +13 -6
- package/dist/private/node/conf-store.js.map +1 -1
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/exchange.d.ts +1 -19
- package/dist/private/node/session/exchange.js +13 -30
- package/dist/private/node/session/exchange.js.map +1 -1
- package/dist/private/node/session/schema.d.ts +62 -62
- package/dist/private/node/session/store.js +1 -1
- package/dist/private/node/session/store.js.map +1 -1
- package/dist/private/node/session/validate.d.ts +4 -5
- package/dist/private/node/session/validate.js +7 -35
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/session.js +18 -65
- package/dist/private/node/session.js.map +1 -1
- package/dist/private/node/testing/ui.d.ts +2 -1
- package/dist/private/node/testing/ui.js +22 -24
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/themes/generate-theme-name.js +0 -1
- package/dist/private/node/themes/generate-theme-name.js.map +1 -1
- package/dist/private/node/ui/alert.js.map +1 -1
- package/dist/private/node/ui/components/Alert.test.js +2 -4
- package/dist/private/node/ui/components/Alert.test.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.js +6 -1
- package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +2 -3
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +0 -1
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/private/node/ui/components/Banner.test.js +2 -2
- package/dist/private/node/ui/components/Banner.test.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +4 -2
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +9 -3
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.js +0 -1
- package/dist/private/node/ui/components/FatalError.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.test.js.map +1 -1
- package/dist/private/node/ui/components/List.test.js.map +1 -1
- package/dist/private/node/ui/components/LoadingBar.js.map +1 -1
- package/dist/private/node/ui/components/LoadingBar.test.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/InfoTable.d.ts +1 -3
- package/dist/private/node/ui/components/Prompts/InfoTable.js +0 -1
- package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/InfoTable.test.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.d.ts +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.js +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.test.js +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.test.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.d.ts +4 -5
- package/dist/private/node/ui/components/SelectInput.js +5 -7
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.js +0 -1
- package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js +0 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/SingleTask.js.map +1 -1
- package/dist/private/node/ui/components/SingleTask.test.js.map +1 -1
- package/dist/private/node/ui/components/Table/ScalarDict.d.ts +2 -4
- package/dist/private/node/ui/components/Table/ScalarDict.js.map +1 -1
- package/dist/private/node/ui/components/Table/Table.js +0 -1
- package/dist/private/node/ui/components/Table/Table.js.map +1 -1
- package/dist/private/node/ui/components/Table/Table.test.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.js +0 -2
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.test.js +2 -6
- package/dist/private/node/ui/components/Tasks.test.js.map +1 -1
- package/dist/private/node/ui/components/TextAnimation.test.js +1 -1
- package/dist/private/node/ui/components/TextAnimation.test.js.map +1 -1
- package/dist/private/node/ui/components/TextInput.js +19 -19
- package/dist/private/node/ui/components/TextInput.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.js +1 -1
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.test.js +0 -1
- package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.js +1 -2
- package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
- package/dist/private/node/ui/contexts/LinksContext.d.ts +1 -3
- package/dist/private/node/ui/contexts/LinksContext.js.map +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js +9 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js.map +1 -1
- package/dist/private/node/ui.js +8 -1
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/array.js +0 -1
- package/dist/public/common/array.js.map +1 -1
- package/dist/public/common/collection.d.ts +1 -3
- package/dist/public/common/collection.js.map +1 -1
- package/dist/public/common/string.js +1 -4
- package/dist/public/common/string.js.map +1 -1
- package/dist/public/common/ts/json-narrowing.d.ts +1 -3
- package/dist/public/common/ts/json-narrowing.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/analytics.js +1 -1
- package/dist/public/node/analytics.js.map +1 -1
- package/dist/public/node/api/admin.d.ts +2 -6
- package/dist/public/node/api/admin.js +1 -2
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/app-dev.d.ts +1 -1
- package/dist/public/node/api/app-dev.js +1 -1
- package/dist/public/node/api/app-dev.js.map +1 -1
- package/dist/public/node/api/app-management.d.ts +1 -3
- package/dist/public/node/api/app-management.js +1 -1
- package/dist/public/node/api/app-management.js.map +1 -1
- package/dist/public/node/api/business-platform.js.map +1 -1
- package/dist/public/node/api/functions.js +1 -1
- package/dist/public/node/api/functions.js.map +1 -1
- package/dist/public/node/api/graphql.d.ts +4 -12
- package/dist/public/node/api/graphql.js.map +1 -1
- package/dist/public/node/api/partners.js +1 -1
- package/dist/public/node/api/partners.js.map +1 -1
- package/dist/public/node/api/rest-api-throttler.js +0 -1
- package/dist/public/node/api/rest-api-throttler.js.map +1 -1
- package/dist/public/node/archiver.js +2 -2
- package/dist/public/node/archiver.js.map +1 -1
- package/dist/public/node/base-command.js +0 -2
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/cli.js.map +1 -1
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/custom-oclif-loader.js +0 -1
- package/dist/public/node/custom-oclif-loader.js.map +1 -1
- package/dist/public/node/doctor/framework.d.ts +14 -9
- package/dist/public/node/doctor/framework.js +10 -3
- package/dist/public/node/doctor/framework.js.map +1 -1
- package/dist/public/node/doctor/reporter.d.ts +23 -0
- package/dist/public/node/doctor/reporter.js +33 -1
- package/dist/public/node/doctor/reporter.js.map +1 -1
- package/dist/public/node/dot-env.d.ts +2 -6
- package/dist/public/node/dot-env.js +1 -2
- package/dist/public/node/dot-env.js.map +1 -1
- package/dist/public/node/environments.d.ts +1 -3
- package/dist/public/node/environments.js.map +1 -1
- package/dist/public/node/error-handler.js +3 -3
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/error.d.ts +1 -1
- package/dist/public/node/error.js +2 -2
- package/dist/public/node/error.js.map +1 -1
- package/dist/public/node/framework.js +0 -1
- package/dist/public/node/framework.js.map +1 -1
- package/dist/public/node/fs.d.ts +1 -1
- package/dist/public/node/fs.js +1 -1
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/git.d.ts +1 -3
- package/dist/public/node/git.js +1 -3
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/github.js +14 -8
- package/dist/public/node/github.js.map +1 -1
- package/dist/public/node/hooks/postrun.js +2 -2
- package/dist/public/node/hooks/postrun.js.map +1 -1
- package/dist/public/node/hooks/prerun.js +2 -2
- package/dist/public/node/hooks/prerun.js.map +1 -1
- package/dist/public/node/http.js +2 -3
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/json-schema.d.ts +1 -3
- package/dist/public/node/json-schema.js +0 -1
- package/dist/public/node/json-schema.js.map +1 -1
- package/dist/public/node/liquid.js +1 -1
- package/dist/public/node/liquid.js.map +1 -1
- package/dist/public/node/local-storage.d.ts +1 -3
- package/dist/public/node/local-storage.js.map +1 -1
- package/dist/public/node/metadata.d.ts +1 -3
- package/dist/public/node/metadata.js +0 -1
- package/dist/public/node/metadata.js.map +1 -1
- package/dist/public/node/mimes.d.ts +1 -3
- package/dist/public/node/mimes.js.map +1 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/multiple-installation-warning.d.ts +1 -3
- package/dist/public/node/multiple-installation-warning.js.map +1 -1
- package/dist/public/node/node-package-manager.d.ts +9 -27
- package/dist/public/node/node-package-manager.js +1 -1
- package/dist/public/node/node-package-manager.js.map +1 -1
- package/dist/public/node/os.js +1 -1
- package/dist/public/node/os.js.map +1 -1
- package/dist/public/node/output.d.ts +1 -3
- package/dist/public/node/output.js +1 -2
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/path.d.ts +13 -0
- package/dist/public/node/path.js +10 -1
- package/dist/public/node/path.js.map +1 -1
- package/dist/public/node/plugins/tunnel.d.ts +5 -11
- package/dist/public/node/plugins/tunnel.js.map +1 -1
- package/dist/public/node/plugins.d.ts +4 -12
- package/dist/public/node/plugins.js.map +1 -1
- package/dist/public/node/result.js +1 -1
- package/dist/public/node/result.js.map +1 -1
- package/dist/public/node/session.js +15 -7
- package/dist/public/node/session.js.map +1 -1
- package/dist/public/node/system.d.ts +1 -3
- package/dist/public/node/system.js +1 -1
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/tcp.js +1 -1
- package/dist/public/node/tcp.js.map +1 -1
- package/dist/public/node/testing/output.js +1 -1
- package/dist/public/node/testing/output.js.map +1 -1
- package/dist/public/node/themes/api.js +2 -2
- package/dist/public/node/themes/api.js.map +1 -1
- package/dist/public/node/themes/conf.d.ts +1 -3
- package/dist/public/node/themes/conf.js.map +1 -1
- package/dist/public/node/tree-kill.js +0 -1
- package/dist/public/node/tree-kill.js.map +1 -1
- package/dist/public/node/ui.js +0 -12
- package/dist/public/node/ui.js.map +1 -1
- package/dist/public/node/vendor/dev_server/dev-server-2016.d.ts +8 -0
- package/dist/public/node/vendor/dev_server/dev-server-2016.js +10 -2
- package/dist/public/node/vendor/dev_server/dev-server-2016.js.map +1 -1
- package/dist/public/node/vendor/dev_server/dev-server-2024.d.ts +8 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.js +10 -2
- package/dist/public/node/vendor/dev_server/dev-server-2024.js.map +1 -1
- package/dist/public/node/vendor/dev_server/dev-server.js +1 -1
- package/dist/public/node/vendor/dev_server/dev-server.js.map +1 -1
- package/dist/public/node/vendor/dev_server/env.d.ts +3 -0
- package/dist/public/node/vendor/dev_server/env.js +3 -0
- package/dist/public/node/vendor/dev_server/env.js.map +1 -1
- package/dist/public/node/vendor/dev_server/network/host.d.ts +7 -0
- package/dist/public/node/vendor/dev_server/network/host.js +7 -1
- package/dist/public/node/vendor/dev_server/network/host.js.map +1 -1
- package/dist/public/node/vendor/dev_server/network/index.d.ts +7 -0
- package/dist/public/node/vendor/dev_server/network/index.js +7 -2
- package/dist/public/node/vendor/dev_server/network/index.js.map +1 -1
- package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.d.ts +1 -1
- package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.js +2 -4
- package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.js.map +1 -1
- package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.d.ts +7 -0
- package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.js +9 -1
- package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.js.map +1 -1
- package/dist/public/node/vendor/otel-js/service/DefaultOtelService/DefaultOtelService.d.ts +12 -1
- package/dist/public/node/vendor/otel-js/service/DefaultOtelService/DefaultOtelService.js +11 -0
- package/dist/public/node/vendor/otel-js/service/DefaultOtelService/DefaultOtelService.js.map +1 -1
- package/dist/public/node/vendor/otel-js/service/types.d.ts +6 -10
- package/dist/public/node/vendor/otel-js/service/types.js.map +1 -1
- package/dist/public/node/vendor/otel-js/utils/throttle.d.ts +10 -2
- package/dist/public/node/vendor/otel-js/utils/throttle.js +9 -0
- package/dist/public/node/vendor/otel-js/utils/throttle.js.map +1 -1
- package/dist/public/node/vendor/otel-js/utils/validators.d.ts +4 -0
- package/dist/public/node/vendor/otel-js/utils/validators.js +4 -0
- package/dist/public/node/vendor/otel-js/utils/validators.js.map +1 -1
- package/dist/public/node/version.js +1 -1
- package/dist/public/node/version.js.map +1 -1
- package/dist/public/node/vscode.js +1 -1
- package/dist/public/node/vscode.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
|
@@ -38,8 +38,6 @@ export declare class BMap<TKey, TValue> extends Map<TKey, TValue> {
|
|
|
38
38
|
set(key: TKey, value: TValue): this;
|
|
39
39
|
delete(key: TKey): boolean;
|
|
40
40
|
clear(): void;
|
|
41
|
-
toObject():
|
|
42
|
-
[key: string]: TValue;
|
|
43
|
-
};
|
|
41
|
+
toObject(): Record<string, TValue>;
|
|
44
42
|
private enforceLimit;
|
|
45
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bounded-collections.js","sourceRoot":"","sources":["../../../../src/private/node/analytics/bounded-collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,cAAc,GAAG,IAAI,CAAA;AAE3B;;GAEG;AACH,MAAM,YAAY,GAAG,IAAI,CAAA;AAEzB;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,MAAU,SAAQ,KAAQ;IACrC,IAAI,CAAC,GAAG,KAAU;QAChB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;IACjB,CAAC;IAED,OAAO;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IAClB,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,IAAmB,SAAQ,GAAiB;IAAzD;;QACU,mBAAc,GAAW,EAAE,CAAA;IAoCrC,CAAC;IAlCC,GAAG,CAAC,GAAS,EAAE,KAAa;QAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC/B,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACrB,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,GAAS;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC9C,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACtC,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,GAAG,EAAE,CAAA;QACxB,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IAED,QAAQ;QACN,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,CAAC,IAAI,GAAG,YAAY,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;YAC7C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Ensures bounded arrays stay within reasonable memory limits.\n */\nconst MAX_ARRAY_SIZE = 1000\n\n/**\n * Estimated ~500KB total across timing, error, retry, and event entries.\n */\nconst MAX_MAP_KEYS = 1000\n\n/**\n * A bounded array that automatically maintains a maximum size by removing\n * the oldest entries when new items are added beyond the limit.\n *\n * Extends the native Array class to provide all standard array methods\n * while enforcing a fixed maximum size of MAX_ARRAY_SIZE (1000 entries).\n *\n * When the size limit is exceeded, the oldest entries (at the beginning\n * of the array) are automatically removed to make room for new ones.\n *\n * @example\n * const commands = new BArray()\n * commands.push(entry) // Automatically removes oldest if over 1000\n */\nexport class BArray<T> extends Array<T> {\n push(...items: T[]): number {\n const result = super.push(...items)\n this.enforceLimit()\n return result\n }\n\n clear(): void {\n this.length = 0\n }\n\n toArray(): T[] {\n return [...this]\n }\n\n private enforceLimit(): void {\n while (this.length > MAX_ARRAY_SIZE) {\n this.shift()\n }\n }\n}\n\n/**\n * A bounded map that automatically maintains a maximum number of keys by\n * removing the oldest entries when new keys are added beyond the limit.\n *\n * Extends the native Map class to provide all standard map methods while\n * enforcing a fixed maximum size of MAX_MAP_KEYS (1000 entries).\n *\n * Tracks insertion order to ensure the oldest keys are removed first when\n * the limit is exceeded. This provides LRU-like behavior based on insertion\n * time rather than access time.\n *\n * @example\n * const events = new BMap()\n * events.set('event', 1) // Automatically removes oldest if over 1000\n */\nexport class BMap<TKey, TValue> extends Map<TKey, TValue> {\n private insertionOrder: TKey[] = []\n\n set(key: TKey, value: TValue): this {\n if (!this.has(key)) {\n this.insertionOrder.push(key)\n }\n super.set(key, value)\n this.enforceLimit()\n return this\n }\n\n delete(key: TKey): boolean {\n const index = this.insertionOrder.indexOf(key)\n if (index > -1) {\n this.insertionOrder.splice(index, 1)\n }\n return super.delete(key)\n }\n\n clear(): void {\n this.insertionOrder = []\n super.clear()\n }\n\n toObject():
|
|
1
|
+
{"version":3,"file":"bounded-collections.js","sourceRoot":"","sources":["../../../../src/private/node/analytics/bounded-collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,cAAc,GAAG,IAAI,CAAA;AAE3B;;GAEG;AACH,MAAM,YAAY,GAAG,IAAI,CAAA;AAEzB;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,MAAU,SAAQ,KAAQ;IACrC,IAAI,CAAC,GAAG,KAAU;QAChB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;IACjB,CAAC;IAED,OAAO;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IAClB,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,IAAmB,SAAQ,GAAiB;IAAzD;;QACU,mBAAc,GAAW,EAAE,CAAA;IAoCrC,CAAC;IAlCC,GAAG,CAAC,GAAS,EAAE,KAAa;QAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC/B,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACrB,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,GAAS;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC9C,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACtC,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,GAAG,EAAE,CAAA;QACxB,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IAED,QAAQ;QACN,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,CAAC,IAAI,GAAG,YAAY,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;YAC7C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Ensures bounded arrays stay within reasonable memory limits.\n */\nconst MAX_ARRAY_SIZE = 1000\n\n/**\n * Estimated ~500KB total across timing, error, retry, and event entries.\n */\nconst MAX_MAP_KEYS = 1000\n\n/**\n * A bounded array that automatically maintains a maximum size by removing\n * the oldest entries when new items are added beyond the limit.\n *\n * Extends the native Array class to provide all standard array methods\n * while enforcing a fixed maximum size of MAX_ARRAY_SIZE (1000 entries).\n *\n * When the size limit is exceeded, the oldest entries (at the beginning\n * of the array) are automatically removed to make room for new ones.\n *\n * @example\n * const commands = new BArray()\n * commands.push(entry) // Automatically removes oldest if over 1000\n */\nexport class BArray<T> extends Array<T> {\n push(...items: T[]): number {\n const result = super.push(...items)\n this.enforceLimit()\n return result\n }\n\n clear(): void {\n this.length = 0\n }\n\n toArray(): T[] {\n return [...this]\n }\n\n private enforceLimit(): void {\n while (this.length > MAX_ARRAY_SIZE) {\n this.shift()\n }\n }\n}\n\n/**\n * A bounded map that automatically maintains a maximum number of keys by\n * removing the oldest entries when new keys are added beyond the limit.\n *\n * Extends the native Map class to provide all standard map methods while\n * enforcing a fixed maximum size of MAX_MAP_KEYS (1000 entries).\n *\n * Tracks insertion order to ensure the oldest keys are removed first when\n * the limit is exceeded. This provides LRU-like behavior based on insertion\n * time rather than access time.\n *\n * @example\n * const events = new BMap()\n * events.set('event', 1) // Automatically removes oldest if over 1000\n */\nexport class BMap<TKey, TValue> extends Map<TKey, TValue> {\n private insertionOrder: TKey[] = []\n\n set(key: TKey, value: TValue): this {\n if (!this.has(key)) {\n this.insertionOrder.push(key)\n }\n super.set(key, value)\n this.enforceLimit()\n return this\n }\n\n delete(key: TKey): boolean {\n const index = this.insertionOrder.indexOf(key)\n if (index > -1) {\n this.insertionOrder.splice(index, 1)\n }\n return super.delete(key)\n }\n\n clear(): void {\n this.insertionOrder = []\n super.clear()\n }\n\n toObject(): Record<string, TValue> {\n return Object.fromEntries(this)\n }\n\n private enforceLimit(): void {\n while (this.size > MAX_MAP_KEYS && this.insertionOrder.length > 0) {\n const oldestKey = this.insertionOrder.shift()\n if (oldestKey !== undefined) {\n super.delete(oldestKey)\n }\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-categorizer.js","sourceRoot":"","sources":["../../../../src/private/node/analytics/error-categorizer.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,aAWX;AAXD,WAAY,aAAa;IACvB,kCAAiB,CAAA;IACjB,2CAA0B,CAAA;IAC1B,oCAAmB,CAAA;IACnB,2CAA0B,CAAA;IAC1B,kDAAiC,CAAA;IACjC,0CAAyB,CAAA;IACzB,0CAAyB,CAAA;IACzB,yCAAwB,CAAA;IACxB,8BAAa,CAAA;IACb,oCAAmB,CAAA;AACrB,CAAC,EAXW,aAAa,KAAb,aAAa,QAWxB;AAED,MAAM,oBAAoB,GAAG;IAC3B,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC;IAClC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAChD,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,aAAa,CAAC;IAC3C,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC;IAC5F,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;QACvB,WAAW;QACX,OAAO;QACP,aAAa;QACb,WAAW;QACX,OAAO;QACP,WAAW;QACX,OAAO;QACP,SAAS;QACT,SAAS;QACT,QAAQ;QACR,2BAA2B;QAC3B,WAAW;QACX,SAAS;KACV;IACD,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;IAC7E,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,CAAC;IAC9E,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,mBAAmB,EAAE,UAAU,CAAC;IAC1E,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,UAAU,CAAC;CAClE,CAAA;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,aAAa,CAAC,OAAO,CAAA;IAE3D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;IAE3C,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACrE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;QAE5D,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,QAAyB,CAAA;QAClC,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC,OAAO,CAAA;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAE,QAAuB;IACxE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAEtE,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAA;IAClE,OAAO,SAAS,CAAC,OAAO,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"error-categorizer.js","sourceRoot":"","sources":["../../../../src/private/node/analytics/error-categorizer.ts"],"names":[],"mappings":"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","sourcesContent":["export enum ErrorCategory {\n Liquid = 'LIQUID',\n ThemeCheck = 'THEME_CHECK',\n Network = 'NETWORK',\n FileSystem = 'FILE_SYSTEM',\n Authentication = 'AUTHENTICATION',\n Validation = 'VALIDATION',\n Permission = 'PERMISSION',\n RateLimit = 'RATE_LIMIT',\n Json = 'JSON',\n Unknown = 'UNKNOWN',\n}\n\nconst ERROR_CATEGORY_TERMS = {\n [ErrorCategory.Liquid]: ['liquid'],\n [ErrorCategory.Json]: ['json', 'parse response'],\n [ErrorCategory.ThemeCheck]: ['theme check'],\n [ErrorCategory.Authentication]: ['unauthorized', 'forbidden', 'auth', 'token', 'credential'],\n [ErrorCategory.Network]: [\n 'eai_again',\n 'econn',\n 'enetunreach',\n 'enotfound',\n 'epipe',\n 'etimedout',\n 'fetch',\n 'network',\n 'request',\n 'socket',\n 'the operation was aborted',\n 'timed out',\n 'timeout',\n ],\n [ErrorCategory.FileSystem]: ['enoent', 'eacces', 'file', 'directory', 'path'],\n [ErrorCategory.Permission]: ['permission', 'denied', 'access', 'insufficient'],\n [ErrorCategory.RateLimit]: ['rate limit', 'too many requests', 'throttle'],\n [ErrorCategory.Validation]: ['validation', 'invalid', 'required'],\n}\n\nexport function categorizeError(error: unknown): ErrorCategory {\n if (!(error instanceof Error)) return ErrorCategory.Unknown\n\n const message = error.message.toLowerCase()\n\n for (const [category, terms] of Object.entries(ERROR_CATEGORY_TERMS)) {\n const hasTerm = terms.some((term) => message.includes(term))\n\n if (hasTerm) {\n return category as ErrorCategory\n }\n }\n\n return ErrorCategory.Unknown\n}\n\n/**\n * Formats an error message for analytics tracking, preserving important information\n * based on the error category while keeping it concise and normalized.\n */\nexport function formatErrorMessage(error: unknown, category: ErrorCategory): string {\n const message = error instanceof Error ? error.message : String(error)\n\n const formatter = ERROR_FORMATTERS[category] || formatGenericError\n return formatter(message)\n}\n\nconst ERROR_FORMATTERS: Record<ErrorCategory, (message: string) => string> = {\n [ErrorCategory.Network]: formatNetworkError,\n [ErrorCategory.Authentication]: formatGenericError,\n [ErrorCategory.FileSystem]: formatGenericError,\n [ErrorCategory.RateLimit]: formatGenericError,\n [ErrorCategory.Json]: formatGenericError,\n [ErrorCategory.Validation]: formatGenericError,\n [ErrorCategory.Permission]: formatGenericError,\n [ErrorCategory.Liquid]: formatGenericError,\n [ErrorCategory.ThemeCheck]: formatGenericError,\n [ErrorCategory.Unknown]: formatGenericError,\n}\n\nfunction formatNetworkError(message: string): string {\n const httpStatusMatch = message.match(/\\b([1-5]\\d{2})\\b/)\n const connectionErrorMatch = message.match(/\\b(E[A-Z]+)\\b/)\n const graphqlCodeMatch = message.match(/(?:code|error)[:\\s]*(\\d{3})/i)\n\n let normalized = message.toLowerCase().substring(0, 50)\n\n if (httpStatusMatch?.[1]) {\n const statusCode = httpStatusMatch[1]\n normalized = `http-${statusCode}-${normalized.replace(/\\b\\d{3}\\b/g, '').trim()}`\n } else if (graphqlCodeMatch?.[1]) {\n const statusCode = graphqlCodeMatch[1]\n normalized = `http-${statusCode}-${normalized.replace(/(?:code|error)[:\\s]*\\d{3}/gi, '').trim()}`\n } else if (connectionErrorMatch?.[1]) {\n const errorCode = connectionErrorMatch[1].toLowerCase()\n normalized = `http-000-${errorCode}-${normalized.replace(/\\b[eE][A-Z]+\\b/g, '').trim()}`\n } else {\n normalized = `http-000-${normalized}`\n }\n\n return normalized\n .replace(/[^a-zA-Z0-9-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .substring(0, 50)\n}\n\nfunction formatGenericError(message: string): string {\n return message\n .toLowerCase()\n .substring(0, 50)\n .replace(/[^a-zA-Z0-9]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/private/node/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,qBAAqB,EAAC,MAAM,cAAc,CAAA;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,6BAA6B,CAAA;AACtD,OAAO,EAAC,iBAAiB,EAAE,2BAA2B,EAAC,MAAM,2CAA2C,CAAA;AAGxG,OAAO,KAAK,QAAQ,MAAM,+BAA+B,CAAA;AACzD,OAAO,EAAC,eAAe,EAAC,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAC,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAC,MAAM,oCAAoC,CAAA;AAC3F,OAAO,EAAC,GAAG,EAAC,MAAM,2BAA2B,CAAA;AAC7C,OAAO,EAAC,sBAAsB,EAAC,MAAM,gCAAgC,CAAA;AACrE,OAAO,EAAC,KAAK,EAAC,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/private/node/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import {getLastSeenAuthMethod} from './session.js'\nimport {hashString} from '../../public/node/crypto.js'\nimport {getPackageManager, packageManagerFromUserAgent} from '../../public/node/node-package-manager.js'\nimport BaseCommand from '../../public/node/base-command.js'\nimport {CommandContent} from '../../public/node/hooks/prerun.js'\nimport * as metadata from '../../public/node/metadata.js'\nimport {platformAndArch} from '../../public/node/os.js'\nimport {ciPlatform, cloudEnvironment, macAddress} from '../../public/node/context/local.js'\nimport {cwd} from '../../public/node/path.js'\nimport {currentProcessIsGlobal} from '../../public/node/is-global.js'\nimport {isWsl} from '../../public/node/system.js'\n\nimport {Command, Interfaces} from '@oclif/core'\n\ninterface StartOptions {\n commandContent: CommandContent\n args: string[]\n currentTime?: number\n commandClass?: Command.Class | typeof BaseCommand\n}\n\nexport async function startAnalytics({\n commandContent,\n args,\n currentTime = new Date().getTime(),\n commandClass,\n}: StartOptions): Promise<void> {\n let startCommand: string = commandContent.command\n if (commandClass && Object.prototype.hasOwnProperty.call(commandClass, 'analyticsNameOverride')) {\n startCommand = (commandClass as typeof BaseCommand).analyticsNameOverride() ?? commandContent.command\n }\n\n let pluginName = commandClass?.plugin?.name\n if (commandClass && 'customPluginName' in commandClass) {\n pluginName = commandClass.customPluginName as string\n }\n\n await metadata.addSensitiveMetadata(() => ({\n commandStartOptions: {\n startTime: currentTime,\n startCommand,\n startArgs: args,\n },\n }))\n\n await metadata.addPublicMetadata(() => ({\n cmd_all_launcher: packageManagerFromUserAgent(),\n cmd_all_alias_used: commandContent.alias,\n cmd_all_topic: commandContent.topic,\n cmd_all_plugin: pluginName,\n cmd_all_force: flagIncluded('force', commandClass) ? args.includes('--force') : undefined,\n }))\n}\n\ninterface EnvironmentData {\n uname: string\n env_ci: boolean\n env_ci_platform?: string\n env_plugin_installed_any_custom: boolean\n env_plugin_installed_shopify: string\n env_shell: string\n env_web_ide: string | undefined\n env_device_id: string\n env_cloud: string\n env_package_manager: string\n env_is_global: boolean\n env_auth_method: string\n env_is_wsl: boolean\n env_build_repository: string\n}\n\nexport async function getEnvironmentData(config: Interfaces.Config): Promise<EnvironmentData> {\n const ciplatform = ciPlatform()\n\n const pluginNames = getPluginNames(config)\n const shopifyPlugins = pluginNames.filter((plugin) => plugin.startsWith('@shopify/'))\n\n const {platform, arch} = platformAndArch()\n\n return {\n uname: `${platform} ${arch}`,\n env_ci: ciplatform.isCI,\n env_ci_platform: ciplatform.name,\n env_plugin_installed_any_custom: pluginNames.length !== shopifyPlugins.length,\n env_plugin_installed_shopify: JSON.stringify(shopifyPlugins),\n env_shell: config.shell,\n env_web_ide: cloudEnvironment().editor ? cloudEnvironment().platform : undefined,\n env_device_id: hashString(await macAddress()),\n env_cloud: cloudEnvironment().platform,\n env_package_manager: await getPackageManager(cwd()),\n env_is_global: currentProcessIsGlobal(),\n env_auth_method: await getLastSeenAuthMethod(),\n env_is_wsl: await isWsl(),\n env_build_repository: process.env.SHOPIFY_CLI_BUILD_REPO ?? 'unknown',\n }\n}\n\nexport async function getSensitiveEnvironmentData(config: Interfaces.Config) {\n return {\n env_plugin_installed_all: JSON.stringify(getPluginNames(config)),\n env_shopify_variables: JSON.stringify(getShopifyEnvironmentVariables()),\n }\n}\n\nfunction getShopifyEnvironmentVariables() {\n return Object.fromEntries(Object.entries(process.env).filter(([key]) => key.startsWith('SHOPIFY_')))\n}\n\nfunction getPluginNames(config: Interfaces.Config) {\n const pluginNames = [...config.plugins.keys()]\n return pluginNames.sort().filter((plugin) => !plugin.startsWith('@oclif/'))\n}\n\nfunction flagIncluded(flag: string, commandClass?: Command.Class | typeof BaseCommand) {\n if (!commandClass) return false\n\n const commandFlags = commandClass.flags ?? {}\n return Object.keys(commandFlags).includes(flag)\n}\n"]}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { Variables } from 'graphql-request';
|
|
2
|
-
export declare function debugLogRequestInfo(api: string, query: string, url: string, variables?: Variables, headers?:
|
|
3
|
-
[key: string]: string;
|
|
4
|
-
}): void;
|
|
2
|
+
export declare function debugLogRequestInfo(api: string, query: string, url: string, variables?: Variables, headers?: Record<string, string>): void;
|
|
5
3
|
export declare function sanitizeVariables(variables: Variables): string;
|
|
6
4
|
export declare function errorHandler(api: string): (error: unknown, requestId?: string) => unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../../src/private/node/api/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAE,sBAAsB,EAAC,MAAM,cAAc,CAAA;AACvE,OAAO,EAAC,WAAW,EAAC,MAAM,WAAW,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,gCAAgC,CAAA;AACxG,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../../src/private/node/api/graphql.ts"],"names":[],"mappings":"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","sourcesContent":["import {GraphQLClientError, sanitizedHeadersOutput} from './headers.js'\nimport {sanitizeURL} from './urls.js'\nimport {stringifyMessage, outputContent, outputToken, outputDebug} from '../../../public/node/output.js'\nimport {AbortError} from '../../../public/node/error.js'\n\nimport {ClientError, Variables} from 'graphql-request'\n\nexport function debugLogRequestInfo(\n api: string,\n query: string,\n url: string,\n variables?: Variables,\n headers: Record<string, string> = {},\n) {\n outputDebug(outputContent`Sending ${outputToken.json(api)} GraphQL request:\n ${outputToken.raw(query.toString().trim())}\n${variables ? `\\nWith variables:\\n${sanitizeVariables(variables)}\\n` : ''}\nWith request headers:\n${sanitizedHeadersOutput(headers)}\\n\nto ${sanitizeURL(url)}`)\n}\n\nexport function sanitizeVariables(variables: Variables): string {\n const result: Variables = {...variables}\n const sensitiveKeys = ['apiKey', 'serialized_script']\n\n const sanitizedResult = sanitizeDeepVariables(result, sensitiveKeys)\n\n return JSON.stringify(sanitizedResult, null, 2)\n}\n\nfunction sanitizeDeepVariables(value: unknown, sensitiveKeys: string[]): unknown {\n // Checking for JSON\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value)\n if (typeof parsed === 'object' && parsed !== null) {\n const sanitized = sanitizeDeepVariables(parsed, sensitiveKeys)\n return JSON.stringify(sanitized, null)\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return value\n }\n }\n\n if (typeof value !== 'object' || value === null) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => sanitizeDeepVariables(item, sensitiveKeys))\n }\n\n const result: Variables = {}\n\n for (const [key, val] of Object.entries(value)) {\n if (sensitiveKeys.includes(key) && typeof val === 'string') {\n result[key] = '*****'\n continue\n }\n\n result[key] = sanitizeDeepVariables(val, sensitiveKeys)\n }\n\n return result\n}\n\nexport function errorHandler(api: string): (error: unknown, requestId?: string) => unknown {\n return (error: unknown, requestId?: string) => {\n if (error instanceof ClientError) {\n const {status} = error.response\n let errorMessage = stringifyMessage(outputContent`\nThe ${outputToken.raw(api)} GraphQL API responded unsuccessfully with${\n status === 200 ? '' : ` the HTTP status ${status} and`\n } errors:\n\n${outputToken.json(error.response.errors)}\n `)\n if (requestId) {\n errorMessage += `\nRequest ID: ${requestId}\n`\n }\n let mappedError: Error\n if (status < 500) {\n mappedError = new GraphQLClientError(errorMessage, status, error.response.errors)\n } else {\n mappedError = new AbortError(errorMessage)\n }\n mappedError.stack = error.stack\n return mappedError\n } else {\n return error\n }\n }\n}\n"]}
|
|
@@ -13,12 +13,8 @@ export declare class GraphQLClientError extends RequestClientError {
|
|
|
13
13
|
* @param headers - HTTP headers.
|
|
14
14
|
* @returns A sanitized version of the headers as a string.
|
|
15
15
|
*/
|
|
16
|
-
export declare function sanitizedHeadersOutput(headers:
|
|
17
|
-
|
|
18
|
-
}): string;
|
|
19
|
-
export declare function buildHeaders(token?: string): {
|
|
20
|
-
[key: string]: string;
|
|
21
|
-
};
|
|
16
|
+
export declare function sanitizedHeadersOutput(headers: Record<string, string>): string;
|
|
17
|
+
export declare function buildHeaders(token?: string): Record<string, string>;
|
|
22
18
|
/**
|
|
23
19
|
* This utility function returns the https.Agent to use for a given service.
|
|
24
20
|
*/
|
|
@@ -29,7 +29,6 @@ export function sanitizedHeadersOutput(headers) {
|
|
|
29
29
|
const keywords = ['token', 'authorization', 'subject_token'];
|
|
30
30
|
Object.keys(headers).forEach((header) => {
|
|
31
31
|
if (keywords.find((keyword) => header.toLocaleLowerCase().includes(keyword)) === undefined) {
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
33
32
|
sanitized[header] = headers[header];
|
|
34
33
|
}
|
|
35
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAA;AACjE,OAAO,EAAC,aAAa,EAAC,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,kBAAmB,SAAQ,UAAU;IAEzC,YAAmB,OAAe,EAAE,UAAkB;QACpD,MAAM,UAAU,GACd,UAAU,KAAK,GAAG;YAChB,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,SAAS,CAAA;QACf,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AACD,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IAIxD,8DAA8D;IAC9D,YAAmB,OAAe,EAAE,UAAkB,EAAE,MAAc;QACpE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAA;AACjE,OAAO,EAAC,aAAa,EAAC,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,kBAAmB,SAAQ,UAAU;IAEzC,YAAmB,OAAe,EAAE,UAAkB;QACpD,MAAM,UAAU,GACd,UAAU,KAAK,GAAG;YAChB,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,SAAS,CAAA;QACf,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AACD,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IAIxD,8DAA8D;IAC9D,YAAmB,OAAe,EAAE,UAAkB,EAAE,MAAc;QACpE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAA+B;IACpE,MAAM,SAAS,GAA2B,EAAE,CAAA;IAC5C,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;IAC5D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAC3F,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAA;QACtC,CAAC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,OAAO,MAAM,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAA;IAC7C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,kBAAkB,eAAe,EAAE,CAAA;IAErD,MAAM,OAAO,GAA2B;QACtC,YAAY,EAAE,SAAS;QACvB,YAAY,EAAE,YAAY;QAC1B,0DAA0D;QAC1D,oBAAoB,EAAE,OAAO,CAAC,QAAQ;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAC,wBAAwB,EAAE,GAAG,EAAC,CAAC;KACxD,CAAA;IACD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAA;QAEhF,OAAO,CAAC,aAAa,GAAG,UAAU,CAAA;QAClC,OAAO,CAAC,wBAAwB,CAAC,GAAG,UAAU,CAAA;IAChD,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC;QACrB,kBAAkB,EAAE,IAAI;QACxB,SAAS,EAAE,IAAI;KAChB,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import {CLI_KIT_VERSION} from '../../../public/common/version.js'\nimport {firstPartyDev} from '../../../public/node/context/local.js'\nimport {AbortError} from '../../../public/node/error.js'\nimport https from 'https'\n\nclass RequestClientError extends AbortError {\n statusCode: number\n public constructor(message: string, statusCode: number) {\n const tryMessage =\n statusCode === 403\n ? 'Ensure you are using the correct account. You can switch with `shopify auth login`'\n : undefined\n super(message, tryMessage)\n this.statusCode = statusCode\n }\n}\nexport class GraphQLClientError extends RequestClientError {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errors?: any[]\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public constructor(message: string, statusCode: number, errors?: any[]) {\n super(message, statusCode)\n this.errors = errors\n this.stack = undefined\n }\n}\n\n/**\n * Removes the sensitive data from the headers and outputs them as a string.\n * @param headers - HTTP headers.\n * @returns A sanitized version of the headers as a string.\n */\nexport function sanitizedHeadersOutput(headers: Record<string, string>): string {\n const sanitized: Record<string, string> = {}\n const keywords = ['token', 'authorization', 'subject_token']\n Object.keys(headers).forEach((header) => {\n if (keywords.find((keyword) => header.toLocaleLowerCase().includes(keyword)) === undefined) {\n sanitized[header] = headers[header]!\n }\n })\n return Object.keys(sanitized)\n .map((header) => {\n return ` - ${header}: ${sanitized[header]}`\n })\n .join('\\n')\n}\n\nexport function buildHeaders(token?: string): Record<string, string> {\n const userAgent = `Shopify CLI; v=${CLI_KIT_VERSION}`\n\n const headers: Record<string, string> = {\n 'User-Agent': userAgent,\n 'Keep-Alive': 'timeout=30',\n // 'Sec-CH-UA': secCHUA, This header requires the Git sha.\n 'Sec-CH-UA-PLATFORM': process.platform,\n 'Content-Type': 'application/json',\n ...(firstPartyDev() && {'X-Shopify-Cli-Employee': '1'}),\n }\n if (token) {\n const authString = token.match(/^shp(at|ua|ca|tka)/) ? token : `Bearer ${token}`\n\n headers.authorization = authString\n headers['X-Shopify-Access-Token'] = authString\n }\n\n return headers\n}\n\n/**\n * This utility function returns the https.Agent to use for a given service.\n */\nexport async function httpsAgent(): Promise<https.Agent> {\n return new https.Agent({\n rejectUnauthorized: true,\n keepAlive: true,\n })\n}\n"]}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { AdminSession } from '../../../public/node/session.js';
|
|
2
2
|
export declare function restRequestBody<T>(requestBody?: T): string | undefined;
|
|
3
|
-
export declare function restRequestUrl(session: AdminSession, apiVersion: string, path: string, searchParams?:
|
|
4
|
-
|
|
5
|
-
}): string;
|
|
6
|
-
export declare function restRequestHeaders(session: AdminSession): {
|
|
7
|
-
[key: string]: string;
|
|
8
|
-
};
|
|
3
|
+
export declare function restRequestUrl(session: AdminSession, apiVersion: string, path: string, searchParams?: Record<string, string>): string;
|
|
4
|
+
export declare function restRequestHeaders(session: AdminSession): Record<string, string>;
|
|
9
5
|
export declare function isThemeAccessSession(session: AdminSession): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../../src/private/node/api/rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAA;AACzC,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAA;AAGpD,MAAM,UAAU,eAAe,CAAI,WAAe;IAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAM;IACR,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAqB,EACrB,UAAkB,EAClB,IAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../../src/private/node/api/rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAA;AACzC,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAA;AAGpD,MAAM,UAAU,eAAe,CAAI,WAAe;IAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAM;IACR,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAqB,EACrB,UAAkB,EAClB,IAAY,EACZ,eAAuC,EAAE;IAEzC,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,oBAAoB,CAAC,OAAO,CAAC;QAC3B,CAAC,CAAC,WAAW,oBAAoB,kBAAkB,UAAU,GAAG,IAAI,OAAO;QAC3E,CAAC,CAAC,WAAW,OAAO,CAAC,SAAS,cAAc,UAAU,GAAG,IAAI,OAAO,CACvE,CAAA;IACD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QACrD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAqB;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAE3C,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAA;QACjC,OAAO,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAA;IAC3C,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAqB;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import {buildHeaders} from './headers.js'\nimport {themeKitAccessDomain} from '../constants.js'\nimport {AdminSession} from '../../../public/node/session.js'\n\nexport function restRequestBody<T>(requestBody?: T) {\n if (!requestBody) {\n return\n }\n return JSON.stringify(requestBody)\n}\n\nexport function restRequestUrl(\n session: AdminSession,\n apiVersion: string,\n path: string,\n searchParams: Record<string, string> = {},\n) {\n const url = new URL(\n isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${apiVersion}${path}.json`\n : `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`,\n )\n Object.entries(searchParams).forEach(([name, value]) => {\n url.searchParams.set(name, value)\n })\n\n return url.toString()\n}\n\nexport function restRequestHeaders(session: AdminSession) {\n const store = session.storeFqdn\n const token = session.token\n const headers = buildHeaders(session.token)\n\n if (isThemeAccessSession(session)) {\n headers['X-Shopify-Shop'] = store\n headers['X-Shopify-Access-Token'] = token\n }\n\n return headers\n}\n\nexport function isThemeAccessSession(session: AdminSession) {\n return session.token.startsWith('shptka_')\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {sleepWithBackoffUntil} from './sleep-with-backoff.js'\nimport {outputDebug} from '../../public/node/output.js'\nimport {recordRetry} from '../../public/node/analytics.js'\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\nexport type NetworkRetryBehaviour =\n | {\n useNetworkLevelRetry: true\n maxRetryTimeMs: number\n recordCommandRetries?: boolean\n }\n | {\n useNetworkLevelRetry: false\n recordCommandRetries?: boolean\n }\n\ntype RequestOptions<T> = {\n request: () => Promise<T>\n url: string\n} & NetworkRetryBehaviour\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ninterface CommonResponse {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n}\n\ntype OkResponse<T> = CommonResponse & {status: 'ok'; response: T}\ntype ClientErrorResponse = CommonResponse & {status: 'client-error'; clientError: ClientError}\ntype UnknownErrorResponse = CommonResponse & {status: 'unknown-error'; error: unknown}\ntype CanRetryErrorResponse = CommonResponse & {\n status: 'can-retry'\n clientError: ClientError\n delayMs: number | undefined\n}\ntype UnauthorizedErrorResponse = CommonResponse & {\n status: 'unauthorized'\n clientError: ClientError\n delayMs: number | undefined\n}\n\ntype VerboseResponse<T> =\n | OkResponse<T>\n | ClientErrorResponse\n | UnknownErrorResponse\n | CanRetryErrorResponse\n | UnauthorizedErrorResponse\n\n/**\n * Checks if an error is a transient network error that is likely to recover with retries.\n *\n * Use this function for retry logic. Use isNetworkError for error classification.\n *\n * Examples of transient errors (worth retrying):\n * - Connection timeouts, resets, and aborts\n * - DNS failures (enotfound, getaddrinfo, eai_again) - can be temporary\n * - Socket disconnects and hang ups\n * - Premature connection closes\n */\nexport function isTransientNetworkError(error: unknown): boolean {\n if (error instanceof Error) {\n const transientErrorMessages = [\n 'socket hang up',\n 'econnreset',\n 'econnaborted',\n 'enotfound',\n 'enetunreach',\n 'network socket disconnected',\n 'etimedout',\n 'econnrefused',\n 'eai_again',\n 'epipe',\n 'the operation was aborted',\n 'timeout',\n 'premature close',\n 'getaddrinfo',\n ]\n const errorMessage = error.message.toLowerCase()\n const anyMatches = transientErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n const missingReason = /^request to .* failed, reason:\\s*$/.test(errorMessage)\n return anyMatches || missingReason\n }\n return false\n}\n\n/**\n * Checks if an error is any kind of network-related error (connection issues, timeouts, DNS failures,\n * TLS/certificate errors, etc.) rather than an application logic error.\n *\n * These errors should be reported as user-facing errors (AbortError) rather than bugs (BugError),\n * regardless of whether they are transient or permanent.\n *\n * Examples include:\n * - Transient: connection timeouts, socket hang ups, temporary DNS failures\n * - Permanent: certificate validation failures, misconfigured SSL\n */\nexport function isNetworkError(error: unknown): boolean {\n // First check if it's a transient network error\n if (isTransientNetworkError(error)) {\n return true\n }\n\n // Then check for permanent network errors (SSL/TLS/certificate issues)\n if (error instanceof Error) {\n const permanentNetworkErrorMessages = ['certificate', 'cert', 'tls', 'ssl', 'altnames']\n const errorMessage = error.message.toLowerCase()\n return permanentNetworkErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n }\n\n return false\n}\n\nasync function runRequestWithNetworkLevelRetry<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<T> {\n if (!requestOptions.useNetworkLevelRetry) {\n return requestOptions.request()\n }\n\n let lastSeenError: unknown\n\n for await (const _delayMs of sleepWithBackoffUntil(requestOptions.maxRetryTimeMs)) {\n try {\n return await requestOptions.request()\n } catch (err) {\n lastSeenError = err\n if (!isTransientNetworkError(err)) {\n throw err\n }\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `network-retry:${(err as Error).message}`)\n }\n\n outputDebug(`Retrying request to ${requestOptions.url} due to network error ${err}`)\n }\n }\n throw lastSeenError\n}\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: {[key: string]: string} = {}\n const sanitizedUrl = sanitizeURL(requestOptions.url)\n let response: T = {} as T\n try {\n response = await runRequestWithNetworkLevelRetry(requestOptions)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response.headers) {\n for (const [key, value] of err.response.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (errorsIncludeStatus429(err)) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n } else if (err.response.status === 401) {\n return {\n status: 'unauthorized',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs: 500,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\nfunction errorsIncludeStatus429(error: ClientError): boolean {\n if (error.response.status === 429) {\n return true\n }\n\n // GraphQL returns a 401 with a string error message when auth fails\n // Therefore error.response.errors can be a string or GraphQLError[]\n if (typeof error.response.errors === 'string') {\n return false\n }\n return error.response.errors?.some((error) => error.extensions?.code === '429') ?? false\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n): Promise<T> {\n const result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unauthorized': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\n/**\n * Makes a HTTP request to some API, retrying if response headers indicate a retryable error.\n *\n * If a request fails with a 429, the retry-after header determines a delay before an automatic retry is performed.\n *\n * If unauthorizedHandler is provided, then it will be called in the case of a 401 and a retry performed. This allows\n * for a token refresh for instance.\n *\n * If there's a network error, e.g. DNS fails to resolve, then API calls are automatically retried.\n *\n * @param request - A function that returns a promise of the response\n * @param url - The URL to request\n * @param errorHandler - A function that handles errors\n * @param unauthorizedHandler - A function that handles unauthorized errors\n * @param retryOptions - Options for the retry\n * @returns The response from the request\n */\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n } else if (result.status === 'unauthorized') {\n throw result.clientError\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `http-retry-${retriesUsed}:${result.status}:`)\n }\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) => {\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest(requestOptions))\n }, retryDelayMs)\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {sleepWithBackoffUntil} from './sleep-with-backoff.js'\nimport {outputDebug} from '../../public/node/output.js'\nimport {recordRetry} from '../../public/node/analytics.js'\n\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\n\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\nexport type NetworkRetryBehaviour =\n | {\n useNetworkLevelRetry: true\n maxRetryTimeMs: number\n recordCommandRetries?: boolean\n }\n | {\n useNetworkLevelRetry: false\n recordCommandRetries?: boolean\n }\n\ntype RequestOptions<T> = {\n request: () => Promise<T>\n url: string\n} & NetworkRetryBehaviour\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ninterface CommonResponse {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n}\n\ntype OkResponse<T> = CommonResponse & {status: 'ok'; response: T}\ntype ClientErrorResponse = CommonResponse & {status: 'client-error'; clientError: ClientError}\ntype UnknownErrorResponse = CommonResponse & {status: 'unknown-error'; error: unknown}\ntype CanRetryErrorResponse = CommonResponse & {\n status: 'can-retry'\n clientError: ClientError\n delayMs: number | undefined\n}\ntype UnauthorizedErrorResponse = CommonResponse & {\n status: 'unauthorized'\n clientError: ClientError\n delayMs: number | undefined\n}\n\ntype VerboseResponse<T> =\n | OkResponse<T>\n | ClientErrorResponse\n | UnknownErrorResponse\n | CanRetryErrorResponse\n | UnauthorizedErrorResponse\n\n/**\n * Checks if an error is a transient network error that is likely to recover with retries.\n *\n * Use this function for retry logic. Use isNetworkError for error classification.\n *\n * Examples of transient errors (worth retrying):\n * - Connection timeouts, resets, and aborts\n * - DNS failures (enotfound, getaddrinfo, eai_again) - can be temporary\n * - Socket disconnects and hang ups\n * - Premature connection closes\n */\nexport function isTransientNetworkError(error: unknown): boolean {\n if (error instanceof Error) {\n const transientErrorMessages = [\n 'socket hang up',\n 'econnreset',\n 'econnaborted',\n 'enotfound',\n 'enetunreach',\n 'network socket disconnected',\n 'etimedout',\n 'econnrefused',\n 'eai_again',\n 'epipe',\n 'the operation was aborted',\n 'timeout',\n 'premature close',\n 'getaddrinfo',\n ]\n const errorMessage = error.message.toLowerCase()\n const anyMatches = transientErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n const missingReason = /^request to .* failed, reason:\\s*$/.test(errorMessage)\n return anyMatches || missingReason\n }\n return false\n}\n\n/**\n * Checks if an error is any kind of network-related error (connection issues, timeouts, DNS failures,\n * TLS/certificate errors, etc.) rather than an application logic error.\n *\n * These errors should be reported as user-facing errors (AbortError) rather than bugs (BugError),\n * regardless of whether they are transient or permanent.\n *\n * Examples include:\n * - Transient: connection timeouts, socket hang ups, temporary DNS failures\n * - Permanent: certificate validation failures, misconfigured SSL\n */\nexport function isNetworkError(error: unknown): boolean {\n // First check if it's a transient network error\n if (isTransientNetworkError(error)) {\n return true\n }\n\n // Then check for permanent network errors (SSL/TLS/certificate issues)\n if (error instanceof Error) {\n const permanentNetworkErrorMessages = ['certificate', 'cert', 'tls', 'ssl', 'altnames']\n const errorMessage = error.message.toLowerCase()\n return permanentNetworkErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n }\n\n return false\n}\n\nasync function runRequestWithNetworkLevelRetry<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<T> {\n if (!requestOptions.useNetworkLevelRetry) {\n return requestOptions.request()\n }\n\n let lastSeenError: unknown\n\n for await (const _delayMs of sleepWithBackoffUntil(requestOptions.maxRetryTimeMs)) {\n try {\n return await requestOptions.request()\n } catch (err) {\n lastSeenError = err\n if (!isTransientNetworkError(err)) {\n throw err\n }\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `network-retry:${(err as Error).message}`)\n }\n\n outputDebug(`Retrying request to ${requestOptions.url} due to network error ${err}`)\n }\n }\n throw lastSeenError\n}\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: Record<string, string> = {}\n const sanitizedUrl = sanitizeURL(requestOptions.url)\n let response: T = {} as T\n try {\n response = await runRequestWithNetworkLevelRetry(requestOptions)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response.headers) {\n for (const [key, value] of err.response.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (errorsIncludeStatus429(err)) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n } else if (err.response.status === 401) {\n return {\n status: 'unauthorized',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs: 500,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\nfunction errorsIncludeStatus429(error: ClientError): boolean {\n if (error.response.status === 429) {\n return true\n }\n\n // GraphQL returns a 401 with a string error message when auth fails\n // Therefore error.response.errors can be a string or GraphQLError[]\n if (typeof error.response.errors === 'string') {\n return false\n }\n return error.response.errors?.some((error) => error.extensions?.code === '429') ?? false\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n): Promise<T> {\n const result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unauthorized': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\n/**\n * Makes a HTTP request to some API, retrying if response headers indicate a retryable error.\n *\n * If a request fails with a 429, the retry-after header determines a delay before an automatic retry is performed.\n *\n * If unauthorizedHandler is provided, then it will be called in the case of a 401 and a retry performed. This allows\n * for a token refresh for instance.\n *\n * If there's a network error, e.g. DNS fails to resolve, then API calls are automatically retried.\n *\n * @param request - A function that returns a promise of the response\n * @param url - The URL to request\n * @param errorHandler - A function that handles errors\n * @param unauthorizedHandler - A function that handles unauthorized errors\n * @param retryOptions - Options for the retry\n * @returns The response from the request\n */\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n } else if (result.status === 'unauthorized') {\n throw result.clientError\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `http-retry-${retriesUsed}:${result.status}:`)\n }\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) => {\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest(requestOptions))\n }, retryDelayMs)\n })\n }\n}\n"]}
|
|
@@ -21,6 +21,8 @@ interface Cache {
|
|
|
21
21
|
export interface ConfSchema {
|
|
22
22
|
sessionStore: string;
|
|
23
23
|
currentSessionId?: string;
|
|
24
|
+
devSessionStore?: string;
|
|
25
|
+
currentDevSessionId?: string;
|
|
24
26
|
cache?: Cache;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
@@ -123,12 +125,10 @@ interface RunWithRateLimitOptions {
|
|
|
123
125
|
* @returns true, or undefined if the task was not run.
|
|
124
126
|
*/
|
|
125
127
|
export declare function runWithRateLimit(options: RunWithRateLimitOptions, config?: LocalStorage<ConfSchema>): Promise<boolean>;
|
|
126
|
-
export declare function getConfigStoreForPartnerStatus(): LocalStorage<{
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
131
|
-
}>;
|
|
128
|
+
export declare function getConfigStoreForPartnerStatus(): LocalStorage<Record<string, {
|
|
129
|
+
status: true;
|
|
130
|
+
checkedAt: string;
|
|
131
|
+
}>>;
|
|
132
132
|
export declare function getCachedPartnerAccountStatus(partnersToken: string): true | null;
|
|
133
133
|
export declare function setCachedPartnerAccountStatus(partnersToken: string): void;
|
|
134
134
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isLocalEnvironment } from './context/service.js';
|
|
1
2
|
import { isUnitTest } from '../../public/node/context/local.js';
|
|
2
3
|
import { LocalStorage } from '../../public/node/local-storage.js';
|
|
3
4
|
import { outputContent, outputDebug } from '../../public/node/output.js';
|
|
@@ -13,6 +14,12 @@ function cliKitStore() {
|
|
|
13
14
|
}
|
|
14
15
|
return _instance;
|
|
15
16
|
}
|
|
17
|
+
function sessionStoreKey() {
|
|
18
|
+
return isLocalEnvironment() ? 'devSessionStore' : 'sessionStore';
|
|
19
|
+
}
|
|
20
|
+
function currentSessionIdKey() {
|
|
21
|
+
return isLocalEnvironment() ? 'currentDevSessionId' : 'currentSessionId';
|
|
22
|
+
}
|
|
16
23
|
/**
|
|
17
24
|
* Get session.
|
|
18
25
|
*
|
|
@@ -20,7 +27,7 @@ function cliKitStore() {
|
|
|
20
27
|
*/
|
|
21
28
|
export function getSessions(config = cliKitStore()) {
|
|
22
29
|
outputDebug(outputContent `Getting session store...`);
|
|
23
|
-
return config.get(
|
|
30
|
+
return config.get(sessionStoreKey());
|
|
24
31
|
}
|
|
25
32
|
/**
|
|
26
33
|
* Set session.
|
|
@@ -29,14 +36,14 @@ export function getSessions(config = cliKitStore()) {
|
|
|
29
36
|
*/
|
|
30
37
|
export function setSessions(session, config = cliKitStore()) {
|
|
31
38
|
outputDebug(outputContent `Setting session store...`);
|
|
32
|
-
config.set(
|
|
39
|
+
config.set(sessionStoreKey(), session);
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* Remove session.
|
|
36
43
|
*/
|
|
37
44
|
export function removeSessions(config = cliKitStore()) {
|
|
38
45
|
outputDebug(outputContent `Removing session store...`);
|
|
39
|
-
config.delete(
|
|
46
|
+
config.delete(sessionStoreKey());
|
|
40
47
|
}
|
|
41
48
|
/**
|
|
42
49
|
* Get current session ID.
|
|
@@ -45,7 +52,7 @@ export function removeSessions(config = cliKitStore()) {
|
|
|
45
52
|
*/
|
|
46
53
|
export function getCurrentSessionId(config = cliKitStore()) {
|
|
47
54
|
outputDebug(outputContent `Getting current session ID...`);
|
|
48
|
-
return config.get(
|
|
55
|
+
return config.get(currentSessionIdKey());
|
|
49
56
|
}
|
|
50
57
|
/**
|
|
51
58
|
* Set current session ID.
|
|
@@ -54,14 +61,14 @@ export function getCurrentSessionId(config = cliKitStore()) {
|
|
|
54
61
|
*/
|
|
55
62
|
export function setCurrentSessionId(sessionId, config = cliKitStore()) {
|
|
56
63
|
outputDebug(outputContent `Setting current session ID...`);
|
|
57
|
-
config.set(
|
|
64
|
+
config.set(currentSessionIdKey(), sessionId);
|
|
58
65
|
}
|
|
59
66
|
/**
|
|
60
67
|
* Remove current session ID.
|
|
61
68
|
*/
|
|
62
69
|
export function removeCurrentSessionId(config = cliKitStore()) {
|
|
63
70
|
outputDebug(outputContent `Removing current session ID...`);
|
|
64
|
-
config.delete(
|
|
71
|
+
config.delete(currentSessionIdKey());
|
|
65
72
|
}
|
|
66
73
|
/**
|
|
67
74
|
* Fetch from cache, or run the provided function to get the value, and cache it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conf-store.js","sourceRoot":"","sources":["../../../src/private/node/conf-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest} from '../../public/node/context/local.js'\nimport {LocalStorage} from '../../public/node/local-storage.js'\nimport {outputContent, outputDebug} from '../../public/node/output.js'\n\ninterface CacheValue<T> {\n value: T\n timestamp: number\n}\n\nexport type PackageVersionKey = `npm-package-${string}`\nexport type NotificationsKey = `notifications-${string}`\nexport type NotificationKey = `notification-${string}`\nexport type GraphQLRequestKey = `q-${string}-${string}-${string}`\ntype MostRecentOccurrenceKey = `most-recent-occurrence-${string}`\ntype RateLimitKey = `rate-limited-occurrences-${string}`\n\ntype ExportedKey = PackageVersionKey | NotificationsKey | NotificationKey | GraphQLRequestKey\n\ninterface Cache {\n [packageVersionKey: PackageVersionKey]: CacheValue<string>\n [notifications: NotificationsKey]: CacheValue<string>\n [notification: NotificationKey]: CacheValue<string>\n [graphQLRequestKey: GraphQLRequestKey]: CacheValue<string>\n [mostRecentOccurrenceKey: MostRecentOccurrenceKey]: CacheValue<boolean>\n [rateLimitKey: RateLimitKey]: CacheValue<number[]>\n}\n\nexport interface ConfSchema {\n sessionStore: string\n currentSessionId?: string\n cache?: Cache\n}\n\nlet _instance: LocalStorage<ConfSchema> | undefined\n\n/**\n * CLIKIT Store.\n *\n * @returns CLIKitStore.\n */\nfunction cliKitStore() {\n if (!_instance) {\n _instance = new LocalStorage<ConfSchema>({projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}`})\n }\n return _instance\n}\n\n/**\n * Get session.\n *\n * @returns Session.\n */\nexport function getSessions(config: LocalStorage<ConfSchema> = cliKitStore()): string | undefined {\n outputDebug(outputContent`Getting session store...`)\n return config.get('sessionStore')\n}\n\n/**\n * Set session.\n *\n * @param session - Session.\n */\nexport function setSessions(session: string, config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Setting session store...`)\n config.set('sessionStore', session)\n}\n\n/**\n * Remove session.\n */\nexport function removeSessions(config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Removing session store...`)\n config.delete('sessionStore')\n}\n\n/**\n * Get current session ID.\n *\n * @returns Current session ID.\n */\nexport function getCurrentSessionId(config: LocalStorage<ConfSchema> = cliKitStore()): string | undefined {\n outputDebug(outputContent`Getting current session ID...`)\n return config.get('currentSessionId')\n}\n\n/**\n * Set current session ID.\n *\n * @param sessionId - Session ID.\n */\nexport function setCurrentSessionId(sessionId: string, config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Setting current session ID...`)\n config.set('currentSessionId', sessionId)\n}\n\n/**\n * Remove current session ID.\n */\nexport function removeCurrentSessionId(config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Removing current session ID...`)\n config.delete('currentSessionId')\n}\n\ntype CacheValueForKey<TKey extends keyof Cache> = NonNullable<Cache[TKey]>['value']\n\n/**\n * Fetch from cache, or run the provided function to get the value, and cache it\n * before returning it.\n * @param key - The key to use for the cache.\n * @param fn - The function to run to get the value to cache, if a cache miss occurs.\n * @param timeout - The maximum valid age of a cached value, in milliseconds.\n * If the cached value is older than this, it will be refreshed.\n * @returns The value from the cache or the result of the function.\n */\nexport async function cacheRetrieveOrRepopulate(\n key: ExportedKey,\n fn: () => Promise<CacheValueForKey<typeof key>>,\n timeout?: number,\n config = cliKitStore(),\n): Promise<CacheValueForKey<typeof key>> {\n const cached = cacheRetrieve(key, config)\n\n if (cached?.value !== undefined && (timeout === undefined || Date.now() - cached.timestamp < timeout)) {\n return cached.value\n }\n\n const value = await fn()\n cacheStore(key, value, config)\n return value\n}\n\nexport function cacheStore(key: ExportedKey, value: string, config = cliKitStore()): void {\n const cache: Cache = config.get('cache') ?? {}\n cache[key] = {value, timestamp: Date.now()}\n config.set('cache', cache)\n}\n\n/**\n * Fetch from cache if already populated, otherwise return undefined.\n * @param key - The key to use for the cache.\n * @returns The chache element.\n */\nexport function cacheRetrieve(key: ExportedKey, config = cliKitStore()): CacheValue<string> | undefined {\n const cache: Cache = config.get('cache') ?? {}\n return cache[key]\n}\n\nexport function cacheClear(config = cliKitStore()): void {\n config.delete('cache')\n}\n\nexport interface TimeInterval {\n days?: number\n hours?: number\n minutes?: number\n seconds?: number\n}\n\nexport function timeIntervalToMilliseconds({days = 0, hours = 0, minutes = 0, seconds = 0}: TimeInterval): number {\n return (days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds) * 1000\n}\n\n/**\n * Execute a task only if the most recent occurrence of the task is older than the specified timeout.\n * @param key - The key to use for the cache.\n * @param timeout - The maximum valid age of the most recent occurrence, expressed as an object with\n * days, hours, minutes, and seconds properties.\n * If the most recent occurrence is older than this, the task will be executed.\n * @param task - The task to run if the most recent occurrence is older than the timeout.\n * @returns true if the task was run, or false if the task was not run.\n */\nexport async function runAtMinimumInterval(\n key: string,\n timeout: TimeInterval,\n task: () => Promise<void>,\n config = cliKitStore(),\n): Promise<boolean> {\n const cache: Cache = config.get('cache') ?? {}\n const cacheKey: MostRecentOccurrenceKey = `most-recent-occurrence-${key}`\n const cached = cache[cacheKey]\n\n if (cached?.value !== undefined && Date.now() - cached.timestamp < timeIntervalToMilliseconds(timeout)) {\n return false\n }\n\n await task()\n cache[cacheKey] = {value: true, timestamp: Date.now()}\n config.set('cache', cache)\n return true\n}\n\ninterface RunWithRateLimitOptions {\n /**\n * The key to use for the cache.\n */\n key: string\n\n /**\n * The number of times the task can be run within the limit\n */\n limit: number\n\n /**\n * The window of time after which the rate limit is refreshed,\n * expressed as an object with days, hours, minutes, and seconds properties.\n * If the most recent occurrence is older than this, the task will be executed.\n */\n timeout: TimeInterval\n\n /**\n * The task to run if the most recent occurrence is older than the timeout.\n */\n task: () => Promise<void>\n}\n\n/**\n * Execute a task with a time-based rate limit. The rate limit is enforced by\n * checking how many times that task has been executed in a window of time ending\n * at the current time. If the task has been executed more than the allowed number\n * of times in that window, the task will not be executed.\n *\n * Note that this function has side effects, as it will also remove events prior\n * to the window of time that is being checked.\n * @param options - The options for the rate limiting.\n * @returns true, or undefined if the task was not run.\n */\nexport async function runWithRateLimit(options: RunWithRateLimitOptions, config = cliKitStore()): Promise<boolean> {\n const {key, limit, timeout, task} = options\n const cache: Cache = config.get('cache') ?? {}\n const cacheKey: RateLimitKey = `rate-limited-occurrences-${key}`\n const cached = cache[cacheKey]\n const now = Date.now()\n\n if (cached?.value) {\n // First sweep through the cache and eliminate old events\n const windowStart = now - timeIntervalToMilliseconds(timeout)\n const occurrences = cached.value.filter((occurrence) => occurrence >= windowStart)\n\n // Now check that the number of occurrences within the interval is below the limit\n if (occurrences.length >= limit) {\n // First remove the old occurrences from the cache\n cache[cacheKey] = {value: occurrences, timestamp: Date.now()}\n config.set('cache', cache)\n\n return false\n }\n\n await task()\n cache[cacheKey] = {value: [...occurrences, now], timestamp: now}\n } else {\n await task()\n cache[cacheKey] = {value: [now], timestamp: now}\n }\n config.set('cache', cache)\n\n return true\n}\n\nexport function getConfigStoreForPartnerStatus() {\n return new LocalStorage<{[partnerToken: string]: {status: true; checkedAt: string}}>({\n projectName: 'shopify-cli-kit-partner-status',\n })\n}\n\nexport function getCachedPartnerAccountStatus(partnersToken: string): true | null {\n if (!partnersToken) return null\n const store = getConfigStoreForPartnerStatus()\n\n const hasPartnerAccount = store.get(partnersToken)\n if (hasPartnerAccount) {\n // this never needs to expire\n return true\n }\n return null\n}\n\nexport function setCachedPartnerAccountStatus(partnersToken: string) {\n const store = getConfigStoreForPartnerStatus()\n\n store.set(partnersToken, {status: true, checkedAt: new Date().toISOString()})\n}\n"]}
|
|
1
|
+
{"version":3,"file":"conf-store.js","sourceRoot":"","sources":["../../../src/private/node/conf-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {isLocalEnvironment} from './context/service.js'\nimport {isUnitTest} from '../../public/node/context/local.js'\nimport {LocalStorage} from '../../public/node/local-storage.js'\nimport {outputContent, outputDebug} from '../../public/node/output.js'\n\ninterface CacheValue<T> {\n value: T\n timestamp: number\n}\n\nexport type PackageVersionKey = `npm-package-${string}`\nexport type NotificationsKey = `notifications-${string}`\nexport type NotificationKey = `notification-${string}`\nexport type GraphQLRequestKey = `q-${string}-${string}-${string}`\ntype MostRecentOccurrenceKey = `most-recent-occurrence-${string}`\ntype RateLimitKey = `rate-limited-occurrences-${string}`\n\ntype ExportedKey = PackageVersionKey | NotificationsKey | NotificationKey | GraphQLRequestKey\n\ninterface Cache {\n [packageVersionKey: PackageVersionKey]: CacheValue<string>\n [notifications: NotificationsKey]: CacheValue<string>\n [notification: NotificationKey]: CacheValue<string>\n [graphQLRequestKey: GraphQLRequestKey]: CacheValue<string>\n [mostRecentOccurrenceKey: MostRecentOccurrenceKey]: CacheValue<boolean>\n [rateLimitKey: RateLimitKey]: CacheValue<number[]>\n}\n\nexport interface ConfSchema {\n sessionStore: string\n currentSessionId?: string\n devSessionStore?: string\n currentDevSessionId?: string\n cache?: Cache\n}\n\nlet _instance: LocalStorage<ConfSchema> | undefined\n\n/**\n * CLIKIT Store.\n *\n * @returns CLIKitStore.\n */\nfunction cliKitStore() {\n if (!_instance) {\n _instance = new LocalStorage<ConfSchema>({projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}`})\n }\n return _instance\n}\n\nfunction sessionStoreKey(): 'devSessionStore' | 'sessionStore' {\n return isLocalEnvironment() ? 'devSessionStore' : 'sessionStore'\n}\n\nfunction currentSessionIdKey(): 'currentDevSessionId' | 'currentSessionId' {\n return isLocalEnvironment() ? 'currentDevSessionId' : 'currentSessionId'\n}\n\n/**\n * Get session.\n *\n * @returns Session.\n */\nexport function getSessions(config: LocalStorage<ConfSchema> = cliKitStore()): string | undefined {\n outputDebug(outputContent`Getting session store...`)\n return config.get(sessionStoreKey())\n}\n\n/**\n * Set session.\n *\n * @param session - Session.\n */\nexport function setSessions(session: string, config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Setting session store...`)\n config.set(sessionStoreKey(), session)\n}\n\n/**\n * Remove session.\n */\nexport function removeSessions(config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Removing session store...`)\n config.delete(sessionStoreKey())\n}\n\n/**\n * Get current session ID.\n *\n * @returns Current session ID.\n */\nexport function getCurrentSessionId(config: LocalStorage<ConfSchema> = cliKitStore()): string | undefined {\n outputDebug(outputContent`Getting current session ID...`)\n return config.get(currentSessionIdKey())\n}\n\n/**\n * Set current session ID.\n *\n * @param sessionId - Session ID.\n */\nexport function setCurrentSessionId(sessionId: string, config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Setting current session ID...`)\n config.set(currentSessionIdKey(), sessionId)\n}\n\n/**\n * Remove current session ID.\n */\nexport function removeCurrentSessionId(config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Removing current session ID...`)\n config.delete(currentSessionIdKey())\n}\n\ntype CacheValueForKey<TKey extends keyof Cache> = NonNullable<Cache[TKey]>['value']\n\n/**\n * Fetch from cache, or run the provided function to get the value, and cache it\n * before returning it.\n * @param key - The key to use for the cache.\n * @param fn - The function to run to get the value to cache, if a cache miss occurs.\n * @param timeout - The maximum valid age of a cached value, in milliseconds.\n * If the cached value is older than this, it will be refreshed.\n * @returns The value from the cache or the result of the function.\n */\nexport async function cacheRetrieveOrRepopulate(\n key: ExportedKey,\n fn: () => Promise<CacheValueForKey<typeof key>>,\n timeout?: number,\n config = cliKitStore(),\n): Promise<CacheValueForKey<typeof key>> {\n const cached = cacheRetrieve(key, config)\n\n if (cached?.value !== undefined && (timeout === undefined || Date.now() - cached.timestamp < timeout)) {\n return cached.value\n }\n\n const value = await fn()\n cacheStore(key, value, config)\n return value\n}\n\nexport function cacheStore(key: ExportedKey, value: string, config = cliKitStore()): void {\n const cache: Cache = config.get('cache') ?? {}\n cache[key] = {value, timestamp: Date.now()}\n config.set('cache', cache)\n}\n\n/**\n * Fetch from cache if already populated, otherwise return undefined.\n * @param key - The key to use for the cache.\n * @returns The chache element.\n */\nexport function cacheRetrieve(key: ExportedKey, config = cliKitStore()): CacheValue<string> | undefined {\n const cache: Cache = config.get('cache') ?? {}\n return cache[key]\n}\n\nexport function cacheClear(config = cliKitStore()): void {\n config.delete('cache')\n}\n\nexport interface TimeInterval {\n days?: number\n hours?: number\n minutes?: number\n seconds?: number\n}\n\nexport function timeIntervalToMilliseconds({days = 0, hours = 0, minutes = 0, seconds = 0}: TimeInterval): number {\n return (days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds) * 1000\n}\n\n/**\n * Execute a task only if the most recent occurrence of the task is older than the specified timeout.\n * @param key - The key to use for the cache.\n * @param timeout - The maximum valid age of the most recent occurrence, expressed as an object with\n * days, hours, minutes, and seconds properties.\n * If the most recent occurrence is older than this, the task will be executed.\n * @param task - The task to run if the most recent occurrence is older than the timeout.\n * @returns true if the task was run, or false if the task was not run.\n */\nexport async function runAtMinimumInterval(\n key: string,\n timeout: TimeInterval,\n task: () => Promise<void>,\n config = cliKitStore(),\n): Promise<boolean> {\n const cache: Cache = config.get('cache') ?? {}\n const cacheKey: MostRecentOccurrenceKey = `most-recent-occurrence-${key}`\n const cached = cache[cacheKey]\n\n if (cached?.value !== undefined && Date.now() - cached.timestamp < timeIntervalToMilliseconds(timeout)) {\n return false\n }\n\n await task()\n cache[cacheKey] = {value: true, timestamp: Date.now()}\n config.set('cache', cache)\n return true\n}\n\ninterface RunWithRateLimitOptions {\n /**\n * The key to use for the cache.\n */\n key: string\n\n /**\n * The number of times the task can be run within the limit\n */\n limit: number\n\n /**\n * The window of time after which the rate limit is refreshed,\n * expressed as an object with days, hours, minutes, and seconds properties.\n * If the most recent occurrence is older than this, the task will be executed.\n */\n timeout: TimeInterval\n\n /**\n * The task to run if the most recent occurrence is older than the timeout.\n */\n task: () => Promise<void>\n}\n\n/**\n * Execute a task with a time-based rate limit. The rate limit is enforced by\n * checking how many times that task has been executed in a window of time ending\n * at the current time. If the task has been executed more than the allowed number\n * of times in that window, the task will not be executed.\n *\n * Note that this function has side effects, as it will also remove events prior\n * to the window of time that is being checked.\n * @param options - The options for the rate limiting.\n * @returns true, or undefined if the task was not run.\n */\nexport async function runWithRateLimit(options: RunWithRateLimitOptions, config = cliKitStore()): Promise<boolean> {\n const {key, limit, timeout, task} = options\n const cache: Cache = config.get('cache') ?? {}\n const cacheKey: RateLimitKey = `rate-limited-occurrences-${key}`\n const cached = cache[cacheKey]\n const now = Date.now()\n\n if (cached?.value) {\n // First sweep through the cache and eliminate old events\n const windowStart = now - timeIntervalToMilliseconds(timeout)\n const occurrences = cached.value.filter((occurrence) => occurrence >= windowStart)\n\n // Now check that the number of occurrences within the interval is below the limit\n if (occurrences.length >= limit) {\n // First remove the old occurrences from the cache\n cache[cacheKey] = {value: occurrences, timestamp: Date.now()}\n config.set('cache', cache)\n\n return false\n }\n\n await task()\n cache[cacheKey] = {value: [...occurrences, now], timestamp: now}\n } else {\n await task()\n cache[cacheKey] = {value: [now], timestamp: now}\n }\n config.set('cache', cache)\n\n return true\n}\n\nexport function getConfigStoreForPartnerStatus() {\n return new LocalStorage<Record<string, {status: true; checkedAt: string}>>({\n projectName: 'shopify-cli-kit-partner-status',\n })\n}\n\nexport function getCachedPartnerAccountStatus(partnersToken: string): true | null {\n if (!partnersToken) return null\n const store = getConfigStoreForPartnerStatus()\n\n const hasPartnerAccount = store.get(partnersToken)\n if (hasPartnerAccount) {\n // this never needs to expire\n return true\n }\n return null\n}\n\nexport function setCachedPartnerAccountStatus(partnersToken: string) {\n const store = getConfigStoreForPartnerStatus()\n\n store.set(partnersToken, {status: true, checkedAt: new Date().toISOString()})\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {exchangeDeviceCodeForAccessToken} from './exchange.js'\nimport {IdentityToken} from './schema.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {outputContent, outputDebug, outputInfo, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../../../public/node/error.js'\nimport {isCloudEnvironment} from '../../../public/node/context/local.js'\nimport {isCI, openURL} from '../../../public/node/system.js'\nimport {isTTY, keypress} from '../../../public/node/ui.js'\nimport {Response} from 'node-fetch'\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string\n userCode: string\n verificationUri: string\n expiresIn: number\n verificationUriComplete?: string\n interval?: number\n}\n\n/**\n * Initiate a device authorization flow.\n * This will return a DeviceAuthorizationResponse containing the URL where user\n * should go to authorize the device without the need of a callback to the CLI.\n *\n * Also returns a `deviceCode` used for polling the token endpoint in the next step.\n *\n * @param scopes - The scopes to request\n * @returns An object with the device authorization response.\n */\nexport async function requestDeviceAuthorization(scopes: string[]): Promise<DeviceAuthorizationResponse> {\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n const queryParams = {client_id: identityClientId, scope: scopes.join(' ')}\n const url = `https://${fqdn}/oauth/device_authorization`\n\n const response = await shopifyFetch(url, {\n method: 'POST',\n headers: {'Content-type': 'application/x-www-form-urlencoded'},\n body: convertRequestToParams(queryParams),\n })\n\n // First read the response body as text so we have it for debugging\n let responseText: string\n try {\n responseText = await response.text()\n } catch (error) {\n throw new BugError(\n `Failed to read response from authorization service (HTTP ${response.status}). Network or streaming error occurred.`,\n 'Check your network connection and try again.',\n )\n }\n\n // Now try to parse the text as JSON\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let jsonResult: any\n try {\n jsonResult = JSON.parse(responseText)\n } catch {\n // JSON.parse failed, handle the parsing error\n const errorMessage = buildAuthorizationParseErrorMessage(response, responseText)\n throw new BugError(errorMessage)\n }\n\n outputDebug(outputContent`Received device authorization code: ${outputToken.json(jsonResult)}`)\n if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {\n throw new BugError('Failed to start authorization process')\n }\n\n outputInfo('\\nTo run this command, log in to Shopify.')\n\n if (isCI()) {\n throw new AbortError(\n 'Authorization is required to continue, but the current environment does not support interactive prompts.',\n 'To resolve this, specify credentials in your environment, or run the command in an interactive environment such as your local terminal.',\n )\n }\n\n outputInfo(outputContent`User verification code: ${jsonResult.user_code}`)\n const linkToken = outputToken.link(jsonResult.verification_uri_complete)\n\n const cloudMessage = () => {\n outputInfo(outputContent`👉 Open this link to start the auth process: ${linkToken}`)\n }\n\n if (isCloudEnvironment() || !isTTY()) {\n cloudMessage()\n } else {\n outputInfo('👉 Press any key to open the login page on your browser')\n await keypress()\n const opened = await openURL(jsonResult.verification_uri_complete)\n if (opened) {\n outputInfo(outputContent`Opened link to start the auth process: ${linkToken}`)\n } else {\n cloudMessage()\n }\n }\n\n return {\n deviceCode: jsonResult.device_code,\n userCode: jsonResult.user_code,\n verificationUri: jsonResult.verification_uri,\n expiresIn: jsonResult.expires_in,\n verificationUriComplete: jsonResult.verification_uri_complete,\n interval: jsonResult.interval,\n }\n}\n\n/**\n * Poll the Oauth token endpoint with the device code obtained from a DeviceAuthorizationResponse.\n * The endpoint will return `authorization_pending` until the user completes the auth flow in the browser.\n * Once the user completes the auth flow, the endpoint will return the identity token.\n *\n * Timeout for the polling is defined by the server and is around 600 seconds.\n *\n * @param code - The device code obtained after starting a device identity flow\n * @param interval - The interval to poll the token endpoint\n * @returns The identity token\n */\nexport async function pollForDeviceAuthorization(code: string, interval = 5): Promise<IdentityToken> {\n let currentIntervalInSeconds = interval\n\n return new Promise<IdentityToken>((resolve, reject) => {\n const onPoll = async () => {\n const result = await exchangeDeviceCodeForAccessToken(code)\n if (!result.isErr()) {\n resolve(result.value)\n return\n }\n\n const error = result.error ?? 'unknown_failure'\n\n outputDebug(outputContent`Polling for device authorization... status: ${error}`)\n switch (error) {\n case 'authorization_pending': {\n startPolling()\n return\n }\n case 'slow_down':\n currentIntervalInSeconds += 5\n startPolling()\n return\n case 'access_denied':\n reject(new AbortError(`Device authorization failed: Access denied.`))\n return\n case 'expired_token':\n reject(new AbortError(`Device authorization failed: Token expired. Please try again.`))\n return\n case 'unknown_failure': {\n reject(new Error(`Device authorization failed: ${error}`))\n }\n }\n }\n\n const startPolling = () => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(onPoll, currentIntervalInSeconds * 1000)\n }\n\n startPolling()\n })\n}\n\nfunction convertRequestToParams(queryParams: {client_id: string; scope: string}): string {\n return Object.entries(queryParams)\n .map(([key, value]) => value && `${key}=${value}`)\n .filter((hasValue) => Boolean(hasValue))\n .join('&')\n}\n\n/**\n * Build a detailed error message for JSON parsing failures from the authorization service.\n * Provides context-specific error messages based on response status and content.\n *\n * @param response - The HTTP response object\n * @param responseText - The raw response body text\n * @returns Detailed error message about the failure\n */\nfunction buildAuthorizationParseErrorMessage(response: Response, responseText: string): string {\n // Build helpful error message based on response status and content\n let errorMessage = `Received invalid response from authorization service (HTTP ${response.status}).`\n\n // Add status-based context\n if (response.status >= 500) {\n errorMessage += ' The service may be experiencing issues.'\n } else if (response.status >= 400) {\n errorMessage += ' The request may be malformed or unauthorized.'\n }\n\n // Add content-based context (check these regardless of status)\n if (responseText.trim().startsWith('<!DOCTYPE') || responseText.trim().startsWith('<html')) {\n errorMessage += ' Received HTML instead of JSON - the service endpoint may have changed.'\n } else if (responseText.trim() === '') {\n errorMessage += ' Received empty response body.'\n } else {\n errorMessage += ' Response could not be parsed as valid JSON.'\n }\n\n return `${errorMessage} If this issue persists, please contact support at https://help.shopify.com`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {exchangeDeviceCodeForAccessToken} from './exchange.js'\nimport {IdentityToken} from './schema.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {outputContent, outputDebug, outputInfo, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../../../public/node/error.js'\nimport {isCloudEnvironment} from '../../../public/node/context/local.js'\nimport {isCI, openURL} from '../../../public/node/system.js'\nimport {isTTY, keypress} from '../../../public/node/ui.js'\n\nimport {Response} from 'node-fetch'\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string\n userCode: string\n verificationUri: string\n expiresIn: number\n verificationUriComplete?: string\n interval?: number\n}\n\n/**\n * Initiate a device authorization flow.\n * This will return a DeviceAuthorizationResponse containing the URL where user\n * should go to authorize the device without the need of a callback to the CLI.\n *\n * Also returns a `deviceCode` used for polling the token endpoint in the next step.\n *\n * @param scopes - The scopes to request\n * @returns An object with the device authorization response.\n */\nexport async function requestDeviceAuthorization(scopes: string[]): Promise<DeviceAuthorizationResponse> {\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n const queryParams = {client_id: identityClientId, scope: scopes.join(' ')}\n const url = `https://${fqdn}/oauth/device_authorization`\n\n const response = await shopifyFetch(url, {\n method: 'POST',\n headers: {'Content-type': 'application/x-www-form-urlencoded'},\n body: convertRequestToParams(queryParams),\n })\n\n // First read the response body as text so we have it for debugging\n let responseText: string\n try {\n responseText = await response.text()\n } catch (error) {\n throw new BugError(\n `Failed to read response from authorization service (HTTP ${response.status}). Network or streaming error occurred.`,\n 'Check your network connection and try again.',\n )\n }\n\n // Now try to parse the text as JSON\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let jsonResult: any\n try {\n jsonResult = JSON.parse(responseText)\n } catch {\n // JSON.parse failed, handle the parsing error\n const errorMessage = buildAuthorizationParseErrorMessage(response, responseText)\n throw new BugError(errorMessage)\n }\n\n outputDebug(outputContent`Received device authorization code: ${outputToken.json(jsonResult)}`)\n if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {\n throw new BugError('Failed to start authorization process')\n }\n\n outputInfo('\\nTo run this command, log in to Shopify.')\n\n if (isCI()) {\n throw new AbortError(\n 'Authorization is required to continue, but the current environment does not support interactive prompts.',\n 'To resolve this, specify credentials in your environment, or run the command in an interactive environment such as your local terminal.',\n )\n }\n\n outputInfo(outputContent`User verification code: ${jsonResult.user_code}`)\n const linkToken = outputToken.link(jsonResult.verification_uri_complete)\n\n const cloudMessage = () => {\n outputInfo(outputContent`👉 Open this link to start the auth process: ${linkToken}`)\n }\n\n if (isCloudEnvironment() || !isTTY()) {\n cloudMessage()\n } else {\n outputInfo('👉 Press any key to open the login page on your browser')\n await keypress()\n const opened = await openURL(jsonResult.verification_uri_complete)\n if (opened) {\n outputInfo(outputContent`Opened link to start the auth process: ${linkToken}`)\n } else {\n cloudMessage()\n }\n }\n\n return {\n deviceCode: jsonResult.device_code,\n userCode: jsonResult.user_code,\n verificationUri: jsonResult.verification_uri,\n expiresIn: jsonResult.expires_in,\n verificationUriComplete: jsonResult.verification_uri_complete,\n interval: jsonResult.interval,\n }\n}\n\n/**\n * Poll the Oauth token endpoint with the device code obtained from a DeviceAuthorizationResponse.\n * The endpoint will return `authorization_pending` until the user completes the auth flow in the browser.\n * Once the user completes the auth flow, the endpoint will return the identity token.\n *\n * Timeout for the polling is defined by the server and is around 600 seconds.\n *\n * @param code - The device code obtained after starting a device identity flow\n * @param interval - The interval to poll the token endpoint\n * @returns The identity token\n */\nexport async function pollForDeviceAuthorization(code: string, interval = 5): Promise<IdentityToken> {\n let currentIntervalInSeconds = interval\n\n return new Promise<IdentityToken>((resolve, reject) => {\n const onPoll = async () => {\n const result = await exchangeDeviceCodeForAccessToken(code)\n if (!result.isErr()) {\n resolve(result.value)\n return\n }\n\n const error = result.error ?? 'unknown_failure'\n\n outputDebug(outputContent`Polling for device authorization... status: ${error}`)\n switch (error) {\n case 'authorization_pending': {\n startPolling()\n return\n }\n case 'slow_down':\n currentIntervalInSeconds += 5\n startPolling()\n return\n case 'access_denied':\n reject(new AbortError(`Device authorization failed: Access denied.`))\n return\n case 'expired_token':\n reject(new AbortError(`Device authorization failed: Token expired. Please try again.`))\n return\n case 'unknown_failure': {\n reject(new Error(`Device authorization failed: ${error}`))\n }\n }\n }\n\n const startPolling = () => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(onPoll, currentIntervalInSeconds * 1000)\n }\n\n startPolling()\n })\n}\n\nfunction convertRequestToParams(queryParams: {client_id: string; scope: string}): string {\n return Object.entries(queryParams)\n .map(([key, value]) => value && `${key}=${value}`)\n .filter((hasValue) => Boolean(hasValue))\n .join('&')\n}\n\n/**\n * Build a detailed error message for JSON parsing failures from the authorization service.\n * Provides context-specific error messages based on response status and content.\n *\n * @param response - The HTTP response object\n * @param responseText - The raw response body text\n * @returns Detailed error message about the failure\n */\nfunction buildAuthorizationParseErrorMessage(response: Response, responseText: string): string {\n // Build helpful error message based on response status and content\n let errorMessage = `Received invalid response from authorization service (HTTP ${response.status}).`\n\n // Add status-based context\n if (response.status >= 500) {\n errorMessage += ' The service may be experiencing issues.'\n } else if (response.status >= 400) {\n errorMessage += ' The request may be malformed or unauthorized.'\n }\n\n // Add content-based context (check these regardless of status)\n if (responseText.trim().startsWith('<!DOCTYPE') || responseText.trim().startsWith('<html')) {\n errorMessage += ' Received HTML instead of JSON - the service endpoint may have changed.'\n } else if (responseText.trim() === '') {\n errorMessage += ' Received empty response body.'\n } else {\n errorMessage += ' Response could not be parsed as valid JSON.'\n }\n\n return `${errorMessage} If this issue persists, please contact support at https://help.shopify.com`\n}\n"]}
|