@btst/stack 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.cjs +9 -1
- package/dist/api/index.d.cts +4 -4
- package/dist/api/index.d.mts +4 -4
- package/dist/api/index.d.ts +4 -4
- package/dist/api/index.mjs +9 -1
- package/dist/client/index.d.cts +2 -2
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/api/getters.cjs +42 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/getters.mjs +39 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +5 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +5 -0
- package/dist/packages/stack/src/plugins/blog/api/getters.cjs +131 -0
- package/dist/packages/stack/src/plugins/blog/api/getters.mjs +127 -0
- package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +9 -107
- package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +9 -107
- package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +1 -1
- package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +1 -1
- package/dist/packages/stack/src/plugins/cms/api/getters.cjs +146 -0
- package/dist/packages/stack/src/plugins/cms/api/getters.mjs +138 -0
- package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +560 -622
- package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +559 -621
- package/dist/packages/stack/src/plugins/cms/client/components/pages/content-editor-page.internal.cjs +1 -1
- package/dist/packages/stack/src/plugins/cms/client/components/pages/content-editor-page.internal.mjs +1 -1
- package/dist/packages/stack/src/plugins/cms/client/hooks/cms-hooks.cjs +6 -3
- package/dist/packages/stack/src/plugins/cms/client/hooks/cms-hooks.mjs +6 -3
- package/dist/packages/stack/src/plugins/form-builder/api/getters.cjs +111 -0
- package/dist/packages/stack/src/plugins/form-builder/api/getters.mjs +104 -0
- package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +16 -88
- package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +12 -84
- package/dist/packages/stack/src/plugins/form-builder/client/components/pages/submissions-page.internal.cjs +1 -1
- package/dist/packages/stack/src/plugins/form-builder/client/components/pages/submissions-page.internal.mjs +1 -1
- package/dist/packages/stack/src/plugins/kanban/api/getters.cjs +84 -0
- package/dist/packages/stack/src/plugins/kanban/api/getters.mjs +81 -0
- package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +9 -123
- package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +9 -123
- package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +1 -1
- package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +1 -1
- package/dist/plugins/ai-chat/api/index.cjs +3 -0
- package/dist/plugins/ai-chat/api/index.d.cts +27 -4
- package/dist/plugins/ai-chat/api/index.d.mts +27 -4
- package/dist/plugins/ai-chat/api/index.d.ts +27 -4
- package/dist/plugins/ai-chat/api/index.mjs +1 -0
- package/dist/plugins/ai-chat/client/hooks/index.d.cts +2 -2
- package/dist/plugins/ai-chat/client/hooks/index.d.mts +2 -2
- package/dist/plugins/ai-chat/client/hooks/index.d.ts +2 -2
- package/dist/plugins/ai-chat/query-keys.d.cts +9 -284
- package/dist/plugins/ai-chat/query-keys.d.mts +9 -284
- package/dist/plugins/ai-chat/query-keys.d.ts +9 -284
- package/dist/plugins/api/index.d.cts +4 -3
- package/dist/plugins/api/index.d.mts +4 -3
- package/dist/plugins/api/index.d.ts +4 -3
- package/dist/plugins/blog/api/index.cjs +4 -0
- package/dist/plugins/blog/api/index.d.cts +3 -2
- package/dist/plugins/blog/api/index.d.mts +3 -2
- package/dist/plugins/blog/api/index.d.ts +3 -2
- package/dist/plugins/blog/api/index.mjs +1 -0
- package/dist/plugins/blog/client/hooks/index.d.cts +4 -4
- package/dist/plugins/blog/client/hooks/index.d.mts +4 -4
- package/dist/plugins/blog/client/hooks/index.d.ts +4 -4
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.cjs +7 -4
- package/dist/plugins/blog/query-keys.d.cts +81 -27
- package/dist/plugins/blog/query-keys.d.mts +81 -27
- package/dist/plugins/blog/query-keys.d.ts +81 -27
- package/dist/plugins/blog/query-keys.mjs +7 -4
- package/dist/plugins/client/index.d.cts +2 -2
- package/dist/plugins/client/index.d.mts +2 -2
- package/dist/plugins/client/index.d.ts +2 -2
- package/dist/plugins/cms/api/index.cjs +4 -0
- package/dist/plugins/cms/api/index.d.cts +61 -5
- package/dist/plugins/cms/api/index.d.mts +61 -5
- package/dist/plugins/cms/api/index.d.ts +61 -5
- package/dist/plugins/cms/api/index.mjs +1 -0
- package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
- package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
- package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
- package/dist/plugins/cms/query-keys.d.cts +2 -1
- package/dist/plugins/cms/query-keys.d.mts +2 -1
- package/dist/plugins/cms/query-keys.d.ts +2 -1
- package/dist/plugins/form-builder/api/index.cjs +4 -0
- package/dist/plugins/form-builder/api/index.d.cts +77 -7
- package/dist/plugins/form-builder/api/index.d.mts +77 -7
- package/dist/plugins/form-builder/api/index.d.ts +77 -7
- package/dist/plugins/form-builder/api/index.mjs +1 -0
- package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
- package/dist/plugins/form-builder/query-keys.d.cts +2 -1
- package/dist/plugins/form-builder/query-keys.d.mts +2 -1
- package/dist/plugins/form-builder/query-keys.d.ts +2 -1
- package/dist/plugins/kanban/api/index.cjs +3 -0
- package/dist/plugins/kanban/api/index.d.cts +40 -43
- package/dist/plugins/kanban/api/index.d.mts +40 -43
- package/dist/plugins/kanban/api/index.d.ts +40 -43
- package/dist/plugins/kanban/api/index.mjs +1 -0
- package/dist/plugins/kanban/client/components/index.d.cts +1 -1
- package/dist/plugins/kanban/client/components/index.d.mts +1 -1
- package/dist/plugins/kanban/client/components/index.d.ts +1 -1
- package/dist/plugins/kanban/client/hooks/index.d.cts +1 -1
- package/dist/plugins/kanban/client/hooks/index.d.mts +1 -1
- package/dist/plugins/kanban/client/hooks/index.d.ts +1 -1
- package/dist/plugins/kanban/client/index.d.cts +1 -1
- package/dist/plugins/kanban/client/index.d.mts +1 -1
- package/dist/plugins/kanban/client/index.d.ts +1 -1
- package/dist/plugins/kanban/query-keys.cjs +4 -3
- package/dist/plugins/kanban/query-keys.d.cts +2 -1
- package/dist/plugins/kanban/query-keys.d.mts +2 -1
- package/dist/plugins/kanban/query-keys.d.ts +2 -1
- package/dist/plugins/kanban/query-keys.mjs +4 -3
- package/dist/plugins/open-api/api/index.d.cts +2 -2
- package/dist/plugins/open-api/api/index.d.mts +2 -2
- package/dist/plugins/open-api/api/index.d.ts +2 -2
- package/dist/plugins/route-docs/client/index.d.cts +1 -1
- package/dist/plugins/route-docs/client/index.d.mts +1 -1
- package/dist/plugins/route-docs/client/index.d.ts +1 -1
- package/dist/plugins/ui-builder/index.d.cts +1 -1
- package/dist/plugins/ui-builder/index.d.mts +1 -1
- package/dist/plugins/ui-builder/index.d.ts +1 -1
- package/dist/shared/{stack.BoA0xkJv.d.cts → stack.7n9Y_u7N.d.cts} +33 -7
- package/dist/shared/{stack.BoA0xkJv.d.mts → stack.7n9Y_u7N.d.mts} +33 -7
- package/dist/shared/{stack.BoA0xkJv.d.ts → stack.7n9Y_u7N.d.ts} +33 -7
- package/dist/shared/stack.BeSm90va.d.ts +289 -0
- package/dist/shared/{stack.DzH_wcvr.d.mts → stack.CIrIsc-A.d.cts} +2 -2
- package/dist/shared/{stack.DzH_wcvr.d.ts → stack.CIrIsc-A.d.mts} +2 -2
- package/dist/shared/{stack.DzH_wcvr.d.cts → stack.CIrIsc-A.d.ts} +2 -2
- package/dist/shared/stack.CMh_EdxW.d.cts +289 -0
- package/dist/shared/{stack.BsXokfNh.d.mts → stack.CXjzTMsb.d.cts} +1 -1
- package/dist/shared/{stack.BsXokfNh.d.ts → stack.CXjzTMsb.d.mts} +1 -1
- package/dist/shared/{stack.BsXokfNh.d.cts → stack.CXjzTMsb.d.ts} +1 -1
- package/dist/shared/stack.Dg09R0oB.d.mts +289 -0
- package/dist/shared/{stack.DKDMI-QO.d.mts → stack.QD1y_7NY.d.cts} +7 -1
- package/dist/shared/{stack.DKDMI-QO.d.ts → stack.QD1y_7NY.d.mts} +7 -1
- package/dist/shared/{stack.DKDMI-QO.d.cts → stack.QD1y_7NY.d.ts} +7 -1
- package/package.json +1 -1
- package/src/__tests__/stack-api.test.ts +118 -0
- package/src/api/index.ts +15 -1
- package/src/plugins/ai-chat/__tests__/getters.test.ts +109 -0
- package/src/plugins/ai-chat/api/getters.ts +71 -0
- package/src/plugins/ai-chat/api/index.ts +1 -0
- package/src/plugins/ai-chat/api/plugin.ts +8 -0
- package/src/plugins/api/index.ts +3 -1
- package/src/plugins/blog/__tests__/getters.test.ts +540 -0
- package/src/plugins/blog/api/getters.ts +243 -0
- package/src/plugins/blog/api/index.ts +7 -0
- package/src/plugins/blog/api/plugin.ts +13 -141
- package/src/plugins/blog/client/plugin.tsx +2 -1
- package/src/plugins/blog/query-keys.ts +16 -13
- package/src/plugins/cms/__tests__/getters.test.ts +206 -0
- package/src/plugins/cms/api/getters.ts +244 -0
- package/src/plugins/cms/api/index.ts +5 -0
- package/src/plugins/cms/api/plugin.ts +50 -154
- package/src/plugins/cms/client/components/pages/content-editor-page.internal.tsx +1 -1
- package/src/plugins/cms/client/hooks/cms-hooks.tsx +3 -0
- package/src/plugins/cms/types.ts +1 -1
- package/src/plugins/form-builder/__tests__/getters.test.ts +159 -0
- package/src/plugins/form-builder/api/getters.ts +203 -0
- package/src/plugins/form-builder/api/index.ts +1 -0
- package/src/plugins/form-builder/api/plugin.ts +22 -115
- package/src/plugins/form-builder/client/components/pages/submissions-page.internal.tsx +1 -1
- package/src/plugins/form-builder/types.ts +2 -2
- package/src/plugins/kanban/__tests__/getters.test.ts +172 -0
- package/src/plugins/kanban/api/getters.ts +149 -0
- package/src/plugins/kanban/api/index.ts +1 -0
- package/src/plugins/kanban/api/plugin.ts +16 -146
- package/src/plugins/kanban/client/plugin.tsx +2 -1
- package/src/plugins/kanban/query-keys.ts +8 -5
- package/src/types.ts +44 -5
- package/dist/shared/{stack.CbuN2zVV.d.cts → stack.BkYlUT_8.d.cts} +6 -6
- package/dist/shared/{stack.CbuN2zVV.d.mts → stack.BkYlUT_8.d.mts} +6 -6
- package/dist/shared/{stack.CbuN2zVV.d.ts → stack.BkYlUT_8.d.ts} +6 -6
|
@@ -5,7 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { kanbanSchema as dbSchema } from "../db";
|
|
6
6
|
import type {
|
|
7
7
|
Board,
|
|
8
|
-
|
|
8
|
+
BoardWithColumns,
|
|
9
9
|
Column,
|
|
10
10
|
ColumnWithTasks,
|
|
11
11
|
Task,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
updateColumnSchema,
|
|
24
24
|
updateTaskSchema,
|
|
25
25
|
} from "../schemas";
|
|
26
|
+
import { getAllBoards, getBoardById } from "./getters";
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Context passed to kanban API hooks
|
|
@@ -84,10 +85,12 @@ export interface KanbanBackendHooks {
|
|
|
84
85
|
) => Promise<boolean> | boolean;
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
|
-
* Called after boards are listed successfully
|
|
88
|
+
* Called after boards are listed successfully.
|
|
89
|
+
* Receives the items array (same shape as `board[]`) for consistency
|
|
90
|
+
* with analogous hooks in other plugins (e.g. `onPostsRead`).
|
|
88
91
|
*/
|
|
89
92
|
onBoardsRead?: (
|
|
90
|
-
boards:
|
|
93
|
+
boards: BoardWithColumns[],
|
|
91
94
|
filter: z.infer<typeof BoardListQuerySchema>,
|
|
92
95
|
context: KanbanApiContext,
|
|
93
96
|
) => Promise<void> | void;
|
|
@@ -261,6 +264,12 @@ export const kanbanBackendPlugin = (hooks?: KanbanBackendHooks) =>
|
|
|
261
264
|
|
|
262
265
|
dbPlugin: dbSchema,
|
|
263
266
|
|
|
267
|
+
api: (adapter) => ({
|
|
268
|
+
getAllBoards: (params?: Parameters<typeof getAllBoards>[1]) =>
|
|
269
|
+
getAllBoards(adapter, params),
|
|
270
|
+
getBoardById: (id: string) => getBoardById(adapter, id),
|
|
271
|
+
}),
|
|
272
|
+
|
|
264
273
|
routes: (adapter: Adapter) => {
|
|
265
274
|
// ============ Board Endpoints ============
|
|
266
275
|
|
|
@@ -284,100 +293,10 @@ export const kanbanBackendPlugin = (hooks?: KanbanBackendHooks) =>
|
|
|
284
293
|
}
|
|
285
294
|
}
|
|
286
295
|
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
if (query.slug) {
|
|
290
|
-
whereConditions.push({
|
|
291
|
-
field: "slug",
|
|
292
|
-
value: query.slug,
|
|
293
|
-
operator: "eq" as const,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (query.ownerId) {
|
|
298
|
-
whereConditions.push({
|
|
299
|
-
field: "ownerId",
|
|
300
|
-
value: query.ownerId,
|
|
301
|
-
operator: "eq" as const,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (query.organizationId) {
|
|
306
|
-
whereConditions.push({
|
|
307
|
-
field: "organizationId",
|
|
308
|
-
value: query.organizationId,
|
|
309
|
-
operator: "eq" as const,
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const boards = await adapter.findMany<BoardWithKanbanColumn>({
|
|
314
|
-
model: "kanbanBoard",
|
|
315
|
-
limit: query.limit ?? 50,
|
|
316
|
-
offset: query.offset ?? 0,
|
|
317
|
-
where: whereConditions,
|
|
318
|
-
sortBy: {
|
|
319
|
-
field: "createdAt",
|
|
320
|
-
direction: "desc",
|
|
321
|
-
},
|
|
322
|
-
join: {
|
|
323
|
-
kanbanColumn: true,
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Get all column IDs to fetch tasks
|
|
328
|
-
// Note: adapter returns joined data under schema key name ("column"), not model name
|
|
329
|
-
const columnIds: string[] = [];
|
|
330
|
-
for (const board of boards) {
|
|
331
|
-
if (board.column) {
|
|
332
|
-
for (const col of board.column) {
|
|
333
|
-
columnIds.push(col.id);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Fetch tasks for each column in parallel (avoids loading all tasks from DB)
|
|
339
|
-
const tasksByColumn = new Map<string, Task[]>();
|
|
340
|
-
if (columnIds.length > 0) {
|
|
341
|
-
const taskQueries = columnIds.map((columnId) =>
|
|
342
|
-
adapter.findMany<Task>({
|
|
343
|
-
model: "kanbanTask",
|
|
344
|
-
where: [
|
|
345
|
-
{
|
|
346
|
-
field: "columnId",
|
|
347
|
-
value: columnId,
|
|
348
|
-
operator: "eq" as const,
|
|
349
|
-
},
|
|
350
|
-
],
|
|
351
|
-
sortBy: { field: "order", direction: "asc" },
|
|
352
|
-
}),
|
|
353
|
-
);
|
|
354
|
-
const taskResults = await Promise.all(taskQueries);
|
|
355
|
-
for (let i = 0; i < columnIds.length; i++) {
|
|
356
|
-
const columnId = columnIds[i];
|
|
357
|
-
const tasks = taskResults[i];
|
|
358
|
-
if (columnId && tasks) {
|
|
359
|
-
tasksByColumn.set(columnId, tasks);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Map boards with columns and tasks
|
|
365
|
-
const result = boards.map((board) => {
|
|
366
|
-
const columns = (board.column || [])
|
|
367
|
-
.sort((a, b) => a.order - b.order)
|
|
368
|
-
.map((col) => ({
|
|
369
|
-
...col,
|
|
370
|
-
tasks: tasksByColumn.get(col.id) || [],
|
|
371
|
-
}));
|
|
372
|
-
const { column: _, ...boardWithoutJoin } = board;
|
|
373
|
-
return {
|
|
374
|
-
...boardWithoutJoin,
|
|
375
|
-
columns,
|
|
376
|
-
};
|
|
377
|
-
});
|
|
296
|
+
const result = await getAllBoards(adapter, query);
|
|
378
297
|
|
|
379
298
|
if (hooks?.onBoardsRead) {
|
|
380
|
-
await hooks.onBoardsRead(result, query, context);
|
|
299
|
+
await hooks.onBoardsRead(result.items, query, context);
|
|
381
300
|
}
|
|
382
301
|
|
|
383
302
|
return result;
|
|
@@ -409,61 +328,12 @@ export const kanbanBackendPlugin = (hooks?: KanbanBackendHooks) =>
|
|
|
409
328
|
}
|
|
410
329
|
}
|
|
411
330
|
|
|
412
|
-
const
|
|
413
|
-
model: "kanbanBoard",
|
|
414
|
-
where: [
|
|
415
|
-
{ field: "id", value: params.id, operator: "eq" as const },
|
|
416
|
-
],
|
|
417
|
-
join: {
|
|
418
|
-
kanbanColumn: true,
|
|
419
|
-
},
|
|
420
|
-
});
|
|
331
|
+
const result = await getBoardById(adapter, params.id);
|
|
421
332
|
|
|
422
|
-
if (!
|
|
333
|
+
if (!result) {
|
|
423
334
|
throw ctx.error(404, { message: "Board not found" });
|
|
424
335
|
}
|
|
425
336
|
|
|
426
|
-
// Fetch tasks for each column in parallel (avoids loading all tasks from DB)
|
|
427
|
-
// Note: adapter returns joined data under schema key name ("column"), not model name
|
|
428
|
-
const columnIds = (board.column || []).map((c) => c.id);
|
|
429
|
-
const tasksByColumn = new Map<string, Task[]>();
|
|
430
|
-
if (columnIds.length > 0) {
|
|
431
|
-
const taskQueries = columnIds.map((columnId) =>
|
|
432
|
-
adapter.findMany<Task>({
|
|
433
|
-
model: "kanbanTask",
|
|
434
|
-
where: [
|
|
435
|
-
{
|
|
436
|
-
field: "columnId",
|
|
437
|
-
value: columnId,
|
|
438
|
-
operator: "eq" as const,
|
|
439
|
-
},
|
|
440
|
-
],
|
|
441
|
-
sortBy: { field: "order", direction: "asc" },
|
|
442
|
-
}),
|
|
443
|
-
);
|
|
444
|
-
const taskResults = await Promise.all(taskQueries);
|
|
445
|
-
for (let i = 0; i < columnIds.length; i++) {
|
|
446
|
-
const columnId = columnIds[i];
|
|
447
|
-
const tasks = taskResults[i];
|
|
448
|
-
if (columnId && tasks) {
|
|
449
|
-
tasksByColumn.set(columnId, tasks);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
const columns = (board.column || [])
|
|
455
|
-
.sort((a, b) => a.order - b.order)
|
|
456
|
-
.map((col) => ({
|
|
457
|
-
...col,
|
|
458
|
-
tasks: tasksByColumn.get(col.id) || [],
|
|
459
|
-
}));
|
|
460
|
-
|
|
461
|
-
const { column: _, ...boardWithoutJoin } = board;
|
|
462
|
-
const result = {
|
|
463
|
-
...boardWithoutJoin,
|
|
464
|
-
columns,
|
|
465
|
-
};
|
|
466
|
-
|
|
467
337
|
if (hooks?.onBoardRead) {
|
|
468
338
|
await hooks.onBoardRead(result, context);
|
|
469
339
|
}
|
|
@@ -437,7 +437,8 @@ export const kanbanClientPlugin = (config: KanbanClientConfig) =>
|
|
|
437
437
|
method: "GET",
|
|
438
438
|
query: { limit: 100 },
|
|
439
439
|
});
|
|
440
|
-
boards
|
|
440
|
+
// /boards returns BoardListResult { items, total, limit, offset }
|
|
441
|
+
boards = ((res.data as any)?.items ??
|
|
441
442
|
[]) as SerializedBoardWithColumns[];
|
|
442
443
|
} catch {
|
|
443
444
|
// Ignore errors for sitemap
|
|
@@ -91,8 +91,10 @@ function createBoardsQueries(
|
|
|
91
91
|
throw toError(errorResponse.error);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
const envelope = (response as { data?: unknown }).data as
|
|
95
|
+
| { items?: SerializedBoardWithColumns[] }
|
|
96
|
+
| undefined;
|
|
97
|
+
return envelope?.items ?? ([] as SerializedBoardWithColumns[]);
|
|
96
98
|
} catch (error) {
|
|
97
99
|
throw error;
|
|
98
100
|
}
|
|
@@ -142,9 +144,10 @@ function createBoardsQueries(
|
|
|
142
144
|
throw toError(errorResponse.error);
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
const envelope = (response as { data?: unknown }).data as
|
|
148
|
+
| { items?: SerializedBoardWithColumns[] }
|
|
149
|
+
| undefined;
|
|
150
|
+
return envelope?.items?.[0] ?? null;
|
|
148
151
|
} catch (error) {
|
|
149
152
|
throw error;
|
|
150
153
|
}
|
package/src/types.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { Endpoint, Router } from "better-call";
|
|
|
8
8
|
*/
|
|
9
9
|
export interface StackContext {
|
|
10
10
|
/** All registered backend plugins */
|
|
11
|
-
plugins: Record<string, BackendPlugin<any>>;
|
|
11
|
+
plugins: Record<string, BackendPlugin<any, any>>;
|
|
12
12
|
/** The API base path (e.g., "/api/data") */
|
|
13
13
|
basePath: string;
|
|
14
14
|
/** The database adapter */
|
|
@@ -40,9 +40,13 @@ export interface ClientStackContext<
|
|
|
40
40
|
* You can optionally provide a base schema via the dbSchema config option.
|
|
41
41
|
*
|
|
42
42
|
* @template TRoutes - The exact shape of routes this plugin provides (preserves keys and endpoint types)
|
|
43
|
+
* @template TApi - The shape of the server-side API surface exposed via `stack().api`.
|
|
44
|
+
* Defaults to `never` so that plugins without an `api` factory are excluded from the
|
|
45
|
+
* `stack().api` namespace entirely, preventing accidental access of `undefined` at runtime.
|
|
43
46
|
*/
|
|
44
47
|
export interface BackendPlugin<
|
|
45
48
|
TRoutes extends Record<string, Endpoint> = Record<string, Endpoint>,
|
|
49
|
+
TApi extends Record<string, (...args: any[]) => any> = never,
|
|
46
50
|
> {
|
|
47
51
|
name: string;
|
|
48
52
|
|
|
@@ -56,6 +60,15 @@ export interface BackendPlugin<
|
|
|
56
60
|
*/
|
|
57
61
|
routes: (adapter: Adapter, context?: StackContext) => TRoutes;
|
|
58
62
|
dbPlugin: DbPlugin;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Optional factory that returns server-side getter functions bound to the adapter.
|
|
66
|
+
* The returned object is merged into `stack().api.<pluginName>.*` for direct
|
|
67
|
+
* server-side or SSG data access without going through HTTP.
|
|
68
|
+
*
|
|
69
|
+
* @param adapter - The adapter instance shared with `routes`
|
|
70
|
+
*/
|
|
71
|
+
api?: (adapter: Adapter) => TApi;
|
|
59
72
|
}
|
|
60
73
|
|
|
61
74
|
/**
|
|
@@ -87,13 +100,30 @@ export interface ClientPlugin<
|
|
|
87
100
|
sitemap?: () => Promise<Sitemap> | Sitemap;
|
|
88
101
|
}
|
|
89
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Utility type that maps each plugin key to the return type of its `api` factory.
|
|
105
|
+
* Plugin keys whose `TApi` resolves to `never` (i.e. plugins with no `api` factory)
|
|
106
|
+
* are excluded from the resulting type via key remapping, preventing TypeScript from
|
|
107
|
+
* suggesting callable functions on what is actually `undefined` at runtime.
|
|
108
|
+
*/
|
|
109
|
+
export type PluginApis<
|
|
110
|
+
TPlugins extends Record<string, BackendPlugin<any, any>>,
|
|
111
|
+
> = {
|
|
112
|
+
[K in keyof TPlugins as _ApiOf<TPlugins[K]> extends never
|
|
113
|
+
? never
|
|
114
|
+
: K]: _ApiOf<TPlugins[K]>;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/** @internal Extract the TApi parameter from a BackendPlugin type. */
|
|
118
|
+
type _ApiOf<T> = T extends BackendPlugin<any, infer TApi> ? TApi : never;
|
|
119
|
+
|
|
90
120
|
/**
|
|
91
121
|
* Configuration for creating the backend library
|
|
92
122
|
*/
|
|
93
123
|
export interface BackendLibConfig<
|
|
94
|
-
TPlugins extends Record<string, BackendPlugin<any>> = Record<
|
|
124
|
+
TPlugins extends Record<string, BackendPlugin<any, any>> = Record<
|
|
95
125
|
string,
|
|
96
|
-
BackendPlugin<any>
|
|
126
|
+
BackendPlugin<any, any>
|
|
97
127
|
>,
|
|
98
128
|
> {
|
|
99
129
|
basePath: string;
|
|
@@ -150,11 +180,12 @@ export type PluginRoutes<
|
|
|
150
180
|
* Example: { messages: { list: Endpoint } } => { messages_list: Endpoint }
|
|
151
181
|
*/
|
|
152
182
|
export type PrefixedPluginRoutes<
|
|
153
|
-
TPlugins extends Record<string, BackendPlugin<any>>,
|
|
183
|
+
TPlugins extends Record<string, BackendPlugin<any, any>>,
|
|
154
184
|
> = UnionToIntersection<
|
|
155
185
|
{
|
|
156
186
|
[PluginKey in keyof TPlugins]: TPlugins[PluginKey] extends BackendPlugin<
|
|
157
|
-
infer TRoutes
|
|
187
|
+
infer TRoutes,
|
|
188
|
+
any
|
|
158
189
|
>
|
|
159
190
|
? {
|
|
160
191
|
[RouteKey in keyof TRoutes as `${PluginKey & string}_${RouteKey & string}`]: TRoutes[RouteKey];
|
|
@@ -172,10 +203,18 @@ export type PrefixedPluginRoutes<
|
|
|
172
203
|
*/
|
|
173
204
|
export interface BackendLib<
|
|
174
205
|
TRoutes extends Record<string, Endpoint> = Record<string, Endpoint>,
|
|
206
|
+
TApis extends Record<
|
|
207
|
+
string,
|
|
208
|
+
Record<string, (...args: any[]) => any>
|
|
209
|
+
> = Record<string, Record<string, (...args: any[]) => any>>,
|
|
175
210
|
> {
|
|
176
211
|
handler: (request: Request) => Promise<Response>; // API route handler
|
|
177
212
|
router: Router; // Better-call router
|
|
178
213
|
dbSchema: DatabaseDefinition; // Better-db schema
|
|
214
|
+
/** The database adapter shared across all plugins */
|
|
215
|
+
adapter: Adapter;
|
|
216
|
+
/** Fully-typed server-side getter functions, namespaced per plugin */
|
|
217
|
+
api: TApis;
|
|
179
218
|
}
|
|
180
219
|
|
|
181
220
|
/**
|
|
@@ -35,15 +35,12 @@ interface SerializedTag extends Omit<Tag, "createdAt" | "updatedAt"> {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
declare const createPostSchema: z.ZodObject<{
|
|
38
|
+
title: z.ZodString;
|
|
38
39
|
slug: z.ZodOptional<z.ZodString>;
|
|
39
|
-
|
|
40
|
+
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
40
41
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
41
42
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
42
|
-
|
|
43
|
-
content: z.ZodString;
|
|
44
|
-
excerpt: z.ZodString;
|
|
45
|
-
image: z.ZodOptional<z.ZodString>;
|
|
46
|
-
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
43
|
+
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
47
44
|
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
48
45
|
name: z.ZodString;
|
|
49
46
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -51,6 +48,9 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
51
48
|
name: z.ZodString;
|
|
52
49
|
slug: z.ZodString;
|
|
53
50
|
}, z.core.$strip>]>>>>;
|
|
51
|
+
content: z.ZodString;
|
|
52
|
+
excerpt: z.ZodString;
|
|
53
|
+
image: z.ZodOptional<z.ZodString>;
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
declare const updatePostSchema: z.ZodObject<{
|
|
56
56
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -35,15 +35,12 @@ interface SerializedTag extends Omit<Tag, "createdAt" | "updatedAt"> {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
declare const createPostSchema: z.ZodObject<{
|
|
38
|
+
title: z.ZodString;
|
|
38
39
|
slug: z.ZodOptional<z.ZodString>;
|
|
39
|
-
|
|
40
|
+
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
40
41
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
41
42
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
42
|
-
|
|
43
|
-
content: z.ZodString;
|
|
44
|
-
excerpt: z.ZodString;
|
|
45
|
-
image: z.ZodOptional<z.ZodString>;
|
|
46
|
-
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
43
|
+
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
47
44
|
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
48
45
|
name: z.ZodString;
|
|
49
46
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -51,6 +48,9 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
51
48
|
name: z.ZodString;
|
|
52
49
|
slug: z.ZodString;
|
|
53
50
|
}, z.core.$strip>]>>>>;
|
|
51
|
+
content: z.ZodString;
|
|
52
|
+
excerpt: z.ZodString;
|
|
53
|
+
image: z.ZodOptional<z.ZodString>;
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
declare const updatePostSchema: z.ZodObject<{
|
|
56
56
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -35,15 +35,12 @@ interface SerializedTag extends Omit<Tag, "createdAt" | "updatedAt"> {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
declare const createPostSchema: z.ZodObject<{
|
|
38
|
+
title: z.ZodString;
|
|
38
39
|
slug: z.ZodOptional<z.ZodString>;
|
|
39
|
-
|
|
40
|
+
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
40
41
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
41
42
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
42
|
-
|
|
43
|
-
content: z.ZodString;
|
|
44
|
-
excerpt: z.ZodString;
|
|
45
|
-
image: z.ZodOptional<z.ZodString>;
|
|
46
|
-
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
43
|
+
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
47
44
|
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
48
45
|
name: z.ZodString;
|
|
49
46
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -51,6 +48,9 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
51
48
|
name: z.ZodString;
|
|
52
49
|
slug: z.ZodString;
|
|
53
50
|
}, z.core.$strip>]>>>>;
|
|
51
|
+
content: z.ZodString;
|
|
52
|
+
excerpt: z.ZodString;
|
|
53
|
+
image: z.ZodOptional<z.ZodString>;
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
declare const updatePostSchema: z.ZodObject<{
|
|
56
56
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|