@uniforge/testing 0.1.0-alpha.2
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/auth/index.d.cts +177 -0
- package/dist/auth/index.d.ts +177 -0
- package/dist/auth/index.js +459 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +418 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/billing/index.d.cts +27 -0
- package/dist/billing/index.d.ts +27 -0
- package/dist/billing/index.js +208 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/index.mjs +178 -0
- package/dist/billing/index.mjs.map +1 -0
- package/dist/database/index.d.cts +399 -0
- package/dist/database/index.d.ts +399 -0
- package/dist/database/index.js +19054 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/index.mjs +19046 -0
- package/dist/database/index.mjs.map +1 -0
- package/dist/graphql/index.d.cts +23 -0
- package/dist/graphql/index.d.ts +23 -0
- package/dist/graphql/index.js +18511 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/index.mjs +18505 -0
- package/dist/graphql/index.mjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -0
- package/dist/multi-store/index.d.cts +66 -0
- package/dist/multi-store/index.d.ts +66 -0
- package/dist/multi-store/index.js +319 -0
- package/dist/multi-store/index.js.map +1 -0
- package/dist/multi-store/index.mjs +287 -0
- package/dist/multi-store/index.mjs.map +1 -0
- package/dist/multi-tenant/index.d.cts +15 -0
- package/dist/multi-tenant/index.d.ts +15 -0
- package/dist/multi-tenant/index.js +87 -0
- package/dist/multi-tenant/index.js.map +1 -0
- package/dist/multi-tenant/index.mjs +57 -0
- package/dist/multi-tenant/index.mjs.map +1 -0
- package/dist/performance/index.d.cts +60 -0
- package/dist/performance/index.d.ts +60 -0
- package/dist/performance/index.js +280 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/index.mjs +246 -0
- package/dist/performance/index.mjs.map +1 -0
- package/dist/platform/index.d.cts +71 -0
- package/dist/platform/index.d.ts +71 -0
- package/dist/platform/index.js +435 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +396 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/rbac/index.d.cts +21 -0
- package/dist/rbac/index.d.ts +21 -0
- package/dist/rbac/index.js +178 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/index.mjs +150 -0
- package/dist/rbac/index.mjs.map +1 -0
- package/dist/security/index.d.cts +73 -0
- package/dist/security/index.d.ts +73 -0
- package/dist/security/index.js +246 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +211 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/shopify-api/index.d.cts +139 -0
- package/dist/shopify-api/index.d.ts +139 -0
- package/dist/shopify-api/index.js +469 -0
- package/dist/shopify-api/index.js.map +1 -0
- package/dist/shopify-api/index.mjs +439 -0
- package/dist/shopify-api/index.mjs.map +1 -0
- package/dist/shopify-compliance/index.d.cts +85 -0
- package/dist/shopify-compliance/index.d.ts +85 -0
- package/dist/shopify-compliance/index.js +287 -0
- package/dist/shopify-compliance/index.js.map +1 -0
- package/dist/shopify-compliance/index.mjs +259 -0
- package/dist/shopify-compliance/index.mjs.map +1 -0
- package/dist/webhooks/index.d.cts +127 -0
- package/dist/webhooks/index.d.ts +127 -0
- package/dist/webhooks/index.js +18934 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/index.mjs +18916 -0
- package/dist/webhooks/index.mjs.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
// src/platform/factories.ts
|
|
2
|
+
import { DEFAULT_CAPABILITIES } from "@uniforge/platform-core/platform";
|
|
3
|
+
function createTestMoney(overrides) {
|
|
4
|
+
const defaults = {
|
|
5
|
+
amount: "10.00",
|
|
6
|
+
currencyCode: "USD"
|
|
7
|
+
};
|
|
8
|
+
return { ...defaults, ...overrides };
|
|
9
|
+
}
|
|
10
|
+
function createTestCapabilities(overrides) {
|
|
11
|
+
return {
|
|
12
|
+
auth: { ...DEFAULT_CAPABILITIES.auth, ...overrides?.auth },
|
|
13
|
+
billing: { ...DEFAULT_CAPABILITIES.billing, ...overrides?.billing },
|
|
14
|
+
webhooks: { ...DEFAULT_CAPABILITIES.webhooks, ...overrides?.webhooks },
|
|
15
|
+
graphql: { ...DEFAULT_CAPABILITIES.graphql, ...overrides?.graphql },
|
|
16
|
+
rbac: overrides?.rbac ?? DEFAULT_CAPABILITIES.rbac,
|
|
17
|
+
multiStore: overrides?.multiStore ?? DEFAULT_CAPABILITIES.multiStore,
|
|
18
|
+
commerce: { ...DEFAULT_CAPABILITIES.commerce, ...overrides?.commerce }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createTestPlatformProvider(overrides) {
|
|
22
|
+
const caps = overrides?.getCapabilities?.() ?? DEFAULT_CAPABILITIES;
|
|
23
|
+
return {
|
|
24
|
+
id: "test-platform",
|
|
25
|
+
name: "Test Platform",
|
|
26
|
+
version: "1.0.0",
|
|
27
|
+
description: "Test platform for testing",
|
|
28
|
+
getCapabilities: () => caps,
|
|
29
|
+
validateConfig: () => ({ valid: true, errors: [] }),
|
|
30
|
+
supportsAuth: () => caps.auth.oauth || caps.auth.tokenExchange || caps.auth.apiKeys,
|
|
31
|
+
supportsBilling: () => caps.billing.subscriptions || caps.billing.oneTimeCharges || caps.billing.usageBased,
|
|
32
|
+
supportsWebhooks: () => caps.webhooks.supported,
|
|
33
|
+
supportsGraphQL: () => caps.graphql.supported,
|
|
34
|
+
supportsRBAC: () => caps.rbac,
|
|
35
|
+
supportsMultiStore: () => caps.multiStore,
|
|
36
|
+
supportsCommerce: () => caps.commerce.products || caps.commerce.orders || caps.commerce.customers,
|
|
37
|
+
...overrides
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function createTestProductImage(overrides) {
|
|
41
|
+
const defaults = {
|
|
42
|
+
id: `img-${Date.now()}`,
|
|
43
|
+
src: "https://example.com/image.png",
|
|
44
|
+
altText: "Test image",
|
|
45
|
+
position: 1
|
|
46
|
+
};
|
|
47
|
+
return { ...defaults, ...overrides };
|
|
48
|
+
}
|
|
49
|
+
function createTestProductVariant(overrides) {
|
|
50
|
+
const defaults = {
|
|
51
|
+
id: `var-${Date.now()}`,
|
|
52
|
+
platformId: `plat-var-${Date.now()}`,
|
|
53
|
+
title: "Default",
|
|
54
|
+
sku: "TEST-SKU-001",
|
|
55
|
+
price: createTestMoney(),
|
|
56
|
+
inventoryQuantity: 100,
|
|
57
|
+
metadata: {}
|
|
58
|
+
};
|
|
59
|
+
return { ...defaults, ...overrides };
|
|
60
|
+
}
|
|
61
|
+
function createTestProduct(overrides) {
|
|
62
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
63
|
+
const defaults = {
|
|
64
|
+
id: `prod-${Date.now()}`,
|
|
65
|
+
platformId: `plat-prod-${Date.now()}`,
|
|
66
|
+
title: "Test Product",
|
|
67
|
+
description: "A test product for unit testing",
|
|
68
|
+
handle: "test-product",
|
|
69
|
+
vendor: "Test Vendor",
|
|
70
|
+
productType: "Test Type",
|
|
71
|
+
status: "active",
|
|
72
|
+
tags: ["test"],
|
|
73
|
+
variants: [createTestProductVariant()],
|
|
74
|
+
images: [createTestProductImage()],
|
|
75
|
+
metadata: {},
|
|
76
|
+
createdAt: now,
|
|
77
|
+
updatedAt: now
|
|
78
|
+
};
|
|
79
|
+
return { ...defaults, ...overrides };
|
|
80
|
+
}
|
|
81
|
+
function createTestOrderLineItem(overrides) {
|
|
82
|
+
const defaults = {
|
|
83
|
+
id: `li-${Date.now()}`,
|
|
84
|
+
title: "Test Line Item",
|
|
85
|
+
quantity: 1,
|
|
86
|
+
price: createTestMoney(),
|
|
87
|
+
sku: "TEST-SKU-001"
|
|
88
|
+
};
|
|
89
|
+
return { ...defaults, ...overrides };
|
|
90
|
+
}
|
|
91
|
+
function createTestOrder(overrides) {
|
|
92
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
93
|
+
const defaults = {
|
|
94
|
+
id: `order-${Date.now()}`,
|
|
95
|
+
platformId: `plat-order-${Date.now()}`,
|
|
96
|
+
orderNumber: "1001",
|
|
97
|
+
status: "open",
|
|
98
|
+
fulfillmentStatus: "unfulfilled",
|
|
99
|
+
financialStatus: "paid",
|
|
100
|
+
lineItems: [createTestOrderLineItem()],
|
|
101
|
+
totalPrice: createTestMoney({ amount: "25.00" }),
|
|
102
|
+
subtotalPrice: createTestMoney({ amount: "22.00" }),
|
|
103
|
+
totalTax: createTestMoney({ amount: "3.00" }),
|
|
104
|
+
customerEmail: "customer@example.com",
|
|
105
|
+
metadata: {},
|
|
106
|
+
createdAt: now,
|
|
107
|
+
updatedAt: now
|
|
108
|
+
};
|
|
109
|
+
return { ...defaults, ...overrides };
|
|
110
|
+
}
|
|
111
|
+
function createTestCustomer(overrides) {
|
|
112
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
113
|
+
const defaults = {
|
|
114
|
+
id: `cust-${Date.now()}`,
|
|
115
|
+
platformId: `plat-cust-${Date.now()}`,
|
|
116
|
+
email: "customer@example.com",
|
|
117
|
+
firstName: "Jane",
|
|
118
|
+
lastName: "Doe",
|
|
119
|
+
phone: "+1234567890",
|
|
120
|
+
ordersCount: 5,
|
|
121
|
+
totalSpent: createTestMoney({ amount: "250.00" }),
|
|
122
|
+
tags: ["vip"],
|
|
123
|
+
metadata: {},
|
|
124
|
+
createdAt: now,
|
|
125
|
+
updatedAt: now
|
|
126
|
+
};
|
|
127
|
+
return { ...defaults, ...overrides };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/platform/mock-registry.ts
|
|
131
|
+
var MockPlatformRegistry = class {
|
|
132
|
+
providers = /* @__PURE__ */ new Map();
|
|
133
|
+
register(provider) {
|
|
134
|
+
this.providers.set(provider.id, provider);
|
|
135
|
+
}
|
|
136
|
+
get(platformId) {
|
|
137
|
+
return this.providers.get(platformId);
|
|
138
|
+
}
|
|
139
|
+
has(platformId) {
|
|
140
|
+
return this.providers.has(platformId);
|
|
141
|
+
}
|
|
142
|
+
list() {
|
|
143
|
+
return Array.from(this.providers.keys());
|
|
144
|
+
}
|
|
145
|
+
getAll() {
|
|
146
|
+
return Array.from(this.providers.values());
|
|
147
|
+
}
|
|
148
|
+
_reset() {
|
|
149
|
+
this.providers.clear();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/platform/mock-commerce.ts
|
|
154
|
+
var MockProductService = class {
|
|
155
|
+
products = /* @__PURE__ */ new Map();
|
|
156
|
+
_addProduct(product) {
|
|
157
|
+
this.products.set(product.id, product);
|
|
158
|
+
}
|
|
159
|
+
_reset() {
|
|
160
|
+
this.products.clear();
|
|
161
|
+
}
|
|
162
|
+
async getProduct(id) {
|
|
163
|
+
return this.products.get(id) ?? null;
|
|
164
|
+
}
|
|
165
|
+
async listProducts(options) {
|
|
166
|
+
const all = Array.from(this.products.values());
|
|
167
|
+
const limit = options?.limit ?? 50;
|
|
168
|
+
const cursorIndex = options?.cursor ? all.findIndex((p) => p.id === options.cursor) + 1 : 0;
|
|
169
|
+
const items = all.slice(cursorIndex, cursorIndex + limit);
|
|
170
|
+
const hasNextPage = cursorIndex + limit < all.length;
|
|
171
|
+
const result = {
|
|
172
|
+
items,
|
|
173
|
+
hasNextPage,
|
|
174
|
+
hasPreviousPage: cursorIndex > 0
|
|
175
|
+
};
|
|
176
|
+
const lastItem = items[items.length - 1];
|
|
177
|
+
if (lastItem && (hasNextPage || cursorIndex > 0)) {
|
|
178
|
+
result.cursor = lastItem.id;
|
|
179
|
+
}
|
|
180
|
+
result.totalCount = all.length;
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
async createProduct(input) {
|
|
184
|
+
const id = `prod-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
185
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
186
|
+
const product = createTestProduct({
|
|
187
|
+
id,
|
|
188
|
+
platformId: id,
|
|
189
|
+
title: input.title,
|
|
190
|
+
handle: input.title.toLowerCase().replace(/\s+/g, "-"),
|
|
191
|
+
createdAt: now,
|
|
192
|
+
updatedAt: now,
|
|
193
|
+
variants: [],
|
|
194
|
+
images: []
|
|
195
|
+
});
|
|
196
|
+
if (input.description !== void 0) {
|
|
197
|
+
product.description = input.description;
|
|
198
|
+
}
|
|
199
|
+
if (input.vendor !== void 0) {
|
|
200
|
+
product.vendor = input.vendor;
|
|
201
|
+
}
|
|
202
|
+
if (input.productType !== void 0) {
|
|
203
|
+
product.productType = input.productType;
|
|
204
|
+
}
|
|
205
|
+
if (input.status !== void 0) {
|
|
206
|
+
product.status = input.status;
|
|
207
|
+
}
|
|
208
|
+
if (input.tags !== void 0) {
|
|
209
|
+
product.tags = input.tags;
|
|
210
|
+
}
|
|
211
|
+
if (input.metadata !== void 0) {
|
|
212
|
+
product.metadata = input.metadata;
|
|
213
|
+
}
|
|
214
|
+
this.products.set(product.id, product);
|
|
215
|
+
return product;
|
|
216
|
+
}
|
|
217
|
+
async updateProduct(id, input) {
|
|
218
|
+
const existing = this.products.get(id);
|
|
219
|
+
if (!existing) {
|
|
220
|
+
throw new Error(`Product not found: ${id}`);
|
|
221
|
+
}
|
|
222
|
+
const updated = {
|
|
223
|
+
...existing,
|
|
224
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
225
|
+
};
|
|
226
|
+
if (input.title !== void 0) {
|
|
227
|
+
updated.title = input.title;
|
|
228
|
+
}
|
|
229
|
+
if (input.description !== void 0) {
|
|
230
|
+
updated.description = input.description;
|
|
231
|
+
}
|
|
232
|
+
if (input.vendor !== void 0) {
|
|
233
|
+
updated.vendor = input.vendor;
|
|
234
|
+
}
|
|
235
|
+
if (input.productType !== void 0) {
|
|
236
|
+
updated.productType = input.productType;
|
|
237
|
+
}
|
|
238
|
+
if (input.status !== void 0) {
|
|
239
|
+
updated.status = input.status;
|
|
240
|
+
}
|
|
241
|
+
if (input.tags !== void 0) {
|
|
242
|
+
updated.tags = input.tags;
|
|
243
|
+
}
|
|
244
|
+
if (input.metadata !== void 0) {
|
|
245
|
+
updated.metadata = input.metadata;
|
|
246
|
+
}
|
|
247
|
+
this.products.set(id, updated);
|
|
248
|
+
return updated;
|
|
249
|
+
}
|
|
250
|
+
async deleteProduct(id) {
|
|
251
|
+
if (!this.products.has(id)) {
|
|
252
|
+
throw new Error(`Product not found: ${id}`);
|
|
253
|
+
}
|
|
254
|
+
this.products.delete(id);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
var MockOrderService = class {
|
|
258
|
+
orders = /* @__PURE__ */ new Map();
|
|
259
|
+
_addOrder(order) {
|
|
260
|
+
this.orders.set(order.id, order);
|
|
261
|
+
}
|
|
262
|
+
_reset() {
|
|
263
|
+
this.orders.clear();
|
|
264
|
+
}
|
|
265
|
+
async getOrder(id) {
|
|
266
|
+
return this.orders.get(id) ?? null;
|
|
267
|
+
}
|
|
268
|
+
async listOrders(options) {
|
|
269
|
+
const all = Array.from(this.orders.values());
|
|
270
|
+
const limit = options?.limit ?? 50;
|
|
271
|
+
const cursorIndex = options?.cursor ? all.findIndex((o) => o.id === options.cursor) + 1 : 0;
|
|
272
|
+
const items = all.slice(cursorIndex, cursorIndex + limit);
|
|
273
|
+
const hasNextPage = cursorIndex + limit < all.length;
|
|
274
|
+
const result = {
|
|
275
|
+
items,
|
|
276
|
+
hasNextPage,
|
|
277
|
+
hasPreviousPage: cursorIndex > 0
|
|
278
|
+
};
|
|
279
|
+
const lastOrderItem = items[items.length - 1];
|
|
280
|
+
if (lastOrderItem && hasNextPage) {
|
|
281
|
+
result.cursor = lastOrderItem.id;
|
|
282
|
+
}
|
|
283
|
+
result.totalCount = all.length;
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var MockCustomerService = class {
|
|
288
|
+
customers = /* @__PURE__ */ new Map();
|
|
289
|
+
_addCustomer(customer) {
|
|
290
|
+
this.customers.set(customer.id, customer);
|
|
291
|
+
}
|
|
292
|
+
_reset() {
|
|
293
|
+
this.customers.clear();
|
|
294
|
+
}
|
|
295
|
+
async getCustomer(id) {
|
|
296
|
+
return this.customers.get(id) ?? null;
|
|
297
|
+
}
|
|
298
|
+
async listCustomers(options) {
|
|
299
|
+
const all = Array.from(this.customers.values());
|
|
300
|
+
const limit = options?.limit ?? 50;
|
|
301
|
+
const cursorIndex = options?.cursor ? all.findIndex((c) => c.id === options.cursor) + 1 : 0;
|
|
302
|
+
const items = all.slice(cursorIndex, cursorIndex + limit);
|
|
303
|
+
const hasNextPage = cursorIndex + limit < all.length;
|
|
304
|
+
const result = {
|
|
305
|
+
items,
|
|
306
|
+
hasNextPage,
|
|
307
|
+
hasPreviousPage: cursorIndex > 0
|
|
308
|
+
};
|
|
309
|
+
const lastCustItem = items[items.length - 1];
|
|
310
|
+
if (lastCustItem && hasNextPage) {
|
|
311
|
+
result.cursor = lastCustItem.id;
|
|
312
|
+
}
|
|
313
|
+
result.totalCount = all.length;
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
316
|
+
async createCustomer(input) {
|
|
317
|
+
const id = `cust-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
318
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
319
|
+
const customer = createTestCustomer({
|
|
320
|
+
id,
|
|
321
|
+
platformId: id,
|
|
322
|
+
email: input.email,
|
|
323
|
+
createdAt: now,
|
|
324
|
+
updatedAt: now
|
|
325
|
+
});
|
|
326
|
+
if (input.firstName !== void 0) {
|
|
327
|
+
customer.firstName = input.firstName;
|
|
328
|
+
}
|
|
329
|
+
if (input.lastName !== void 0) {
|
|
330
|
+
customer.lastName = input.lastName;
|
|
331
|
+
}
|
|
332
|
+
if (input.phone !== void 0) {
|
|
333
|
+
customer.phone = input.phone;
|
|
334
|
+
}
|
|
335
|
+
if (input.tags !== void 0) {
|
|
336
|
+
customer.tags = input.tags;
|
|
337
|
+
}
|
|
338
|
+
if (input.metadata !== void 0) {
|
|
339
|
+
customer.metadata = input.metadata;
|
|
340
|
+
}
|
|
341
|
+
this.customers.set(customer.id, customer);
|
|
342
|
+
return customer;
|
|
343
|
+
}
|
|
344
|
+
async updateCustomer(id, input) {
|
|
345
|
+
const existing = this.customers.get(id);
|
|
346
|
+
if (!existing) {
|
|
347
|
+
throw new Error(`Customer not found: ${id}`);
|
|
348
|
+
}
|
|
349
|
+
const updated = {
|
|
350
|
+
...existing,
|
|
351
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
352
|
+
};
|
|
353
|
+
if (input.email !== void 0) {
|
|
354
|
+
updated.email = input.email;
|
|
355
|
+
}
|
|
356
|
+
if (input.firstName !== void 0) {
|
|
357
|
+
updated.firstName = input.firstName;
|
|
358
|
+
}
|
|
359
|
+
if (input.lastName !== void 0) {
|
|
360
|
+
updated.lastName = input.lastName;
|
|
361
|
+
}
|
|
362
|
+
if (input.phone !== void 0) {
|
|
363
|
+
updated.phone = input.phone;
|
|
364
|
+
}
|
|
365
|
+
if (input.tags !== void 0) {
|
|
366
|
+
updated.tags = input.tags;
|
|
367
|
+
}
|
|
368
|
+
if (input.metadata !== void 0) {
|
|
369
|
+
updated.metadata = input.metadata;
|
|
370
|
+
}
|
|
371
|
+
this.customers.set(id, updated);
|
|
372
|
+
return updated;
|
|
373
|
+
}
|
|
374
|
+
async deleteCustomer(id) {
|
|
375
|
+
if (!this.customers.has(id)) {
|
|
376
|
+
throw new Error(`Customer not found: ${id}`);
|
|
377
|
+
}
|
|
378
|
+
this.customers.delete(id);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
export {
|
|
382
|
+
MockCustomerService,
|
|
383
|
+
MockOrderService,
|
|
384
|
+
MockPlatformRegistry,
|
|
385
|
+
MockProductService,
|
|
386
|
+
createTestCapabilities,
|
|
387
|
+
createTestCustomer,
|
|
388
|
+
createTestMoney,
|
|
389
|
+
createTestOrder,
|
|
390
|
+
createTestOrderLineItem,
|
|
391
|
+
createTestPlatformProvider,
|
|
392
|
+
createTestProduct,
|
|
393
|
+
createTestProductImage,
|
|
394
|
+
createTestProductVariant
|
|
395
|
+
};
|
|
396
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/platform/factories.ts","../../src/platform/mock-registry.ts","../../src/platform/mock-commerce.ts"],"sourcesContent":["/**\n * Test data factories for platform types.\n *\n * Each factory provides sensible defaults that can be overridden.\n */\n\nimport { DEFAULT_CAPABILITIES } from '@uniforge/platform-core/platform';\nimport type {\n PlatformProvider,\n PlatformCapabilities,\n Product,\n ProductVariant,\n ProductImage,\n Order,\n OrderLineItem,\n Customer,\n Money,\n} from '@uniforge/platform-core/platform';\n\nexport function createTestMoney(overrides?: Partial<Money>): Money {\n const defaults: Money = {\n amount: '10.00',\n currencyCode: 'USD',\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestCapabilities(\n overrides?: Partial<PlatformCapabilities>,\n): PlatformCapabilities {\n return {\n auth: { ...DEFAULT_CAPABILITIES.auth, ...overrides?.auth },\n billing: { ...DEFAULT_CAPABILITIES.billing, ...overrides?.billing },\n webhooks: { ...DEFAULT_CAPABILITIES.webhooks, ...overrides?.webhooks },\n graphql: { ...DEFAULT_CAPABILITIES.graphql, ...overrides?.graphql },\n rbac: overrides?.rbac ?? DEFAULT_CAPABILITIES.rbac,\n multiStore: overrides?.multiStore ?? DEFAULT_CAPABILITIES.multiStore,\n commerce: { ...DEFAULT_CAPABILITIES.commerce, ...overrides?.commerce },\n };\n}\n\nexport function createTestPlatformProvider(\n overrides?: Partial<PlatformProvider>,\n): PlatformProvider {\n const caps = overrides?.getCapabilities?.() ?? DEFAULT_CAPABILITIES;\n return {\n id: 'test-platform',\n name: 'Test Platform',\n version: '1.0.0',\n description: 'Test platform for testing',\n getCapabilities: () => caps,\n validateConfig: () => ({ valid: true, errors: [] }),\n supportsAuth: () =>\n caps.auth.oauth || caps.auth.tokenExchange || caps.auth.apiKeys,\n supportsBilling: () =>\n caps.billing.subscriptions ||\n caps.billing.oneTimeCharges ||\n caps.billing.usageBased,\n supportsWebhooks: () => caps.webhooks.supported,\n supportsGraphQL: () => caps.graphql.supported,\n supportsRBAC: () => caps.rbac,\n supportsMultiStore: () => caps.multiStore,\n supportsCommerce: () =>\n caps.commerce.products ||\n caps.commerce.orders ||\n caps.commerce.customers,\n ...overrides,\n };\n}\n\nexport function createTestProductImage(\n overrides?: Partial<ProductImage>,\n): ProductImage {\n const defaults: ProductImage = {\n id: `img-${Date.now()}`,\n src: 'https://example.com/image.png',\n altText: 'Test image',\n position: 1,\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestProductVariant(\n overrides?: Partial<ProductVariant>,\n): ProductVariant {\n const defaults: ProductVariant = {\n id: `var-${Date.now()}`,\n platformId: `plat-var-${Date.now()}`,\n title: 'Default',\n sku: 'TEST-SKU-001',\n price: createTestMoney(),\n inventoryQuantity: 100,\n metadata: {},\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestProduct(overrides?: Partial<Product>): Product {\n const now = new Date().toISOString();\n const defaults: Product = {\n id: `prod-${Date.now()}`,\n platformId: `plat-prod-${Date.now()}`,\n title: 'Test Product',\n description: 'A test product for unit testing',\n handle: 'test-product',\n vendor: 'Test Vendor',\n productType: 'Test Type',\n status: 'active',\n tags: ['test'],\n variants: [createTestProductVariant()],\n images: [createTestProductImage()],\n metadata: {},\n createdAt: now,\n updatedAt: now,\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestOrderLineItem(\n overrides?: Partial<OrderLineItem>,\n): OrderLineItem {\n const defaults: OrderLineItem = {\n id: `li-${Date.now()}`,\n title: 'Test Line Item',\n quantity: 1,\n price: createTestMoney(),\n sku: 'TEST-SKU-001',\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestOrder(overrides?: Partial<Order>): Order {\n const now = new Date().toISOString();\n const defaults: Order = {\n id: `order-${Date.now()}`,\n platformId: `plat-order-${Date.now()}`,\n orderNumber: '1001',\n status: 'open',\n fulfillmentStatus: 'unfulfilled',\n financialStatus: 'paid',\n lineItems: [createTestOrderLineItem()],\n totalPrice: createTestMoney({ amount: '25.00' }),\n subtotalPrice: createTestMoney({ amount: '22.00' }),\n totalTax: createTestMoney({ amount: '3.00' }),\n customerEmail: 'customer@example.com',\n metadata: {},\n createdAt: now,\n updatedAt: now,\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestCustomer(overrides?: Partial<Customer>): Customer {\n const now = new Date().toISOString();\n const defaults: Customer = {\n id: `cust-${Date.now()}`,\n platformId: `plat-cust-${Date.now()}`,\n email: 'customer@example.com',\n firstName: 'Jane',\n lastName: 'Doe',\n phone: '+1234567890',\n ordersCount: 5,\n totalSpent: createTestMoney({ amount: '250.00' }),\n tags: ['vip'],\n metadata: {},\n createdAt: now,\n updatedAt: now,\n };\n return { ...defaults, ...overrides };\n}\n","/**\n * Mock PlatformRegistry for unit testing.\n *\n * In-memory implementation of the PlatformRegistry interface\n * with a _reset() method for test isolation.\n */\n\nimport type {\n PlatformRegistry,\n PlatformProvider,\n PlatformId,\n} from '@uniforge/platform-core/platform';\n\nexport class MockPlatformRegistry implements PlatformRegistry {\n private providers = new Map<PlatformId, PlatformProvider>();\n\n register(provider: PlatformProvider): void {\n this.providers.set(provider.id, provider);\n }\n\n get(platformId: PlatformId): PlatformProvider | undefined {\n return this.providers.get(platformId);\n }\n\n has(platformId: PlatformId): boolean {\n return this.providers.has(platformId);\n }\n\n list(): PlatformId[] {\n return Array.from(this.providers.keys());\n }\n\n getAll(): PlatformProvider[] {\n return Array.from(this.providers.values());\n }\n\n _reset(): void {\n this.providers.clear();\n }\n}\n","/**\n * Mock commerce services for unit testing.\n *\n * In-memory implementations of ProductService, OrderService,\n * and CustomerService with helpers for seeding test data.\n */\n\nimport type {\n ProductService,\n OrderService,\n CustomerService,\n Product,\n Order,\n Customer,\n PaginatedResult,\n ListOptions,\n CreateProductInput,\n UpdateProductInput,\n CreateCustomerInput,\n UpdateCustomerInput,\n} from '@uniforge/platform-core/platform';\n\nimport { createTestProduct, createTestCustomer } from './factories';\n\n// ── MockProductService ──\n\nexport class MockProductService implements ProductService {\n private products = new Map<string, Product>();\n\n _addProduct(product: Product): void {\n this.products.set(product.id, product);\n }\n\n _reset(): void {\n this.products.clear();\n }\n\n async getProduct(id: string): Promise<Product | null> {\n return this.products.get(id) ?? null;\n }\n\n async listProducts(options?: ListOptions): Promise<PaginatedResult<Product>> {\n const all = Array.from(this.products.values());\n const limit = options?.limit ?? 50;\n const cursorIndex = options?.cursor\n ? all.findIndex((p) => p.id === options.cursor) + 1\n : 0;\n const items = all.slice(cursorIndex, cursorIndex + limit);\n const hasNextPage = cursorIndex + limit < all.length;\n const result: PaginatedResult<Product> = {\n items,\n hasNextPage,\n hasPreviousPage: cursorIndex > 0,\n };\n const lastItem = items[items.length - 1];\n if (lastItem && (hasNextPage || cursorIndex > 0)) {\n result.cursor = lastItem.id;\n }\n result.totalCount = all.length;\n return result;\n }\n\n async createProduct(input: CreateProductInput): Promise<Product> {\n const id = `prod-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const now = new Date().toISOString();\n const product = createTestProduct({\n id,\n platformId: id,\n title: input.title,\n handle: input.title.toLowerCase().replace(/\\s+/g, '-'),\n createdAt: now,\n updatedAt: now,\n variants: [],\n images: [],\n });\n if (input.description !== undefined) {\n product.description = input.description;\n }\n if (input.vendor !== undefined) {\n product.vendor = input.vendor;\n }\n if (input.productType !== undefined) {\n product.productType = input.productType;\n }\n if (input.status !== undefined) {\n product.status = input.status;\n }\n if (input.tags !== undefined) {\n product.tags = input.tags;\n }\n if (input.metadata !== undefined) {\n product.metadata = input.metadata;\n }\n this.products.set(product.id, product);\n return product;\n }\n\n async updateProduct(\n id: string,\n input: UpdateProductInput,\n ): Promise<Product> {\n const existing = this.products.get(id);\n if (!existing) {\n throw new Error(`Product not found: ${id}`);\n }\n const updated: Product = {\n ...existing,\n updatedAt: new Date().toISOString(),\n };\n if (input.title !== undefined) {\n updated.title = input.title;\n }\n if (input.description !== undefined) {\n updated.description = input.description;\n }\n if (input.vendor !== undefined) {\n updated.vendor = input.vendor;\n }\n if (input.productType !== undefined) {\n updated.productType = input.productType;\n }\n if (input.status !== undefined) {\n updated.status = input.status;\n }\n if (input.tags !== undefined) {\n updated.tags = input.tags;\n }\n if (input.metadata !== undefined) {\n updated.metadata = input.metadata;\n }\n this.products.set(id, updated);\n return updated;\n }\n\n async deleteProduct(id: string): Promise<void> {\n if (!this.products.has(id)) {\n throw new Error(`Product not found: ${id}`);\n }\n this.products.delete(id);\n }\n}\n\n// ── MockOrderService ──\n\nexport class MockOrderService implements OrderService {\n private orders = new Map<string, Order>();\n\n _addOrder(order: Order): void {\n this.orders.set(order.id, order);\n }\n\n _reset(): void {\n this.orders.clear();\n }\n\n async getOrder(id: string): Promise<Order | null> {\n return this.orders.get(id) ?? null;\n }\n\n async listOrders(options?: ListOptions): Promise<PaginatedResult<Order>> {\n const all = Array.from(this.orders.values());\n const limit = options?.limit ?? 50;\n const cursorIndex = options?.cursor\n ? all.findIndex((o) => o.id === options.cursor) + 1\n : 0;\n const items = all.slice(cursorIndex, cursorIndex + limit);\n const hasNextPage = cursorIndex + limit < all.length;\n const result: PaginatedResult<Order> = {\n items,\n hasNextPage,\n hasPreviousPage: cursorIndex > 0,\n };\n const lastOrderItem = items[items.length - 1];\n if (lastOrderItem && hasNextPage) {\n result.cursor = lastOrderItem.id;\n }\n result.totalCount = all.length;\n return result;\n }\n}\n\n// ── MockCustomerService ──\n\nexport class MockCustomerService implements CustomerService {\n private customers = new Map<string, Customer>();\n\n _addCustomer(customer: Customer): void {\n this.customers.set(customer.id, customer);\n }\n\n _reset(): void {\n this.customers.clear();\n }\n\n async getCustomer(id: string): Promise<Customer | null> {\n return this.customers.get(id) ?? null;\n }\n\n async listCustomers(\n options?: ListOptions,\n ): Promise<PaginatedResult<Customer>> {\n const all = Array.from(this.customers.values());\n const limit = options?.limit ?? 50;\n const cursorIndex = options?.cursor\n ? all.findIndex((c) => c.id === options.cursor) + 1\n : 0;\n const items = all.slice(cursorIndex, cursorIndex + limit);\n const hasNextPage = cursorIndex + limit < all.length;\n const result: PaginatedResult<Customer> = {\n items,\n hasNextPage,\n hasPreviousPage: cursorIndex > 0,\n };\n const lastCustItem = items[items.length - 1];\n if (lastCustItem && hasNextPage) {\n result.cursor = lastCustItem.id;\n }\n result.totalCount = all.length;\n return result;\n }\n\n async createCustomer(input: CreateCustomerInput): Promise<Customer> {\n const id = `cust-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const now = new Date().toISOString();\n const customer = createTestCustomer({\n id,\n platformId: id,\n email: input.email,\n createdAt: now,\n updatedAt: now,\n });\n if (input.firstName !== undefined) {\n customer.firstName = input.firstName;\n }\n if (input.lastName !== undefined) {\n customer.lastName = input.lastName;\n }\n if (input.phone !== undefined) {\n customer.phone = input.phone;\n }\n if (input.tags !== undefined) {\n customer.tags = input.tags;\n }\n if (input.metadata !== undefined) {\n customer.metadata = input.metadata;\n }\n this.customers.set(customer.id, customer);\n return customer;\n }\n\n async updateCustomer(\n id: string,\n input: UpdateCustomerInput,\n ): Promise<Customer> {\n const existing = this.customers.get(id);\n if (!existing) {\n throw new Error(`Customer not found: ${id}`);\n }\n const updated: Customer = {\n ...existing,\n updatedAt: new Date().toISOString(),\n };\n if (input.email !== undefined) {\n updated.email = input.email;\n }\n if (input.firstName !== undefined) {\n updated.firstName = input.firstName;\n }\n if (input.lastName !== undefined) {\n updated.lastName = input.lastName;\n }\n if (input.phone !== undefined) {\n updated.phone = input.phone;\n }\n if (input.tags !== undefined) {\n updated.tags = input.tags;\n }\n if (input.metadata !== undefined) {\n updated.metadata = input.metadata;\n }\n this.customers.set(id, updated);\n return updated;\n }\n\n async deleteCustomer(id: string): Promise<void> {\n if (!this.customers.has(id)) {\n throw new Error(`Customer not found: ${id}`);\n }\n this.customers.delete(id);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RBACService, ShopMember } from '@uniforge/platform-core/rbac';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mock RBACService for unit testing.
|
|
5
|
+
*
|
|
6
|
+
* Provides an in-memory implementation with internal Maps.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
type MockRBACService = RBACService & {
|
|
10
|
+
_members: Map<string, ShopMember>;
|
|
11
|
+
_reset(): void;
|
|
12
|
+
};
|
|
13
|
+
declare function createMockRBACService(): MockRBACService;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Test data factories for RBAC types.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare function createTestShopMember(overrides?: Partial<ShopMember>): ShopMember;
|
|
20
|
+
|
|
21
|
+
export { type MockRBACService, createMockRBACService, createTestShopMember };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RBACService, ShopMember } from '@uniforge/platform-core/rbac';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mock RBACService for unit testing.
|
|
5
|
+
*
|
|
6
|
+
* Provides an in-memory implementation with internal Maps.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
type MockRBACService = RBACService & {
|
|
10
|
+
_members: Map<string, ShopMember>;
|
|
11
|
+
_reset(): void;
|
|
12
|
+
};
|
|
13
|
+
declare function createMockRBACService(): MockRBACService;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Test data factories for RBAC types.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare function createTestShopMember(overrides?: Partial<ShopMember>): ShopMember;
|
|
20
|
+
|
|
21
|
+
export { type MockRBACService, createMockRBACService, createTestShopMember };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/rbac/index.ts
|
|
21
|
+
var rbac_exports = {};
|
|
22
|
+
__export(rbac_exports, {
|
|
23
|
+
createMockRBACService: () => createMockRBACService,
|
|
24
|
+
createTestShopMember: () => createTestShopMember
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(rbac_exports);
|
|
27
|
+
|
|
28
|
+
// src/rbac/mock-rbac-service.ts
|
|
29
|
+
var import_rbac = require("@uniforge/platform-core/rbac");
|
|
30
|
+
var MOCK_ROLE_PERMISSIONS = {
|
|
31
|
+
owner: [],
|
|
32
|
+
admin: [
|
|
33
|
+
"products:read",
|
|
34
|
+
"products:write",
|
|
35
|
+
"orders:read",
|
|
36
|
+
"orders:write",
|
|
37
|
+
"customers:read",
|
|
38
|
+
"customers:write",
|
|
39
|
+
"analytics:read",
|
|
40
|
+
"settings:read",
|
|
41
|
+
"settings:write",
|
|
42
|
+
"settings:manage",
|
|
43
|
+
"staff:read",
|
|
44
|
+
"staff:write"
|
|
45
|
+
],
|
|
46
|
+
staff: [
|
|
47
|
+
"products:read",
|
|
48
|
+
"products:write",
|
|
49
|
+
"orders:read",
|
|
50
|
+
"orders:write",
|
|
51
|
+
"customers:read",
|
|
52
|
+
"analytics:read",
|
|
53
|
+
"settings:read"
|
|
54
|
+
],
|
|
55
|
+
collaborator: [
|
|
56
|
+
"products:read",
|
|
57
|
+
"orders:read",
|
|
58
|
+
"analytics:read"
|
|
59
|
+
]
|
|
60
|
+
};
|
|
61
|
+
function makeKey(shopDomain, userId) {
|
|
62
|
+
return `${shopDomain}:${userId}`;
|
|
63
|
+
}
|
|
64
|
+
function createMockRBACService() {
|
|
65
|
+
const _members = /* @__PURE__ */ new Map();
|
|
66
|
+
function _reset() {
|
|
67
|
+
_members.clear();
|
|
68
|
+
}
|
|
69
|
+
async function upsertMember(input) {
|
|
70
|
+
const key = makeKey(input.shopDomain, input.userId);
|
|
71
|
+
const existing = _members.get(key);
|
|
72
|
+
const now = /* @__PURE__ */ new Date();
|
|
73
|
+
const member = {
|
|
74
|
+
id: existing?.id ?? `mock-member-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
75
|
+
shopDomain: input.shopDomain,
|
|
76
|
+
userId: input.userId,
|
|
77
|
+
email: input.email,
|
|
78
|
+
role: input.role,
|
|
79
|
+
customPermissions: input.customPermissions ?? null,
|
|
80
|
+
createdAt: existing?.createdAt ?? now,
|
|
81
|
+
updatedAt: now
|
|
82
|
+
};
|
|
83
|
+
_members.set(key, member);
|
|
84
|
+
return member;
|
|
85
|
+
}
|
|
86
|
+
async function getMember(shopDomain, userId) {
|
|
87
|
+
return _members.get(makeKey(shopDomain, userId)) ?? null;
|
|
88
|
+
}
|
|
89
|
+
async function listMembers(shopDomain) {
|
|
90
|
+
const result = [];
|
|
91
|
+
for (const member of _members.values()) {
|
|
92
|
+
if (member.shopDomain === shopDomain) {
|
|
93
|
+
result.push(member);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
async function updateMember(shopDomain, userId, input) {
|
|
99
|
+
const key = makeKey(shopDomain, userId);
|
|
100
|
+
const existing = _members.get(key);
|
|
101
|
+
if (!existing) {
|
|
102
|
+
throw new Error(`Member not found: ${shopDomain}:${userId}`);
|
|
103
|
+
}
|
|
104
|
+
if (input.role !== void 0) {
|
|
105
|
+
existing.role = input.role;
|
|
106
|
+
}
|
|
107
|
+
if (input.email !== void 0) {
|
|
108
|
+
existing.email = input.email;
|
|
109
|
+
}
|
|
110
|
+
if (input.customPermissions !== void 0) {
|
|
111
|
+
existing.customPermissions = input.customPermissions;
|
|
112
|
+
}
|
|
113
|
+
existing.updatedAt = /* @__PURE__ */ new Date();
|
|
114
|
+
return existing;
|
|
115
|
+
}
|
|
116
|
+
async function removeMember(shopDomain, userId) {
|
|
117
|
+
_members.delete(makeKey(shopDomain, userId));
|
|
118
|
+
}
|
|
119
|
+
async function hasPermission(shopDomain, userId, permission) {
|
|
120
|
+
const member = _members.get(makeKey(shopDomain, userId));
|
|
121
|
+
if (!member) return false;
|
|
122
|
+
if (member.role === "owner") return true;
|
|
123
|
+
const perms = resolvePerms(member.role, member.customPermissions);
|
|
124
|
+
return perms.includes(permission);
|
|
125
|
+
}
|
|
126
|
+
async function getEffectivePermissions(shopDomain, userId) {
|
|
127
|
+
const member = _members.get(makeKey(shopDomain, userId));
|
|
128
|
+
if (!member) return [];
|
|
129
|
+
if (member.role === "owner") return ["*"];
|
|
130
|
+
return resolvePerms(member.role, member.customPermissions);
|
|
131
|
+
}
|
|
132
|
+
function isRoleAtLeast(role, minimumRole) {
|
|
133
|
+
const roleIndex = import_rbac.ROLE_HIERARCHY.indexOf(role);
|
|
134
|
+
const minIndex = import_rbac.ROLE_HIERARCHY.indexOf(minimumRole);
|
|
135
|
+
if (roleIndex === -1 || minIndex === -1) return false;
|
|
136
|
+
return roleIndex <= minIndex;
|
|
137
|
+
}
|
|
138
|
+
function resolvePerms(role, custom) {
|
|
139
|
+
const rolePerms = MOCK_ROLE_PERMISSIONS[role] ?? [];
|
|
140
|
+
if (!custom || custom.length === 0) return [...rolePerms];
|
|
141
|
+
const combined = /* @__PURE__ */ new Set([...rolePerms, ...custom]);
|
|
142
|
+
return [...combined];
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
_members,
|
|
146
|
+
_reset,
|
|
147
|
+
upsertMember,
|
|
148
|
+
getMember,
|
|
149
|
+
listMembers,
|
|
150
|
+
updateMember,
|
|
151
|
+
removeMember,
|
|
152
|
+
hasPermission,
|
|
153
|
+
getEffectivePermissions,
|
|
154
|
+
isRoleAtLeast
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/rbac/factories.ts
|
|
159
|
+
function createTestShopMember(overrides) {
|
|
160
|
+
const now = /* @__PURE__ */ new Date();
|
|
161
|
+
const defaults = {
|
|
162
|
+
id: `member-${Date.now()}`,
|
|
163
|
+
shopDomain: "test-shop.myshopify.com",
|
|
164
|
+
userId: 12345,
|
|
165
|
+
email: "staff@test-shop.com",
|
|
166
|
+
role: "staff",
|
|
167
|
+
customPermissions: null,
|
|
168
|
+
createdAt: now,
|
|
169
|
+
updatedAt: now
|
|
170
|
+
};
|
|
171
|
+
return { ...defaults, ...overrides };
|
|
172
|
+
}
|
|
173
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
174
|
+
0 && (module.exports = {
|
|
175
|
+
createMockRBACService,
|
|
176
|
+
createTestShopMember
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/rbac/index.ts","../../src/rbac/mock-rbac-service.ts","../../src/rbac/factories.ts"],"sourcesContent":["/**\n * @uniforge/testing - RBAC\n *\n * Mock RBAC service and test data factories.\n */\n\nexport { createMockRBACService } from './mock-rbac-service.js';\nexport type { MockRBACService } from './mock-rbac-service.js';\nexport { createTestShopMember } from './factories.js';\n","/**\n * Mock RBACService for unit testing.\n *\n * Provides an in-memory implementation with internal Maps.\n */\n\nimport type {\n RBACService,\n Role,\n ShopMember,\n UpsertShopMemberInput,\n UpdateShopMemberInput,\n} from '@uniforge/platform-core/rbac';\nimport { ROLE_HIERARCHY } from '@uniforge/platform-core/rbac';\n\nexport type MockRBACService = RBACService & {\n _members: Map<string, ShopMember>;\n _reset(): void;\n};\n\n// Default permissions for each role (mirrors core implementation)\nconst MOCK_ROLE_PERMISSIONS: Record<Role, string[]> = {\n owner: [],\n admin: [\n 'products:read', 'products:write',\n 'orders:read', 'orders:write',\n 'customers:read', 'customers:write',\n 'analytics:read',\n 'settings:read', 'settings:write', 'settings:manage',\n 'staff:read', 'staff:write',\n ],\n staff: [\n 'products:read', 'products:write',\n 'orders:read', 'orders:write',\n 'customers:read',\n 'analytics:read',\n 'settings:read',\n ],\n collaborator: [\n 'products:read',\n 'orders:read',\n 'analytics:read',\n ],\n};\n\nfunction makeKey(shopDomain: string, userId: number): string {\n return `${shopDomain}:${userId}`;\n}\n\nexport function createMockRBACService(): MockRBACService {\n const _members = new Map<string, ShopMember>();\n\n function _reset(): void {\n _members.clear();\n }\n\n async function upsertMember(input: UpsertShopMemberInput): Promise<ShopMember> {\n const key = makeKey(input.shopDomain, input.userId);\n const existing = _members.get(key);\n const now = new Date();\n const member: ShopMember = {\n id: existing?.id ?? `mock-member-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n shopDomain: input.shopDomain,\n userId: input.userId,\n email: input.email,\n role: input.role,\n customPermissions: input.customPermissions ?? null,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n };\n _members.set(key, member);\n return member;\n }\n\n async function getMember(shopDomain: string, userId: number): Promise<ShopMember | null> {\n return _members.get(makeKey(shopDomain, userId)) ?? null;\n }\n\n async function listMembers(shopDomain: string): Promise<ShopMember[]> {\n const result: ShopMember[] = [];\n for (const member of _members.values()) {\n if (member.shopDomain === shopDomain) {\n result.push(member);\n }\n }\n return result;\n }\n\n async function updateMember(\n shopDomain: string,\n userId: number,\n input: UpdateShopMemberInput,\n ): Promise<ShopMember> {\n const key = makeKey(shopDomain, userId);\n const existing = _members.get(key);\n if (!existing) {\n throw new Error(`Member not found: ${shopDomain}:${userId}`);\n }\n if (input.role !== undefined) {\n existing.role = input.role;\n }\n if (input.email !== undefined) {\n existing.email = input.email;\n }\n if (input.customPermissions !== undefined) {\n existing.customPermissions = input.customPermissions;\n }\n existing.updatedAt = new Date();\n return existing;\n }\n\n async function removeMember(shopDomain: string, userId: number): Promise<void> {\n _members.delete(makeKey(shopDomain, userId));\n }\n\n async function hasPermission(\n shopDomain: string,\n userId: number,\n permission: string,\n ): Promise<boolean> {\n const member = _members.get(makeKey(shopDomain, userId));\n if (!member) return false;\n if (member.role === 'owner') return true;\n const perms = resolvePerms(member.role, member.customPermissions);\n return perms.includes(permission);\n }\n\n async function getEffectivePermissions(\n shopDomain: string,\n userId: number,\n ): Promise<string[]> {\n const member = _members.get(makeKey(shopDomain, userId));\n if (!member) return [];\n if (member.role === 'owner') return ['*'];\n return resolvePerms(member.role, member.customPermissions);\n }\n\n function isRoleAtLeast(role: Role, minimumRole: Role): boolean {\n const roleIndex = ROLE_HIERARCHY.indexOf(role);\n const minIndex = ROLE_HIERARCHY.indexOf(minimumRole);\n if (roleIndex === -1 || minIndex === -1) return false;\n return roleIndex <= minIndex;\n }\n\n function resolvePerms(role: Role, custom: string[] | null): string[] {\n const rolePerms = MOCK_ROLE_PERMISSIONS[role] ?? [];\n if (!custom || custom.length === 0) return [...rolePerms];\n const combined = new Set([...rolePerms, ...custom]);\n return [...combined];\n }\n\n return {\n _members,\n _reset,\n upsertMember,\n getMember,\n listMembers,\n updateMember,\n removeMember,\n hasPermission,\n getEffectivePermissions,\n isRoleAtLeast,\n };\n}\n","/**\n * Test data factories for RBAC types.\n */\n\nimport type { ShopMember } from '@uniforge/platform-core/rbac';\n\nexport function createTestShopMember(overrides?: Partial<ShopMember>): ShopMember {\n const now = new Date();\n const defaults: ShopMember = {\n id: `member-${Date.now()}`,\n shopDomain: 'test-shop.myshopify.com',\n userId: 12345,\n email: 'staff@test-shop.com',\n role: 'staff',\n customPermissions: null,\n createdAt: now,\n updatedAt: now,\n };\n return { ...defaults, ...overrides };\n}\n"],"mappings":"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","names":[]}
|