@unifiedcommerce/core 0.1.0 → 0.2.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.
Files changed (245) hide show
  1. package/dist/auth/setup.d.ts.map +1 -1
  2. package/dist/auth/setup.js +8 -3
  3. package/dist/config/types.d.ts +3 -1
  4. package/dist/config/types.d.ts.map +1 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/interfaces/mcp/server.d.ts +3 -5
  9. package/dist/interfaces/mcp/server.d.ts.map +1 -1
  10. package/dist/interfaces/mcp/server.js +25 -510
  11. package/dist/interfaces/mcp/tool-builder.d.ts +120 -0
  12. package/dist/interfaces/mcp/tool-builder.d.ts.map +1 -0
  13. package/dist/interfaces/mcp/tool-builder.js +224 -0
  14. package/dist/interfaces/mcp/tools/analytics.d.ts +42 -0
  15. package/dist/interfaces/mcp/tools/analytics.d.ts.map +1 -0
  16. package/dist/interfaces/mcp/tools/analytics.js +70 -0
  17. package/dist/interfaces/mcp/tools/cart.d.ts +14 -0
  18. package/dist/interfaces/mcp/tools/cart.d.ts.map +1 -0
  19. package/dist/interfaces/mcp/tools/cart.js +47 -0
  20. package/dist/interfaces/mcp/tools/catalog.d.ts +53 -0
  21. package/dist/interfaces/mcp/tools/catalog.d.ts.map +1 -0
  22. package/dist/interfaces/mcp/tools/catalog.js +284 -0
  23. package/dist/interfaces/mcp/tools/index.d.ts +3 -0
  24. package/dist/interfaces/mcp/tools/index.d.ts.map +1 -0
  25. package/dist/interfaces/mcp/tools/index.js +20 -0
  26. package/dist/interfaces/mcp/tools/inventory.d.ts +27 -0
  27. package/dist/interfaces/mcp/tools/inventory.d.ts.map +1 -0
  28. package/dist/interfaces/mcp/tools/inventory.js +143 -0
  29. package/dist/interfaces/mcp/tools/orders.d.ts +18 -0
  30. package/dist/interfaces/mcp/tools/orders.d.ts.map +1 -0
  31. package/dist/interfaces/mcp/tools/orders.js +82 -0
  32. package/dist/interfaces/mcp/tools/pricing.d.ts +29 -0
  33. package/dist/interfaces/mcp/tools/pricing.d.ts.map +1 -0
  34. package/dist/interfaces/mcp/tools/pricing.js +90 -0
  35. package/dist/interfaces/mcp/tools/promotions.d.ts +44 -0
  36. package/dist/interfaces/mcp/tools/promotions.d.ts.map +1 -0
  37. package/dist/interfaces/mcp/tools/promotions.js +109 -0
  38. package/dist/interfaces/mcp/tools/registry.d.ts +32 -0
  39. package/dist/interfaces/mcp/tools/registry.d.ts.map +1 -0
  40. package/dist/interfaces/mcp/tools/registry.js +55 -0
  41. package/dist/interfaces/mcp/tools/search.d.ts +14 -0
  42. package/dist/interfaces/mcp/tools/search.d.ts.map +1 -0
  43. package/dist/interfaces/mcp/tools/search.js +39 -0
  44. package/dist/interfaces/mcp/tools/webhooks.d.ts +15 -0
  45. package/dist/interfaces/mcp/tools/webhooks.d.ts.map +1 -0
  46. package/dist/interfaces/mcp/tools/webhooks.js +48 -0
  47. package/dist/interfaces/mcp/transport.d.ts +17 -2
  48. package/dist/interfaces/mcp/transport.d.ts.map +1 -1
  49. package/dist/interfaces/mcp/transport.js +91 -44
  50. package/dist/interfaces/rest/router.d.ts.map +1 -1
  51. package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
  52. package/dist/interfaces/rest/routes/checkout.js +1 -1
  53. package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
  54. package/dist/interfaces/rest/routes/promotions.js +3 -2
  55. package/dist/kernel/database/adapter.d.ts +8 -0
  56. package/dist/kernel/database/adapter.d.ts.map +1 -1
  57. package/dist/kernel/factory/repository-factory.d.ts.map +1 -1
  58. package/dist/kernel/factory/repository-factory.js +3 -1
  59. package/dist/kernel/local-api.d.ts.map +1 -1
  60. package/dist/kernel/local-api.js +2 -0
  61. package/dist/kernel/plugin/manifest.d.ts +3 -3
  62. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  63. package/dist/kernel/plugin/manifest.js +36 -7
  64. package/dist/runtime/kernel.d.ts +1 -2
  65. package/dist/runtime/kernel.d.ts.map +1 -1
  66. package/dist/runtime/kernel.js +16 -8
  67. package/dist/runtime/server.d.ts.map +1 -1
  68. package/dist/runtime/server.js +8 -3
  69. package/dist/test-utils/create-pglite-adapter.d.ts.map +1 -1
  70. package/dist/test-utils/create-pglite-adapter.js +7 -6
  71. package/dist/tsconfig.tsbuildinfo +1 -0
  72. package/package.json +2 -2
  73. package/src/adapters/console-email.ts +0 -43
  74. package/src/auth/access.ts +0 -187
  75. package/src/auth/auth-schema.ts +0 -139
  76. package/src/auth/middleware.ts +0 -161
  77. package/src/auth/org.ts +0 -41
  78. package/src/auth/permissions.ts +0 -28
  79. package/src/auth/setup.ts +0 -169
  80. package/src/auth/system-actor.ts +0 -19
  81. package/src/auth/types.ts +0 -10
  82. package/src/config/defaults.ts +0 -82
  83. package/src/config/define-config.ts +0 -53
  84. package/src/config/types.ts +0 -299
  85. package/src/generated/plugin-capabilities.d.ts +0 -20
  86. package/src/generated/plugin-manifest.ts +0 -23
  87. package/src/generated/plugin-repositories.d.ts +0 -20
  88. package/src/hooks/checkout-completion.ts +0 -262
  89. package/src/hooks/checkout.ts +0 -677
  90. package/src/hooks/order-emails.ts +0 -62
  91. package/src/index.ts +0 -214
  92. package/src/interfaces/mcp/agent-prompt.ts +0 -174
  93. package/src/interfaces/mcp/context-enrichment.ts +0 -177
  94. package/src/interfaces/mcp/server.ts +0 -617
  95. package/src/interfaces/mcp/transport.ts +0 -68
  96. package/src/interfaces/rest/customer-portal.ts +0 -299
  97. package/src/interfaces/rest/index.ts +0 -74
  98. package/src/interfaces/rest/router.ts +0 -334
  99. package/src/interfaces/rest/routes/admin-jobs.ts +0 -58
  100. package/src/interfaces/rest/routes/audit.ts +0 -50
  101. package/src/interfaces/rest/routes/carts.ts +0 -89
  102. package/src/interfaces/rest/routes/catalog.ts +0 -493
  103. package/src/interfaces/rest/routes/checkout.ts +0 -283
  104. package/src/interfaces/rest/routes/inventory.ts +0 -70
  105. package/src/interfaces/rest/routes/media.ts +0 -86
  106. package/src/interfaces/rest/routes/orders.ts +0 -78
  107. package/src/interfaces/rest/routes/payments.ts +0 -60
  108. package/src/interfaces/rest/routes/pricing.ts +0 -57
  109. package/src/interfaces/rest/routes/promotions.ts +0 -92
  110. package/src/interfaces/rest/routes/search.ts +0 -71
  111. package/src/interfaces/rest/routes/webhooks.ts +0 -46
  112. package/src/interfaces/rest/schemas/admin-jobs.ts +0 -40
  113. package/src/interfaces/rest/schemas/audit.ts +0 -46
  114. package/src/interfaces/rest/schemas/carts.ts +0 -125
  115. package/src/interfaces/rest/schemas/catalog.ts +0 -450
  116. package/src/interfaces/rest/schemas/checkout.ts +0 -66
  117. package/src/interfaces/rest/schemas/customer-portal.ts +0 -195
  118. package/src/interfaces/rest/schemas/inventory.ts +0 -138
  119. package/src/interfaces/rest/schemas/media.ts +0 -75
  120. package/src/interfaces/rest/schemas/orders.ts +0 -104
  121. package/src/interfaces/rest/schemas/pricing.ts +0 -80
  122. package/src/interfaces/rest/schemas/promotions.ts +0 -110
  123. package/src/interfaces/rest/schemas/responses.ts +0 -85
  124. package/src/interfaces/rest/schemas/search.ts +0 -58
  125. package/src/interfaces/rest/schemas/shared.ts +0 -62
  126. package/src/interfaces/rest/schemas/webhooks.ts +0 -68
  127. package/src/interfaces/rest/utils.ts +0 -104
  128. package/src/interfaces/rest/webhook-router.ts +0 -50
  129. package/src/kernel/compensation/executor.ts +0 -61
  130. package/src/kernel/compensation/types.ts +0 -26
  131. package/src/kernel/database/adapter.ts +0 -13
  132. package/src/kernel/database/drizzle-db.ts +0 -56
  133. package/src/kernel/database/migrate.ts +0 -76
  134. package/src/kernel/database/plugin-types.ts +0 -34
  135. package/src/kernel/database/schema.ts +0 -49
  136. package/src/kernel/database/scoped-db.ts +0 -68
  137. package/src/kernel/database/tx-context.ts +0 -46
  138. package/src/kernel/error-mapper.ts +0 -15
  139. package/src/kernel/errors.ts +0 -89
  140. package/src/kernel/factory/repository-factory.ts +0 -242
  141. package/src/kernel/hooks/create-context.ts +0 -43
  142. package/src/kernel/hooks/executor.ts +0 -88
  143. package/src/kernel/hooks/registry.ts +0 -74
  144. package/src/kernel/hooks/types.ts +0 -52
  145. package/src/kernel/http-error.ts +0 -44
  146. package/src/kernel/jobs/adapter.ts +0 -36
  147. package/src/kernel/jobs/drizzle-adapter.ts +0 -58
  148. package/src/kernel/jobs/runner.ts +0 -153
  149. package/src/kernel/jobs/schema.ts +0 -46
  150. package/src/kernel/jobs/types.ts +0 -30
  151. package/src/kernel/local-api.ts +0 -185
  152. package/src/kernel/plugin/manifest.ts +0 -253
  153. package/src/kernel/query/executor.ts +0 -184
  154. package/src/kernel/query/registry.ts +0 -46
  155. package/src/kernel/result.ts +0 -33
  156. package/src/kernel/schema/extra-columns.ts +0 -37
  157. package/src/kernel/service-registry.ts +0 -76
  158. package/src/kernel/service-timing.ts +0 -89
  159. package/src/kernel/state-machine/machine.ts +0 -101
  160. package/src/modules/analytics/drizzle-adapter.ts +0 -426
  161. package/src/modules/analytics/hooks.ts +0 -11
  162. package/src/modules/analytics/models.ts +0 -125
  163. package/src/modules/analytics/repository/index.ts +0 -6
  164. package/src/modules/analytics/service.ts +0 -245
  165. package/src/modules/analytics/types.ts +0 -180
  166. package/src/modules/audit/hooks.ts +0 -78
  167. package/src/modules/audit/schema.ts +0 -33
  168. package/src/modules/audit/service.ts +0 -151
  169. package/src/modules/cart/access.ts +0 -27
  170. package/src/modules/cart/matcher.ts +0 -26
  171. package/src/modules/cart/repository/index.ts +0 -234
  172. package/src/modules/cart/schema.ts +0 -42
  173. package/src/modules/cart/schemas.ts +0 -38
  174. package/src/modules/cart/service.ts +0 -541
  175. package/src/modules/catalog/repository/index.ts +0 -772
  176. package/src/modules/catalog/schema.ts +0 -203
  177. package/src/modules/catalog/schemas.ts +0 -104
  178. package/src/modules/catalog/service.ts +0 -1544
  179. package/src/modules/customers/repository/index.ts +0 -327
  180. package/src/modules/customers/schema.ts +0 -64
  181. package/src/modules/customers/service.ts +0 -171
  182. package/src/modules/fulfillment/repository/index.ts +0 -426
  183. package/src/modules/fulfillment/schema.ts +0 -101
  184. package/src/modules/fulfillment/service.ts +0 -555
  185. package/src/modules/fulfillment/types.ts +0 -59
  186. package/src/modules/inventory/repository/index.ts +0 -509
  187. package/src/modules/inventory/schema.ts +0 -94
  188. package/src/modules/inventory/schemas.ts +0 -38
  189. package/src/modules/inventory/service.ts +0 -490
  190. package/src/modules/media/adapter.ts +0 -17
  191. package/src/modules/media/repository/index.ts +0 -274
  192. package/src/modules/media/schema.ts +0 -41
  193. package/src/modules/media/service.ts +0 -151
  194. package/src/modules/orders/repository/index.ts +0 -287
  195. package/src/modules/orders/schema.ts +0 -66
  196. package/src/modules/orders/service.ts +0 -619
  197. package/src/modules/orders/stale-order-cleanup.ts +0 -76
  198. package/src/modules/organization/service.ts +0 -191
  199. package/src/modules/payments/adapter.ts +0 -47
  200. package/src/modules/payments/repository/index.ts +0 -6
  201. package/src/modules/payments/service.ts +0 -107
  202. package/src/modules/pricing/repository/index.ts +0 -291
  203. package/src/modules/pricing/schema.ts +0 -71
  204. package/src/modules/pricing/schemas.ts +0 -38
  205. package/src/modules/pricing/service.ts +0 -494
  206. package/src/modules/promotions/repository/index.ts +0 -325
  207. package/src/modules/promotions/schema.ts +0 -62
  208. package/src/modules/promotions/schemas.ts +0 -38
  209. package/src/modules/promotions/service.ts +0 -598
  210. package/src/modules/search/adapter.ts +0 -57
  211. package/src/modules/search/hooks.ts +0 -12
  212. package/src/modules/search/repository/index.ts +0 -6
  213. package/src/modules/search/service.ts +0 -315
  214. package/src/modules/shipping/calculator.ts +0 -188
  215. package/src/modules/shipping/repository/index.ts +0 -6
  216. package/src/modules/shipping/service.ts +0 -51
  217. package/src/modules/tax/adapter.ts +0 -60
  218. package/src/modules/tax/repository/index.ts +0 -6
  219. package/src/modules/tax/service.ts +0 -53
  220. package/src/modules/webhooks/hook.ts +0 -34
  221. package/src/modules/webhooks/repository/index.ts +0 -278
  222. package/src/modules/webhooks/schema.ts +0 -56
  223. package/src/modules/webhooks/service.ts +0 -117
  224. package/src/modules/webhooks/signing.ts +0 -6
  225. package/src/modules/webhooks/ssrf-guard.ts +0 -71
  226. package/src/modules/webhooks/tasks.ts +0 -52
  227. package/src/modules/webhooks/worker.ts +0 -134
  228. package/src/runtime/commerce.ts +0 -145
  229. package/src/runtime/kernel.ts +0 -419
  230. package/src/runtime/logger.ts +0 -36
  231. package/src/runtime/server.ts +0 -349
  232. package/src/runtime/shutdown.ts +0 -43
  233. package/src/test-utils/create-pglite-adapter.ts +0 -129
  234. package/src/test-utils/create-plugin-test-app.ts +0 -128
  235. package/src/test-utils/create-repository-test-harness.ts +0 -16
  236. package/src/test-utils/create-test-config.ts +0 -190
  237. package/src/test-utils/create-test-kernel.ts +0 -7
  238. package/src/test-utils/create-test-plugin-context.ts +0 -75
  239. package/src/test-utils/rest-api-test-utils.ts +0 -265
  240. package/src/test-utils/test-actors.ts +0 -62
  241. package/src/test-utils/typed-hooks.ts +0 -54
  242. package/src/types/commerce-types.ts +0 -34
  243. package/src/utils/id.ts +0 -3
  244. package/src/utils/logger.ts +0 -18
  245. package/src/utils/pagination.ts +0 -22
@@ -1,16 +0,0 @@
1
- import type { CommerceConfig } from "../config/types.js";
2
- import { createTestConfig } from "./create-test-config.js";
3
- import { createKernel } from "../runtime/kernel.js";
4
-
5
- export interface RepositoryTestHarness {
6
- config: CommerceConfig;
7
- kernel: ReturnType<typeof createKernel>;
8
- }
9
-
10
- export async function createRepositoryTestHarness(
11
- overrides: Partial<CommerceConfig> = {},
12
- ): Promise<RepositoryTestHarness> {
13
- const config = await createTestConfig(overrides);
14
- const kernel = createKernel(config);
15
- return { config, kernel };
16
- }
@@ -1,190 +0,0 @@
1
- import { defineConfig } from "../config/define-config.js";
2
- import type { CommerceConfig } from "../config/types.js";
3
- import { Ok } from "../kernel/result.js";
4
- import type { StorageAdapter } from "../modules/media/adapter.js";
5
-
6
- function createInMemoryStorageAdapter(): StorageAdapter {
7
- const files = new Map<string, { data: ArrayBuffer; contentType: string }>();
8
- const baseUrl = "http://localhost:3000/test-assets";
9
-
10
- return {
11
- providerId: "test-memory-storage",
12
- async upload(key, data, contentType) {
13
- const body =
14
- data instanceof ArrayBuffer
15
- ? data
16
- : await new Response(data).arrayBuffer();
17
- files.set(key, { data: body, contentType });
18
- return Ok({
19
- key,
20
- url: `${baseUrl}/${key}`,
21
- contentType,
22
- size: body.byteLength,
23
- });
24
- },
25
- async getUrl(key) {
26
- return Ok(`${baseUrl}/${key}`);
27
- },
28
- async getSignedUrl(key, expiresIn) {
29
- return Ok(`${baseUrl}/${key}?expiresIn=${expiresIn}`);
30
- },
31
- async delete(key) {
32
- files.delete(key);
33
- return Ok(undefined);
34
- },
35
- async list(prefix) {
36
- return Ok(
37
- Array.from(files.entries())
38
- .filter(([key]) => key.startsWith(prefix))
39
- .map(([key, file]) => ({
40
- key,
41
- url: `${baseUrl}/${key}`,
42
- contentType: file.contentType,
43
- size: file.data.byteLength,
44
- })),
45
- );
46
- },
47
- };
48
- }
49
-
50
- export async function createTestConfig(
51
- overrides: Partial<CommerceConfig> = {},
52
- ): Promise<CommerceConfig> {
53
- // Auto-provision PGlite when no databaseAdapter is provided
54
- if (!overrides.databaseAdapter) {
55
- const { createPGliteTestAdapter } = await import("./create-pglite-adapter.js");
56
- const { adapter } = await createPGliteTestAdapter();
57
- overrides = { ...overrides, databaseAdapter: adapter };
58
- }
59
-
60
- return defineConfig({
61
- version: "0.0.1-test",
62
- storeName: "Test Store",
63
- database: {
64
- provider: "postgresql",
65
- },
66
- auth: {
67
- requireEmailVerification: false,
68
- apiKeys: { enabled: true, defaultPermissions: ["catalog:read"] },
69
- enableDevKey: true,
70
- devKey: "dev-staff-key",
71
- posPin: { enabled: true },
72
- roles: {
73
- owner: { permissions: ["*:*"] },
74
- admin: { permissions: ["*:*"] },
75
- staff: {
76
- permissions: [
77
- "catalog:create",
78
- "catalog:update",
79
- "catalog:delete",
80
- "catalog:read",
81
- "inventory:adjust",
82
- "orders:create",
83
- "orders:read",
84
- "orders:update",
85
- "cart:create",
86
- "cart:update",
87
- "customers:update:self",
88
- ],
89
- },
90
- ai_agent: {
91
- permissions: [
92
- "catalog:read",
93
- "catalog:create",
94
- "inventory:read",
95
- "inventory:adjust",
96
- "orders:read",
97
- "cart:create",
98
- "cart:update",
99
- "mcp:access",
100
- ],
101
- },
102
- },
103
- customerPermissions: [
104
- "catalog:read",
105
- "cart:create",
106
- "cart:read",
107
- "cart:update",
108
- "orders:create",
109
- "orders:read:own",
110
- "customers:read:self",
111
- "customers:update:self",
112
- ],
113
- },
114
- entities: {
115
- product: {
116
- fields: [
117
- { name: "weight", type: "number" },
118
- { name: "brand", type: "text" },
119
- ],
120
- variants: { enabled: true, optionTypes: ["size", "color"] },
121
- fulfillment: "physical",
122
- },
123
- digitalDownload: {
124
- fields: [{ name: "fileAssetId", type: "text" }],
125
- variants: { enabled: false },
126
- fulfillment: "digital-download",
127
- },
128
- course: {
129
- fields: [{ name: "modules", type: "json" }],
130
- variants: { enabled: false },
131
- fulfillment: "digital-access",
132
- },
133
- },
134
- cart: {
135
- ttlMinutes: 5,
136
- hooks: {},
137
- },
138
- checkout: {
139
- hooks: {
140
- beforeCreate: [],
141
- afterCreate: [],
142
- },
143
- },
144
- orders: {
145
- hooks: {
146
- beforeCreate: [],
147
- afterCreate: [],
148
- beforeStatusChange: [],
149
- afterStatusChange: [],
150
- },
151
- },
152
- inventory: {
153
- hooks: {
154
- afterAdjust: [],
155
- },
156
- },
157
- email: {
158
- async send() {
159
- // no-op for tests
160
- },
161
- },
162
- storage: createInMemoryStorageAdapter(),
163
- ...overrides,
164
- });
165
- }
166
-
167
- /**
168
- * Creates a test config backed by PGlite (in-memory PostgreSQL).
169
- *
170
- * This provides production parity for tests by using real SQL execution
171
- * and PostgreSQL behavior while remaining fast and self-contained.
172
- *
173
- * @param overrides - Optional config overrides
174
- * @returns A promise resolving to an object containing:
175
- * - config: The CommerceConfig to pass to createKernel
176
- * - cleanup: Async function to reset data between tests
177
- */
178
- export async function createPGliteTestConfig(
179
- overrides: Partial<CommerceConfig> = {},
180
- ): Promise<{ config: CommerceConfig; cleanup: () => Promise<void> }> {
181
- const { createPGliteTestAdapter } = await import("./create-pglite-adapter.js");
182
- const { adapter, cleanup } = await createPGliteTestAdapter();
183
-
184
- const config = await createTestConfig({
185
- databaseAdapter: adapter,
186
- ...overrides,
187
- });
188
-
189
- return { config, cleanup };
190
- }
@@ -1,7 +0,0 @@
1
- import type { CommerceConfig } from "../config/types.js";
2
- import { createKernel } from "../runtime/kernel.js";
3
- import { createTestConfig } from "./create-test-config.js";
4
-
5
- export async function createTestKernel(overrides: Partial<CommerceConfig> = {}) {
6
- return createKernel(await createTestConfig(overrides));
7
- }
@@ -1,75 +0,0 @@
1
- import { HookRegistry } from "../kernel/hooks/registry.js";
2
- import { createLogger } from "../utils/logger.js";
3
- import { createTestConfig } from "./create-test-config.js";
4
- import type { CommerceConfig, MCPTool } from "../config/types.js";
5
-
6
- interface PluginContextShape {
7
- hooks: HookRegistry;
8
- config: CommerceConfig;
9
- services: Record<string, unknown>;
10
- routes: { add(method: string, path: string, handler: (...args: unknown[]) => unknown): void };
11
- mcp: { registerTool(tool: MCPTool): void };
12
- analytics: { registerModel(model: unknown): void };
13
- database: {
14
- registerSchema(schema: Record<string, unknown>): void;
15
- query: unknown;
16
- transaction<T>(fn: (tx: unknown) => Promise<T>): Promise<T>;
17
- };
18
- logger: { info(message: string, data?: unknown): void; warn(message: string, data?: unknown): void; error(message: string, data?: unknown): void };
19
- }
20
-
21
- export interface TestPluginContext extends PluginContextShape {
22
- registeredRoutes: Array<{ method: string; path: string; handler: (...args: unknown[]) => unknown }>;
23
- registeredMCPTools: MCPTool[];
24
- registeredAnalyticsModels: unknown[];
25
- registeredSchemas: Array<Record<string, unknown>>;
26
- }
27
-
28
- export async function createTestPluginContext(options?: {
29
- config?: Partial<CommerceConfig>;
30
- services?: Record<string, unknown>;
31
- }): Promise<TestPluginContext> {
32
- const hooks = new HookRegistry();
33
- const config = await createTestConfig(options?.config ?? {});
34
- const services = options?.services ?? {};
35
-
36
- const registeredRoutes: TestPluginContext["registeredRoutes"] = [];
37
- const registeredMCPTools: MCPTool[] = [];
38
- const registeredAnalyticsModels: unknown[] = [];
39
- const registeredSchemas: Array<Record<string, unknown>> = [];
40
-
41
- return {
42
- hooks,
43
- config,
44
- services,
45
- routes: {
46
- add(method, path, handler) {
47
- registeredRoutes.push({ method: method.toUpperCase(), path, handler });
48
- },
49
- },
50
- mcp: {
51
- registerTool(tool) {
52
- registeredMCPTools.push(tool);
53
- },
54
- },
55
- analytics: {
56
- registerModel(model) {
57
- registeredAnalyticsModels.push(model);
58
- },
59
- },
60
- database: {
61
- registerSchema(schema) {
62
- registeredSchemas.push(schema);
63
- },
64
- query: {},
65
- async transaction<T>(fn: (tx: unknown) => Promise<T>): Promise<T> {
66
- return fn({});
67
- },
68
- },
69
- logger: createLogger("test-plugin-context"),
70
- registeredRoutes,
71
- registeredMCPTools,
72
- registeredAnalyticsModels,
73
- registeredSchemas,
74
- };
75
- }
@@ -1,265 +0,0 @@
1
- /**
2
- * Integration test utilities for REST API endpoints.
3
- *
4
- * Provides helper functions to test Hono routes with a real kernel,
5
- * PGlite database, and authentication middleware.
6
- */
7
-
8
- import { Hono } from "hono";
9
- import { createKernel } from "../runtime/kernel.js";
10
- import { createAuth } from "../auth/setup.js";
11
- import { authMiddleware } from "../auth/middleware.js";
12
- import { createRestRoutes } from "../interfaces/rest/index.js";
13
- import { createPGliteTestConfig } from "./create-test-config.js";
14
- import { CommerceValidationError } from "../kernel/errors.js";
15
- import { Ok, Err } from "../kernel/result.js";
16
- import type { CommerceConfig } from "../config/types.js";
17
- import type { Actor } from "../auth/types.js";
18
- import type { AuthInstance } from "../auth/setup.js";
19
-
20
- type ServerEnv = {
21
- Variables: {
22
- auth: AuthInstance;
23
- actor: Actor | null;
24
- };
25
- };
26
-
27
- const mockPaymentAdapter = {
28
- providerId: "test-payments",
29
- async createPaymentIntent(params: { amount: number; currency: string }) {
30
- return Ok({
31
- id: "pi_test_" + Date.now(),
32
- status: "requires_capture",
33
- amount: params.amount,
34
- currency: params.currency,
35
- clientSecret: "secret_test",
36
- });
37
- },
38
- async capturePayment() {
39
- return Ok({ id: "pi_test_" + Date.now(), status: "succeeded", amountCaptured: 1000 });
40
- },
41
- async refundPayment() {
42
- return Ok({ id: "re_test_" + Date.now(), status: "succeeded", amountRefunded: 1000 });
43
- },
44
- async cancelPaymentIntent() {
45
- return Ok(undefined);
46
- },
47
- async verifyWebhook(request: Request) {
48
- // Extract signature from headers
49
- const signature = request.headers.get("stripe-signature") || request.headers.get("webhook-signature");
50
-
51
- // Extract payload from request body
52
- let payload: Record<string, unknown> | undefined;
53
- try {
54
- payload = await request.clone().json();
55
- } catch {
56
- return Err(new CommerceValidationError("Webhook payload is invalid or missing"));
57
- }
58
-
59
- // Simulate signature verification for production-hardened testing
60
- // Reject invalid signatures like "invalid_signature"
61
- if (signature === "invalid_signature") {
62
- return Err(new CommerceValidationError("Invalid webhook signature"));
63
- }
64
-
65
- // Reject requests with no required fields
66
- if (!payload || !payload.type) {
67
- return Err(new CommerceValidationError("Webhook payload is missing required fields"));
68
- }
69
-
70
- return Ok({ id: "evt_test_" + Date.now(), type: String(payload.type), data: (payload.data ?? {}) as unknown });
71
- },
72
- };
73
-
74
- /**
75
- * Creates a test server with PGlite-backed kernel for REST API testing.
76
- */
77
- export async function createTestServer(
78
- overrides: Partial<CommerceConfig> = {},
79
- ): Promise<{
80
- server: Hono<ServerEnv>;
81
- kernel: ReturnType<typeof createKernel>;
82
- auth: AuthInstance;
83
- cleanup: () => Promise<void>;
84
- }> {
85
- const { config, cleanup } = await createPGliteTestConfig({
86
- payments: [mockPaymentAdapter],
87
- ...overrides,
88
- });
89
-
90
- const kernel = createKernel(config);
91
- const auth = createAuth(kernel.database, config);
92
- const app = new Hono<ServerEnv>();
93
-
94
- // Set auth in context (like createServer does)
95
- app.use("*", async (c, next) => {
96
- c.set("auth", auth);
97
- await next();
98
- });
99
-
100
- // Test middleware: allow direct actor injection via x-test-actor header for testing
101
- app.use("*", async (c, next) => {
102
- const testActorHeader = c.req.header("x-test-actor");
103
- if (testActorHeader) {
104
- try {
105
- const actor = JSON.parse(testActorHeader) as Actor;
106
- c.set("actor", actor);
107
- await next();
108
- return;
109
- } catch {
110
- // Invalid JSON, continue to auth middleware
111
- }
112
- }
113
- await next();
114
- });
115
-
116
- // Add auth middleware
117
- app.use("*", authMiddleware(auth, config));
118
-
119
- // Error handling middleware - catch thrown errors and convert to JSON
120
- app.use("*", async (c, next) => {
121
- try {
122
- await next();
123
- } catch (error) {
124
- // Import error handling utilities
125
- const { mapErrorToResponse, mapErrorToStatus } = await import("../interfaces/rest/utils.js");
126
- return c.json(
127
- mapErrorToResponse(error),
128
- mapErrorToStatus(error),
129
- );
130
- }
131
- });
132
-
133
- // Add REST routes
134
- app.route("/api", createRestRoutes(kernel));
135
-
136
- return { server: app, kernel, auth, cleanup };
137
- }
138
-
139
- /**
140
- * Helper to parse JSON response from Hono Response
141
- */
142
- export async function parseJsonResponse<T = unknown>(response: Response): Promise<T> {
143
- return response.json() as Promise<T>;
144
- }
145
-
146
- /**
147
- * Common test actor with staff permissions
148
- */
149
- export const testActor: Actor = {
150
- type: "user",
151
- userId: "00000000-0000-0000-0000-000000000001",
152
- email: "test@example.com",
153
- name: "Test Staff",
154
- vendorId: null,
155
- organizationId: "org_default",
156
- role: "staff",
157
- permissions: [
158
- "catalog:create",
159
- "catalog:update",
160
- "catalog:read",
161
- "inventory:adjust",
162
- "inventory:read",
163
- "orders:create",
164
- "orders:read",
165
- "orders:update",
166
- "cart:create",
167
- "cart:update",
168
- "cart:read",
169
- "customers:update:self",
170
- "webhooks:manage",
171
- "pricing:manage",
172
- "promotions:manage",
173
- "promotions:read",
174
- "audit:read",
175
- "media:write",
176
- ],
177
- };
178
-
179
- /**
180
- * Test actor with read-only permissions
181
- */
182
- export const readonlyActor: Actor = {
183
- type: "user",
184
- userId: "00000000-0000-0000-0000-000000000002",
185
- email: "readonly@example.com",
186
- name: "Read Only User",
187
- vendorId: null,
188
- organizationId: "org_default",
189
- role: "customer",
190
- permissions: ["catalog:read", "cart:read", "orders:read:own"],
191
- };
192
-
193
- /**
194
- * Test actor with no permissions
195
- */
196
- export const noPermActor: Actor = {
197
- type: "user",
198
- userId: "00000000-0000-0000-0000-000000000003",
199
- email: "noperm@example.com",
200
- name: "No Perm",
201
- vendorId: null,
202
- organizationId: "org_default",
203
- role: "customer",
204
- permissions: [],
205
- };
206
-
207
- /**
208
- * Helper to create a mock request with actor context
209
- */
210
- export function createMockRequest(server: Hono<ServerEnv>, options: {
211
- method: string;
212
- url: string;
213
- body?: unknown;
214
- headers?: Record<string, string>;
215
- actor?: Actor;
216
- }) {
217
- const url = new URL(options.url, "http://localhost");
218
-
219
- const headers: Record<string, string> = {
220
- "content-type": "application/json",
221
- ...options.headers,
222
- };
223
-
224
- // Add actor as header for test middleware
225
- if (options.actor) {
226
- headers["x-test-actor"] = JSON.stringify(options.actor);
227
- }
228
-
229
- // Build the request
230
- const requestInit: RequestInit = {
231
- method: options.method,
232
- headers,
233
- };
234
- if (options.body) {
235
- requestInit.body = JSON.stringify(options.body);
236
- }
237
- const request = new Request(url, requestInit);
238
-
239
- return request;
240
- }
241
-
242
- /**
243
- * Helper to make authenticated requests to the test server
244
- */
245
- export async function makeRequest(
246
- server: Hono<ServerEnv>,
247
- options: {
248
- method: string;
249
- url: string;
250
- body?: unknown;
251
- headers?: Record<string, string>;
252
- actor?: Actor;
253
- },
254
- ) {
255
- // Create request with actor header (defaults to testActor)
256
- const request = createMockRequest(server, {
257
- ...options,
258
- actor: options.actor ?? testActor,
259
- });
260
-
261
- // Route the request through Hono
262
- const response = await server.fetch(request);
263
-
264
- return response;
265
- }
@@ -1,62 +0,0 @@
1
- import type { Actor } from "../auth/types.js";
2
-
3
- /** Admin with wildcard permissions. Use for setup operations in beforeAll. */
4
- export const testAdminActor: Actor = {
5
- type: "user",
6
- userId: "test-admin-1",
7
- email: "admin@test.local",
8
- name: "Test Admin",
9
- vendorId: null,
10
- organizationId: "org_default",
11
- role: "admin",
12
- permissions: ["*:*"],
13
- };
14
-
15
- /** Staff with common operational permissions. */
16
- export const testStaffActor: Actor = {
17
- type: "user",
18
- userId: "test-staff-1",
19
- email: "staff@test.local",
20
- name: "Test Staff",
21
- vendorId: null,
22
- organizationId: "org_default",
23
- role: "staff",
24
- permissions: [
25
- "catalog:read", "catalog:create", "catalog:update",
26
- "inventory:adjust", "orders:read", "orders:create", "orders:update",
27
- ],
28
- };
29
-
30
- /** Customer with minimal read/write-own permissions. */
31
- export const testCustomerActor: Actor = {
32
- type: "user",
33
- userId: "test-customer-1",
34
- email: "customer@test.local",
35
- name: "Test Customer",
36
- vendorId: null,
37
- organizationId: "org_default",
38
- role: "customer",
39
- permissions: ["catalog:read", "cart:create", "cart:read", "orders:read:own"],
40
- };
41
-
42
- /** Actor with zero permissions. Use for negative auth/perm tests. */
43
- export const testNoPermActor: Actor = {
44
- type: "user",
45
- userId: "test-noperm-1",
46
- email: "noperm@test.local",
47
- name: "No Permissions",
48
- vendorId: null,
49
- organizationId: "org_default",
50
- role: "customer",
51
- permissions: [],
52
- };
53
-
54
- /**
55
- * Builds request headers with optional test actor injection.
56
- * The x-test-actor header is parsed by createPluginTestApp's middleware.
57
- */
58
- export function jsonHeaders(actor?: Actor): Record<string, string> {
59
- const headers: Record<string, string> = { "Content-Type": "application/json" };
60
- if (actor) headers["x-test-actor"] = JSON.stringify(actor);
61
- return headers;
62
- }
@@ -1,54 +0,0 @@
1
- import type { PluginHookRegistration } from "../kernel/plugin/manifest.js";
2
- import type { HookContext, HookOperation } from "../kernel/hooks/types.js";
3
-
4
- /**
5
- * Creates a typed before-hook registration for plugins.
6
- *
7
- * Narrows the handler signature from the loose `(...args: unknown[]) => unknown`
8
- * on PluginHookRegistration to the actual `{ data, operation, context }` shape,
9
- * providing autocomplete on context.jobs.enqueue(), context.logger.info(), etc.
10
- *
11
- * @example
12
- * ```typescript
13
- * hooks: () => [
14
- * beforeHook<{ customerId: string }>("orders.beforeCreate", async ({ data, context }) => {
15
- * context.logger.info("order_creating", { customerId: data.customerId });
16
- * return data;
17
- * }),
18
- * ],
19
- * ```
20
- */
21
- export function beforeHook<TData>(
22
- key: string,
23
- handler: (args: {
24
- data: TData;
25
- operation: HookOperation;
26
- context: HookContext;
27
- }) => Promise<TData> | TData,
28
- ): PluginHookRegistration {
29
- return { key, handler: handler as PluginHookRegistration["handler"] };
30
- }
31
-
32
- /**
33
- * Creates a typed after-hook registration for plugins.
34
- *
35
- * @example
36
- * ```typescript
37
- * hooks: () => [
38
- * afterHook<{ id: string; grandTotal: number }>("orders.afterCreate", async ({ result, context }) => {
39
- * await context.jobs.enqueue("loyalty:award-points", { orderId: result.id });
40
- * }),
41
- * ],
42
- * ```
43
- */
44
- export function afterHook<TData>(
45
- key: string,
46
- handler: (args: {
47
- data: TData | null;
48
- result: TData;
49
- operation: HookOperation;
50
- context: HookContext;
51
- }) => Promise<void> | void,
52
- ): PluginHookRegistration {
53
- return { key, handler: handler as PluginHookRegistration["handler"] };
54
- }