@shopify/cli-kit 0.8.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/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@shopify/cli-kit",
3
+ "version": "0.8.0",
4
+ "private": false,
5
+ "description": "A set of utilities, interfaces, and models that are common across all the platform features",
6
+ "keywords": [
7
+ "shopify",
8
+ "shopify-cli",
9
+ "shopify-partners"
10
+ ],
11
+ "license": "MIT",
12
+ "type": "module",
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.js",
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "/src",
22
+ "/npm-shrinkwrap.json"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public",
26
+ "@shopify:registry": "https://registry.npmjs.org"
27
+ },
28
+ "scripts": {
29
+ "clean": "shx rm -rf dist",
30
+ "build": "shx rm -rf dist && rollup -c",
31
+ "prepublishOnly": "yarn run build",
32
+ "lint": "prettier -c src/** && eslint src/**",
33
+ "lint:fix": "prettier src/** && eslint src/** --fix",
34
+ "test": "shx rm -rf dist && vitest run",
35
+ "test:watch": "vitest watch",
36
+ "tsc": "tsc -b"
37
+ },
38
+ "eslintConfig": {
39
+ "extends": [
40
+ "../../package.json"
41
+ ]
42
+ },
43
+ "engine-strict": true,
44
+ "engines": {
45
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
46
+ },
47
+ "os": [
48
+ "darwin",
49
+ "linux",
50
+ "win32"
51
+ ],
52
+ "devDependencies": {
53
+ "@types/inquirer": "^8.2.0",
54
+ "camelcase": "^6.3.0",
55
+ "fast-glob": "^3.2.11",
56
+ "find-up": "^6.2.0",
57
+ "inquirer": "^8.2.0",
58
+ "liquidjs": "^9.34.0",
59
+ "param-case": "^3.0.4",
60
+ "pathe": "^0.2.0",
61
+ "picocolors": "^1.0.0",
62
+ "term-size": "^3.0.1"
63
+ }
64
+ }
@@ -0,0 +1,11 @@
1
+ const constants = {
2
+ environmentVariables: {
3
+ config: 'SHOPIFY_CONFIG',
4
+ partnersApiEnv: 'SHOPIFY_PARTNERS_API_ENV',
5
+ adminApiEnv: 'SHOPIFY_ADMIN_API_ENV',
6
+ storefrontRendererApiEnv: 'SHOPIFY_STOREFRONT_RENDERER_API_ENV',
7
+ identityEnv: 'SHOPIFY_IDENTITY_ENV',
8
+ },
9
+ };
10
+
11
+ export default constants;
@@ -0,0 +1,221 @@
1
+ import {expect, it, describe} from 'vitest';
2
+
3
+ import {
4
+ isDebug,
5
+ isRelease,
6
+ partnersApiEnvironment,
7
+ adminApiEnvironment,
8
+ storefrontRendererApiEnvironment,
9
+ identityEnvironment,
10
+ } from './environment';
11
+ import {Environment} from './network/service';
12
+
13
+ describe('isDebug', () => {
14
+ it('returns true when SHOPIFY_CONFIG is debug', () => {
15
+ // Given
16
+ const env = {SHOPIFY_CONFIG: 'debug'};
17
+
18
+ // When
19
+ const got = isDebug(env);
20
+
21
+ // Then
22
+ expect(got).toBe(true);
23
+ });
24
+ });
25
+
26
+ describe('isRelease', () => {
27
+ it("returns true when SHOPIFY_CONFIG isn't defined", () => {
28
+ // Given
29
+ const env = {};
30
+
31
+ // When
32
+ const got = isRelease(env);
33
+
34
+ // Then
35
+ expect(got).toBe(true);
36
+ });
37
+ });
38
+
39
+ describe('partnersApiEnvironment', () => {
40
+ it('returns local when the environment variable points to the local environment', () => {
41
+ // Given
42
+ const env = {SHOPIFY_PARTNERS_API_ENV: 'local'};
43
+
44
+ // When
45
+ const got = partnersApiEnvironment(env);
46
+
47
+ // Then
48
+ expect(got).toBe(Environment.Local);
49
+ });
50
+
51
+ it('returns Spin when the environment variable points to the spin environment', () => {
52
+ // Given
53
+ const env = {SHOPIFY_PARTNERS_API_ENV: 'spin'};
54
+
55
+ // When
56
+ const got = partnersApiEnvironment(env);
57
+
58
+ // Then
59
+ expect(got).toBe(Environment.Spin);
60
+ });
61
+
62
+ it('returns Production when the environment variable points to the production environment', () => {
63
+ // Given
64
+ const env = {SHOPIFY_PARTNERS_API_ENV: 'production'};
65
+
66
+ // When
67
+ const got = partnersApiEnvironment(env);
68
+
69
+ // Then
70
+ expect(got).toBe(Environment.Production);
71
+ });
72
+
73
+ it("returns Production when the environment variable doesn't exist", () => {
74
+ // Given
75
+ const env = {};
76
+
77
+ // When
78
+ const got = partnersApiEnvironment(env);
79
+
80
+ // Then
81
+ expect(got).toBe(Environment.Production);
82
+ });
83
+ });
84
+
85
+ describe('adminApiEnvironment', () => {
86
+ it('returns local when the environment variable points to the local environment', () => {
87
+ // Given
88
+ const env = {SHOPIFY_ADMIN_API_ENV: 'local'};
89
+
90
+ // When
91
+ const got = adminApiEnvironment(env);
92
+
93
+ // Then
94
+ expect(got).toBe(Environment.Local);
95
+ });
96
+
97
+ it('returns Spin when the environment variable points to the spin environment', () => {
98
+ // Given
99
+ const env = {SHOPIFY_ADMIN_API_ENV: 'spin'};
100
+
101
+ // When
102
+ const got = adminApiEnvironment(env);
103
+
104
+ // Then
105
+ expect(got).toBe(Environment.Spin);
106
+ });
107
+
108
+ it('returns Production when the environment variable points to the production environment', () => {
109
+ // Given
110
+ const env = {SHOPIFY_ADMIN_API_ENV: 'production'};
111
+
112
+ // When
113
+ const got = adminApiEnvironment(env);
114
+
115
+ // Then
116
+ expect(got).toBe(Environment.Production);
117
+ });
118
+
119
+ it("returns Production when the environment variable doesn't exist", () => {
120
+ // Given
121
+ const env = {};
122
+
123
+ // When
124
+ const got = adminApiEnvironment(env);
125
+
126
+ // Then
127
+ expect(got).toBe(Environment.Production);
128
+ });
129
+ });
130
+
131
+ describe('storefrontRendererApiEnvironment', () => {
132
+ it('returns local when the environment variable points to the local environment', () => {
133
+ // Given
134
+ const env = {SHOPIFY_STOREFRONT_RENDERER_API_ENV: 'local'};
135
+
136
+ // When
137
+ const got = storefrontRendererApiEnvironment(env);
138
+
139
+ // Then
140
+ expect(got).toBe(Environment.Local);
141
+ });
142
+
143
+ it('returns Spin when the environment variable points to the spin environment', () => {
144
+ // Given
145
+ const env = {SHOPIFY_STOREFRONT_RENDERER_API_ENV: 'spin'};
146
+
147
+ // When
148
+ const got = storefrontRendererApiEnvironment(env);
149
+
150
+ // Then
151
+ expect(got).toBe(Environment.Spin);
152
+ });
153
+
154
+ it('returns Production when the environment variable points to the production environment', () => {
155
+ // Given
156
+ const env = {SHOPIFY_STOREFRONT_RENDERER_API_ENV: 'production'};
157
+
158
+ // When
159
+ const got = storefrontRendererApiEnvironment(env);
160
+
161
+ // Then
162
+ expect(got).toBe(Environment.Production);
163
+ });
164
+
165
+ it("returns Production when the environment variable doesn't exist", () => {
166
+ // Given
167
+ const env = {};
168
+
169
+ // When
170
+ const got = storefrontRendererApiEnvironment(env);
171
+
172
+ // Then
173
+ expect(got).toBe(Environment.Production);
174
+ });
175
+ });
176
+
177
+ describe('identityEnvironment', () => {
178
+ it('returns local when the environment variable points to the local environment', () => {
179
+ // Given
180
+ const env = {SHOPIFY_IDENTITY_ENV: 'local'};
181
+
182
+ // When
183
+ const got = identityEnvironment(env);
184
+
185
+ // Then
186
+ expect(got).toBe(Environment.Local);
187
+ });
188
+
189
+ it('returns Spin when the environment variable points to the spin environment', () => {
190
+ // Given
191
+ const env = {SHOPIFY_IDENTITY_ENV: 'spin'};
192
+
193
+ // When
194
+ const got = identityEnvironment(env);
195
+
196
+ // Then
197
+ expect(got).toBe(Environment.Spin);
198
+ });
199
+
200
+ it('returns Production when the environment variable points to the production environment', () => {
201
+ // Given
202
+ const env = {SHOPIFY_IDENTITY_ENV: 'production'};
203
+
204
+ // When
205
+ const got = identityEnvironment(env);
206
+
207
+ // Then
208
+ expect(got).toBe(Environment.Production);
209
+ });
210
+
211
+ it("returns Production when the environment variable doesn't exist", () => {
212
+ // Given
213
+ const env = {};
214
+
215
+ // When
216
+ const got = identityEnvironment(env);
217
+
218
+ // Then
219
+ expect(got).toBe(Environment.Production);
220
+ });
221
+ });
@@ -0,0 +1,72 @@
1
+ import constants from './constants';
2
+ import {Environment} from './network/service';
3
+
4
+ /**
5
+ * Given an environment variable that represents the environment to use for a given serve,
6
+ * it returns the environment as a enum;
7
+ * @param value The environment variable value.
8
+ * @returns {ServiceEnvironment} representing the environment to use.
9
+ */
10
+ function serviceEnvironment(value: undefined | string): Environment {
11
+ if (value === 'local') {
12
+ return Environment.Local;
13
+ } else if (value === 'spin') {
14
+ return Environment.Spin;
15
+ } else {
16
+ return Environment.Production;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Returns true if the CLI is running in debug mode.
22
+ * @param env The environment variables from the environment of the current process.
23
+ * @returns true if SHOPIFY_CONFIG is debug
24
+ */
25
+ export function isDebug(env = process.env): boolean {
26
+ return env[constants.environmentVariables.config] === 'debug';
27
+ }
28
+
29
+ /**
30
+ * Returns true if the CLI is running in release mode.
31
+ * @param env The environment variables from the environment of the current process.
32
+ * @returns true if SHOPIFY_CONFIG isn't debug
33
+ */
34
+ export function isRelease(env = process.env): boolean {
35
+ return env[constants.environmentVariables.config] !== 'debug';
36
+ }
37
+
38
+ /**
39
+ * Returns the environment to be used for the interactions with the partners' CLI API.
40
+ * @param env The environment variables from the environment of the current process.
41
+ */
42
+ export function partnersApiEnvironment(env = process.env): Environment {
43
+ return serviceEnvironment(env[constants.environmentVariables.partnersApiEnv]);
44
+ }
45
+
46
+ /**
47
+ * Returns the environment to be used for the interactions with the admin API.
48
+ * @param env The environment variables from the environment of the current process.
49
+ */
50
+ export function adminApiEnvironment(env = process.env): Environment {
51
+ return serviceEnvironment(env[constants.environmentVariables.adminApiEnv]);
52
+ }
53
+
54
+ /**
55
+ * Returns the environment to be used for the interactions with the storefront renderer API.
56
+ * @param env The environment variables from the environment of the current process.
57
+ */
58
+ export function storefrontRendererApiEnvironment(
59
+ env = process.env,
60
+ ): Environment {
61
+ return serviceEnvironment(
62
+ env[constants.environmentVariables.storefrontRendererApiEnv],
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Returns the environment to be used for the interactions with identity.
68
+ * @param env The environment variables from the environment of the current process.
69
+ */
70
+ export function identityEnvironment(env = process.env): Environment {
71
+ return serviceEnvironment(env[constants.environmentVariables.identityEnv]);
72
+ }
package/src/error.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A fatal error represents an error shouldn't be rescued and that causes the execution to terminate.
3
+ * There shouldn't be code that catches fatal errors.
4
+ */
5
+ export class Fatal extends Error {
6
+ tryMessage: string | null;
7
+ constructor(message: string, tryMessage: string | null = null) {
8
+ super(message);
9
+ this.tryMessage = tryMessage;
10
+ }
11
+ }
12
+
13
+ /**
14
+ * An abort error is a fatal error that shouldn't be reported as a bug.
15
+ * Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer
16
+ */
17
+ export class Abort extends Fatal {}
18
+
19
+ /**
20
+ * A bug error is an error that represents a bug and therefore should be reported.
21
+ */
22
+ export class Bug extends Fatal {}
package/src/fs.ts ADDED
@@ -0,0 +1,12 @@
1
+ import fs from 'fs';
2
+ import type {PathLike} from 'fs';
3
+
4
+ export const readFile = async (path: string) => {
5
+ return fs.promises.readFile(path, {encoding: 'utf-8'});
6
+ };
7
+
8
+ export const write = async (path: PathLike, data: string) => {
9
+ return fs.promises.writeFile(path, data);
10
+ };
11
+
12
+ export const isDirectory = (path: string) => fs.lstatSync(path).isDirectory();
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * as ui from './ui';
2
+ export * as error from './error';
3
+ export * as system from './system';
4
+ export {template} from './template';
5
+ export * as string from './string';
6
+ export * as path from './path';
7
+ export * as fs from './fs';
8
+ export * as output from './output';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Enum for the differnet APIs the CLI can interact with.
3
+ * @readonly
4
+ * @enum {number}
5
+ */
6
+ export enum Service {
7
+ PartnersApi = 'partners-api',
8
+ StorefrontRendererApi = 'storefront-renderer-api',
9
+ AdminApi = 'admin-api',
10
+ IdentityApi = 'identity-api',
11
+ }
12
+
13
+ /**
14
+ * Enum that represents the environment to use for a given service.
15
+ * @readonly
16
+ * @enum {number}
17
+ */
18
+ export enum Environment {
19
+ Local = 'local',
20
+ Production = 'production',
21
+ Spin = 'spin',
22
+ }
package/src/output.ts ADDED
@@ -0,0 +1,61 @@
1
+ import pc from 'picocolors';
2
+
3
+ enum ContentTokenType {
4
+ Command,
5
+ Path,
6
+ }
7
+
8
+ class ContentToken {
9
+ type: ContentTokenType;
10
+ value: string;
11
+
12
+ constructor(value: string, type: ContentTokenType) {
13
+ this.type = type;
14
+ this.value = value;
15
+ }
16
+ }
17
+
18
+ export const token = {
19
+ command: (value: string) => {
20
+ return new ContentToken(value, ContentTokenType.Command);
21
+ },
22
+ path: (value: string) => {
23
+ return new ContentToken(value, ContentTokenType.Path);
24
+ },
25
+ };
26
+
27
+ // output.content`Something ${output.token.command(Something)}`
28
+
29
+ class Message {
30
+ value: string;
31
+ constructor(value: string) {
32
+ this.value = value;
33
+ }
34
+ }
35
+
36
+ export function content(
37
+ strings: TemplateStringsArray,
38
+ ...keys: ContentToken[]
39
+ ): Message {
40
+ let output = ``;
41
+ strings.forEach((string, i) => {
42
+ output += string;
43
+ if (i >= keys.length) {
44
+ return;
45
+ }
46
+ const token = keys[i];
47
+ switch (token.type) {
48
+ case ContentTokenType.Command:
49
+ output += pc.bold(token.value);
50
+ break;
51
+ case ContentTokenType.Path:
52
+ output += pc.italic(token.value);
53
+ break;
54
+ }
55
+ });
56
+ return new Message(output);
57
+ }
58
+
59
+ export const success = (content: Message) => {
60
+ console.log(pc.green(`🎉 ${content.value}`));
61
+ };
package/src/path.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from 'pathe';
2
+ export {findUp} from 'find-up';
3
+ export {default as glob} from 'fast-glob';
package/src/prompt.ts ADDED
@@ -0,0 +1,4 @@
1
+ import inquirer from 'inquirer';
2
+
3
+ const prompt: typeof inquirer = inquirer;
4
+ export default prompt;
@@ -0,0 +1,3 @@
1
+ const authenticate = () => {};
2
+
3
+ export default authenticate;
@@ -0,0 +1,44 @@
1
+ import {Abort, Bug} from '../error';
2
+ import {
3
+ adminApiEnvironment,
4
+ partnersApiEnvironment,
5
+ storefrontRendererApiEnvironment,
6
+ } from '../environment';
7
+ import {Environment, Service} from '../network/service';
8
+
9
+ export function applicationId(service: Service): string {
10
+ switch (service) {
11
+ case Service.AdminApi: {
12
+ const environment = adminApiEnvironment();
13
+ if (environment === Environment.Local) {
14
+ return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52';
15
+ } else if (environment === Environment.Production) {
16
+ return '7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c';
17
+ } else {
18
+ throw new Abort(`Spin is not yet supported for the Shopify Admin API`);
19
+ }
20
+ }
21
+ case Service.PartnersApi: {
22
+ const environment = partnersApiEnvironment();
23
+ if (environment === Environment.Local) {
24
+ return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978';
25
+ } else if (environment === Environment.Production) {
26
+ return '271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6';
27
+ } else {
28
+ throw new Abort(`Spin is not yet supported for the Partners API`);
29
+ }
30
+ }
31
+ case Service.StorefrontRendererApi: {
32
+ const environment = storefrontRendererApiEnvironment();
33
+ if (environment === Environment.Local) {
34
+ return '46f603de-894f-488d-9471-5b721280ff49';
35
+ } else if (environment === Environment.Production) {
36
+ return 'ee139b3d-5861-4d45-b387-1bc3ada7811c';
37
+ } else {
38
+ throw new Abort(`Spin is not yet supported for the Partners API`);
39
+ }
40
+ }
41
+ default:
42
+ throw new Bug(`Application id for service of type: ${service}`);
43
+ }
44
+ }
package/src/string.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {default as camelize} from 'camelcase';
2
+ export {paramCase as hyphenize} from 'param-case';
package/src/system.ts ADDED
@@ -0,0 +1,5 @@
1
+ import fs from 'fs';
2
+
3
+ export async function mkdir(path: fs.PathLike) {
4
+ return fs.promises.mkdir(path, {recursive: true});
5
+ }
@@ -0,0 +1,9 @@
1
+ import {Liquid} from 'liquidjs';
2
+
3
+ // This line is necessary to register additional helpers.
4
+ export function template(templateContent: string) {
5
+ return (data: object): Promise<string> => {
6
+ const engine = new Liquid();
7
+ return engine.render(engine.parse(templateContent), data);
8
+ };
9
+ }
package/src/ui.ts ADDED
@@ -0,0 +1,9 @@
1
+ import inquirer from 'inquirer';
2
+ import type {Answers, QuestionCollection} from 'inquirer';
3
+
4
+ export const prompt = <T extends Answers = Answers>(
5
+ questions: QuestionCollection<T>,
6
+ initialAnswers?: Partial<T>,
7
+ ): Promise<T> => {
8
+ return inquirer.prompt(questions, initialAnswers);
9
+ };