@palbase/backend 0.5.0 → 0.9.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.
- package/dist/chunk-4J3F32SH.js +96 -0
- package/dist/chunk-4J3F32SH.js.map +1 -0
- package/dist/db/index.cjs +12 -12
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +3 -70
- package/dist/db/index.d.ts +3 -70
- package/dist/db/index.js +11 -83
- package/dist/db/index.js.map +1 -1
- package/dist/endpoint-DysSe3SI.d.ts +1299 -0
- package/dist/endpoint-_1Qq8AFz.d.cts +1299 -0
- package/dist/index.cjs +125 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -20
- package/dist/index.d.ts +12 -20
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -1
- package/dist/schema-zk-a0Dv7.d.cts +133 -0
- package/dist/schema-zk-a0Dv7.d.ts +133 -0
- package/dist/test/index.cjs +151 -12
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +2 -1
- package/dist/test/index.d.ts +2 -1
- package/dist/test/index.js +151 -12
- package/dist/test/index.js.map +1 -1
- package/package.json +3 -1
- package/dist/endpoint-tZi55HU8.d.cts +0 -115
- package/dist/endpoint-tZi55HU8.d.ts +0 -115
package/dist/test/index.cjs
CHANGED
|
@@ -34,6 +34,9 @@ function createMockDB() {
|
|
|
34
34
|
deleted: /* @__PURE__ */ new Map()
|
|
35
35
|
};
|
|
36
36
|
return {
|
|
37
|
+
async query(_sql, _params) {
|
|
38
|
+
return [];
|
|
39
|
+
},
|
|
37
40
|
async insert(table, data) {
|
|
38
41
|
const record = { id: crypto.randomUUID(), ...data };
|
|
39
42
|
if (!store.has(table)) store.set(table, []);
|
|
@@ -105,28 +108,157 @@ function createMockLogger(logs) {
|
|
|
105
108
|
}
|
|
106
109
|
function createMockCache() {
|
|
107
110
|
const store = /* @__PURE__ */ new Map();
|
|
111
|
+
const get = async (key) => {
|
|
112
|
+
return store.has(key) ? store.get(key) : null;
|
|
113
|
+
};
|
|
114
|
+
const set = async (key, value, _ttl) => {
|
|
115
|
+
store.set(key, value);
|
|
116
|
+
};
|
|
108
117
|
return {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
},
|
|
112
|
-
async set(key, value, _ttl) {
|
|
113
|
-
store.set(key, value);
|
|
114
|
-
},
|
|
118
|
+
get,
|
|
119
|
+
set,
|
|
115
120
|
async del(key) {
|
|
116
121
|
store.delete(key);
|
|
117
122
|
},
|
|
118
123
|
async incr(key) {
|
|
119
|
-
const
|
|
124
|
+
const raw = store.get(key);
|
|
125
|
+
const current = typeof raw === "number" ? raw : parseInt(String(raw ?? "0"), 10);
|
|
120
126
|
const next = current + 1;
|
|
121
|
-
store.set(key,
|
|
127
|
+
store.set(key, next);
|
|
122
128
|
return next;
|
|
129
|
+
},
|
|
130
|
+
async getOrSet(key, ttl, fn) {
|
|
131
|
+
const hit = await get(key);
|
|
132
|
+
if (hit !== null) {
|
|
133
|
+
return hit;
|
|
134
|
+
}
|
|
135
|
+
const value = await fn();
|
|
136
|
+
await set(key, value, ttl);
|
|
137
|
+
return value;
|
|
123
138
|
}
|
|
124
139
|
};
|
|
125
140
|
}
|
|
126
|
-
function
|
|
141
|
+
function createMockModuleClients() {
|
|
142
|
+
const notImpl = (label) => {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`${label} not configured in test mock \u2014 override ctx.${label.split(".")[0]} on the returned context`
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
const docs = {
|
|
148
|
+
collection: () => notImpl("docs.collection"),
|
|
149
|
+
doc: () => notImpl("docs.doc")
|
|
150
|
+
};
|
|
151
|
+
const auth = {
|
|
152
|
+
verifyUserToken: () => notImpl("auth.verifyUserToken"),
|
|
153
|
+
getSession: () => notImpl("auth.getSession"),
|
|
154
|
+
mfa: {
|
|
155
|
+
enroll: () => notImpl("auth.mfa.enroll"),
|
|
156
|
+
verifyEnrollment: () => notImpl("auth.mfa.verifyEnrollment"),
|
|
157
|
+
challenge: () => notImpl("auth.mfa.challenge"),
|
|
158
|
+
recovery: () => notImpl("auth.mfa.recovery"),
|
|
159
|
+
listFactors: () => notImpl("auth.mfa.listFactors"),
|
|
160
|
+
removeFactor: () => notImpl("auth.mfa.removeFactor"),
|
|
161
|
+
regenerateRecoveryCodes: () => notImpl("auth.mfa.regenerateRecoveryCodes"),
|
|
162
|
+
emailEnroll: () => notImpl("auth.mfa.emailEnroll"),
|
|
163
|
+
emailChallenge: () => notImpl("auth.mfa.emailChallenge"),
|
|
164
|
+
emailVerify: () => notImpl("auth.mfa.emailVerify")
|
|
165
|
+
},
|
|
166
|
+
device: {
|
|
167
|
+
generateChallenge: () => notImpl("auth.device.generateChallenge"),
|
|
168
|
+
attestAndroid: () => notImpl("auth.device.attestAndroid"),
|
|
169
|
+
attestiOS: () => notImpl("auth.device.attestiOS"),
|
|
170
|
+
bind: () => notImpl("auth.device.bind"),
|
|
171
|
+
list: () => notImpl("auth.device.list"),
|
|
172
|
+
delete: () => notImpl("auth.device.delete"),
|
|
173
|
+
verifyRequestSignature: () => notImpl("auth.device.verifyRequestSignature"),
|
|
174
|
+
getToken: () => notImpl("auth.device.getToken"),
|
|
175
|
+
get isActive() {
|
|
176
|
+
return notImpl("auth.device.isActive");
|
|
177
|
+
},
|
|
178
|
+
setCachedToken: () => notImpl("auth.device.setCachedToken"),
|
|
179
|
+
dispose: () => notImpl("auth.device.dispose")
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const storage = {
|
|
183
|
+
bucket: () => notImpl("storage.bucket")
|
|
184
|
+
};
|
|
185
|
+
const realtime = {
|
|
186
|
+
channel: () => notImpl("realtime.channel"),
|
|
187
|
+
removeChannel: () => notImpl("realtime.removeChannel"),
|
|
188
|
+
removeAllChannels: () => notImpl("realtime.removeAllChannels")
|
|
189
|
+
};
|
|
190
|
+
const functions = {
|
|
191
|
+
invoke: () => notImpl("functions.invoke")
|
|
192
|
+
};
|
|
193
|
+
const flags = {
|
|
194
|
+
isEnabled: () => notImpl("flags.isEnabled"),
|
|
195
|
+
getVariant: () => notImpl("flags.getVariant"),
|
|
196
|
+
getAll: () => notImpl("flags.getAll")
|
|
197
|
+
};
|
|
198
|
+
const notifications = {
|
|
199
|
+
push: { send: () => notImpl("notifications.push.send") },
|
|
200
|
+
email: { send: () => notImpl("notifications.email.send") },
|
|
201
|
+
sms: { send: () => notImpl("notifications.sms.send") },
|
|
202
|
+
inbox: {
|
|
203
|
+
send: () => notImpl("notifications.inbox.send"),
|
|
204
|
+
list: () => notImpl("notifications.inbox.list"),
|
|
205
|
+
unreadCount: () => notImpl("notifications.inbox.unreadCount"),
|
|
206
|
+
markRead: () => notImpl("notifications.inbox.markRead"),
|
|
207
|
+
markAllRead: () => notImpl("notifications.inbox.markAllRead"),
|
|
208
|
+
archive: () => notImpl("notifications.inbox.archive")
|
|
209
|
+
},
|
|
210
|
+
preferences: {
|
|
211
|
+
get: () => notImpl("notifications.preferences.get"),
|
|
212
|
+
update: () => notImpl("notifications.preferences.update")
|
|
213
|
+
},
|
|
214
|
+
registerDevice: () => notImpl("notifications.registerDevice"),
|
|
215
|
+
unregisterDevice: () => notImpl("notifications.unregisterDevice")
|
|
216
|
+
};
|
|
217
|
+
const analytics = {
|
|
218
|
+
capture: () => notImpl("analytics.capture"),
|
|
219
|
+
identify: () => notImpl("analytics.identify"),
|
|
220
|
+
screen: () => notImpl("analytics.screen"),
|
|
221
|
+
query: {
|
|
222
|
+
count: () => notImpl("analytics.query.count"),
|
|
223
|
+
events: () => notImpl("analytics.query.events"),
|
|
224
|
+
properties: () => notImpl("analytics.query.properties"),
|
|
225
|
+
users: () => notImpl("analytics.query.users"),
|
|
226
|
+
funnel: () => notImpl("analytics.query.funnel"),
|
|
227
|
+
retention: () => notImpl("analytics.query.retention"),
|
|
228
|
+
cohort: () => notImpl("analytics.query.cohort")
|
|
229
|
+
},
|
|
230
|
+
management: {
|
|
231
|
+
overview: () => notImpl("analytics.management.overview"),
|
|
232
|
+
eventNames: () => notImpl("analytics.management.eventNames"),
|
|
233
|
+
userDetail: () => notImpl("analytics.management.userDetail"),
|
|
234
|
+
deleteUser: () => notImpl("analytics.management.deleteUser")
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
const links = {
|
|
238
|
+
create: () => notImpl("links.create"),
|
|
239
|
+
list: () => notImpl("links.list"),
|
|
240
|
+
get: () => notImpl("links.get"),
|
|
241
|
+
update: () => notImpl("links.update"),
|
|
242
|
+
delete: () => notImpl("links.delete"),
|
|
243
|
+
analytics: () => notImpl("links.analytics"),
|
|
244
|
+
qrCode: () => notImpl("links.qrCode"),
|
|
245
|
+
match: () => notImpl("links.match")
|
|
246
|
+
};
|
|
247
|
+
const cms = {
|
|
248
|
+
find: () => notImpl("cms.find"),
|
|
249
|
+
findOne: () => notImpl("cms.findOne")
|
|
250
|
+
};
|
|
127
251
|
return {
|
|
128
|
-
auth
|
|
129
|
-
storage
|
|
252
|
+
auth,
|
|
253
|
+
storage,
|
|
254
|
+
docs,
|
|
255
|
+
realtime,
|
|
256
|
+
functions,
|
|
257
|
+
flags,
|
|
258
|
+
notifications,
|
|
259
|
+
analytics,
|
|
260
|
+
links,
|
|
261
|
+
cms
|
|
130
262
|
};
|
|
131
263
|
}
|
|
132
264
|
function createTestContext(options = {}) {
|
|
@@ -137,17 +269,24 @@ function createTestContext(options = {}) {
|
|
|
137
269
|
db.seed(table, data);
|
|
138
270
|
}
|
|
139
271
|
}
|
|
272
|
+
const mockQueue = {
|
|
273
|
+
push: async (_worker, _payload) => ({ jobId: "" })
|
|
274
|
+
};
|
|
140
275
|
const ctx = {
|
|
141
276
|
input: options.input ?? {},
|
|
142
277
|
params: options.params ?? {},
|
|
143
278
|
query: options.query ?? {},
|
|
144
279
|
headers: options.headers ?? {},
|
|
145
280
|
user: options.user ?? null,
|
|
281
|
+
method: "POST",
|
|
282
|
+
endpointPath: "/test",
|
|
283
|
+
file: null,
|
|
146
284
|
db,
|
|
147
285
|
env: options.env ?? {},
|
|
148
286
|
log: createMockLogger(logs),
|
|
149
287
|
cache: createMockCache(),
|
|
150
|
-
|
|
288
|
+
queue: mockQueue,
|
|
289
|
+
...createMockModuleClients(),
|
|
151
290
|
requestId: "req_test_000000000000",
|
|
152
291
|
projectId: "proj_test_000000000000",
|
|
153
292
|
environmentId: "env_test_000000000000",
|
package/dist/test/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/index.ts","../../src/test/mock-db.ts","../../src/test/context.ts"],"sourcesContent":["export { createTestContext } from \"./context.js\";\nexport type { TestContextOptions, TestContext, LogEntry } from \"./context.js\";\nexport { createMockDB } from \"./mock-db.js\";\nexport type { MockDBClient } from \"./mock-db.js\";\n","import type { DBClient } from \"../endpoint.js\";\n\n/** Tracked records for assertions. */\ninterface TrackedRecords {\n inserted: Map<string, Record<string, unknown>[]>;\n updated: Map<string, Record<string, unknown>[]>;\n deleted: Map<string, string[]>;\n}\n\n/** Mock DB client with tracking and seed data support. */\nexport interface MockDBClient extends DBClient {\n /** Get records inserted into a table. */\n inserted(table: string): Record<string, unknown>[];\n /** Get records updated in a table. */\n updated(table: string): Record<string, unknown>[];\n /** Get IDs deleted from a table. */\n deleted(table: string): string[];\n /** Pre-seed data into a table for findById/findMany. */\n seed(table: string, data: Record<string, unknown>[]): void;\n}\n\n/** Create a mock DB client with in-memory tracking. */\nexport function createMockDB(): MockDBClient {\n const store = new Map<string, Record<string, unknown>[]>();\n const tracked: TrackedRecords = {\n inserted: new Map(),\n updated: new Map(),\n deleted: new Map(),\n };\n\n return {\n async insert(table: string, data: Record<string, unknown>) {\n const record = { id: crypto.randomUUID(), ...data };\n if (!store.has(table)) store.set(table, []);\n store.get(table)!.push(record);\n if (!tracked.inserted.has(table)) tracked.inserted.set(table, []);\n tracked.inserted.get(table)!.push(record);\n return record;\n },\n\n async update(table: string, id: string, data: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n const updated = idx >= 0\n ? { ...rows[idx], ...data }\n : { id, ...data };\n if (idx >= 0) {\n rows[idx] = updated;\n }\n if (!tracked.updated.has(table)) tracked.updated.set(table, []);\n tracked.updated.get(table)!.push(updated);\n return updated;\n },\n\n async delete(table: string, id: string) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n if (idx >= 0) rows.splice(idx, 1);\n if (!tracked.deleted.has(table)) tracked.deleted.set(table, []);\n tracked.deleted.get(table)!.push(id);\n },\n\n async findById(table: string, id: string) {\n const rows = store.get(table) ?? [];\n return rows.find((r) => r[\"id\"] === id) ?? null;\n },\n\n async findMany(table: string, query?: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n if (!query) return rows;\n return rows.filter((row) =>\n Object.entries(query).every(([key, val]) => row[key] === val),\n );\n },\n\n inserted(table: string) {\n return tracked.inserted.get(table) ?? [];\n },\n\n updated(table: string) {\n return tracked.updated.get(table) ?? [];\n },\n\n deleted(table: string) {\n return tracked.deleted.get(table) ?? [];\n },\n\n seed(table: string, data: Record<string, unknown>[]) {\n store.set(table, [...data]);\n },\n };\n}\n","import type {\n CacheClient,\n EndpointContext,\n Logger,\n PalbaseBindings,\n} from \"../endpoint.js\";\nimport type { User } from \"../types.js\";\nimport { createMockDB, type MockDBClient } from \"./mock-db.js\";\n\n/** Options for creating a test context. */\nexport interface TestContextOptions<TInput = unknown> {\n user?: User | null;\n input?: TInput;\n params?: Record<string, string>;\n query?: Record<string, string>;\n headers?: Record<string, string>;\n env?: Record<string, string>;\n db?: { seed?: Record<string, Record<string, unknown>[]> };\n}\n\n/** Log entry captured by the mock logger. */\nexport interface LogEntry {\n level: \"info\" | \"warn\" | \"error\" | \"debug\";\n message: string;\n args: unknown[];\n}\n\n/** Test context with mock helpers exposed. */\nexport interface TestContext<TInput = unknown> extends EndpointContext<TInput> {\n db: MockDBClient;\n /** Captured log entries. */\n logs: LogEntry[];\n}\n\n/** Create a mock logger that captures entries. */\nfunction createMockLogger(logs: LogEntry[]): Logger {\n return {\n info(message: string, ...args: unknown[]) {\n logs.push({ level: \"info\", message, args });\n },\n warn(message: string, ...args: unknown[]) {\n logs.push({ level: \"warn\", message, args });\n },\n error(message: string, ...args: unknown[]) {\n logs.push({ level: \"error\", message, args });\n },\n debug(message: string, ...args: unknown[]) {\n logs.push({ level: \"debug\", message, args });\n },\n };\n}\n\n/** Create a mock in-memory cache. */\nfunction createMockCache(): CacheClient {\n const store = new Map<string, string>();\n\n return {\n async get(key: string) {\n return store.get(key) ?? null;\n },\n async set(key: string, value: string, _ttl?: number) {\n store.set(key, value);\n },\n async del(key: string) {\n store.delete(key);\n },\n async incr(key: string) {\n const current = parseInt(store.get(key) ?? \"0\", 10);\n const next = current + 1;\n store.set(key, String(next));\n return next;\n },\n };\n}\n\n/** Create a mock Palbase service bindings. */\nfunction createMockPalbase(): PalbaseBindings {\n return {\n auth: {},\n storage: {},\n };\n}\n\n/** Create a fully mocked EndpointContext for testing user endpoints. */\nexport function createTestContext<TInput = unknown>(\n options: TestContextOptions<TInput> = {},\n): TestContext<TInput> {\n const logs: LogEntry[] = [];\n const db = createMockDB();\n\n // Seed data if provided\n if (options.db?.seed) {\n for (const [table, data] of Object.entries(options.db.seed)) {\n db.seed(table, data);\n }\n }\n\n const ctx: TestContext<TInput> = {\n input: (options.input ?? {}) as TInput,\n params: options.params ?? {},\n query: options.query ?? {},\n headers: options.headers ?? {},\n user: options.user ?? null,\n db,\n env: options.env ?? {},\n log: createMockLogger(logs),\n cache: createMockCache(),\n palbase: createMockPalbase(),\n requestId: \"req_test_000000000000\",\n projectId: \"proj_test_000000000000\",\n environmentId: \"env_test_000000000000\",\n logs,\n };\n\n return ctx;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/test/index.ts","../../src/test/mock-db.ts","../../src/test/context.ts"],"sourcesContent":["export { createTestContext } from \"./context.js\";\nexport type { TestContextOptions, TestContext, LogEntry } from \"./context.js\";\nexport { createMockDB } from \"./mock-db.js\";\nexport type { MockDBClient } from \"./mock-db.js\";\n","import type { DBClient } from \"../endpoint.js\";\n\n/** Tracked records for assertions. */\ninterface TrackedRecords {\n inserted: Map<string, Record<string, unknown>[]>;\n updated: Map<string, Record<string, unknown>[]>;\n deleted: Map<string, string[]>;\n}\n\n/** Mock DB client with tracking and seed data support. */\nexport interface MockDBClient extends DBClient {\n /** Get records inserted into a table. */\n inserted(table: string): Record<string, unknown>[];\n /** Get records updated in a table. */\n updated(table: string): Record<string, unknown>[];\n /** Get IDs deleted from a table. */\n deleted(table: string): string[];\n /** Pre-seed data into a table for findById/findMany. */\n seed(table: string, data: Record<string, unknown>[]): void;\n}\n\n/** Create a mock DB client with in-memory tracking. */\nexport function createMockDB(): MockDBClient {\n const store = new Map<string, Record<string, unknown>[]>();\n const tracked: TrackedRecords = {\n inserted: new Map(),\n updated: new Map(),\n deleted: new Map(),\n };\n\n return {\n async query(_sql: string, _params?: unknown[]) {\n return [];\n },\n\n async insert(table: string, data: Record<string, unknown>) {\n const record = { id: crypto.randomUUID(), ...data };\n if (!store.has(table)) store.set(table, []);\n store.get(table)!.push(record);\n if (!tracked.inserted.has(table)) tracked.inserted.set(table, []);\n tracked.inserted.get(table)!.push(record);\n return record;\n },\n\n async update(table: string, id: string, data: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n const updated = idx >= 0\n ? { ...rows[idx], ...data }\n : { id, ...data };\n if (idx >= 0) {\n rows[idx] = updated;\n }\n if (!tracked.updated.has(table)) tracked.updated.set(table, []);\n tracked.updated.get(table)!.push(updated);\n return updated;\n },\n\n async delete(table: string, id: string) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n if (idx >= 0) rows.splice(idx, 1);\n if (!tracked.deleted.has(table)) tracked.deleted.set(table, []);\n tracked.deleted.get(table)!.push(id);\n },\n\n async findById(table: string, id: string) {\n const rows = store.get(table) ?? [];\n return rows.find((r) => r[\"id\"] === id) ?? null;\n },\n\n async findMany(table: string, query?: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n if (!query) return rows;\n return rows.filter((row) =>\n Object.entries(query).every(([key, val]) => row[key] === val),\n );\n },\n\n inserted(table: string) {\n return tracked.inserted.get(table) ?? [];\n },\n\n updated(table: string) {\n return tracked.updated.get(table) ?? [];\n },\n\n deleted(table: string) {\n return tracked.deleted.get(table) ?? [];\n },\n\n seed(table: string, data: Record<string, unknown>[]) {\n store.set(table, [...data]);\n },\n };\n}\n","import type {\n CacheClient,\n EndpointContext,\n Logger,\n PalbaseModuleClients,\n QueueClient,\n} from \"../endpoint.js\";\nimport type {\n PalbaseAuthClient,\n PalbaseStorageClient,\n PalbaseRealtimeClient,\n PalbaseFunctionsClient,\n PalbaseFlagsClient,\n PalbaseNotificationsClient,\n PalbaseAnalyticsClient,\n PalbaseLinksClient,\n PalbaseCmsClient,\n} from \"../clients.js\";\nimport type { User } from \"../types.js\";\nimport { createMockDB, type MockDBClient } from \"./mock-db.js\";\n\n/** Options for creating a test context. */\nexport interface TestContextOptions<TInput = unknown> {\n user?: User | null;\n input?: TInput;\n params?: Record<string, string>;\n query?: Record<string, string>;\n headers?: Record<string, string>;\n env?: Record<string, string>;\n db?: { seed?: Record<string, Record<string, unknown>[]> };\n}\n\n/** Log entry captured by the mock logger. */\nexport interface LogEntry {\n level: \"info\" | \"warn\" | \"error\" | \"debug\";\n message: string;\n args: unknown[];\n}\n\n/** Test context with mock helpers exposed. */\nexport interface TestContext<TInput = unknown> extends EndpointContext<TInput> {\n db: MockDBClient;\n /** Captured log entries. */\n logs: LogEntry[];\n}\n\n/** Create a mock logger that captures entries. */\nfunction createMockLogger(logs: LogEntry[]): Logger {\n return {\n info(message: string, ...args: unknown[]) {\n logs.push({ level: \"info\", message, args });\n },\n warn(message: string, ...args: unknown[]) {\n logs.push({ level: \"warn\", message, args });\n },\n error(message: string, ...args: unknown[]) {\n logs.push({ level: \"error\", message, args });\n },\n debug(message: string, ...args: unknown[]) {\n logs.push({ level: \"debug\", message, args });\n },\n };\n}\n\n/** Create a mock in-memory cache.\n *\n * Mirrors the runtime's JSON-typed semantics (values are arbitrary JSON, not\n * just strings). getOrSet is single-process here, so it does not need the\n * distributed lock the real runtime uses — it is just get-miss → fn → set.\n * The cross-replica stampede protection is covered by the worker.js tests.\n */\nfunction createMockCache(): CacheClient {\n const store = new Map<string, unknown>();\n\n const get = async <T = unknown>(key: string): Promise<T | null> => {\n return store.has(key) ? (store.get(key) as T) : null;\n };\n const set = async (key: string, value: unknown, _ttl?: number): Promise<void> => {\n store.set(key, value);\n };\n\n return {\n get,\n set,\n async del(key: string) {\n store.delete(key);\n },\n async incr(key: string) {\n const raw = store.get(key);\n const current = typeof raw === \"number\" ? raw : parseInt(String(raw ?? \"0\"), 10);\n const next = current + 1;\n store.set(key, next);\n return next;\n },\n async getOrSet<T>(key: string, ttl: number, fn: () => Promise<T> | T): Promise<T> {\n const hit = await get<T>(key);\n if (hit !== null) {\n return hit;\n }\n const value = await fn();\n await set(key, value, ttl);\n return value;\n },\n };\n}\n\n/** Create mock Palbase module clients (ctx.docs, ctx.storage, …).\n *\n * Every slot throws with a descriptive error so tests that access a\n * module client surface without configuring it fail loudly rather than\n * silently returning undefined. Override individual clients on the\n * returned context for tests that need them:\n * const ctx = createTestContext();\n * ctx.flags = { isEnabled: vi.fn().mockResolvedValue({ data: true, error: null }) };\n */\nfunction createMockModuleClients(): PalbaseModuleClients {\n const notImpl = (label: string): never => {\n throw new Error(\n `${label} not configured in test mock — override ctx.${label.split(\".\")[0]} on the returned context`,\n );\n };\n\n const docs: PalbaseModuleClients[\"docs\"] = {\n collection: () => notImpl(\"docs.collection\"),\n doc: () => notImpl(\"docs.doc\"),\n };\n\n const auth: PalbaseAuthClient = {\n verifyUserToken: () => notImpl(\"auth.verifyUserToken\"),\n getSession: () => notImpl(\"auth.getSession\"),\n mfa: {\n enroll: () => notImpl(\"auth.mfa.enroll\"),\n verifyEnrollment: () => notImpl(\"auth.mfa.verifyEnrollment\"),\n challenge: () => notImpl(\"auth.mfa.challenge\"),\n recovery: () => notImpl(\"auth.mfa.recovery\"),\n listFactors: () => notImpl(\"auth.mfa.listFactors\"),\n removeFactor: () => notImpl(\"auth.mfa.removeFactor\"),\n regenerateRecoveryCodes: () => notImpl(\"auth.mfa.regenerateRecoveryCodes\"),\n emailEnroll: () => notImpl(\"auth.mfa.emailEnroll\"),\n emailChallenge: () => notImpl(\"auth.mfa.emailChallenge\"),\n emailVerify: () => notImpl(\"auth.mfa.emailVerify\"),\n },\n device: {\n generateChallenge: () => notImpl(\"auth.device.generateChallenge\"),\n attestAndroid: () => notImpl(\"auth.device.attestAndroid\"),\n attestiOS: () => notImpl(\"auth.device.attestiOS\"),\n bind: () => notImpl(\"auth.device.bind\"),\n list: () => notImpl(\"auth.device.list\"),\n delete: () => notImpl(\"auth.device.delete\"),\n verifyRequestSignature: () => notImpl(\"auth.device.verifyRequestSignature\"),\n getToken: () => notImpl(\"auth.device.getToken\"),\n get isActive(): never {\n return notImpl(\"auth.device.isActive\");\n },\n setCachedToken: () => notImpl(\"auth.device.setCachedToken\"),\n dispose: () => notImpl(\"auth.device.dispose\"),\n },\n };\n\n const storage: PalbaseStorageClient = {\n bucket: () => notImpl(\"storage.bucket\"),\n };\n\n const realtime: PalbaseRealtimeClient = {\n channel: () => notImpl(\"realtime.channel\"),\n removeChannel: () => notImpl(\"realtime.removeChannel\"),\n removeAllChannels: () => notImpl(\"realtime.removeAllChannels\"),\n };\n\n const functions: PalbaseFunctionsClient = {\n invoke: () => notImpl(\"functions.invoke\"),\n };\n\n const flags: PalbaseFlagsClient = {\n isEnabled: () => notImpl(\"flags.isEnabled\"),\n getVariant: () => notImpl(\"flags.getVariant\"),\n getAll: () => notImpl(\"flags.getAll\"),\n };\n\n const notifications: PalbaseNotificationsClient = {\n push: { send: () => notImpl(\"notifications.push.send\") },\n email: { send: () => notImpl(\"notifications.email.send\") },\n sms: { send: () => notImpl(\"notifications.sms.send\") },\n inbox: {\n send: () => notImpl(\"notifications.inbox.send\"),\n list: () => notImpl(\"notifications.inbox.list\"),\n unreadCount: () => notImpl(\"notifications.inbox.unreadCount\"),\n markRead: () => notImpl(\"notifications.inbox.markRead\"),\n markAllRead: () => notImpl(\"notifications.inbox.markAllRead\"),\n archive: () => notImpl(\"notifications.inbox.archive\"),\n },\n preferences: {\n get: () => notImpl(\"notifications.preferences.get\"),\n update: () => notImpl(\"notifications.preferences.update\"),\n },\n registerDevice: () => notImpl(\"notifications.registerDevice\"),\n unregisterDevice: () => notImpl(\"notifications.unregisterDevice\"),\n };\n\n const analytics: PalbaseAnalyticsClient = {\n capture: () => notImpl(\"analytics.capture\"),\n identify: () => notImpl(\"analytics.identify\"),\n screen: () => notImpl(\"analytics.screen\"),\n query: {\n count: () => notImpl(\"analytics.query.count\"),\n events: () => notImpl(\"analytics.query.events\"),\n properties: () => notImpl(\"analytics.query.properties\"),\n users: () => notImpl(\"analytics.query.users\"),\n funnel: () => notImpl(\"analytics.query.funnel\"),\n retention: () => notImpl(\"analytics.query.retention\"),\n cohort: () => notImpl(\"analytics.query.cohort\"),\n },\n management: {\n overview: () => notImpl(\"analytics.management.overview\"),\n eventNames: () => notImpl(\"analytics.management.eventNames\"),\n userDetail: () => notImpl(\"analytics.management.userDetail\"),\n deleteUser: () => notImpl(\"analytics.management.deleteUser\"),\n },\n };\n\n const links: PalbaseLinksClient = {\n create: () => notImpl(\"links.create\"),\n list: () => notImpl(\"links.list\"),\n get: () => notImpl(\"links.get\"),\n update: () => notImpl(\"links.update\"),\n delete: () => notImpl(\"links.delete\"),\n analytics: () => notImpl(\"links.analytics\"),\n qrCode: () => notImpl(\"links.qrCode\"),\n match: () => notImpl(\"links.match\"),\n };\n\n const cms: PalbaseCmsClient = {\n find: () => notImpl(\"cms.find\"),\n findOne: () => notImpl(\"cms.findOne\"),\n };\n\n return {\n auth,\n storage,\n docs,\n realtime,\n functions,\n flags,\n notifications,\n analytics,\n links,\n cms,\n };\n}\n\n/** Create a fully mocked EndpointContext for testing user endpoints. */\nexport function createTestContext<TInput = unknown>(\n options: TestContextOptions<TInput> = {},\n): TestContext<TInput> {\n const logs: LogEntry[] = [];\n const db = createMockDB();\n\n // Seed data if provided\n if (options.db?.seed) {\n for (const [table, data] of Object.entries(options.db.seed)) {\n db.seed(table, data);\n }\n }\n\n const mockQueue: QueueClient = {\n push: async (_worker: string, _payload: unknown) => ({ jobId: \"\" }),\n };\n\n const ctx: TestContext<TInput> = {\n input: (options.input ?? {}) as TInput,\n params: options.params ?? {},\n query: options.query ?? {},\n headers: options.headers ?? {},\n user: options.user ?? null,\n method: \"POST\",\n endpointPath: \"/test\",\n file: null,\n db,\n env: options.env ?? {},\n log: createMockLogger(logs),\n cache: createMockCache(),\n queue: mockQueue,\n ...createMockModuleClients(),\n requestId: \"req_test_000000000000\",\n projectId: \"proj_test_000000000000\",\n environmentId: \"env_test_000000000000\",\n logs,\n };\n\n return ctx;\n}\n"],"mappings":"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","names":[]}
|
package/dist/test/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { D as DBClient, E as EndpointContext,
|
|
1
|
+
import { D as DBClient, E as EndpointContext, aR as User } from '../endpoint-_1Qq8AFz.cjs';
|
|
2
2
|
import 'zod';
|
|
3
|
+
import '../schema-zk-a0Dv7.cjs';
|
|
3
4
|
|
|
4
5
|
/** Mock DB client with tracking and seed data support. */
|
|
5
6
|
interface MockDBClient extends DBClient {
|
package/dist/test/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { D as DBClient, E as EndpointContext,
|
|
1
|
+
import { D as DBClient, E as EndpointContext, aR as User } from '../endpoint-DysSe3SI.js';
|
|
2
2
|
import 'zod';
|
|
3
|
+
import '../schema-zk-a0Dv7.js';
|
|
3
4
|
|
|
4
5
|
/** Mock DB client with tracking and seed data support. */
|
|
5
6
|
interface MockDBClient extends DBClient {
|
package/dist/test/index.js
CHANGED
|
@@ -7,6 +7,9 @@ function createMockDB() {
|
|
|
7
7
|
deleted: /* @__PURE__ */ new Map()
|
|
8
8
|
};
|
|
9
9
|
return {
|
|
10
|
+
async query(_sql, _params) {
|
|
11
|
+
return [];
|
|
12
|
+
},
|
|
10
13
|
async insert(table, data) {
|
|
11
14
|
const record = { id: crypto.randomUUID(), ...data };
|
|
12
15
|
if (!store.has(table)) store.set(table, []);
|
|
@@ -78,28 +81,157 @@ function createMockLogger(logs) {
|
|
|
78
81
|
}
|
|
79
82
|
function createMockCache() {
|
|
80
83
|
const store = /* @__PURE__ */ new Map();
|
|
84
|
+
const get = async (key) => {
|
|
85
|
+
return store.has(key) ? store.get(key) : null;
|
|
86
|
+
};
|
|
87
|
+
const set = async (key, value, _ttl) => {
|
|
88
|
+
store.set(key, value);
|
|
89
|
+
};
|
|
81
90
|
return {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
},
|
|
85
|
-
async set(key, value, _ttl) {
|
|
86
|
-
store.set(key, value);
|
|
87
|
-
},
|
|
91
|
+
get,
|
|
92
|
+
set,
|
|
88
93
|
async del(key) {
|
|
89
94
|
store.delete(key);
|
|
90
95
|
},
|
|
91
96
|
async incr(key) {
|
|
92
|
-
const
|
|
97
|
+
const raw = store.get(key);
|
|
98
|
+
const current = typeof raw === "number" ? raw : parseInt(String(raw ?? "0"), 10);
|
|
93
99
|
const next = current + 1;
|
|
94
|
-
store.set(key,
|
|
100
|
+
store.set(key, next);
|
|
95
101
|
return next;
|
|
102
|
+
},
|
|
103
|
+
async getOrSet(key, ttl, fn) {
|
|
104
|
+
const hit = await get(key);
|
|
105
|
+
if (hit !== null) {
|
|
106
|
+
return hit;
|
|
107
|
+
}
|
|
108
|
+
const value = await fn();
|
|
109
|
+
await set(key, value, ttl);
|
|
110
|
+
return value;
|
|
96
111
|
}
|
|
97
112
|
};
|
|
98
113
|
}
|
|
99
|
-
function
|
|
114
|
+
function createMockModuleClients() {
|
|
115
|
+
const notImpl = (label) => {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`${label} not configured in test mock \u2014 override ctx.${label.split(".")[0]} on the returned context`
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
const docs = {
|
|
121
|
+
collection: () => notImpl("docs.collection"),
|
|
122
|
+
doc: () => notImpl("docs.doc")
|
|
123
|
+
};
|
|
124
|
+
const auth = {
|
|
125
|
+
verifyUserToken: () => notImpl("auth.verifyUserToken"),
|
|
126
|
+
getSession: () => notImpl("auth.getSession"),
|
|
127
|
+
mfa: {
|
|
128
|
+
enroll: () => notImpl("auth.mfa.enroll"),
|
|
129
|
+
verifyEnrollment: () => notImpl("auth.mfa.verifyEnrollment"),
|
|
130
|
+
challenge: () => notImpl("auth.mfa.challenge"),
|
|
131
|
+
recovery: () => notImpl("auth.mfa.recovery"),
|
|
132
|
+
listFactors: () => notImpl("auth.mfa.listFactors"),
|
|
133
|
+
removeFactor: () => notImpl("auth.mfa.removeFactor"),
|
|
134
|
+
regenerateRecoveryCodes: () => notImpl("auth.mfa.regenerateRecoveryCodes"),
|
|
135
|
+
emailEnroll: () => notImpl("auth.mfa.emailEnroll"),
|
|
136
|
+
emailChallenge: () => notImpl("auth.mfa.emailChallenge"),
|
|
137
|
+
emailVerify: () => notImpl("auth.mfa.emailVerify")
|
|
138
|
+
},
|
|
139
|
+
device: {
|
|
140
|
+
generateChallenge: () => notImpl("auth.device.generateChallenge"),
|
|
141
|
+
attestAndroid: () => notImpl("auth.device.attestAndroid"),
|
|
142
|
+
attestiOS: () => notImpl("auth.device.attestiOS"),
|
|
143
|
+
bind: () => notImpl("auth.device.bind"),
|
|
144
|
+
list: () => notImpl("auth.device.list"),
|
|
145
|
+
delete: () => notImpl("auth.device.delete"),
|
|
146
|
+
verifyRequestSignature: () => notImpl("auth.device.verifyRequestSignature"),
|
|
147
|
+
getToken: () => notImpl("auth.device.getToken"),
|
|
148
|
+
get isActive() {
|
|
149
|
+
return notImpl("auth.device.isActive");
|
|
150
|
+
},
|
|
151
|
+
setCachedToken: () => notImpl("auth.device.setCachedToken"),
|
|
152
|
+
dispose: () => notImpl("auth.device.dispose")
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const storage = {
|
|
156
|
+
bucket: () => notImpl("storage.bucket")
|
|
157
|
+
};
|
|
158
|
+
const realtime = {
|
|
159
|
+
channel: () => notImpl("realtime.channel"),
|
|
160
|
+
removeChannel: () => notImpl("realtime.removeChannel"),
|
|
161
|
+
removeAllChannels: () => notImpl("realtime.removeAllChannels")
|
|
162
|
+
};
|
|
163
|
+
const functions = {
|
|
164
|
+
invoke: () => notImpl("functions.invoke")
|
|
165
|
+
};
|
|
166
|
+
const flags = {
|
|
167
|
+
isEnabled: () => notImpl("flags.isEnabled"),
|
|
168
|
+
getVariant: () => notImpl("flags.getVariant"),
|
|
169
|
+
getAll: () => notImpl("flags.getAll")
|
|
170
|
+
};
|
|
171
|
+
const notifications = {
|
|
172
|
+
push: { send: () => notImpl("notifications.push.send") },
|
|
173
|
+
email: { send: () => notImpl("notifications.email.send") },
|
|
174
|
+
sms: { send: () => notImpl("notifications.sms.send") },
|
|
175
|
+
inbox: {
|
|
176
|
+
send: () => notImpl("notifications.inbox.send"),
|
|
177
|
+
list: () => notImpl("notifications.inbox.list"),
|
|
178
|
+
unreadCount: () => notImpl("notifications.inbox.unreadCount"),
|
|
179
|
+
markRead: () => notImpl("notifications.inbox.markRead"),
|
|
180
|
+
markAllRead: () => notImpl("notifications.inbox.markAllRead"),
|
|
181
|
+
archive: () => notImpl("notifications.inbox.archive")
|
|
182
|
+
},
|
|
183
|
+
preferences: {
|
|
184
|
+
get: () => notImpl("notifications.preferences.get"),
|
|
185
|
+
update: () => notImpl("notifications.preferences.update")
|
|
186
|
+
},
|
|
187
|
+
registerDevice: () => notImpl("notifications.registerDevice"),
|
|
188
|
+
unregisterDevice: () => notImpl("notifications.unregisterDevice")
|
|
189
|
+
};
|
|
190
|
+
const analytics = {
|
|
191
|
+
capture: () => notImpl("analytics.capture"),
|
|
192
|
+
identify: () => notImpl("analytics.identify"),
|
|
193
|
+
screen: () => notImpl("analytics.screen"),
|
|
194
|
+
query: {
|
|
195
|
+
count: () => notImpl("analytics.query.count"),
|
|
196
|
+
events: () => notImpl("analytics.query.events"),
|
|
197
|
+
properties: () => notImpl("analytics.query.properties"),
|
|
198
|
+
users: () => notImpl("analytics.query.users"),
|
|
199
|
+
funnel: () => notImpl("analytics.query.funnel"),
|
|
200
|
+
retention: () => notImpl("analytics.query.retention"),
|
|
201
|
+
cohort: () => notImpl("analytics.query.cohort")
|
|
202
|
+
},
|
|
203
|
+
management: {
|
|
204
|
+
overview: () => notImpl("analytics.management.overview"),
|
|
205
|
+
eventNames: () => notImpl("analytics.management.eventNames"),
|
|
206
|
+
userDetail: () => notImpl("analytics.management.userDetail"),
|
|
207
|
+
deleteUser: () => notImpl("analytics.management.deleteUser")
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const links = {
|
|
211
|
+
create: () => notImpl("links.create"),
|
|
212
|
+
list: () => notImpl("links.list"),
|
|
213
|
+
get: () => notImpl("links.get"),
|
|
214
|
+
update: () => notImpl("links.update"),
|
|
215
|
+
delete: () => notImpl("links.delete"),
|
|
216
|
+
analytics: () => notImpl("links.analytics"),
|
|
217
|
+
qrCode: () => notImpl("links.qrCode"),
|
|
218
|
+
match: () => notImpl("links.match")
|
|
219
|
+
};
|
|
220
|
+
const cms = {
|
|
221
|
+
find: () => notImpl("cms.find"),
|
|
222
|
+
findOne: () => notImpl("cms.findOne")
|
|
223
|
+
};
|
|
100
224
|
return {
|
|
101
|
-
auth
|
|
102
|
-
storage
|
|
225
|
+
auth,
|
|
226
|
+
storage,
|
|
227
|
+
docs,
|
|
228
|
+
realtime,
|
|
229
|
+
functions,
|
|
230
|
+
flags,
|
|
231
|
+
notifications,
|
|
232
|
+
analytics,
|
|
233
|
+
links,
|
|
234
|
+
cms
|
|
103
235
|
};
|
|
104
236
|
}
|
|
105
237
|
function createTestContext(options = {}) {
|
|
@@ -110,17 +242,24 @@ function createTestContext(options = {}) {
|
|
|
110
242
|
db.seed(table, data);
|
|
111
243
|
}
|
|
112
244
|
}
|
|
245
|
+
const mockQueue = {
|
|
246
|
+
push: async (_worker, _payload) => ({ jobId: "" })
|
|
247
|
+
};
|
|
113
248
|
const ctx = {
|
|
114
249
|
input: options.input ?? {},
|
|
115
250
|
params: options.params ?? {},
|
|
116
251
|
query: options.query ?? {},
|
|
117
252
|
headers: options.headers ?? {},
|
|
118
253
|
user: options.user ?? null,
|
|
254
|
+
method: "POST",
|
|
255
|
+
endpointPath: "/test",
|
|
256
|
+
file: null,
|
|
119
257
|
db,
|
|
120
258
|
env: options.env ?? {},
|
|
121
259
|
log: createMockLogger(logs),
|
|
122
260
|
cache: createMockCache(),
|
|
123
|
-
|
|
261
|
+
queue: mockQueue,
|
|
262
|
+
...createMockModuleClients(),
|
|
124
263
|
requestId: "req_test_000000000000",
|
|
125
264
|
projectId: "proj_test_000000000000",
|
|
126
265
|
environmentId: "env_test_000000000000",
|
package/dist/test/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/mock-db.ts","../../src/test/context.ts"],"sourcesContent":["import type { DBClient } from \"../endpoint.js\";\n\n/** Tracked records for assertions. */\ninterface TrackedRecords {\n inserted: Map<string, Record<string, unknown>[]>;\n updated: Map<string, Record<string, unknown>[]>;\n deleted: Map<string, string[]>;\n}\n\n/** Mock DB client with tracking and seed data support. */\nexport interface MockDBClient extends DBClient {\n /** Get records inserted into a table. */\n inserted(table: string): Record<string, unknown>[];\n /** Get records updated in a table. */\n updated(table: string): Record<string, unknown>[];\n /** Get IDs deleted from a table. */\n deleted(table: string): string[];\n /** Pre-seed data into a table for findById/findMany. */\n seed(table: string, data: Record<string, unknown>[]): void;\n}\n\n/** Create a mock DB client with in-memory tracking. */\nexport function createMockDB(): MockDBClient {\n const store = new Map<string, Record<string, unknown>[]>();\n const tracked: TrackedRecords = {\n inserted: new Map(),\n updated: new Map(),\n deleted: new Map(),\n };\n\n return {\n async insert(table: string, data: Record<string, unknown>) {\n const record = { id: crypto.randomUUID(), ...data };\n if (!store.has(table)) store.set(table, []);\n store.get(table)!.push(record);\n if (!tracked.inserted.has(table)) tracked.inserted.set(table, []);\n tracked.inserted.get(table)!.push(record);\n return record;\n },\n\n async update(table: string, id: string, data: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n const updated = idx >= 0\n ? { ...rows[idx], ...data }\n : { id, ...data };\n if (idx >= 0) {\n rows[idx] = updated;\n }\n if (!tracked.updated.has(table)) tracked.updated.set(table, []);\n tracked.updated.get(table)!.push(updated);\n return updated;\n },\n\n async delete(table: string, id: string) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n if (idx >= 0) rows.splice(idx, 1);\n if (!tracked.deleted.has(table)) tracked.deleted.set(table, []);\n tracked.deleted.get(table)!.push(id);\n },\n\n async findById(table: string, id: string) {\n const rows = store.get(table) ?? [];\n return rows.find((r) => r[\"id\"] === id) ?? null;\n },\n\n async findMany(table: string, query?: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n if (!query) return rows;\n return rows.filter((row) =>\n Object.entries(query).every(([key, val]) => row[key] === val),\n );\n },\n\n inserted(table: string) {\n return tracked.inserted.get(table) ?? [];\n },\n\n updated(table: string) {\n return tracked.updated.get(table) ?? [];\n },\n\n deleted(table: string) {\n return tracked.deleted.get(table) ?? [];\n },\n\n seed(table: string, data: Record<string, unknown>[]) {\n store.set(table, [...data]);\n },\n };\n}\n","import type {\n CacheClient,\n EndpointContext,\n Logger,\n PalbaseBindings,\n} from \"../endpoint.js\";\nimport type { User } from \"../types.js\";\nimport { createMockDB, type MockDBClient } from \"./mock-db.js\";\n\n/** Options for creating a test context. */\nexport interface TestContextOptions<TInput = unknown> {\n user?: User | null;\n input?: TInput;\n params?: Record<string, string>;\n query?: Record<string, string>;\n headers?: Record<string, string>;\n env?: Record<string, string>;\n db?: { seed?: Record<string, Record<string, unknown>[]> };\n}\n\n/** Log entry captured by the mock logger. */\nexport interface LogEntry {\n level: \"info\" | \"warn\" | \"error\" | \"debug\";\n message: string;\n args: unknown[];\n}\n\n/** Test context with mock helpers exposed. */\nexport interface TestContext<TInput = unknown> extends EndpointContext<TInput> {\n db: MockDBClient;\n /** Captured log entries. */\n logs: LogEntry[];\n}\n\n/** Create a mock logger that captures entries. */\nfunction createMockLogger(logs: LogEntry[]): Logger {\n return {\n info(message: string, ...args: unknown[]) {\n logs.push({ level: \"info\", message, args });\n },\n warn(message: string, ...args: unknown[]) {\n logs.push({ level: \"warn\", message, args });\n },\n error(message: string, ...args: unknown[]) {\n logs.push({ level: \"error\", message, args });\n },\n debug(message: string, ...args: unknown[]) {\n logs.push({ level: \"debug\", message, args });\n },\n };\n}\n\n/** Create a mock in-memory cache. */\nfunction createMockCache(): CacheClient {\n const store = new Map<string, string>();\n\n return {\n async get(key: string) {\n return store.get(key) ?? null;\n },\n async set(key: string, value: string, _ttl?: number) {\n store.set(key, value);\n },\n async del(key: string) {\n store.delete(key);\n },\n async incr(key: string) {\n const current = parseInt(store.get(key) ?? \"0\", 10);\n const next = current + 1;\n store.set(key, String(next));\n return next;\n },\n };\n}\n\n/** Create a mock Palbase service bindings. */\nfunction createMockPalbase(): PalbaseBindings {\n return {\n auth: {},\n storage: {},\n };\n}\n\n/** Create a fully mocked EndpointContext for testing user endpoints. */\nexport function createTestContext<TInput = unknown>(\n options: TestContextOptions<TInput> = {},\n): TestContext<TInput> {\n const logs: LogEntry[] = [];\n const db = createMockDB();\n\n // Seed data if provided\n if (options.db?.seed) {\n for (const [table, data] of Object.entries(options.db.seed)) {\n db.seed(table, data);\n }\n }\n\n const ctx: TestContext<TInput> = {\n input: (options.input ?? {}) as TInput,\n params: options.params ?? {},\n query: options.query ?? {},\n headers: options.headers ?? {},\n user: options.user ?? null,\n db,\n env: options.env ?? {},\n log: createMockLogger(logs),\n cache: createMockCache(),\n palbase: createMockPalbase(),\n requestId: \"req_test_000000000000\",\n projectId: \"proj_test_000000000000\",\n environmentId: \"env_test_000000000000\",\n logs,\n };\n\n return ctx;\n}\n"],"mappings":";AAsBO,SAAS,eAA6B;AAC3C,QAAM,QAAQ,oBAAI,IAAuC;AACzD,QAAM,UAA0B;AAAA,IAC9B,UAAU,oBAAI,IAAI;AAAA,IAClB,SAAS,oBAAI,IAAI;AAAA,IACjB,SAAS,oBAAI,IAAI;AAAA,EACnB;AAEA,SAAO;AAAA,IACL,MAAM,OAAO,OAAe,MAA+B;AACzD,YAAM,SAAS,EAAE,IAAI,OAAO,WAAW,GAAG,GAAG,KAAK;AAClD,UAAI,CAAC,MAAM,IAAI,KAAK,EAAG,OAAM,IAAI,OAAO,CAAC,CAAC;AAC1C,YAAM,IAAI,KAAK,EAAG,KAAK,MAAM;AAC7B,UAAI,CAAC,QAAQ,SAAS,IAAI,KAAK,EAAG,SAAQ,SAAS,IAAI,OAAO,CAAC,CAAC;AAChE,cAAQ,SAAS,IAAI,KAAK,EAAG,KAAK,MAAM;AACxC,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,OAAO,OAAe,IAAY,MAA+B;AACrE,YAAM,OAAO,MAAM,IAAI,KAAK,KAAK,CAAC;AAClC,YAAM,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,IAAI,MAAM,EAAE;AAChD,YAAM,UAAU,OAAO,IACnB,EAAE,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,IACxB,EAAE,IAAI,GAAG,KAAK;AAClB,UAAI,OAAO,GAAG;AACZ,aAAK,GAAG,IAAI;AAAA,MACd;AACA,UAAI,CAAC,QAAQ,QAAQ,IAAI,KAAK,EAAG,SAAQ,QAAQ,IAAI,OAAO,CAAC,CAAC;AAC9D,cAAQ,QAAQ,IAAI,KAAK,EAAG,KAAK,OAAO;AACxC,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,OAAO,OAAe,IAAY;AACtC,YAAM,OAAO,MAAM,IAAI,KAAK,KAAK,CAAC;AAClC,YAAM,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,IAAI,MAAM,EAAE;AAChD,UAAI,OAAO,EAAG,MAAK,OAAO,KAAK,CAAC;AAChC,UAAI,CAAC,QAAQ,QAAQ,IAAI,KAAK,EAAG,SAAQ,QAAQ,IAAI,OAAO,CAAC,CAAC;AAC9D,cAAQ,QAAQ,IAAI,KAAK,EAAG,KAAK,EAAE;AAAA,IACrC;AAAA,IAEA,MAAM,SAAS,OAAe,IAAY;AACxC,YAAM,OAAO,MAAM,IAAI,KAAK,KAAK,CAAC;AAClC,aAAO,KAAK,KAAK,CAAC,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK;AAAA,IAC7C;AAAA,IAEA,MAAM,SAAS,OAAe,OAAiC;AAC7D,YAAM,OAAO,MAAM,IAAI,KAAK,KAAK,CAAC;AAClC,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO,KAAK;AAAA,QAAO,CAAC,QAClB,OAAO,QAAQ,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,GAAG,MAAM,IAAI,GAAG,MAAM,GAAG;AAAA,MAC9D;AAAA,IACF;AAAA,IAEA,SAAS,OAAe;AACtB,aAAO,QAAQ,SAAS,IAAI,KAAK,KAAK,CAAC;AAAA,IACzC;AAAA,IAEA,QAAQ,OAAe;AACrB,aAAO,QAAQ,QAAQ,IAAI,KAAK,KAAK,CAAC;AAAA,IACxC;AAAA,IAEA,QAAQ,OAAe;AACrB,aAAO,QAAQ,QAAQ,IAAI,KAAK,KAAK,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,OAAe,MAAiC;AACnD,YAAM,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC;AAAA,IAC5B;AAAA,EACF;AACF;;;ACxDA,SAAS,iBAAiB,MAA0B;AAClD,SAAO;AAAA,IACL,KAAK,YAAoB,MAAiB;AACxC,WAAK,KAAK,EAAE,OAAO,QAAQ,SAAS,KAAK,CAAC;AAAA,IAC5C;AAAA,IACA,KAAK,YAAoB,MAAiB;AACxC,WAAK,KAAK,EAAE,OAAO,QAAQ,SAAS,KAAK,CAAC;AAAA,IAC5C;AAAA,IACA,MAAM,YAAoB,MAAiB;AACzC,WAAK,KAAK,EAAE,OAAO,SAAS,SAAS,KAAK,CAAC;AAAA,IAC7C;AAAA,IACA,MAAM,YAAoB,MAAiB;AACzC,WAAK,KAAK,EAAE,OAAO,SAAS,SAAS,KAAK,CAAC;AAAA,IAC7C;AAAA,EACF;AACF;AAGA,SAAS,kBAA+B;AACtC,QAAM,QAAQ,oBAAI,IAAoB;AAEtC,SAAO;AAAA,IACL,MAAM,IAAI,KAAa;AACrB,aAAO,MAAM,IAAI,GAAG,KAAK;AAAA,IAC3B;AAAA,IACA,MAAM,IAAI,KAAa,OAAe,MAAe;AACnD,YAAM,IAAI,KAAK,KAAK;AAAA,IACtB;AAAA,IACA,MAAM,IAAI,KAAa;AACrB,YAAM,OAAO,GAAG;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,KAAa;AACtB,YAAM,UAAU,SAAS,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE;AAClD,YAAM,OAAO,UAAU;AACvB,YAAM,IAAI,KAAK,OAAO,IAAI,CAAC;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,SAAS,oBAAqC;AAC5C,SAAO;AAAA,IACL,MAAM,CAAC;AAAA,IACP,SAAS,CAAC;AAAA,EACZ;AACF;AAGO,SAAS,kBACd,UAAsC,CAAC,GAClB;AACrB,QAAM,OAAmB,CAAC;AAC1B,QAAM,KAAK,aAAa;AAGxB,MAAI,QAAQ,IAAI,MAAM;AACpB,eAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG,IAAI,GAAG;AAC3D,SAAG,KAAK,OAAO,IAAI;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,MAA2B;AAAA,IAC/B,OAAQ,QAAQ,SAAS,CAAC;AAAA,IAC1B,QAAQ,QAAQ,UAAU,CAAC;AAAA,IAC3B,OAAO,QAAQ,SAAS,CAAC;AAAA,IACzB,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC7B,MAAM,QAAQ,QAAQ;AAAA,IACtB;AAAA,IACA,KAAK,QAAQ,OAAO,CAAC;AAAA,IACrB,KAAK,iBAAiB,IAAI;AAAA,IAC1B,OAAO,gBAAgB;AAAA,IACvB,SAAS,kBAAkB;AAAA,IAC3B,WAAW;AAAA,IACX,WAAW;AAAA,IACX,eAAe;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/test/mock-db.ts","../../src/test/context.ts"],"sourcesContent":["import type { DBClient } from \"../endpoint.js\";\n\n/** Tracked records for assertions. */\ninterface TrackedRecords {\n inserted: Map<string, Record<string, unknown>[]>;\n updated: Map<string, Record<string, unknown>[]>;\n deleted: Map<string, string[]>;\n}\n\n/** Mock DB client with tracking and seed data support. */\nexport interface MockDBClient extends DBClient {\n /** Get records inserted into a table. */\n inserted(table: string): Record<string, unknown>[];\n /** Get records updated in a table. */\n updated(table: string): Record<string, unknown>[];\n /** Get IDs deleted from a table. */\n deleted(table: string): string[];\n /** Pre-seed data into a table for findById/findMany. */\n seed(table: string, data: Record<string, unknown>[]): void;\n}\n\n/** Create a mock DB client with in-memory tracking. */\nexport function createMockDB(): MockDBClient {\n const store = new Map<string, Record<string, unknown>[]>();\n const tracked: TrackedRecords = {\n inserted: new Map(),\n updated: new Map(),\n deleted: new Map(),\n };\n\n return {\n async query(_sql: string, _params?: unknown[]) {\n return [];\n },\n\n async insert(table: string, data: Record<string, unknown>) {\n const record = { id: crypto.randomUUID(), ...data };\n if (!store.has(table)) store.set(table, []);\n store.get(table)!.push(record);\n if (!tracked.inserted.has(table)) tracked.inserted.set(table, []);\n tracked.inserted.get(table)!.push(record);\n return record;\n },\n\n async update(table: string, id: string, data: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n const updated = idx >= 0\n ? { ...rows[idx], ...data }\n : { id, ...data };\n if (idx >= 0) {\n rows[idx] = updated;\n }\n if (!tracked.updated.has(table)) tracked.updated.set(table, []);\n tracked.updated.get(table)!.push(updated);\n return updated;\n },\n\n async delete(table: string, id: string) {\n const rows = store.get(table) ?? [];\n const idx = rows.findIndex((r) => r[\"id\"] === id);\n if (idx >= 0) rows.splice(idx, 1);\n if (!tracked.deleted.has(table)) tracked.deleted.set(table, []);\n tracked.deleted.get(table)!.push(id);\n },\n\n async findById(table: string, id: string) {\n const rows = store.get(table) ?? [];\n return rows.find((r) => r[\"id\"] === id) ?? null;\n },\n\n async findMany(table: string, query?: Record<string, unknown>) {\n const rows = store.get(table) ?? [];\n if (!query) return rows;\n return rows.filter((row) =>\n Object.entries(query).every(([key, val]) => row[key] === val),\n );\n },\n\n inserted(table: string) {\n return tracked.inserted.get(table) ?? [];\n },\n\n updated(table: string) {\n return tracked.updated.get(table) ?? [];\n },\n\n deleted(table: string) {\n return tracked.deleted.get(table) ?? [];\n },\n\n seed(table: string, data: Record<string, unknown>[]) {\n store.set(table, [...data]);\n },\n };\n}\n","import type {\n CacheClient,\n EndpointContext,\n Logger,\n PalbaseModuleClients,\n QueueClient,\n} from \"../endpoint.js\";\nimport type {\n PalbaseAuthClient,\n PalbaseStorageClient,\n PalbaseRealtimeClient,\n PalbaseFunctionsClient,\n PalbaseFlagsClient,\n PalbaseNotificationsClient,\n PalbaseAnalyticsClient,\n PalbaseLinksClient,\n PalbaseCmsClient,\n} from \"../clients.js\";\nimport type { User } from \"../types.js\";\nimport { createMockDB, type MockDBClient } from \"./mock-db.js\";\n\n/** Options for creating a test context. */\nexport interface TestContextOptions<TInput = unknown> {\n user?: User | null;\n input?: TInput;\n params?: Record<string, string>;\n query?: Record<string, string>;\n headers?: Record<string, string>;\n env?: Record<string, string>;\n db?: { seed?: Record<string, Record<string, unknown>[]> };\n}\n\n/** Log entry captured by the mock logger. */\nexport interface LogEntry {\n level: \"info\" | \"warn\" | \"error\" | \"debug\";\n message: string;\n args: unknown[];\n}\n\n/** Test context with mock helpers exposed. */\nexport interface TestContext<TInput = unknown> extends EndpointContext<TInput> {\n db: MockDBClient;\n /** Captured log entries. */\n logs: LogEntry[];\n}\n\n/** Create a mock logger that captures entries. */\nfunction createMockLogger(logs: LogEntry[]): Logger {\n return {\n info(message: string, ...args: unknown[]) {\n logs.push({ level: \"info\", message, args });\n },\n warn(message: string, ...args: unknown[]) {\n logs.push({ level: \"warn\", message, args });\n },\n error(message: string, ...args: unknown[]) {\n logs.push({ level: \"error\", message, args });\n },\n debug(message: string, ...args: unknown[]) {\n logs.push({ level: \"debug\", message, args });\n },\n };\n}\n\n/** Create a mock in-memory cache.\n *\n * Mirrors the runtime's JSON-typed semantics (values are arbitrary JSON, not\n * just strings). getOrSet is single-process here, so it does not need the\n * distributed lock the real runtime uses — it is just get-miss → fn → set.\n * The cross-replica stampede protection is covered by the worker.js tests.\n */\nfunction createMockCache(): CacheClient {\n const store = new Map<string, unknown>();\n\n const get = async <T = unknown>(key: string): Promise<T | null> => {\n return store.has(key) ? (store.get(key) as T) : null;\n };\n const set = async (key: string, value: unknown, _ttl?: number): Promise<void> => {\n store.set(key, value);\n };\n\n return {\n get,\n set,\n async del(key: string) {\n store.delete(key);\n },\n async incr(key: string) {\n const raw = store.get(key);\n const current = typeof raw === \"number\" ? raw : parseInt(String(raw ?? \"0\"), 10);\n const next = current + 1;\n store.set(key, next);\n return next;\n },\n async getOrSet<T>(key: string, ttl: number, fn: () => Promise<T> | T): Promise<T> {\n const hit = await get<T>(key);\n if (hit !== null) {\n return hit;\n }\n const value = await fn();\n await set(key, value, ttl);\n return value;\n },\n };\n}\n\n/** Create mock Palbase module clients (ctx.docs, ctx.storage, …).\n *\n * Every slot throws with a descriptive error so tests that access a\n * module client surface without configuring it fail loudly rather than\n * silently returning undefined. Override individual clients on the\n * returned context for tests that need them:\n * const ctx = createTestContext();\n * ctx.flags = { isEnabled: vi.fn().mockResolvedValue({ data: true, error: null }) };\n */\nfunction createMockModuleClients(): PalbaseModuleClients {\n const notImpl = (label: string): never => {\n throw new Error(\n `${label} not configured in test mock — override ctx.${label.split(\".\")[0]} on the returned context`,\n );\n };\n\n const docs: PalbaseModuleClients[\"docs\"] = {\n collection: () => notImpl(\"docs.collection\"),\n doc: () => notImpl(\"docs.doc\"),\n };\n\n const auth: PalbaseAuthClient = {\n verifyUserToken: () => notImpl(\"auth.verifyUserToken\"),\n getSession: () => notImpl(\"auth.getSession\"),\n mfa: {\n enroll: () => notImpl(\"auth.mfa.enroll\"),\n verifyEnrollment: () => notImpl(\"auth.mfa.verifyEnrollment\"),\n challenge: () => notImpl(\"auth.mfa.challenge\"),\n recovery: () => notImpl(\"auth.mfa.recovery\"),\n listFactors: () => notImpl(\"auth.mfa.listFactors\"),\n removeFactor: () => notImpl(\"auth.mfa.removeFactor\"),\n regenerateRecoveryCodes: () => notImpl(\"auth.mfa.regenerateRecoveryCodes\"),\n emailEnroll: () => notImpl(\"auth.mfa.emailEnroll\"),\n emailChallenge: () => notImpl(\"auth.mfa.emailChallenge\"),\n emailVerify: () => notImpl(\"auth.mfa.emailVerify\"),\n },\n device: {\n generateChallenge: () => notImpl(\"auth.device.generateChallenge\"),\n attestAndroid: () => notImpl(\"auth.device.attestAndroid\"),\n attestiOS: () => notImpl(\"auth.device.attestiOS\"),\n bind: () => notImpl(\"auth.device.bind\"),\n list: () => notImpl(\"auth.device.list\"),\n delete: () => notImpl(\"auth.device.delete\"),\n verifyRequestSignature: () => notImpl(\"auth.device.verifyRequestSignature\"),\n getToken: () => notImpl(\"auth.device.getToken\"),\n get isActive(): never {\n return notImpl(\"auth.device.isActive\");\n },\n setCachedToken: () => notImpl(\"auth.device.setCachedToken\"),\n dispose: () => notImpl(\"auth.device.dispose\"),\n },\n };\n\n const storage: PalbaseStorageClient = {\n bucket: () => notImpl(\"storage.bucket\"),\n };\n\n const realtime: PalbaseRealtimeClient = {\n channel: () => notImpl(\"realtime.channel\"),\n removeChannel: () => notImpl(\"realtime.removeChannel\"),\n removeAllChannels: () => notImpl(\"realtime.removeAllChannels\"),\n };\n\n const functions: PalbaseFunctionsClient = {\n invoke: () => notImpl(\"functions.invoke\"),\n };\n\n const flags: PalbaseFlagsClient = {\n isEnabled: () => notImpl(\"flags.isEnabled\"),\n getVariant: () => notImpl(\"flags.getVariant\"),\n getAll: () => notImpl(\"flags.getAll\"),\n };\n\n const notifications: PalbaseNotificationsClient = {\n push: { send: () => notImpl(\"notifications.push.send\") },\n email: { send: () => notImpl(\"notifications.email.send\") },\n sms: { send: () => notImpl(\"notifications.sms.send\") },\n inbox: {\n send: () => notImpl(\"notifications.inbox.send\"),\n list: () => notImpl(\"notifications.inbox.list\"),\n unreadCount: () => notImpl(\"notifications.inbox.unreadCount\"),\n markRead: () => notImpl(\"notifications.inbox.markRead\"),\n markAllRead: () => notImpl(\"notifications.inbox.markAllRead\"),\n archive: () => notImpl(\"notifications.inbox.archive\"),\n },\n preferences: {\n get: () => notImpl(\"notifications.preferences.get\"),\n update: () => notImpl(\"notifications.preferences.update\"),\n },\n registerDevice: () => notImpl(\"notifications.registerDevice\"),\n unregisterDevice: () => notImpl(\"notifications.unregisterDevice\"),\n };\n\n const analytics: PalbaseAnalyticsClient = {\n capture: () => notImpl(\"analytics.capture\"),\n identify: () => notImpl(\"analytics.identify\"),\n screen: () => notImpl(\"analytics.screen\"),\n query: {\n count: () => notImpl(\"analytics.query.count\"),\n events: () => notImpl(\"analytics.query.events\"),\n properties: () => notImpl(\"analytics.query.properties\"),\n users: () => notImpl(\"analytics.query.users\"),\n funnel: () => notImpl(\"analytics.query.funnel\"),\n retention: () => notImpl(\"analytics.query.retention\"),\n cohort: () => notImpl(\"analytics.query.cohort\"),\n },\n management: {\n overview: () => notImpl(\"analytics.management.overview\"),\n eventNames: () => notImpl(\"analytics.management.eventNames\"),\n userDetail: () => notImpl(\"analytics.management.userDetail\"),\n deleteUser: () => notImpl(\"analytics.management.deleteUser\"),\n },\n };\n\n const links: PalbaseLinksClient = {\n create: () => notImpl(\"links.create\"),\n list: () => notImpl(\"links.list\"),\n get: () => notImpl(\"links.get\"),\n update: () => notImpl(\"links.update\"),\n delete: () => notImpl(\"links.delete\"),\n analytics: () => notImpl(\"links.analytics\"),\n qrCode: () => notImpl(\"links.qrCode\"),\n match: () => notImpl(\"links.match\"),\n };\n\n const cms: PalbaseCmsClient = {\n find: () => notImpl(\"cms.find\"),\n findOne: () => notImpl(\"cms.findOne\"),\n };\n\n return {\n auth,\n storage,\n docs,\n realtime,\n functions,\n flags,\n notifications,\n analytics,\n links,\n cms,\n };\n}\n\n/** Create a fully mocked EndpointContext for testing user endpoints. */\nexport function createTestContext<TInput = unknown>(\n options: TestContextOptions<TInput> = {},\n): TestContext<TInput> {\n const logs: LogEntry[] = [];\n const db = createMockDB();\n\n // Seed data if provided\n if (options.db?.seed) {\n for (const [table, data] of Object.entries(options.db.seed)) {\n db.seed(table, data);\n }\n }\n\n const mockQueue: QueueClient = {\n push: async (_worker: string, _payload: unknown) => ({ jobId: \"\" }),\n };\n\n const ctx: TestContext<TInput> = {\n input: (options.input ?? {}) as TInput,\n params: options.params ?? {},\n query: options.query ?? {},\n headers: options.headers ?? {},\n user: options.user ?? null,\n method: \"POST\",\n endpointPath: \"/test\",\n file: null,\n db,\n env: options.env ?? {},\n log: createMockLogger(logs),\n cache: createMockCache(),\n queue: mockQueue,\n ...createMockModuleClients(),\n requestId: \"req_test_000000000000\",\n projectId: \"proj_test_000000000000\",\n environmentId: \"env_test_000000000000\",\n logs,\n };\n\n return ctx;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@palbase/backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Palbase Backend SDK — defineEndpoint, context types, schema DSL",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -48,10 +48,12 @@
|
|
|
48
48
|
"dist"
|
|
49
49
|
],
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"@asteasolutions/zod-to-openapi": "^7.3.4",
|
|
51
52
|
"zod": "^3.24.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@types/node": "^25.5.2",
|
|
56
|
+
"fast-glob": "^3.3.3",
|
|
55
57
|
"tsup": "^8.0.0",
|
|
56
58
|
"typescript": "^5.7.0",
|
|
57
59
|
"vitest": "^3.0.0"
|