@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,459 @@
|
|
|
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/auth/index.ts
|
|
21
|
+
var auth_exports = {};
|
|
22
|
+
__export(auth_exports, {
|
|
23
|
+
AuthFlowSimulator: () => AuthFlowSimulator,
|
|
24
|
+
MemorySessionStorage: () => MemorySessionStorage,
|
|
25
|
+
SessionFixtureBuilder: () => SessionFixtureBuilder,
|
|
26
|
+
computeShopifyHmac: () => computeShopifyHmac,
|
|
27
|
+
computeWebhookHmac: () => computeWebhookHmac,
|
|
28
|
+
createMockAuthEvent: () => createMockAuthEvent,
|
|
29
|
+
createMockSession: () => createMockSession,
|
|
30
|
+
createMockShop: () => createMockShop,
|
|
31
|
+
createSignedQueryString: () => createSignedQueryString,
|
|
32
|
+
createSignedUrl: () => createSignedUrl,
|
|
33
|
+
mockOAuthCallbackResponse: () => mockOAuthCallbackResponse,
|
|
34
|
+
mockOnlineTokenExchangeResponse: () => mockOnlineTokenExchangeResponse,
|
|
35
|
+
mockRefreshTokenResponse: () => mockRefreshTokenResponse,
|
|
36
|
+
mockTokenExchangeResponse: () => mockTokenExchangeResponse,
|
|
37
|
+
verifyHmac: () => verifyHmac
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(auth_exports);
|
|
40
|
+
|
|
41
|
+
// src/auth/mock-session-storage.ts
|
|
42
|
+
var MemorySessionStorage = class {
|
|
43
|
+
sessions = /* @__PURE__ */ new Map();
|
|
44
|
+
async storeSession(session) {
|
|
45
|
+
this.sessions.set(session.id, { ...session });
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
async loadSession(id) {
|
|
49
|
+
const session = this.sessions.get(id);
|
|
50
|
+
return session ? { ...session } : void 0;
|
|
51
|
+
}
|
|
52
|
+
async deleteSession(id) {
|
|
53
|
+
return this.sessions.delete(id);
|
|
54
|
+
}
|
|
55
|
+
async deleteSessions(ids) {
|
|
56
|
+
for (const id of ids) {
|
|
57
|
+
this.sessions.delete(id);
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
async findSessionsByShop(shop) {
|
|
62
|
+
const results = [];
|
|
63
|
+
for (const session of this.sessions.values()) {
|
|
64
|
+
if (session.shop === shop) {
|
|
65
|
+
results.push({ ...session });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
clear() {
|
|
71
|
+
this.sessions.clear();
|
|
72
|
+
}
|
|
73
|
+
get size() {
|
|
74
|
+
return this.sessions.size;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/auth/factories.ts
|
|
79
|
+
function createMockSession(overrides = {}) {
|
|
80
|
+
const now = /* @__PURE__ */ new Date();
|
|
81
|
+
return {
|
|
82
|
+
id: "offline_test-shop.myshopify.com",
|
|
83
|
+
shop: "test-shop.myshopify.com",
|
|
84
|
+
state: "test-state-nonce",
|
|
85
|
+
isOnline: false,
|
|
86
|
+
scope: "read_products,write_orders",
|
|
87
|
+
expires: null,
|
|
88
|
+
accessToken: "shpat_test_token",
|
|
89
|
+
createdAt: now,
|
|
90
|
+
updatedAt: now,
|
|
91
|
+
...overrides
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function createMockShop(overrides = {}) {
|
|
95
|
+
const now = /* @__PURE__ */ new Date();
|
|
96
|
+
return {
|
|
97
|
+
shopDomain: "test-shop.myshopify.com",
|
|
98
|
+
isInstalled: true,
|
|
99
|
+
installedAt: now,
|
|
100
|
+
uninstalledAt: null,
|
|
101
|
+
scopes: "read_products,write_orders",
|
|
102
|
+
shopifyPlan: "basic",
|
|
103
|
+
createdAt: now,
|
|
104
|
+
updatedAt: now,
|
|
105
|
+
...overrides
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function createMockAuthEvent(overrides = {}) {
|
|
109
|
+
const now = /* @__PURE__ */ new Date();
|
|
110
|
+
return {
|
|
111
|
+
id: "00000000-0000-4000-a000-000000000001",
|
|
112
|
+
type: "session_created",
|
|
113
|
+
shopDomain: "test-shop.myshopify.com",
|
|
114
|
+
sessionId: "offline_test-shop.myshopify.com",
|
|
115
|
+
userId: null,
|
|
116
|
+
outcome: "success",
|
|
117
|
+
metadata: {},
|
|
118
|
+
timestamp: now,
|
|
119
|
+
...overrides
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/auth/mock-shopify-api.ts
|
|
124
|
+
function mockTokenExchangeResponse(overrides = {}) {
|
|
125
|
+
return {
|
|
126
|
+
access_token: "shpat_test_exchanged_token",
|
|
127
|
+
scope: "read_products,write_orders",
|
|
128
|
+
...overrides
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function mockOnlineTokenExchangeResponse(overrides = {}) {
|
|
132
|
+
return {
|
|
133
|
+
access_token: "shpat_test_online_token",
|
|
134
|
+
scope: "read_products,write_orders",
|
|
135
|
+
expires_in: 86400,
|
|
136
|
+
associated_user_scope: "read_products",
|
|
137
|
+
associated_user: {
|
|
138
|
+
id: 12345,
|
|
139
|
+
first_name: "Test",
|
|
140
|
+
last_name: "User",
|
|
141
|
+
email: "test@example.com",
|
|
142
|
+
email_verified: true,
|
|
143
|
+
account_owner: true,
|
|
144
|
+
locale: "en",
|
|
145
|
+
collaborator: false
|
|
146
|
+
},
|
|
147
|
+
...overrides
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function mockOAuthCallbackResponse(overrides = {}) {
|
|
151
|
+
return {
|
|
152
|
+
access_token: "shpat_test_oauth_token",
|
|
153
|
+
scope: "read_products,write_orders",
|
|
154
|
+
...overrides
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function mockRefreshTokenResponse(overrides = {}) {
|
|
158
|
+
return {
|
|
159
|
+
access_token: "shpat_test_refreshed_token",
|
|
160
|
+
refresh_token: "shprt_test_new_refresh_token",
|
|
161
|
+
expires_in: 3600,
|
|
162
|
+
scope: "read_products,write_orders",
|
|
163
|
+
...overrides
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/auth/session-fixture-builder.ts
|
|
168
|
+
var SessionFixtureBuilder = class _SessionFixtureBuilder {
|
|
169
|
+
data;
|
|
170
|
+
constructor(shop, isOnline, userId) {
|
|
171
|
+
const now = /* @__PURE__ */ new Date();
|
|
172
|
+
const id = isOnline ? `online_${shop}_${userId ?? 1}` : `offline_${shop}`;
|
|
173
|
+
this.data = {
|
|
174
|
+
id,
|
|
175
|
+
shop,
|
|
176
|
+
state: "test-state-nonce",
|
|
177
|
+
isOnline,
|
|
178
|
+
scope: "read_products,write_orders",
|
|
179
|
+
expires: null,
|
|
180
|
+
accessToken: "shpat_test_token",
|
|
181
|
+
createdAt: now,
|
|
182
|
+
updatedAt: now
|
|
183
|
+
};
|
|
184
|
+
if (isOnline && userId !== void 0) {
|
|
185
|
+
this.data.onlineAccessInfo = {
|
|
186
|
+
expiresIn: 86400,
|
|
187
|
+
associatedUserScope: "read_products",
|
|
188
|
+
associatedUser: {
|
|
189
|
+
id: userId,
|
|
190
|
+
firstName: "Test",
|
|
191
|
+
lastName: "User",
|
|
192
|
+
email: "test@example.com",
|
|
193
|
+
emailVerified: true,
|
|
194
|
+
accountOwner: true,
|
|
195
|
+
locale: "en",
|
|
196
|
+
collaborator: false
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
static offline(shop = "test-shop.myshopify.com") {
|
|
202
|
+
return new _SessionFixtureBuilder(shop, false);
|
|
203
|
+
}
|
|
204
|
+
static online(shop = "test-shop.myshopify.com", userId = 1) {
|
|
205
|
+
return new _SessionFixtureBuilder(shop, true, userId);
|
|
206
|
+
}
|
|
207
|
+
withAccessToken(token) {
|
|
208
|
+
this.data.accessToken = token;
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
withScopes(scopes) {
|
|
212
|
+
this.data.scope = Array.isArray(scopes) ? scopes.join(",") : scopes;
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
expired(minutesAgo = 60) {
|
|
216
|
+
const past = /* @__PURE__ */ new Date();
|
|
217
|
+
past.setMinutes(past.getMinutes() - minutesAgo);
|
|
218
|
+
this.data.expires = past;
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
expiringSoon(minutesUntil = 5) {
|
|
222
|
+
const soon = /* @__PURE__ */ new Date();
|
|
223
|
+
soon.setMinutes(soon.getMinutes() + minutesUntil);
|
|
224
|
+
this.data.expires = soon;
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
valid(hoursUntil = 24) {
|
|
228
|
+
const future = /* @__PURE__ */ new Date();
|
|
229
|
+
future.setHours(future.getHours() + hoursUntil);
|
|
230
|
+
this.data.expires = future;
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
withRefreshToken(token, expiresAt) {
|
|
234
|
+
this.data.refreshToken = token;
|
|
235
|
+
if (expiresAt !== void 0) {
|
|
236
|
+
this.data.refreshTokenExpiresAt = expiresAt;
|
|
237
|
+
}
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
240
|
+
withOnlineAccessInfo(info) {
|
|
241
|
+
const existing = this.data.onlineAccessInfo ?? {
|
|
242
|
+
expiresIn: 86400,
|
|
243
|
+
associatedUserScope: "read_products",
|
|
244
|
+
associatedUser: {
|
|
245
|
+
id: 1,
|
|
246
|
+
firstName: "Test",
|
|
247
|
+
lastName: "User",
|
|
248
|
+
email: "test@example.com",
|
|
249
|
+
emailVerified: true,
|
|
250
|
+
accountOwner: true,
|
|
251
|
+
locale: "en",
|
|
252
|
+
collaborator: false
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
this.data.onlineAccessInfo = { ...existing, ...info };
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
258
|
+
withState(state) {
|
|
259
|
+
this.data.state = state;
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
262
|
+
withId(id) {
|
|
263
|
+
this.data.id = id;
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
build() {
|
|
267
|
+
return { ...this.data };
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// src/auth/hmac-helper.ts
|
|
272
|
+
var import_node_crypto = require("crypto");
|
|
273
|
+
function computeShopifyHmac(params, secret) {
|
|
274
|
+
const sorted = Object.keys(params).filter((k) => k !== "hmac").sort().map((k) => `${k}=${params[k]}`).join("&");
|
|
275
|
+
return (0, import_node_crypto.createHmac)("sha256", secret).update(sorted).digest("hex");
|
|
276
|
+
}
|
|
277
|
+
function computeWebhookHmac(body, secret) {
|
|
278
|
+
return (0, import_node_crypto.createHmac)("sha256", secret).update(body).digest("base64");
|
|
279
|
+
}
|
|
280
|
+
function verifyHmac(computed, provided) {
|
|
281
|
+
const computedBuf = Buffer.from(computed, "utf-8");
|
|
282
|
+
const providedBuf = Buffer.from(provided, "utf-8");
|
|
283
|
+
if (computedBuf.length !== providedBuf.length) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
return (0, import_node_crypto.timingSafeEqual)(computedBuf, providedBuf);
|
|
287
|
+
}
|
|
288
|
+
function createSignedQueryString(params, secret) {
|
|
289
|
+
const hmac = computeShopifyHmac(params, secret);
|
|
290
|
+
const sorted = Object.keys(params).filter((k) => k !== "hmac").sort().map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`).join("&");
|
|
291
|
+
return `${sorted}&hmac=${hmac}`;
|
|
292
|
+
}
|
|
293
|
+
function createSignedUrl(baseUrl, params, secret) {
|
|
294
|
+
const queryString = createSignedQueryString(params, secret);
|
|
295
|
+
const separator = baseUrl.includes("?") ? "&" : "?";
|
|
296
|
+
return `${baseUrl}${separator}${queryString}`;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// src/auth/auth-flow-simulator.ts
|
|
300
|
+
var import_node_crypto2 = require("crypto");
|
|
301
|
+
var DEFAULT_CONFIG = {
|
|
302
|
+
apiKey: "test-api-key",
|
|
303
|
+
apiSecretKey: "test-api-secret",
|
|
304
|
+
scopes: ["read_products", "write_orders"],
|
|
305
|
+
hostName: "test-app.example.com"
|
|
306
|
+
};
|
|
307
|
+
var AuthFlowSimulator = class {
|
|
308
|
+
config;
|
|
309
|
+
constructor(config) {
|
|
310
|
+
this.config = { ...DEFAULT_CONFIG };
|
|
311
|
+
if (config) {
|
|
312
|
+
if (config.apiKey !== void 0) {
|
|
313
|
+
this.config.apiKey = config.apiKey;
|
|
314
|
+
}
|
|
315
|
+
if (config.apiSecretKey !== void 0) {
|
|
316
|
+
this.config.apiSecretKey = config.apiSecretKey;
|
|
317
|
+
}
|
|
318
|
+
if (config.scopes !== void 0) {
|
|
319
|
+
this.config.scopes = config.scopes;
|
|
320
|
+
}
|
|
321
|
+
if (config.hostName !== void 0) {
|
|
322
|
+
this.config.hostName = config.hostName;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
simulateTokenExchange(shopDomain, options) {
|
|
327
|
+
const isOnline = options?.isOnline ?? false;
|
|
328
|
+
const userId = options?.userId ?? 1;
|
|
329
|
+
const scopes = options?.scopes ?? this.config.scopes;
|
|
330
|
+
const accessToken = options?.accessToken ?? "shpat_test_exchanged_token";
|
|
331
|
+
const now = /* @__PURE__ */ new Date();
|
|
332
|
+
const expires = new Date(now.getTime() + 86400 * 1e3);
|
|
333
|
+
const id = isOnline ? `online_${shopDomain}_${userId}` : `offline_${shopDomain}`;
|
|
334
|
+
const session = {
|
|
335
|
+
id,
|
|
336
|
+
shop: shopDomain,
|
|
337
|
+
state: (0, import_node_crypto2.randomUUID)(),
|
|
338
|
+
isOnline,
|
|
339
|
+
scope: scopes.join(","),
|
|
340
|
+
expires: isOnline ? expires : null,
|
|
341
|
+
accessToken,
|
|
342
|
+
createdAt: now,
|
|
343
|
+
updatedAt: now
|
|
344
|
+
};
|
|
345
|
+
if (isOnline) {
|
|
346
|
+
session.onlineAccessInfo = {
|
|
347
|
+
expiresIn: 86400,
|
|
348
|
+
associatedUserScope: scopes.join(","),
|
|
349
|
+
associatedUser: {
|
|
350
|
+
id: userId,
|
|
351
|
+
firstName: "Test",
|
|
352
|
+
lastName: "User",
|
|
353
|
+
email: "test@example.com",
|
|
354
|
+
emailVerified: true,
|
|
355
|
+
accountOwner: true,
|
|
356
|
+
locale: "en",
|
|
357
|
+
collaborator: false
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
const shopContext = {
|
|
362
|
+
shopDomain,
|
|
363
|
+
accessToken,
|
|
364
|
+
scopes,
|
|
365
|
+
session
|
|
366
|
+
};
|
|
367
|
+
return { session, shopContext };
|
|
368
|
+
}
|
|
369
|
+
simulateOAuthFlow(shopDomain, options) {
|
|
370
|
+
const scopes = options?.scopes ?? this.config.scopes;
|
|
371
|
+
const state = (0, import_node_crypto2.randomUUID)();
|
|
372
|
+
const authCode = `auth_code_${(0, import_node_crypto2.randomUUID)().slice(0, 8)}`;
|
|
373
|
+
const authorizeUrl = `https://${shopDomain}/admin/oauth/authorize?client_id=${this.config.apiKey}&scope=${scopes.join(",")}&redirect_uri=https://${this.config.hostName}/auth/callback&state=${state}`;
|
|
374
|
+
const exchangeOptions = {
|
|
375
|
+
scopes,
|
|
376
|
+
accessToken: "shpat_test_oauth_token"
|
|
377
|
+
};
|
|
378
|
+
if (options?.isOnline !== void 0) {
|
|
379
|
+
exchangeOptions.isOnline = options.isOnline;
|
|
380
|
+
}
|
|
381
|
+
if (options?.userId !== void 0) {
|
|
382
|
+
exchangeOptions.userId = options.userId;
|
|
383
|
+
}
|
|
384
|
+
const { session: callbackSession, shopContext } = this.simulateTokenExchange(shopDomain, exchangeOptions);
|
|
385
|
+
return { authorizeUrl, authCode, callbackSession, shopContext };
|
|
386
|
+
}
|
|
387
|
+
simulateTokenRefresh(session, options) {
|
|
388
|
+
const now = /* @__PURE__ */ new Date();
|
|
389
|
+
const expires = new Date(now.getTime() + 86400 * 1e3);
|
|
390
|
+
const refreshed = {
|
|
391
|
+
...session,
|
|
392
|
+
accessToken: options?.newAccessToken ?? "shpat_test_refreshed_token",
|
|
393
|
+
expires,
|
|
394
|
+
updatedAt: now
|
|
395
|
+
};
|
|
396
|
+
if (options?.newRefreshToken !== void 0) {
|
|
397
|
+
refreshed.refreshToken = options.newRefreshToken;
|
|
398
|
+
refreshed.refreshTokenExpiresAt = new Date(
|
|
399
|
+
now.getTime() + 7 * 86400 * 1e3
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
if (options?.newScopes !== void 0) {
|
|
403
|
+
refreshed.scope = options.newScopes.join(",");
|
|
404
|
+
}
|
|
405
|
+
return refreshed;
|
|
406
|
+
}
|
|
407
|
+
createExpiredSession(shopDomain, options) {
|
|
408
|
+
const minutesAgo = options?.expiredMinutesAgo ?? 60;
|
|
409
|
+
const now = /* @__PURE__ */ new Date();
|
|
410
|
+
const expiredAt = new Date(now.getTime() - minutesAgo * 60 * 1e3);
|
|
411
|
+
const isOnline = options?.isOnline ?? false;
|
|
412
|
+
const id = isOnline ? `online_${shopDomain}_1` : `offline_${shopDomain}`;
|
|
413
|
+
return {
|
|
414
|
+
id,
|
|
415
|
+
shop: shopDomain,
|
|
416
|
+
state: "expired-state",
|
|
417
|
+
isOnline,
|
|
418
|
+
scope: this.config.scopes.join(","),
|
|
419
|
+
expires: expiredAt,
|
|
420
|
+
accessToken: "shpat_expired_token",
|
|
421
|
+
createdAt: new Date(expiredAt.getTime() - 86400 * 1e3),
|
|
422
|
+
updatedAt: expiredAt
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
generateAuthEvent(type, shopDomain, options) {
|
|
426
|
+
return {
|
|
427
|
+
id: (0, import_node_crypto2.randomUUID)(),
|
|
428
|
+
type,
|
|
429
|
+
shopDomain,
|
|
430
|
+
sessionId: options?.sessionId ?? `offline_${shopDomain}`,
|
|
431
|
+
userId: options?.userId ?? null,
|
|
432
|
+
outcome: options?.outcome ?? "success",
|
|
433
|
+
metadata: options?.metadata ?? {},
|
|
434
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
get secret() {
|
|
438
|
+
return this.config.apiSecretKey;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
442
|
+
0 && (module.exports = {
|
|
443
|
+
AuthFlowSimulator,
|
|
444
|
+
MemorySessionStorage,
|
|
445
|
+
SessionFixtureBuilder,
|
|
446
|
+
computeShopifyHmac,
|
|
447
|
+
computeWebhookHmac,
|
|
448
|
+
createMockAuthEvent,
|
|
449
|
+
createMockSession,
|
|
450
|
+
createMockShop,
|
|
451
|
+
createSignedQueryString,
|
|
452
|
+
createSignedUrl,
|
|
453
|
+
mockOAuthCallbackResponse,
|
|
454
|
+
mockOnlineTokenExchangeResponse,
|
|
455
|
+
mockRefreshTokenResponse,
|
|
456
|
+
mockTokenExchangeResponse,
|
|
457
|
+
verifyHmac
|
|
458
|
+
});
|
|
459
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/index.ts","../../src/auth/mock-session-storage.ts","../../src/auth/factories.ts","../../src/auth/mock-shopify-api.ts","../../src/auth/session-fixture-builder.ts","../../src/auth/hmac-helper.ts","../../src/auth/auth-flow-simulator.ts"],"sourcesContent":["/**\n * @uniforge/testing - Authentication\n *\n * Mock implementations and test factories for authentication testing.\n */\n\n// Mock session storage\nexport { MemorySessionStorage } from './mock-session-storage';\n\n// Test data factories\nexport {\n createMockSession,\n createMockShop,\n createMockAuthEvent,\n} from './factories';\n\n// Shopify API response mocks\nexport {\n mockTokenExchangeResponse,\n mockOnlineTokenExchangeResponse,\n mockOAuthCallbackResponse,\n mockRefreshTokenResponse,\n} from './mock-shopify-api';\nexport type {\n MockTokenExchangeResponse,\n MockOAuthCallbackResponse,\n MockRefreshTokenResponse,\n} from './mock-shopify-api';\n\n// Session fixture builder\nexport { SessionFixtureBuilder } from './session-fixture-builder';\n\n// HMAC helpers\nexport {\n computeShopifyHmac,\n computeWebhookHmac,\n verifyHmac,\n createSignedQueryString,\n createSignedUrl,\n} from './hmac-helper';\n\n// Auth flow simulator\nexport { AuthFlowSimulator } from './auth-flow-simulator';\nexport type {\n AuthFlowSimulatorConfig,\n TokenExchangeResult,\n OAuthFlowResult,\n} from './auth-flow-simulator';\n","/**\n * In-memory session storage for testing.\n */\n\nimport type {\n Session,\n SessionStorage,\n} from '@uniforge/platform-core/auth';\n\nexport class MemorySessionStorage implements SessionStorage {\n private sessions = new Map<string, Session>();\n\n async storeSession(session: Session): Promise<boolean> {\n this.sessions.set(session.id, { ...session });\n return true;\n }\n\n async loadSession(id: string): Promise<Session | undefined> {\n const session = this.sessions.get(id);\n return session ? { ...session } : undefined;\n }\n\n async deleteSession(id: string): Promise<boolean> {\n return this.sessions.delete(id);\n }\n\n async deleteSessions(ids: string[]): Promise<boolean> {\n for (const id of ids) {\n this.sessions.delete(id);\n }\n return true;\n }\n\n async findSessionsByShop(shop: string): Promise<Session[]> {\n const results: Session[] = [];\n for (const session of this.sessions.values()) {\n if (session.shop === shop) {\n results.push({ ...session });\n }\n }\n return results;\n }\n\n clear(): void {\n this.sessions.clear();\n }\n\n get size(): number {\n return this.sessions.size;\n }\n}\n","/**\n * Test data factories for authentication types.\n *\n * Each factory provides sensible defaults that can be overridden.\n */\n\nimport type {\n Session,\n Shop,\n AuthEvent,\n AuthEventType,\n} from '@uniforge/platform-core/auth';\n\nexport function createMockSession(overrides: Partial<Session> = {}): Session {\n const now = new Date();\n return {\n id: 'offline_test-shop.myshopify.com',\n shop: 'test-shop.myshopify.com',\n state: 'test-state-nonce',\n isOnline: false,\n scope: 'read_products,write_orders',\n expires: null,\n accessToken: 'shpat_test_token',\n createdAt: now,\n updatedAt: now,\n ...overrides,\n };\n}\n\nexport function createMockShop(overrides: Partial<Shop> = {}): Shop {\n const now = new Date();\n return {\n shopDomain: 'test-shop.myshopify.com',\n isInstalled: true,\n installedAt: now,\n uninstalledAt: null,\n scopes: 'read_products,write_orders',\n shopifyPlan: 'basic',\n createdAt: now,\n updatedAt: now,\n ...overrides,\n };\n}\n\nexport function createMockAuthEvent(\n overrides: Partial<AuthEvent> = {},\n): AuthEvent {\n const now = new Date();\n return {\n id: '00000000-0000-4000-a000-000000000001',\n type: 'session_created' as AuthEventType,\n shopDomain: 'test-shop.myshopify.com',\n sessionId: 'offline_test-shop.myshopify.com',\n userId: null,\n outcome: 'success',\n metadata: {},\n timestamp: now,\n ...overrides,\n };\n}\n","/**\n * Mock Shopify API response factories for testing.\n *\n * These mocks simulate Shopify API responses for token exchange,\n * OAuth callback, and token refresh flows.\n */\n\nexport interface MockTokenExchangeResponse {\n access_token: string;\n scope: string;\n expires_in?: number;\n associated_user_scope?: string;\n associated_user?: {\n id: number;\n first_name: string;\n last_name: string;\n email: string;\n email_verified: boolean;\n account_owner: boolean;\n locale: string;\n collaborator: boolean;\n };\n}\n\nexport interface MockOAuthCallbackResponse {\n access_token: string;\n scope: string;\n}\n\nexport interface MockRefreshTokenResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n scope: string;\n}\n\nexport function mockTokenExchangeResponse(\n overrides: Partial<MockTokenExchangeResponse> = {},\n): MockTokenExchangeResponse {\n return {\n access_token: 'shpat_test_exchanged_token',\n scope: 'read_products,write_orders',\n ...overrides,\n };\n}\n\nexport function mockOnlineTokenExchangeResponse(\n overrides: Partial<MockTokenExchangeResponse> = {},\n): MockTokenExchangeResponse {\n return {\n access_token: 'shpat_test_online_token',\n scope: 'read_products,write_orders',\n expires_in: 86400,\n associated_user_scope: 'read_products',\n associated_user: {\n id: 12345,\n first_name: 'Test',\n last_name: 'User',\n email: 'test@example.com',\n email_verified: true,\n account_owner: true,\n locale: 'en',\n collaborator: false,\n },\n ...overrides,\n };\n}\n\nexport function mockOAuthCallbackResponse(\n overrides: Partial<MockOAuthCallbackResponse> = {},\n): MockOAuthCallbackResponse {\n return {\n access_token: 'shpat_test_oauth_token',\n scope: 'read_products,write_orders',\n ...overrides,\n };\n}\n\nexport function mockRefreshTokenResponse(\n overrides: Partial<MockRefreshTokenResponse> = {},\n): MockRefreshTokenResponse {\n return {\n access_token: 'shpat_test_refreshed_token',\n refresh_token: 'shprt_test_new_refresh_token',\n expires_in: 3600,\n scope: 'read_products,write_orders',\n ...overrides,\n };\n}\n","/**\n * Fluent builder for creating session test fixtures in various states.\n *\n * Provides a chainable API for constructing Session objects with\n * controlled expiry, tokens, and online access information.\n */\n\nimport type {\n Session,\n OnlineAccessInfo,\n AssociatedUser,\n} from '@uniforge/platform-core/auth';\n\nexport class SessionFixtureBuilder {\n private data: Record<string, unknown>;\n\n private constructor(shop: string, isOnline: boolean, userId?: number) {\n const now = new Date();\n const id = isOnline\n ? `online_${shop}_${userId ?? 1}`\n : `offline_${shop}`;\n\n this.data = {\n id,\n shop,\n state: 'test-state-nonce',\n isOnline,\n scope: 'read_products,write_orders',\n expires: null,\n accessToken: 'shpat_test_token',\n createdAt: now,\n updatedAt: now,\n };\n\n if (isOnline && userId !== undefined) {\n this.data.onlineAccessInfo = {\n expiresIn: 86400,\n associatedUserScope: 'read_products',\n associatedUser: {\n id: userId,\n firstName: 'Test',\n lastName: 'User',\n email: 'test@example.com',\n emailVerified: true,\n accountOwner: true,\n locale: 'en',\n collaborator: false,\n } satisfies AssociatedUser,\n } satisfies OnlineAccessInfo;\n }\n }\n\n static offline(shop = 'test-shop.myshopify.com'): SessionFixtureBuilder {\n return new SessionFixtureBuilder(shop, false);\n }\n\n static online(\n shop = 'test-shop.myshopify.com',\n userId = 1,\n ): SessionFixtureBuilder {\n return new SessionFixtureBuilder(shop, true, userId);\n }\n\n withAccessToken(token: string): this {\n this.data.accessToken = token;\n return this;\n }\n\n withScopes(scopes: string[] | string): this {\n this.data.scope = Array.isArray(scopes) ? scopes.join(',') : scopes;\n return this;\n }\n\n expired(minutesAgo = 60): this {\n const past = new Date();\n past.setMinutes(past.getMinutes() - minutesAgo);\n this.data.expires = past;\n return this;\n }\n\n expiringSoon(minutesUntil = 5): this {\n const soon = new Date();\n soon.setMinutes(soon.getMinutes() + minutesUntil);\n this.data.expires = soon;\n return this;\n }\n\n valid(hoursUntil = 24): this {\n const future = new Date();\n future.setHours(future.getHours() + hoursUntil);\n this.data.expires = future;\n return this;\n }\n\n withRefreshToken(token: string, expiresAt?: Date): this {\n this.data.refreshToken = token;\n if (expiresAt !== undefined) {\n this.data.refreshTokenExpiresAt = expiresAt;\n }\n return this;\n }\n\n withOnlineAccessInfo(info: Partial<OnlineAccessInfo>): this {\n const existing = (this.data.onlineAccessInfo as OnlineAccessInfo) ?? {\n expiresIn: 86400,\n associatedUserScope: 'read_products',\n associatedUser: {\n id: 1,\n firstName: 'Test',\n lastName: 'User',\n email: 'test@example.com',\n emailVerified: true,\n accountOwner: true,\n locale: 'en',\n collaborator: false,\n } satisfies AssociatedUser,\n };\n this.data.onlineAccessInfo = { ...existing, ...info };\n return this;\n }\n\n withState(state: string): this {\n this.data.state = state;\n return this;\n }\n\n withId(id: string): this {\n this.data.id = id;\n return this;\n }\n\n build(): Session {\n return { ...this.data } as unknown as Session;\n }\n}\n","/**\n * HMAC test utilities for Shopify authentication testing.\n *\n * Provides helpers for computing and verifying HMACs used in\n * OAuth callbacks and webhook validation.\n */\n\nimport { createHmac, timingSafeEqual } from 'node:crypto';\n\n/**\n * Compute Shopify HMAC for query params.\n * Sorts params alphabetically, joins as key=value pairs with &,\n * and returns a hex HMAC-SHA256 digest.\n */\nexport function computeShopifyHmac(\n params: Record<string, string>,\n secret: string,\n): string {\n const sorted = Object.keys(params)\n .filter((k) => k !== 'hmac')\n .sort()\n .map((k) => `${k}=${params[k]!}`)\n .join('&');\n\n return createHmac('sha256', secret).update(sorted).digest('hex');\n}\n\n/**\n * Compute webhook HMAC (base64 digest).\n * Used for validating Shopify webhook request bodies.\n */\nexport function computeWebhookHmac(\n body: string | Buffer,\n secret: string,\n): string {\n return createHmac('sha256', secret).update(body).digest('base64');\n}\n\n/**\n * Verify HMAC with timing-safe comparison.\n * Returns true if computed matches provided.\n */\nexport function verifyHmac(computed: string, provided: string): boolean {\n const computedBuf = Buffer.from(computed, 'utf-8');\n const providedBuf = Buffer.from(provided, 'utf-8');\n\n if (computedBuf.length !== providedBuf.length) {\n return false;\n }\n\n return timingSafeEqual(computedBuf, providedBuf);\n}\n\n/**\n * Generate a query string with HMAC appended.\n * Sorts params, computes HMAC, and returns the full query string.\n */\nexport function createSignedQueryString(\n params: Record<string, string>,\n secret: string,\n): string {\n const hmac = computeShopifyHmac(params, secret);\n const sorted = Object.keys(params)\n .filter((k) => k !== 'hmac')\n .sort()\n .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k]!)}`)\n .join('&');\n\n return `${sorted}&hmac=${hmac}`;\n}\n\n/**\n * Create a complete signed URL for OAuth callbacks.\n * Appends signed query params to the base URL.\n */\nexport function createSignedUrl(\n baseUrl: string,\n params: Record<string, string>,\n secret: string,\n): string {\n const queryString = createSignedQueryString(params, secret);\n const separator = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${separator}${queryString}`;\n}\n","/**\n * Auth flow simulator for testing authentication workflows.\n *\n * Simulates token exchange, OAuth flows, token refresh, and\n * generates auth events without requiring a real Shopify API.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type {\n Session,\n ShopContext,\n AuthEvent,\n AuthEventType,\n OnlineAccessInfo,\n AssociatedUser,\n} from '@uniforge/platform-core/auth';\nexport interface AuthFlowSimulatorConfig {\n apiKey?: string;\n apiSecretKey?: string;\n scopes?: string[];\n hostName?: string;\n}\n\nexport interface TokenExchangeResult {\n session: Session;\n shopContext: ShopContext;\n}\n\nexport interface OAuthFlowResult {\n authorizeUrl: string;\n authCode: string;\n callbackSession: Session;\n shopContext: ShopContext;\n}\n\nconst DEFAULT_CONFIG: Required<AuthFlowSimulatorConfig> = {\n apiKey: 'test-api-key',\n apiSecretKey: 'test-api-secret',\n scopes: ['read_products', 'write_orders'],\n hostName: 'test-app.example.com',\n};\n\nexport class AuthFlowSimulator {\n private readonly config: Required<AuthFlowSimulatorConfig>;\n\n constructor(config?: AuthFlowSimulatorConfig) {\n this.config = { ...DEFAULT_CONFIG };\n if (config) {\n if (config.apiKey !== undefined) {\n this.config.apiKey = config.apiKey;\n }\n if (config.apiSecretKey !== undefined) {\n this.config.apiSecretKey = config.apiSecretKey;\n }\n if (config.scopes !== undefined) {\n this.config.scopes = config.scopes;\n }\n if (config.hostName !== undefined) {\n this.config.hostName = config.hostName;\n }\n }\n }\n\n simulateTokenExchange(\n shopDomain: string,\n options?: {\n isOnline?: boolean;\n userId?: number;\n scopes?: string[];\n accessToken?: string;\n },\n ): TokenExchangeResult {\n const isOnline = options?.isOnline ?? false;\n const userId = options?.userId ?? 1;\n const scopes = options?.scopes ?? this.config.scopes;\n const accessToken = options?.accessToken ?? 'shpat_test_exchanged_token';\n const now = new Date();\n const expires = new Date(now.getTime() + 86400 * 1000);\n\n const id = isOnline\n ? `online_${shopDomain}_${userId}`\n : `offline_${shopDomain}`;\n\n const session: Session = {\n id,\n shop: shopDomain,\n state: randomUUID(),\n isOnline,\n scope: scopes.join(','),\n expires: isOnline ? expires : null,\n accessToken,\n createdAt: now,\n updatedAt: now,\n };\n\n if (isOnline) {\n session.onlineAccessInfo = {\n expiresIn: 86400,\n associatedUserScope: scopes.join(','),\n associatedUser: {\n id: userId,\n firstName: 'Test',\n lastName: 'User',\n email: 'test@example.com',\n emailVerified: true,\n accountOwner: true,\n locale: 'en',\n collaborator: false,\n } satisfies AssociatedUser,\n } satisfies OnlineAccessInfo;\n }\n\n const shopContext: ShopContext = {\n shopDomain,\n accessToken,\n scopes,\n session,\n };\n\n return { session, shopContext };\n }\n\n simulateOAuthFlow(\n shopDomain: string,\n options?: {\n isOnline?: boolean;\n userId?: number;\n scopes?: string[];\n },\n ): OAuthFlowResult {\n const scopes = options?.scopes ?? this.config.scopes;\n const state = randomUUID();\n const authCode = `auth_code_${randomUUID().slice(0, 8)}`;\n\n const authorizeUrl =\n `https://${shopDomain}/admin/oauth/authorize` +\n `?client_id=${this.config.apiKey}` +\n `&scope=${scopes.join(',')}` +\n `&redirect_uri=https://${this.config.hostName}/auth/callback` +\n `&state=${state}`;\n\n const exchangeOptions: {\n isOnline?: boolean;\n userId?: number;\n scopes?: string[];\n accessToken?: string;\n } = {\n scopes,\n accessToken: 'shpat_test_oauth_token',\n };\n if (options?.isOnline !== undefined) {\n exchangeOptions.isOnline = options.isOnline;\n }\n if (options?.userId !== undefined) {\n exchangeOptions.userId = options.userId;\n }\n const { session: callbackSession, shopContext } =\n this.simulateTokenExchange(shopDomain, exchangeOptions);\n\n return { authorizeUrl, authCode, callbackSession, shopContext };\n }\n\n simulateTokenRefresh(\n session: Session,\n options?: {\n newAccessToken?: string;\n newRefreshToken?: string;\n newScopes?: string[];\n },\n ): Session {\n const now = new Date();\n const expires = new Date(now.getTime() + 86400 * 1000);\n const refreshed: Session = {\n ...session,\n accessToken: options?.newAccessToken ?? 'shpat_test_refreshed_token',\n expires,\n updatedAt: now,\n };\n\n if (options?.newRefreshToken !== undefined) {\n refreshed.refreshToken = options.newRefreshToken;\n refreshed.refreshTokenExpiresAt = new Date(\n now.getTime() + 7 * 86400 * 1000,\n );\n }\n\n if (options?.newScopes !== undefined) {\n refreshed.scope = options.newScopes.join(',');\n }\n\n return refreshed;\n }\n\n createExpiredSession(\n shopDomain: string,\n options?: {\n isOnline?: boolean;\n expiredMinutesAgo?: number;\n },\n ): Session {\n const minutesAgo = options?.expiredMinutesAgo ?? 60;\n const now = new Date();\n const expiredAt = new Date(now.getTime() - minutesAgo * 60 * 1000);\n const isOnline = options?.isOnline ?? false;\n const id = isOnline\n ? `online_${shopDomain}_1`\n : `offline_${shopDomain}`;\n\n return {\n id,\n shop: shopDomain,\n state: 'expired-state',\n isOnline,\n scope: this.config.scopes.join(','),\n expires: expiredAt,\n accessToken: 'shpat_expired_token',\n createdAt: new Date(expiredAt.getTime() - 86400 * 1000),\n updatedAt: expiredAt,\n };\n }\n\n generateAuthEvent(\n type: AuthEventType,\n shopDomain: string,\n options?: {\n sessionId?: string;\n userId?: number;\n outcome?: 'success' | 'failure';\n metadata?: Record<string, string>;\n },\n ): AuthEvent {\n return {\n id: randomUUID(),\n type,\n shopDomain,\n sessionId: options?.sessionId ?? `offline_${shopDomain}`,\n userId: options?.userId ?? null,\n outcome: options?.outcome ?? 'success',\n metadata: options?.metadata ?? {},\n timestamp: new Date(),\n };\n }\n\n get secret(): string {\n return this.config.apiSecretKey;\n }\n}\n"],"mappings":"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","names":["import_node_crypto"]}
|