@commercetools/cli-topic-integration-layer 0.7.0 → 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.
|
@@ -3,9 +3,10 @@ import { basename, join, resolve } from "node:path";
|
|
|
3
3
|
import { Args, Command, Flags } from "@oclif/core";
|
|
4
4
|
// `init` scaffolds a MONOREPO you own and grow — a pnpm workspace whose members are
|
|
5
5
|
// individual extensions (`extensions/*`), seeded with one buildable hello-world
|
|
6
|
-
// extension that extends `Query
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// extension that extends `Query` and a colocated Vitest test that exercises its
|
|
7
|
+
// resolver. The build/validate/push flow itself lives in this published CLI plugin,
|
|
8
|
+
// not in the scaffold, so an extension package stays tiny (just `src/extension.ts` +
|
|
9
|
+
// its `*.test.ts` + a thin package.json/tsconfig). Everything is vendored inline —
|
|
9
10
|
// no network fetch — and kept dependency-light so the extension commands work on it
|
|
10
11
|
// out of the box. The `basic` template is the only one today.
|
|
11
12
|
/** Derive a valid npm package name from the scaffold directory (fallback: a generic one). */
|
|
@@ -31,6 +32,7 @@ function templateFiles(projectName) {
|
|
|
31
32
|
"build": "commercetools integration-layer extension build --all",
|
|
32
33
|
"typecheck": "pnpm -r typecheck",
|
|
33
34
|
"lint": "eslint .",
|
|
35
|
+
"test": "pnpm -r test",
|
|
34
36
|
"dev": "commercetools integration-layer extension serve --all",
|
|
35
37
|
"validate": "commercetools integration-layer extension validate --all",
|
|
36
38
|
"push": "commercetools integration-layer extension push --all"
|
|
@@ -127,20 +129,26 @@ pnpm install
|
|
|
127
129
|
# From the repo root — these operate on the ONE combined bundle:
|
|
128
130
|
pnpm dev # serve the merged subgraph behind a local federated gateway with the
|
|
129
131
|
# Commerce Integration Layer, at http://localhost:4000/graphql. Needs a login.
|
|
132
|
+
pnpm test # run every extension's unit tests (Vitest) — no login, no network
|
|
130
133
|
pnpm validate # compose the combined bundle against your live schema (no upload)
|
|
131
134
|
pnpm push # validate + upload it (replacing the Project's current bundle)
|
|
132
135
|
|
|
133
136
|
# …or iterate on one extension in isolation (standalone subgraph, no login needed):
|
|
134
137
|
pnpm --filter @extensions/hello-world dev
|
|
138
|
+
pnpm --filter @extensions/hello-world test
|
|
135
139
|
\`\`\`
|
|
136
140
|
|
|
141
|
+
Resolvers, hooks, and API-extension handlers are plain functions, so you unit-test them
|
|
142
|
+
by calling them directly — see \`extensions/hello-world/src/extension.test.ts\` for the
|
|
143
|
+
pattern (a minimal fake for the host context, no gateway required).
|
|
144
|
+
|
|
137
145
|
With \`pnpm dev\` running, \`/graphql\` is the gateway, \`/_extension\` the raw combined
|
|
138
146
|
subgraph, and \`/composed\` the browsable merged schema.
|
|
139
147
|
|
|
140
148
|
To add an extension, copy \`extensions/hello-world\`, rename it in its \`package.json\`,
|
|
141
|
-
and edit its \`src/extension.ts\`
|
|
142
|
-
extensions can each add fields to \`Query\`; they
|
|
143
|
-
field.
|
|
149
|
+
and edit its \`src/extension.ts\` (and the colocated \`src/extension.test.ts\`) — the root
|
|
150
|
+
scripts discover it automatically. Two extensions can each add fields to \`Query\`; they
|
|
151
|
+
only clash if they declare the *same* field.
|
|
144
152
|
|
|
145
153
|
Optionally copy \`.env.example\` to \`.env\` to override the Commerce Integration Layer edge URL.
|
|
146
154
|
|
|
@@ -161,11 +169,13 @@ Optionally copy \`.env.example\` to \`.env\` to override the Commerce Integratio
|
|
|
161
169
|
"scripts": {
|
|
162
170
|
"build": "commercetools integration-layer extension build",
|
|
163
171
|
"dev": "commercetools integration-layer extension serve",
|
|
164
|
-
"typecheck": "tsc --noEmit"
|
|
172
|
+
"typecheck": "tsc --noEmit",
|
|
173
|
+
"test": "vitest run"
|
|
165
174
|
},
|
|
166
175
|
"devDependencies": {
|
|
167
176
|
"@types/node": "^22.20.1",
|
|
168
|
-
"typescript": "~6.0.3"
|
|
177
|
+
"typescript": "~6.0.3",
|
|
178
|
+
"vitest": "^4.1.8"
|
|
169
179
|
}
|
|
170
180
|
}
|
|
171
181
|
`,
|
|
@@ -223,6 +233,43 @@ export const resolvers = {
|
|
|
223
233
|
},
|
|
224
234
|
},
|
|
225
235
|
};
|
|
236
|
+
`,
|
|
237
|
+
"extensions/hello-world/src/extension.test.ts": `/**
|
|
238
|
+
* A resolver is a plain function, so you test it by calling it directly — no gateway,
|
|
239
|
+
* no network, no login. \`pnpm test\` runs this (Vitest) both here and, from the repo
|
|
240
|
+
* root, across every extension. Copy this file alongside your own \`extension.ts\` and
|
|
241
|
+
* assert what your resolvers/hooks/API-extension handlers return.
|
|
242
|
+
*
|
|
243
|
+
* The restricted runtime hands each resolver a context (\`now()\` + the project's
|
|
244
|
+
* \`config\` map). Tests stand in a minimal fake for it — see \`ctx\` below.
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
import { describe, expect, it } from "vitest";
|
|
248
|
+
import { resolvers } from "./extension.js";
|
|
249
|
+
|
|
250
|
+
// A minimal stand-in for the host-provided ExtensionContext. Pass a \`config\` to
|
|
251
|
+
// exercise merchant-supplied settings (e.g. \`GREETING\`).
|
|
252
|
+
const ctx = (config: Record<string, string> = {}) => ({ now: () => Date.now(), config });
|
|
253
|
+
|
|
254
|
+
describe("hello-world extension", () => {
|
|
255
|
+
it("greets the world by default", () => {
|
|
256
|
+
expect(resolvers.Query.hello({}, {}, ctx())).toBe(
|
|
257
|
+
"Hello, world, from your integration-layer extension!",
|
|
258
|
+
);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("greets a named visitor", () => {
|
|
262
|
+
expect(resolvers.Query.hello({}, { name: "Ada" }, ctx())).toBe(
|
|
263
|
+
"Hello, Ada, from your integration-layer extension!",
|
|
264
|
+
);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("honours the GREETING config override set per project", () => {
|
|
268
|
+
expect(resolvers.Query.hello({}, { name: "Ada" }, ctx({ GREETING: "Hi" }))).toBe(
|
|
269
|
+
"Hi, Ada, from your integration-layer extension!",
|
|
270
|
+
);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
226
273
|
`,
|
|
227
274
|
};
|
|
228
275
|
}
|
|
@@ -271,6 +318,7 @@ export default class Init extends Command {
|
|
|
271
318
|
if (dir !== ".")
|
|
272
319
|
this.log(` cd ${dir}`);
|
|
273
320
|
this.log(" pnpm install");
|
|
321
|
+
this.log(" pnpm test # run the hello-world extension's unit tests");
|
|
274
322
|
this.log(" pnpm dev # run the hello-world extension locally");
|
|
275
323
|
}
|
|
276
324
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/integration-layer/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEnD,oFAAoF;AACpF,gFAAgF;AAChF,oFAAoF;AACpF,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/integration-layer/init.ts"],"names":[],"mappings":"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"}
|