@swell/cli 2.2.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/app/dev.js +5 -3
- package/dist/commands/create/content.js +1 -1
- package/dist/commands/create/index.js +5 -1
- package/dist/commands/create/tests.d.ts +15 -0
- package/dist/commands/create/tests.js +79 -0
- package/dist/commands/inspect/content.js +1 -1
- package/dist/lib/apps/index.js +1 -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/oclif.manifest.json +2529 -0
- package/package.json +1 -1
package/dist/commands/app/dev.js
CHANGED
|
@@ -189,9 +189,11 @@ ENVIRONMENT = "development"
|
|
|
189
189
|
}
|
|
190
190
|
else if (config?.route) {
|
|
191
191
|
this.log(` Trigger: Route`);
|
|
192
|
-
|
|
193
|
-
.
|
|
194
|
-
|
|
192
|
+
if (config.route.methods?.length) {
|
|
193
|
+
this.log(` Methods: ${style.dim(config.route.methods
|
|
194
|
+
.map((m) => String(m).toUpperCase())
|
|
195
|
+
.join(', '))}`);
|
|
196
|
+
}
|
|
195
197
|
if (config.route.headers) {
|
|
196
198
|
const headers = Object.entries(config.route.headers).map(([key, value]) => `${key}: ${value}`);
|
|
197
199
|
this.log(` Headers:`);
|
|
@@ -3,8 +3,8 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { CreateCollectionCommand } from '../../create-collection-command.js';
|
|
4
4
|
import { ConfigType } from '../../lib/apps/index.js';
|
|
5
5
|
import { parseFields, parseViews, validateViews, } from '../../lib/create/content.js';
|
|
6
|
-
import { SCHEMAS } from '../../lib/create/schemas.js';
|
|
7
6
|
import { toCollectionLabel, toCollectionName, toFileName, } from '../../lib/create/index.js';
|
|
7
|
+
import { SCHEMAS } from '../../lib/create/schemas.js';
|
|
8
8
|
export default class CreateContent extends CreateCollectionCommand {
|
|
9
9
|
static args = {
|
|
10
10
|
collection: Args.string({
|
|
@@ -26,9 +26,13 @@ export default class Create extends Command {
|
|
|
26
26
|
name: 'Notification',
|
|
27
27
|
value: 'notification',
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
name: 'Tests',
|
|
31
|
+
value: 'tests',
|
|
32
|
+
},
|
|
29
33
|
],
|
|
30
34
|
message: 'What do you want to create?',
|
|
31
35
|
});
|
|
32
|
-
this.
|
|
36
|
+
await this.config.runCommand(`create:${createTarget}`);
|
|
33
37
|
}
|
|
34
38
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AppCommand } from '../../app-command.js';
|
|
2
|
+
export default class CreateTests extends AppCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static summary: string;
|
|
5
|
+
static examples: {
|
|
6
|
+
command: string;
|
|
7
|
+
description: string;
|
|
8
|
+
}[];
|
|
9
|
+
static flags: {
|
|
10
|
+
overwrite: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
11
|
+
yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
private logScaffoldResult;
|
|
15
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { AppCommand } from '../../app-command.js';
|
|
3
|
+
import { toAppId } from '../../lib/create/index.js';
|
|
4
|
+
import { createTestsScaffold, } from '../../lib/create/tests.js';
|
|
5
|
+
export default class CreateTests extends AppCommand {
|
|
6
|
+
static description = 'Initialize a vitest + Cloudflare Workers test setup that reuses swell-cli authentication.';
|
|
7
|
+
static summary = 'Create test scaffolding for your Swell app.';
|
|
8
|
+
static examples = [
|
|
9
|
+
{
|
|
10
|
+
command: 'swell create tests',
|
|
11
|
+
description: 'Create a basic test setup using TypeScript.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
command: 'swell create tests --overwrite',
|
|
15
|
+
description: 'Regenerate test files, overwriting existing ones.',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
overwrite: Flags.boolean({
|
|
20
|
+
default: false,
|
|
21
|
+
description: 'overwrite existing test files if they already exist',
|
|
22
|
+
}),
|
|
23
|
+
yes: Flags.boolean({
|
|
24
|
+
char: 'y',
|
|
25
|
+
default: false,
|
|
26
|
+
description: 'accept defaults, skip prompts (no prompts currently, included for consistency)',
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { flags } = await this.parse(CreateTests);
|
|
31
|
+
const appIdFromConfig = (this.swellConfig.get('id') ||
|
|
32
|
+
this.swellConfig.get('private_id') ||
|
|
33
|
+
this.swellConfig.get('public_id'));
|
|
34
|
+
const appId = appIdFromConfig ||
|
|
35
|
+
toAppId(this.swellConfig.get('name')) ||
|
|
36
|
+
'app';
|
|
37
|
+
const result = await createTestsScaffold({
|
|
38
|
+
appPath: this.appPath,
|
|
39
|
+
appId,
|
|
40
|
+
overwrite: Boolean(flags.overwrite),
|
|
41
|
+
});
|
|
42
|
+
this.logScaffoldResult(result);
|
|
43
|
+
}
|
|
44
|
+
logScaffoldResult(result) {
|
|
45
|
+
const hasChanges = result.createdFiles.length > 0 || result.packageJsonUpdated;
|
|
46
|
+
if (hasChanges) {
|
|
47
|
+
this.log('');
|
|
48
|
+
this.log('✓ Created test scaffolding');
|
|
49
|
+
}
|
|
50
|
+
if (result.createdFiles.length > 0) {
|
|
51
|
+
this.log('');
|
|
52
|
+
this.log('Created:');
|
|
53
|
+
for (const file of result.createdFiles) {
|
|
54
|
+
this.log(` ${file}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (result.skippedFiles.length > 0) {
|
|
58
|
+
this.log('');
|
|
59
|
+
this.log('Skipped (already exist):');
|
|
60
|
+
for (const file of result.skippedFiles) {
|
|
61
|
+
this.log(` ${file}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (result.packageJsonUpdated) {
|
|
65
|
+
this.log('');
|
|
66
|
+
this.log('Updated package.json with test scripts and devDependencies.');
|
|
67
|
+
}
|
|
68
|
+
for (const warning of result.warnings) {
|
|
69
|
+
this.warn(warning);
|
|
70
|
+
}
|
|
71
|
+
if (hasChanges) {
|
|
72
|
+
this.log('');
|
|
73
|
+
this.log('Next steps:');
|
|
74
|
+
this.log(' 1. npm install');
|
|
75
|
+
this.log(' 2. npm test');
|
|
76
|
+
}
|
|
77
|
+
this.log('');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -132,7 +132,7 @@ With a content ID, it retrieves the configuration for that specific content view
|
|
|
132
132
|
return resolvedId; // custom IDs don't need reverse resolution
|
|
133
133
|
}
|
|
134
134
|
// Check if identifier is already an app ID (ObjectID format)
|
|
135
|
-
if (
|
|
135
|
+
if (/^[\da-f]{24}$/.test(identifier)) {
|
|
136
136
|
return resolvedId; // already unresolved format
|
|
137
137
|
}
|
|
138
138
|
// type === 'app': resolve slug to app ID
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -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;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export function swellClientTemplate() {
|
|
2
|
+
return `\
|
|
3
|
+
import { env } from "cloudflare:test";
|
|
4
|
+
|
|
5
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
|
|
6
|
+
|
|
7
|
+
type BasicSwellClient = Pick<
|
|
8
|
+
SwellAPI,
|
|
9
|
+
"get" | "post" | "put" | "delete" | "settings"
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
async function makeRequest(
|
|
13
|
+
method: HttpMethod,
|
|
14
|
+
url: string,
|
|
15
|
+
data?: any
|
|
16
|
+
): Promise<any> {
|
|
17
|
+
const baseUrl = env.SWELL_API_BASE_URL || "https://api.swell.store";
|
|
18
|
+
const sessionId = env.SWELL_SESSION_ID;
|
|
19
|
+
|
|
20
|
+
if (!sessionId) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
"Missing SWELL_SESSION_ID binding. Run \\\`swell login\\\` or set it explicitly for tests.",
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let endpointUrl = String(url).startsWith("/") ? url.substring(1) : String(url);
|
|
27
|
+
if (!endpointUrl.startsWith("data/")) {
|
|
28
|
+
endpointUrl = \`data/\${endpointUrl}\`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let fullUrl = \`\${baseUrl}/\${endpointUrl}\`;
|
|
32
|
+
const headers: HeadersInit = {
|
|
33
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
34
|
+
"User-Agent": "swell-app-tests/1.0",
|
|
35
|
+
"X-Session": sessionId,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const options: RequestInit = {
|
|
39
|
+
method,
|
|
40
|
+
headers,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
if (data) {
|
|
44
|
+
if (method === "GET") {
|
|
45
|
+
const params = new URLSearchParams();
|
|
46
|
+
|
|
47
|
+
function append(prefix: string, value: any) {
|
|
48
|
+
if (value === null || value === undefined) return;
|
|
49
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
50
|
+
for (const [k, v] of Object.entries(value)) {
|
|
51
|
+
append(\`\${prefix}[\${k}]\`, v);
|
|
52
|
+
}
|
|
53
|
+
} else if (Array.isArray(value)) {
|
|
54
|
+
for (const v of value) {
|
|
55
|
+
append(\`\${prefix}[]\`, v);
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
params.append(prefix, String(value));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
for (const [key, value] of Object.entries(data)) {
|
|
63
|
+
append(key, value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const query = params.toString();
|
|
67
|
+
if (query) {
|
|
68
|
+
fullUrl += \`?\${query}\`;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
options.body = JSON.stringify(data);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const response = await fetch(fullUrl, options);
|
|
76
|
+
const text = await response.text();
|
|
77
|
+
|
|
78
|
+
let result: any;
|
|
79
|
+
try {
|
|
80
|
+
result = text ? JSON.parse(text) : null;
|
|
81
|
+
} catch {
|
|
82
|
+
result = text;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
throw new (globalThis as any).SwellError(result || text || "Request failed", {
|
|
87
|
+
status: response.status,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (result?.errors) {
|
|
92
|
+
throw new (globalThis as any).SwellError(result.errors, {
|
|
93
|
+
status: 400,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function createSwellClient(): BasicSwellClient {
|
|
101
|
+
return {
|
|
102
|
+
get(url: string, query?: any) {
|
|
103
|
+
return makeRequest("GET", url, query);
|
|
104
|
+
},
|
|
105
|
+
post(url: string, data?: any) {
|
|
106
|
+
return makeRequest("POST", url, data);
|
|
107
|
+
},
|
|
108
|
+
put(url: string, data?: any) {
|
|
109
|
+
return makeRequest("PUT", url, data);
|
|
110
|
+
},
|
|
111
|
+
delete(url: string, data?: any) {
|
|
112
|
+
return makeRequest("DELETE", url, data);
|
|
113
|
+
},
|
|
114
|
+
settings(id?: string) {
|
|
115
|
+
const appId = id || env.SWELL_APP_ID;
|
|
116
|
+
if (!appId) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
"Missing app id. Pass an id to settings() or set SWELL_APP_ID binding.",
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return makeRequest("GET", \`/settings/\${appId}\`);
|
|
122
|
+
},
|
|
123
|
+
} as BasicSwellClient;
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function tsconfigTemplate(): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function tsconfigTemplate() {
|
|
2
|
+
const config = {
|
|
3
|
+
extends: '../tsconfig.json',
|
|
4
|
+
compilerOptions: {
|
|
5
|
+
moduleResolution: 'bundler',
|
|
6
|
+
types: [
|
|
7
|
+
'@cloudflare/vitest-pool-workers',
|
|
8
|
+
'@swell/app-types',
|
|
9
|
+
'vitest/globals',
|
|
10
|
+
],
|
|
11
|
+
},
|
|
12
|
+
include: ['./**/*.ts', '../functions/**/*.ts'],
|
|
13
|
+
};
|
|
14
|
+
return `${JSON.stringify(config, null, 2)}\n`;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function unitTestTemplate(): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function unitTestTemplate() {
|
|
2
|
+
return `\
|
|
3
|
+
import { describe, it, expect, vi } from "vitest";
|
|
4
|
+
import { createMockRequest } from "../helpers/mock-request";
|
|
5
|
+
|
|
6
|
+
// Import your functions to test:
|
|
7
|
+
// import handler from "../../functions/my-handler";
|
|
8
|
+
|
|
9
|
+
describe("Unit test examples", () => {
|
|
10
|
+
it("creates a mock request with data and session", () => {
|
|
11
|
+
const req = createMockRequest({
|
|
12
|
+
data: { product_id: "prod_123" },
|
|
13
|
+
session: { account_id: "acc_456" },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(req.data.product_id).toBe("prod_123");
|
|
17
|
+
expect(req.session.account_id).toBe("acc_456");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("mocks swell.get", async () => {
|
|
21
|
+
const mockGet = vi.fn().mockResolvedValue({ id: "123", name: "Test" });
|
|
22
|
+
const req = createMockRequest({ swell: { get: mockGet } });
|
|
23
|
+
|
|
24
|
+
const result = await req.swell.get("/products/{id}", { id: "123" });
|
|
25
|
+
|
|
26
|
+
expect(result.name).toBe("Test");
|
|
27
|
+
expect(mockGet).toHaveBeenCalledWith("/products/{id}", { id: "123" });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("mocks swell.settings", async () => {
|
|
31
|
+
const mockSettings = vi.fn().mockResolvedValue({
|
|
32
|
+
feature: { enabled: true },
|
|
33
|
+
});
|
|
34
|
+
const req = createMockRequest({ swell: { settings: mockSettings } });
|
|
35
|
+
|
|
36
|
+
const settings = await req.swell.settings();
|
|
37
|
+
|
|
38
|
+
expect(settings.feature.enabled).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
`;
|
|
42
|
+
}
|