@swell/cli 2.1.0 → 2.2.1
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/commands/api/delete.d.ts +15 -0
- package/dist/commands/api/delete.js +26 -0
- package/dist/commands/api/get.d.ts +15 -0
- package/dist/commands/api/get.js +31 -0
- package/dist/commands/api/index.d.ts +7 -0
- package/dist/commands/api/index.js +16 -0
- package/dist/commands/api/post.d.ts +16 -0
- package/dist/commands/api/post.js +33 -0
- package/dist/commands/api/put.d.ts +16 -0
- package/dist/commands/api/put.js +33 -0
- package/dist/commands/app/dev.d.ts +9 -9
- package/dist/commands/app/dev.js +163 -139
- package/dist/commands/app/frontend/dev.d.ts +1 -1
- package/dist/commands/app/frontend/dev.js +84 -78
- package/dist/commands/app/install.js +3 -3
- package/dist/commands/app/pull.d.ts +1 -1
- package/dist/commands/app/pull.js +6 -6
- package/dist/commands/app/push.d.ts +3 -3
- package/dist/commands/app/push.js +8 -6
- package/dist/commands/app/release.d.ts +1 -1
- package/dist/commands/app/release.js +1 -1
- package/dist/commands/app/version.d.ts +1 -1
- package/dist/commands/app/version.js +5 -3
- package/dist/commands/create/app.d.ts +10 -2
- package/dist/commands/create/app.js +226 -57
- package/dist/commands/create/content.d.ts +4 -0
- package/dist/commands/create/content.js +83 -15
- package/dist/commands/create/function.js +27 -5
- package/dist/commands/create/index.js +5 -1
- package/dist/commands/create/model.d.ts +4 -0
- package/dist/commands/create/model.js +120 -25
- package/dist/commands/create/tests.d.ts +15 -0
- package/dist/commands/create/tests.js +79 -0
- package/dist/commands/inspect/content.d.ts +25 -0
- package/dist/commands/inspect/content.js +159 -0
- package/dist/commands/inspect/index.d.ts +7 -0
- package/dist/commands/inspect/index.js +16 -0
- package/dist/commands/inspect/models.d.ts +27 -0
- package/dist/commands/inspect/models.js +197 -0
- package/dist/commands/schema.d.ts +27 -0
- package/dist/commands/schema.js +231 -0
- package/dist/commands/theme/dev.d.ts +1 -1
- package/dist/commands/theme/dev.js +2 -2
- package/dist/commands/theme/init.d.ts +1 -1
- package/dist/commands/theme/init.js +1 -1
- package/dist/commands/theme/pull.d.ts +2 -2
- package/dist/commands/theme/pull.js +2 -2
- package/dist/commands/theme/push.d.ts +1 -1
- package/dist/commands/theme/push.js +1 -1
- package/dist/create-app-command.d.ts +12 -2
- package/dist/create-app-command.js +103 -80
- package/dist/create-collection-command.js +4 -1
- package/dist/create-config-command.js +4 -0
- package/dist/env/local.d.ts +1 -0
- package/dist/env/local.js +1 -0
- package/dist/env/production.d.ts +1 -0
- package/dist/env/production.js +1 -0
- package/dist/env/review.d.ts +1 -0
- package/dist/env/review.js +1 -0
- package/dist/env/staging.d.ts +1 -0
- package/dist/env/staging.js +1 -0
- package/dist/lib/api.d.ts +16 -5
- package/dist/lib/api.js +67 -25
- package/dist/lib/app-config.js +1 -0
- package/dist/lib/apps/index.d.ts +2 -0
- package/dist/lib/apps/index.js +20 -14
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.js +1 -0
- package/dist/lib/create/content.d.ts +5 -1
- package/dist/lib/create/content.js +8 -1
- package/dist/lib/create/function.d.ts +2 -1
- package/dist/lib/create/function.js +7 -3
- package/dist/lib/create/model.d.ts +1 -0
- package/dist/lib/create/schemas.d.ts +6 -0
- package/dist/lib/create/schemas.js +6 -0
- package/dist/lib/create/tests/templates/env-dts.d.ts +1 -0
- package/dist/lib/create/tests/templates/env-dts.js +14 -0
- package/dist/lib/create/tests/templates/index.d.ts +8 -0
- package/dist/lib/create/tests/templates/index.js +8 -0
- package/dist/lib/create/tests/templates/integration-test.d.ts +1 -0
- package/dist/lib/create/tests/templates/integration-test.js +19 -0
- package/dist/lib/create/tests/templates/mock-request.d.ts +2 -0
- package/dist/lib/create/tests/templates/mock-request.js +112 -0
- package/dist/lib/create/tests/templates/setup-globals.d.ts +1 -0
- package/dist/lib/create/tests/templates/setup-globals.js +23 -0
- package/dist/lib/create/tests/templates/swell-client.d.ts +1 -0
- package/dist/lib/create/tests/templates/swell-client.js +126 -0
- package/dist/lib/create/tests/templates/tsconfig.d.ts +1 -0
- package/dist/lib/create/tests/templates/tsconfig.js +15 -0
- package/dist/lib/create/tests/templates/unit-test.d.ts +1 -0
- package/dist/lib/create/tests/templates/unit-test.js +42 -0
- package/dist/lib/create/tests/templates/vitest-config.d.ts +2 -0
- package/dist/lib/create/tests/templates/vitest-config.js +121 -0
- package/dist/lib/create/tests/types.d.ts +21 -0
- package/dist/lib/create/tests/types.js +1 -0
- package/dist/lib/create/tests.d.ts +4 -0
- package/dist/lib/create/tests.js +113 -0
- package/dist/lib/sessions.js +4 -3
- package/dist/lib/style.js +0 -1
- package/dist/lib/theme-sync.d.ts +6 -6
- package/dist/lib/theme-sync.js +49 -39
- package/dist/push-app-command.d.ts +7 -7
- package/dist/push-app-command.js +38 -36
- package/dist/remote-app-command.d.ts +1 -1
- package/dist/remote-app-command.js +4 -2
- package/dist/swell-api-command.d.ts +13 -0
- package/dist/swell-api-command.js +75 -0
- package/dist/swell-command.d.ts +1 -1
- package/dist/swell-command.js +9 -9
- package/oclif.manifest.json +639 -46
- package/package.json +8 -1
package/dist/lib/api.js
CHANGED
|
@@ -2,6 +2,14 @@ import fetch from 'node-fetch';
|
|
|
2
2
|
import { stringify } from 'qs';
|
|
3
3
|
import config from './config.js';
|
|
4
4
|
import { API_BASE_URL, getAdminApiBaseUrl } from './constants.js';
|
|
5
|
+
export var HttpMethod;
|
|
6
|
+
(function (HttpMethod) {
|
|
7
|
+
HttpMethod["GET"] = "get";
|
|
8
|
+
HttpMethod["POST"] = "post";
|
|
9
|
+
HttpMethod["PUT"] = "put";
|
|
10
|
+
HttpMethod["DELETE"] = "delete";
|
|
11
|
+
})(HttpMethod || (HttpMethod = {}));
|
|
12
|
+
const GET_ALL_LIMIT = 1000;
|
|
5
13
|
const defaultHeaders = (opts) => ({
|
|
6
14
|
'Content-Type': 'application/json',
|
|
7
15
|
...opts,
|
|
@@ -59,6 +67,9 @@ export default class Api {
|
|
|
59
67
|
if (!path)
|
|
60
68
|
throw new Error('Operation not supported.');
|
|
61
69
|
const res = await fetch(path, fetchOptions);
|
|
70
|
+
if (options.rawResponse) {
|
|
71
|
+
return res;
|
|
72
|
+
}
|
|
62
73
|
const resData = await res.text();
|
|
63
74
|
if (!res.ok) {
|
|
64
75
|
// Try to parse error message
|
|
@@ -84,31 +95,46 @@ export default class Api {
|
|
|
84
95
|
return null;
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
|
-
async delete(pathOpts, options = {}) {
|
|
88
|
-
// ensure post body is stringified
|
|
89
|
-
if (options.body)
|
|
90
|
-
options.body = JSON.stringify(options.body);
|
|
91
|
-
const response = await this.api(pathOpts, {
|
|
92
|
-
method: 'DELETE',
|
|
93
|
-
...options,
|
|
94
|
-
});
|
|
95
|
-
return this.waitForAsyncResponse(response, pathOpts, options);
|
|
96
|
-
}
|
|
97
98
|
async get(pathOpts, options = {}) {
|
|
98
99
|
return this.api(pathOpts, {
|
|
99
|
-
method:
|
|
100
|
+
method: HttpMethod.GET,
|
|
100
101
|
...options,
|
|
101
102
|
});
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
async getAll(pathOpts, options = {}) {
|
|
105
|
+
const result = {
|
|
106
|
+
results: [],
|
|
107
|
+
count: 0,
|
|
108
|
+
};
|
|
109
|
+
let page = 1;
|
|
110
|
+
do {
|
|
111
|
+
// eslint-disable-next-line no-await-in-loop
|
|
112
|
+
const pageResult = await this.api(pathOpts, {
|
|
113
|
+
method: HttpMethod.GET,
|
|
114
|
+
...options,
|
|
115
|
+
query: {
|
|
116
|
+
limit: GET_ALL_LIMIT,
|
|
117
|
+
...options.query,
|
|
118
|
+
page,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
if (pageResult && pageResult.results) {
|
|
122
|
+
result.results = [...result.results, ...pageResult.results];
|
|
123
|
+
result.count = pageResult.count;
|
|
124
|
+
page++;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
} while (result.count > result.results.length && result.results.length > 0);
|
|
130
|
+
return result;
|
|
105
131
|
}
|
|
106
132
|
async post(pathOpts, options = {}) {
|
|
107
133
|
// ensure post body is stringified
|
|
108
134
|
if (options.body)
|
|
109
135
|
options.body = JSON.stringify(options.body);
|
|
110
136
|
const response = await this.api(pathOpts, {
|
|
111
|
-
method:
|
|
137
|
+
method: HttpMethod.POST,
|
|
112
138
|
...options,
|
|
113
139
|
});
|
|
114
140
|
return this.waitForAsyncResponse(response, pathOpts, options);
|
|
@@ -118,20 +144,20 @@ export default class Api {
|
|
|
118
144
|
if (options.body)
|
|
119
145
|
options.body = JSON.stringify(options.body);
|
|
120
146
|
const response = await this.api(pathOpts, {
|
|
121
|
-
method:
|
|
147
|
+
method: HttpMethod.PUT,
|
|
122
148
|
...options,
|
|
123
149
|
});
|
|
124
150
|
return this.waitForAsyncResponse(response, pathOpts, options);
|
|
125
151
|
}
|
|
126
|
-
async
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
this.
|
|
152
|
+
async delete(pathOpts, options = {}) {
|
|
153
|
+
// ensure post body is stringified
|
|
154
|
+
if (options.body)
|
|
155
|
+
options.body = JSON.stringify(options.body);
|
|
156
|
+
const response = await this.api(pathOpts, {
|
|
157
|
+
method: HttpMethod.DELETE,
|
|
158
|
+
...options,
|
|
159
|
+
});
|
|
160
|
+
return this.waitForAsyncResponse(response, pathOpts, options);
|
|
135
161
|
}
|
|
136
162
|
async isTestEnvEnabled() {
|
|
137
163
|
const clientRecord = await this.get({
|
|
@@ -139,6 +165,22 @@ export default class Api {
|
|
|
139
165
|
});
|
|
140
166
|
return clientRecord.test_enabled !== false;
|
|
141
167
|
}
|
|
168
|
+
async setEnv(envId) {
|
|
169
|
+
const hasTestEnv = await this.isTestEnvEnabled();
|
|
170
|
+
if (!hasTestEnv) {
|
|
171
|
+
throw new Error('Test environment is not enabled for this store.');
|
|
172
|
+
}
|
|
173
|
+
this.envId = envId;
|
|
174
|
+
}
|
|
175
|
+
async setStoreEnv(storeId, envId) {
|
|
176
|
+
if (envId) {
|
|
177
|
+
await this.setEnv(envId);
|
|
178
|
+
}
|
|
179
|
+
this.storeId = storeId;
|
|
180
|
+
}
|
|
181
|
+
isAdmin() {
|
|
182
|
+
return !this.secretKey;
|
|
183
|
+
}
|
|
142
184
|
truncatePath(path) {
|
|
143
185
|
return path?.startsWith('/') ? path.slice(1) : path;
|
|
144
186
|
}
|
|
@@ -151,7 +193,7 @@ export default class Api {
|
|
|
151
193
|
setTimeout(resolve, 1000);
|
|
152
194
|
});
|
|
153
195
|
const asyncResponse = await this.api(onAsyncGetPath(response), {
|
|
154
|
-
method:
|
|
196
|
+
method: HttpMethod.GET,
|
|
155
197
|
onAsyncGetPath,
|
|
156
198
|
});
|
|
157
199
|
if (asyncResponse?.async_error) {
|
package/dist/lib/app-config.js
CHANGED
package/dist/lib/apps/index.d.ts
CHANGED
|
@@ -125,6 +125,8 @@ export interface FrontendProjectType {
|
|
|
125
125
|
slug: string;
|
|
126
126
|
}
|
|
127
127
|
export declare const FrontendProjectTypes: FrontendProjectType[];
|
|
128
|
+
export declare function getFrontendProjectSlugs(withNone?: boolean, withLegacy?: boolean): string[];
|
|
129
|
+
export declare function getFrontendProjectValidValues(withNone?: boolean, withLegacy?: boolean): string;
|
|
128
130
|
export declare function getAppSlugId(app: App): string | undefined;
|
|
129
131
|
export declare function getFrontendProjectType(appPath: string): FrontendProjectType | undefined;
|
|
130
132
|
export declare function getConfigTypeFromPath(path: string): ConfigType | undefined;
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -46,7 +46,7 @@ const ConfigTypeBatchOrder = [
|
|
|
46
46
|
ConfigType.FRONTEND,
|
|
47
47
|
ConfigType.FILE,
|
|
48
48
|
];
|
|
49
|
-
// Configs available for
|
|
49
|
+
// Configs available for admin/integration app types
|
|
50
50
|
const StandardConfigTypes = [
|
|
51
51
|
'MODEL',
|
|
52
52
|
'CONTENT',
|
|
@@ -140,7 +140,7 @@ export const FrontendProjectTypes = [
|
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
142
|
buildCommand: 'npm exec --workspace=frontend -- opennextjs-cloudflare build',
|
|
143
|
-
//devCommand: 'npm exec --workspace=frontend -- opennextjs-cloudflare build && npm exec --workspace=frontend -- opennextjs-cloudflare preview --port=${PORT}',
|
|
143
|
+
// devCommand: 'npm exec --workspace=frontend -- opennextjs-cloudflare build && npm exec --workspace=frontend -- opennextjs-cloudflare preview --port=${PORT}',
|
|
144
144
|
devCommand: 'npm exec --workspace=frontend -- next dev --turbopack --port ${PORT}',
|
|
145
145
|
installCommand: 'npm create cloudflare@latest -- frontend --framework=next --deploy=false --git=false -- --typescript --use-npm --src-dir --app --eslint --import-alias "@/*" --tailwind --turbopack',
|
|
146
146
|
mainPackage: 'next',
|
|
@@ -148,6 +148,19 @@ export const FrontendProjectTypes = [
|
|
|
148
148
|
slug: 'nextjs',
|
|
149
149
|
},
|
|
150
150
|
];
|
|
151
|
+
export function getFrontendProjectSlugs(withNone = true, withLegacy = true) {
|
|
152
|
+
const types = withLegacy
|
|
153
|
+
? FrontendProjectTypes
|
|
154
|
+
: FrontendProjectTypes.filter((projectType) => projectType.installCommand);
|
|
155
|
+
const slugs = types.map((projectType) => projectType.slug);
|
|
156
|
+
if (withNone) {
|
|
157
|
+
slugs.push('none');
|
|
158
|
+
}
|
|
159
|
+
return slugs;
|
|
160
|
+
}
|
|
161
|
+
export function getFrontendProjectValidValues(withNone = true, withLegacy = true) {
|
|
162
|
+
return getFrontendProjectSlugs(withNone, withLegacy).join(', ');
|
|
163
|
+
}
|
|
151
164
|
export function getAppSlugId(app) {
|
|
152
165
|
return toAppId(app.private_id) || app.public_id || app.id;
|
|
153
166
|
}
|
|
@@ -158,7 +171,7 @@ function hasWorkspaceStructure(appPath) {
|
|
|
158
171
|
return false;
|
|
159
172
|
}
|
|
160
173
|
try {
|
|
161
|
-
const content = fs.readFileSync(rootPkgPath, '
|
|
174
|
+
const content = fs.readFileSync(rootPkgPath, 'utf8');
|
|
162
175
|
const pkg = JSON.parse(content);
|
|
163
176
|
return Array.isArray(pkg.workspaces) && pkg.workspaces.includes('frontend');
|
|
164
177
|
}
|
|
@@ -182,7 +195,7 @@ export function getFrontendProjectType(appPath) {
|
|
|
182
195
|
continue;
|
|
183
196
|
}
|
|
184
197
|
try {
|
|
185
|
-
const content = fs.readFileSync(pkgPath, '
|
|
198
|
+
const content = fs.readFileSync(pkgPath, 'utf8');
|
|
186
199
|
const pkg = JSON.parse(content);
|
|
187
200
|
for (const projectType of projectTypes) {
|
|
188
201
|
if (pkg.dependencies?.[projectType.mainPackage] ||
|
|
@@ -190,16 +203,9 @@ export function getFrontendProjectType(appPath) {
|
|
|
190
203
|
// Create a copy to avoid mutating the original
|
|
191
204
|
const detectedType = { ...projectType };
|
|
192
205
|
// If buildCommand not explicitly set in framework definition, detect it
|
|
193
|
-
|
|
194
|
-
// Check if package.json has a "build" script
|
|
195
|
-
|
|
196
|
-
detectedType.buildCommand = 'npm run build';
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
// No build script found, set to empty string (no build needed)
|
|
200
|
-
detectedType.buildCommand = '';
|
|
201
|
-
}
|
|
202
|
-
}
|
|
206
|
+
detectedType.buildCommand ||=
|
|
207
|
+
// Check if package.json has a "build" script, if not set to empty string (no build needed)
|
|
208
|
+
pkg.scripts?.build ? 'npm run build' : '';
|
|
203
209
|
return detectedType;
|
|
204
210
|
}
|
|
205
211
|
}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ declare function getAll(): any;
|
|
|
8
8
|
declare function getDefaultStore(): string;
|
|
9
9
|
declare function setDefaultStore(storeId: string): void;
|
|
10
10
|
declare function getDefaultStorefront(appPath: string): {
|
|
11
|
-
id: string;
|
|
12
11
|
env?: string;
|
|
12
|
+
id: string;
|
|
13
13
|
};
|
|
14
14
|
declare function setDefaultStorefront(appPath: string, storefrontId: string, env?: string): void;
|
|
15
15
|
declare function getSessionId(storeId: string): any;
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const API_BASE_URL: any;
|
|
2
2
|
export declare const LOCAL_PROXY_PROVIDER: any;
|
|
3
|
+
export declare const SCHEMAS_BASE_URL: any;
|
|
3
4
|
export declare function getAdminApiBaseUrl(storeId: string): any;
|
|
4
5
|
export declare function getLoginHost(storeId?: string): any;
|
|
5
6
|
export declare function getAppFrontendHost(storeId: string, installedAppId: string): any;
|
package/dist/lib/constants.js
CHANGED
|
@@ -14,6 +14,7 @@ const STOREFRONT_FRONTEND_HOST = env.get('STOREFRONT_FRONTEND_HOST') ||
|
|
|
14
14
|
env.get('STOREFRONT_PAGES_HOST') || // Deprecated
|
|
15
15
|
defaultEnv.STOREFRONT_FRONTEND_HOST;
|
|
16
16
|
export const LOCAL_PROXY_PROVIDER = env.get('LOCAL_PROXY_PROVIDER') || defaultEnv.LOCAL_PROXY_PROVIDER;
|
|
17
|
+
export const SCHEMAS_BASE_URL = env.get('SCHEMAS_BASE_URL') || defaultEnv.SCHEMAS_BASE_URL;
|
|
17
18
|
// helpers to get constants with replacements
|
|
18
19
|
export function getAdminApiBaseUrl(storeId) {
|
|
19
20
|
return ADMIN_API_BASE_URL.replace('${STORE_ID}', storeId);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
interface CreateContentFileBody {
|
|
2
|
+
$schema: string;
|
|
2
3
|
collection: string;
|
|
3
4
|
description?: string;
|
|
4
5
|
fields?: ContentFieldProps[];
|
|
@@ -18,6 +19,9 @@ interface ContentFieldProps {
|
|
|
18
19
|
label: string;
|
|
19
20
|
type?: ContentType;
|
|
20
21
|
}
|
|
22
|
+
declare const validateViews: (values: string[], onError: (msg: string, options: {
|
|
23
|
+
exit: number;
|
|
24
|
+
}) => never) => void;
|
|
21
25
|
declare const parseViews: (views: string[]) => ContentViewProps[];
|
|
22
26
|
declare const parseFields: (fields: string[]) => ContentFieldProps[];
|
|
23
|
-
export { CreateContentFileBody, parseFields, parseViews };
|
|
27
|
+
export { CreateContentFileBody, parseFields, parseViews, validateViews };
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { titleize } from 'inflection';
|
|
2
|
+
const validContentViewValues = ['list', 'edit', 'new'];
|
|
3
|
+
const validateViews = (values, onError) => {
|
|
4
|
+
const invalid = values.filter((v) => !validContentViewValues.includes(v));
|
|
5
|
+
if (invalid.length > 0) {
|
|
6
|
+
onError(`Invalid view(s): ${invalid.join(', ')}\n\nValid views: ${validContentViewValues.join(', ')}\n\nExample: swell create content visitors -v list,edit,new -y`, { exit: 1 });
|
|
7
|
+
}
|
|
8
|
+
};
|
|
2
9
|
const parseViews = (views) => {
|
|
3
10
|
if (views.length === 0) {
|
|
4
11
|
return [];
|
|
@@ -37,4 +44,4 @@ const parseFields = (fields) => {
|
|
|
37
44
|
}
|
|
38
45
|
return fieldResponse;
|
|
39
46
|
};
|
|
40
|
-
export { parseFields, parseViews };
|
|
47
|
+
export { parseFields, parseViews, validateViews };
|
|
@@ -7,11 +7,12 @@ interface CreateFunctionArgs {
|
|
|
7
7
|
interface WriteFunctionFileParams {
|
|
8
8
|
description: string;
|
|
9
9
|
events: string;
|
|
10
|
+
extension?: string;
|
|
10
11
|
functionName: string;
|
|
11
12
|
language: FunctionLanguage;
|
|
12
13
|
route: string;
|
|
13
14
|
schedule: string;
|
|
14
15
|
trigger: FunctionType;
|
|
15
16
|
}
|
|
16
|
-
declare const getFunctionTemplate: ({ description, events, language, route, schedule, trigger, }: WriteFunctionFileParams) => string;
|
|
17
|
+
declare const getFunctionTemplate: ({ description, events, extension, language, route, schedule, trigger, }: WriteFunctionFileParams) => string;
|
|
17
18
|
export { CreateFunctionArgs, FunctionLanguage, FunctionType, WriteFunctionFileParams, getFunctionTemplate, };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const getFunctionTemplate = ({ description, events, language, route, schedule, trigger, }) => {
|
|
1
|
+
const getFunctionTemplate = ({ description, events, extension, language, route, schedule, trigger, }) => {
|
|
2
2
|
let typeAppend = ``;
|
|
3
3
|
if (trigger === 'model') {
|
|
4
4
|
const eventsList = events
|
|
@@ -24,12 +24,16 @@ const getFunctionTemplate = ({ description, events, language, route, schedule, t
|
|
|
24
24
|
schedule: '${schedule}',
|
|
25
25
|
},`;
|
|
26
26
|
}
|
|
27
|
+
let extensionAppend = '';
|
|
28
|
+
if (extension) {
|
|
29
|
+
extensionAppend = `extension: '${extension}',\n `;
|
|
30
|
+
}
|
|
27
31
|
return `export const config${language === 'ts' ? ': SwellConfig' : ''} = {
|
|
28
|
-
description: '${description}'${typeAppend}
|
|
32
|
+
${extensionAppend}description: '${description}'${typeAppend}
|
|
29
33
|
};
|
|
30
34
|
|
|
31
35
|
export default async function (req${language === 'ts' ? ': SwellRequest' : ''}) {
|
|
32
|
-
const { swell, store,
|
|
36
|
+
const { swell, store, data } = req;
|
|
33
37
|
}
|
|
34
38
|
`;
|
|
35
39
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const SCHEMAS: {
|
|
2
|
+
readonly CONTENT: "https://json.swell.store/content.json";
|
|
3
|
+
readonly MODEL: "https://json.swell.store/model.json";
|
|
4
|
+
readonly NOTIFICATION: "https://json.swell.store/notification.json";
|
|
5
|
+
readonly SETTING: "https://json.swell.store/setting.json";
|
|
6
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function envDtsTemplate(): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function envDtsTemplate() {
|
|
2
|
+
return `\
|
|
3
|
+
declare module "cloudflare:test" {
|
|
4
|
+
interface ProvidedEnv {
|
|
5
|
+
SWELL_STORE_ID: string;
|
|
6
|
+
SWELL_SESSION_ID: string;
|
|
7
|
+
SWELL_API_BASE_URL: string;
|
|
8
|
+
SWELL_APP_ID: string;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {};
|
|
13
|
+
`;
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { envDtsTemplate } from './env-dts.js';
|
|
2
|
+
export { integrationTestTemplate } from './integration-test.js';
|
|
3
|
+
export { mockRequestTemplate } from './mock-request.js';
|
|
4
|
+
export { setupGlobalsTemplate } from './setup-globals.js';
|
|
5
|
+
export { swellClientTemplate } from './swell-client.js';
|
|
6
|
+
export { tsconfigTemplate } from './tsconfig.js';
|
|
7
|
+
export { unitTestTemplate } from './unit-test.js';
|
|
8
|
+
export { vitestConfigTemplate } from './vitest-config.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { envDtsTemplate } from './env-dts.js';
|
|
2
|
+
export { integrationTestTemplate } from './integration-test.js';
|
|
3
|
+
export { mockRequestTemplate } from './mock-request.js';
|
|
4
|
+
export { setupGlobalsTemplate } from './setup-globals.js';
|
|
5
|
+
export { swellClientTemplate } from './swell-client.js';
|
|
6
|
+
export { tsconfigTemplate } from './tsconfig.js';
|
|
7
|
+
export { unitTestTemplate } from './unit-test.js';
|
|
8
|
+
export { vitestConfigTemplate } from './vitest-config.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function integrationTestTemplate(): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function integrationTestTemplate() {
|
|
2
|
+
return `\
|
|
3
|
+
import { describe, it, expect } from "vitest";
|
|
4
|
+
import { createSwellClient } from "../helpers/swell-client";
|
|
5
|
+
|
|
6
|
+
describe("Store settings (read-only)", () => {
|
|
7
|
+
it("loads general store settings using CLI auth", async () => {
|
|
8
|
+
const swell = createSwellClient();
|
|
9
|
+
|
|
10
|
+
const general = await swell.get("/settings/general");
|
|
11
|
+
|
|
12
|
+
expect(general).toBeDefined();
|
|
13
|
+
expect(general.id).toBe("general");
|
|
14
|
+
expect(general.features).toBeDefined();
|
|
15
|
+
expect(typeof general.features.carts).toBe("boolean");
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export function mockRequestTemplate(options) {
|
|
2
|
+
return `\
|
|
3
|
+
import { env } from "cloudflare:test";
|
|
4
|
+
import { createSwellClient } from "./swell-client";
|
|
5
|
+
|
|
6
|
+
export interface MockRequestOptions {
|
|
7
|
+
data?: SwellData;
|
|
8
|
+
query?: { [key: string]: string };
|
|
9
|
+
session?: { [key: string]: any };
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
method?: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
swell?: Partial<SwellAPI>;
|
|
14
|
+
store?: Partial<SwellStore>;
|
|
15
|
+
appId?: string;
|
|
16
|
+
useRealSwell?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function createDefaultSwellMock(): Partial<SwellAPI> {
|
|
20
|
+
const notMocked = (method: string) => () => {
|
|
21
|
+
throw new Error(
|
|
22
|
+
\`swell.\${method}() not mocked. Pass { swell: { \${method}: vi.fn() } } to createMockRequest().\`
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
get: notMocked("get"),
|
|
27
|
+
post: notMocked("post"),
|
|
28
|
+
put: notMocked("put"),
|
|
29
|
+
delete: notMocked("delete"),
|
|
30
|
+
settings: notMocked("settings"),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createMockRequest(options: MockRequestOptions = {}): SwellRequest {
|
|
35
|
+
const {
|
|
36
|
+
data = {},
|
|
37
|
+
query = {},
|
|
38
|
+
session = {},
|
|
39
|
+
headers = {},
|
|
40
|
+
method = "POST",
|
|
41
|
+
url = "https://example.com/test",
|
|
42
|
+
swell,
|
|
43
|
+
store,
|
|
44
|
+
appId,
|
|
45
|
+
useRealSwell = false,
|
|
46
|
+
} = options;
|
|
47
|
+
|
|
48
|
+
const requestHeaders = new Headers(headers);
|
|
49
|
+
const originalRequest = new Request(url, {
|
|
50
|
+
method,
|
|
51
|
+
headers: requestHeaders,
|
|
52
|
+
body: method === "GET" ? undefined : JSON.stringify(data),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const storeId = store?.id || env.SWELL_STORE_ID || "test-store";
|
|
56
|
+
|
|
57
|
+
const resolvedStore = {
|
|
58
|
+
id: storeId,
|
|
59
|
+
url: store?.url || "",
|
|
60
|
+
admin_url: store?.admin_url || "",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const context = {
|
|
64
|
+
waitUntil: async (promise: Promise<unknown>) => {
|
|
65
|
+
await promise;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const swellClient =
|
|
70
|
+
swell || (useRealSwell ? createSwellClient() : createDefaultSwellMock());
|
|
71
|
+
|
|
72
|
+
const resolvedAppId = appId || env.SWELL_APP_ID || "${options.appId}";
|
|
73
|
+
|
|
74
|
+
const req: Partial<SwellRequest> & { appId: string; storeId: string } = {
|
|
75
|
+
originalRequest,
|
|
76
|
+
context,
|
|
77
|
+
url,
|
|
78
|
+
method,
|
|
79
|
+
headers: requestHeaders,
|
|
80
|
+
referrer: originalRequest.referrer,
|
|
81
|
+
credentials: "include",
|
|
82
|
+
appId: resolvedAppId,
|
|
83
|
+
storeId,
|
|
84
|
+
accessToken: null,
|
|
85
|
+
publicKey: null,
|
|
86
|
+
store: resolvedStore,
|
|
87
|
+
session,
|
|
88
|
+
apiHost: env.SWELL_API_BASE_URL || "",
|
|
89
|
+
logParams: undefined,
|
|
90
|
+
swell: swellClient as SwellAPI,
|
|
91
|
+
body: data,
|
|
92
|
+
data,
|
|
93
|
+
query,
|
|
94
|
+
initialize: async () => {},
|
|
95
|
+
parseJson: (input: string) => JSON.parse(input),
|
|
96
|
+
appValues: (idOrValues: string | SwellData, values?: SwellData) => {
|
|
97
|
+
const targetAppId =
|
|
98
|
+
typeof idOrValues === "string" ? idOrValues : resolvedAppId;
|
|
99
|
+
const appValues = typeof idOrValues === "string" ? values : idOrValues;
|
|
100
|
+
if (!targetAppId || !appValues) return undefined;
|
|
101
|
+
return {
|
|
102
|
+
$app: {
|
|
103
|
+
[targetAppId]: appValues,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return req as SwellRequest;
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setupGlobalsTemplate(): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function setupGlobalsTemplate() {
|
|
2
|
+
return `\
|
|
3
|
+
class SwellErrorImpl extends Error {
|
|
4
|
+
status: number;
|
|
5
|
+
|
|
6
|
+
constructor(message: string | object, options: { status?: number } = {}) {
|
|
7
|
+
const text =
|
|
8
|
+
typeof message === "string"
|
|
9
|
+
? message
|
|
10
|
+
: JSON.stringify(message, null, 2);
|
|
11
|
+
|
|
12
|
+
super(text);
|
|
13
|
+
this.name = "SwellError";
|
|
14
|
+
this.status = options.status ?? 500;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
(globalThis as any).SwellError = SwellErrorImpl;
|
|
20
|
+
|
|
21
|
+
export {};
|
|
22
|
+
`;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function swellClientTemplate(): string;
|