@btst/stack 2.11.0 → 2.11.1
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/packages/stack/src/plugins/media/api/plugin.cjs +4 -1
- package/dist/packages/stack/src/plugins/media/api/plugin.mjs +5 -2
- package/dist/plugins/blog/api/index.d.cts +2 -2
- package/dist/plugins/blog/api/index.d.mts +2 -2
- package/dist/plugins/blog/api/index.d.ts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +2 -2
- package/dist/plugins/blog/client/index.d.mts +2 -2
- package/dist/plugins/blog/client/index.d.ts +2 -2
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/kanban/api/index.d.cts +1 -1
- package/dist/plugins/kanban/api/index.d.mts +1 -1
- package/dist/plugins/kanban/api/index.d.ts +1 -1
- package/dist/plugins/kanban/query-keys.d.cts +1 -1
- package/dist/plugins/kanban/query-keys.d.mts +1 -1
- package/dist/plugins/kanban/query-keys.d.ts +1 -1
- package/dist/{packages/stack/src/plugins → plugins}/media/api/adapters/local.cjs +7 -1
- package/dist/plugins/media/api/adapters/local.d.cts +30 -0
- package/dist/plugins/media/api/adapters/local.d.mts +30 -0
- package/dist/plugins/media/api/adapters/local.d.ts +30 -0
- package/dist/{packages/stack/src/plugins → plugins}/media/api/adapters/local.mjs +7 -1
- package/dist/plugins/media/api/adapters/s3.d.cts +1 -1
- package/dist/plugins/media/api/adapters/s3.d.mts +1 -1
- package/dist/plugins/media/api/adapters/s3.d.ts +1 -1
- package/dist/plugins/media/api/adapters/vercel-blob.d.cts +1 -1
- package/dist/plugins/media/api/adapters/vercel-blob.d.mts +1 -1
- package/dist/plugins/media/api/adapters/vercel-blob.d.ts +1 -1
- package/dist/plugins/media/api/index.cjs +0 -2
- package/dist/plugins/media/api/index.d.cts +5 -102
- package/dist/plugins/media/api/index.d.mts +5 -102
- package/dist/plugins/media/api/index.d.ts +5 -102
- package/dist/plugins/media/api/index.mjs +0 -1
- package/dist/plugins/media/query-keys.d.cts +2 -2
- package/dist/plugins/media/query-keys.d.mts +2 -2
- package/dist/plugins/media/query-keys.d.ts +2 -2
- package/dist/shared/{stack.Bci0-plK.d.ts → stack.C5ucdatf.d.ts} +76 -3
- package/dist/shared/{stack.IUeyQKrm.d.mts → stack.DEW8EtFu.d.cts} +13 -13
- package/dist/shared/{stack.6mEHS2WH.d.mts → stack.DGsFF5qb.d.cts} +6 -6
- package/dist/shared/{stack.C_MUwwgR.d.mts → stack.DpZoZd98.d.mts} +76 -3
- package/dist/shared/{stack.DjgpFWq3.d.cts → stack.DvMUCTTl.d.mts} +13 -13
- package/dist/shared/{stack.AJTXI7kw.d.cts → stack.NtflNnnH.d.mts} +6 -6
- package/dist/shared/{stack.QYn-Px94.d.ts → stack.QrBE0Bc8.d.ts} +6 -6
- package/dist/shared/{stack.DO6vOGQG.d.cts → stack.lkebw2nj.d.cts} +1 -1
- package/dist/shared/{stack.DO6vOGQG.d.mts → stack.lkebw2nj.d.mts} +1 -1
- package/dist/shared/{stack.DO6vOGQG.d.ts → stack.lkebw2nj.d.ts} +1 -1
- package/dist/shared/{stack.D7HSzZdG.d.ts → stack.qta0-CPq.d.ts} +13 -13
- package/dist/shared/{stack.D6zyQnMo.d.cts → stack.vVFh38aS.d.cts} +76 -3
- package/package.json +14 -1
- package/src/plugins/media/__tests__/storage-adapters.test.ts +11 -0
- package/src/plugins/media/api/adapters/local.ts +10 -1
- package/src/plugins/media/api/index.ts +0 -5
- package/src/plugins/media/api/plugin.ts +6 -0
- package/dist/shared/{stack.eq5eg1yt.d.cts → stack.BOokfhZD.d.cts} +13 -13
- package/dist/shared/{stack.CMbX8Q5C.d.ts → stack.BvCR4-9H.d.ts} +13 -13
- package/dist/shared/{stack.Dj04W2c3.d.mts → stack.CWxAl9K3.d.mts} +13 -13
- package/dist/shared/{stack.BQmuNl5p.d.ts → stack.Sod_PZhB.d.cts} +9 -9
- package/dist/shared/{stack.BQmuNl5p.d.cts → stack.Sod_PZhB.d.mts} +9 -9
- package/dist/shared/{stack.BQmuNl5p.d.mts → stack.Sod_PZhB.d.ts} +9 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
|
-
import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.
|
|
2
|
+
import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.Sod_PZhB.mjs';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -128,6 +128,10 @@ declare function useSuspenseTags(): {
|
|
|
128
128
|
};
|
|
129
129
|
/** Create a new post */
|
|
130
130
|
declare function useCreatePost(): _tanstack_react_query.UseMutationResult<SerializedPost | null, Error, {
|
|
131
|
+
published: boolean;
|
|
132
|
+
title: string;
|
|
133
|
+
content: string;
|
|
134
|
+
excerpt: string;
|
|
131
135
|
tags: ({
|
|
132
136
|
name: string;
|
|
133
137
|
} | {
|
|
@@ -135,14 +139,10 @@ declare function useCreatePost(): _tanstack_react_query.UseMutationResult<Serial
|
|
|
135
139
|
name: string;
|
|
136
140
|
slug: string;
|
|
137
141
|
})[];
|
|
138
|
-
title: string;
|
|
139
|
-
content: string;
|
|
140
|
-
excerpt: string;
|
|
141
|
-
published: boolean;
|
|
142
142
|
slug?: string | undefined;
|
|
143
|
+
publishedAt?: Date | undefined;
|
|
143
144
|
createdAt?: Date | undefined;
|
|
144
145
|
updatedAt?: Date | undefined;
|
|
145
|
-
publishedAt?: Date | undefined;
|
|
146
146
|
image?: string | undefined;
|
|
147
147
|
}, unknown>;
|
|
148
148
|
/** Update an existing post by id */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
|
-
import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.
|
|
2
|
+
import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.Sod_PZhB.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -128,6 +128,10 @@ declare function useSuspenseTags(): {
|
|
|
128
128
|
};
|
|
129
129
|
/** Create a new post */
|
|
130
130
|
declare function useCreatePost(): _tanstack_react_query.UseMutationResult<SerializedPost | null, Error, {
|
|
131
|
+
published: boolean;
|
|
132
|
+
title: string;
|
|
133
|
+
content: string;
|
|
134
|
+
excerpt: string;
|
|
131
135
|
tags: ({
|
|
132
136
|
name: string;
|
|
133
137
|
} | {
|
|
@@ -135,14 +139,10 @@ declare function useCreatePost(): _tanstack_react_query.UseMutationResult<Serial
|
|
|
135
139
|
name: string;
|
|
136
140
|
slug: string;
|
|
137
141
|
})[];
|
|
138
|
-
title: string;
|
|
139
|
-
content: string;
|
|
140
|
-
excerpt: string;
|
|
141
|
-
published: boolean;
|
|
142
142
|
slug?: string | undefined;
|
|
143
|
+
publishedAt?: Date | undefined;
|
|
143
144
|
createdAt?: Date | undefined;
|
|
144
145
|
updatedAt?: Date | undefined;
|
|
145
|
-
publishedAt?: Date | undefined;
|
|
146
146
|
image?: string | undefined;
|
|
147
147
|
}, unknown>;
|
|
148
148
|
/** Update an existing post by id */
|
|
@@ -131,4 +131,4 @@ interface VercelBlobStorageAdapter {
|
|
|
131
131
|
}
|
|
132
132
|
type StorageAdapter = DirectStorageAdapter | S3StorageAdapter | VercelBlobStorageAdapter;
|
|
133
133
|
|
|
134
|
-
export type { DirectStorageAdapter as D,
|
|
134
|
+
export type { DirectStorageAdapter as D, StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, S3StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
|
|
@@ -131,4 +131,4 @@ interface VercelBlobStorageAdapter {
|
|
|
131
131
|
}
|
|
132
132
|
type StorageAdapter = DirectStorageAdapter | S3StorageAdapter | VercelBlobStorageAdapter;
|
|
133
133
|
|
|
134
|
-
export type { DirectStorageAdapter as D,
|
|
134
|
+
export type { DirectStorageAdapter as D, StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, S3StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
|
|
@@ -131,4 +131,4 @@ interface VercelBlobStorageAdapter {
|
|
|
131
131
|
}
|
|
132
132
|
type StorageAdapter = DirectStorageAdapter | S3StorageAdapter | VercelBlobStorageAdapter;
|
|
133
133
|
|
|
134
|
-
export type { DirectStorageAdapter as D,
|
|
134
|
+
export type { DirectStorageAdapter as D, StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, S3StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
2
|
import { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { createApiClient } from '@btst/stack/plugins/client';
|
|
4
|
-
import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.
|
|
4
|
+
import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.Sod_PZhB.js';
|
|
5
5
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
6
6
|
import { DBAdapter } from '@btst/db';
|
|
7
7
|
import * as better_call from 'better-call';
|
|
@@ -236,6 +236,12 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
236
236
|
title: string;
|
|
237
237
|
content: string;
|
|
238
238
|
excerpt: string;
|
|
239
|
+
slug?: string | undefined;
|
|
240
|
+
published?: boolean | undefined;
|
|
241
|
+
publishedAt?: unknown;
|
|
242
|
+
createdAt?: unknown;
|
|
243
|
+
updatedAt?: unknown;
|
|
244
|
+
image?: string | undefined;
|
|
239
245
|
tags?: ({
|
|
240
246
|
name: string;
|
|
241
247
|
} | {
|
|
@@ -243,16 +249,16 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
243
249
|
name: string;
|
|
244
250
|
slug: string;
|
|
245
251
|
})[] | undefined;
|
|
246
|
-
slug?: string | undefined;
|
|
247
|
-
createdAt?: unknown;
|
|
248
|
-
updatedAt?: unknown;
|
|
249
|
-
publishedAt?: unknown;
|
|
250
|
-
image?: string | undefined;
|
|
251
|
-
published?: boolean | undefined;
|
|
252
252
|
}, {
|
|
253
253
|
title: string;
|
|
254
254
|
content: string;
|
|
255
255
|
excerpt: string;
|
|
256
|
+
slug?: string | undefined;
|
|
257
|
+
published?: boolean | undefined;
|
|
258
|
+
publishedAt?: unknown;
|
|
259
|
+
createdAt?: unknown;
|
|
260
|
+
updatedAt?: unknown;
|
|
261
|
+
image?: string | undefined;
|
|
256
262
|
tags?: ({
|
|
257
263
|
name: string;
|
|
258
264
|
} | {
|
|
@@ -260,12 +266,6 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
260
266
|
name: string;
|
|
261
267
|
slug: string;
|
|
262
268
|
})[] | undefined;
|
|
263
|
-
slug?: string | undefined;
|
|
264
|
-
createdAt?: unknown;
|
|
265
|
-
updatedAt?: unknown;
|
|
266
|
-
publishedAt?: unknown;
|
|
267
|
-
image?: string | undefined;
|
|
268
|
-
published?: boolean | undefined;
|
|
269
269
|
}>;
|
|
270
270
|
}, Post>;
|
|
271
271
|
readonly updatePost: better_call.StrictEndpoint<"/posts/:id", {} & {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
2
|
-
import {
|
|
2
|
+
import { S as StorageAdapter, b as S3UploadToken } from './stack.lkebw2nj.cjs';
|
|
3
3
|
import { d as AssetListResult, l as listAssets, a as listFolders, A as AssetListParams } from './stack.jU2iG86n.cjs';
|
|
4
4
|
import * as better_call from 'better-call';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { A as Asset, F as Folder } from './stack.BMlLOMED.cjs';
|
|
7
|
+
import { DBAdapter } from '@btst/db';
|
|
7
8
|
|
|
8
9
|
declare const AssetListQuerySchema: z.ZodObject<{
|
|
9
10
|
folderId: z.ZodOptional<z.ZodString>;
|
|
@@ -21,6 +22,75 @@ declare const createFolderSchema: z.ZodObject<{
|
|
|
21
22
|
parentId: z.ZodOptional<z.ZodString>;
|
|
22
23
|
}, z.core.$strip>;
|
|
23
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Input for creating a new asset record.
|
|
27
|
+
*/
|
|
28
|
+
interface CreateAssetInput {
|
|
29
|
+
filename: string;
|
|
30
|
+
originalName: string;
|
|
31
|
+
mimeType: string;
|
|
32
|
+
size: number;
|
|
33
|
+
url: string;
|
|
34
|
+
folderId?: string;
|
|
35
|
+
alt?: string;
|
|
36
|
+
tenantId?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Input for updating an existing asset record.
|
|
40
|
+
*/
|
|
41
|
+
interface UpdateAssetInput {
|
|
42
|
+
alt?: string;
|
|
43
|
+
folderId?: string | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Input for creating a new folder.
|
|
47
|
+
*/
|
|
48
|
+
interface CreateFolderInput {
|
|
49
|
+
name: string;
|
|
50
|
+
parentId?: string;
|
|
51
|
+
tenantId?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create an asset record in the database.
|
|
55
|
+
* Pure DB function — no authorization hooks, no HTTP context.
|
|
56
|
+
*
|
|
57
|
+
* @remarks **Security:** No authorization hooks (e.g. `onBeforeUpload`) are called.
|
|
58
|
+
* The caller is responsible for any access-control checks before invoking this function.
|
|
59
|
+
*/
|
|
60
|
+
declare function createAsset(adapter: DBAdapter, input: CreateAssetInput): Promise<Asset>;
|
|
61
|
+
/**
|
|
62
|
+
* Update an asset's `alt` text or `folderId`.
|
|
63
|
+
* Pure DB function — no authorization hooks, no HTTP context.
|
|
64
|
+
*
|
|
65
|
+
* @remarks **Security:** No authorization hooks are called.
|
|
66
|
+
*/
|
|
67
|
+
declare function updateAsset(adapter: DBAdapter, id: string, input: UpdateAssetInput): Promise<Asset | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Delete an asset record from the database by its ID.
|
|
70
|
+
* Does NOT delete the underlying file — the caller must do that via the storage adapter.
|
|
71
|
+
* Pure DB function — no authorization hooks, no HTTP context.
|
|
72
|
+
*
|
|
73
|
+
* @remarks **Security:** No authorization hooks are called.
|
|
74
|
+
*/
|
|
75
|
+
declare function deleteAsset(adapter: DBAdapter, id: string): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Create a folder record in the database.
|
|
78
|
+
* Pure DB function — no authorization hooks, no HTTP context.
|
|
79
|
+
*
|
|
80
|
+
* @remarks **Security:** No authorization hooks are called.
|
|
81
|
+
*/
|
|
82
|
+
declare function createFolder(adapter: DBAdapter, input: CreateFolderInput): Promise<Folder>;
|
|
83
|
+
/**
|
|
84
|
+
* Delete a folder record from the database by its ID.
|
|
85
|
+
* Child folders are cascade-deleted automatically. Throws if the folder or
|
|
86
|
+
* any of its descendants contain assets (which have associated storage files
|
|
87
|
+
* that must be deleted via the storage adapter first).
|
|
88
|
+
* Pure DB function — no authorization hooks, no HTTP context.
|
|
89
|
+
*
|
|
90
|
+
* @remarks **Security:** No authorization hooks are called.
|
|
91
|
+
*/
|
|
92
|
+
declare function deleteFolder(adapter: DBAdapter, id: string): Promise<void>;
|
|
93
|
+
|
|
24
94
|
/**
|
|
25
95
|
* Context passed to media API hooks.
|
|
26
96
|
*/
|
|
@@ -270,9 +340,12 @@ declare const mediaBackendPlugin: (config: MediaBackendConfig) => _btst_stack_pl
|
|
|
270
340
|
}, {
|
|
271
341
|
listAssets: (params?: Parameters<typeof listAssets>[1]) => Promise<AssetListResult>;
|
|
272
342
|
getAssetById: (id: string) => Promise<Asset | null>;
|
|
343
|
+
createAsset: (input: Parameters<typeof createAsset>[1]) => Promise<Asset>;
|
|
344
|
+
updateAsset: (id: string, input: Parameters<typeof updateAsset>[2]) => Promise<Asset | null>;
|
|
273
345
|
listFolders: (params?: Parameters<typeof listFolders>[1]) => Promise<Folder[]>;
|
|
274
346
|
getFolderById: (id: string) => Promise<Folder | null>;
|
|
275
347
|
getFolderByName: (name: string, parentId?: string | null, tenantId?: string) => Promise<Folder | null>;
|
|
348
|
+
createFolder: (input: Parameters<typeof createFolder>[1]) => Promise<Folder>;
|
|
276
349
|
}>;
|
|
277
350
|
type MediaApiRouter = ReturnType<ReturnType<typeof mediaBackendPlugin>["routes"]>;
|
|
278
351
|
|
|
@@ -300,5 +373,5 @@ declare const MEDIA_QUERY_KEYS: {
|
|
|
300
373
|
foldersList: (parentId?: string | null) => readonly ["media", "folders", "list", string];
|
|
301
374
|
};
|
|
302
375
|
|
|
303
|
-
export { MEDIA_QUERY_KEYS as a,
|
|
304
|
-
export type { AssetListDiscriminator as A,
|
|
376
|
+
export { MEDIA_QUERY_KEYS as M, createFolder as a, deleteFolder as b, createAsset as c, deleteAsset as d, assetListDiscriminator as f, mediaBackendPlugin as m, updateAsset as u };
|
|
377
|
+
export type { AssetListDiscriminator as A, CreateAssetInput as C, UpdateAssetInput as U, CreateFolderInput as e, MediaApiContext as g, MediaBackendHooks as h, MediaBackendConfig as i, MediaApiRouter as j };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btst/stack",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.1",
|
|
4
4
|
"description": "A composable, plugin-based library for building full-stack applications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -424,6 +424,16 @@
|
|
|
424
424
|
"default": "./dist/plugins/media/api/index.cjs"
|
|
425
425
|
}
|
|
426
426
|
},
|
|
427
|
+
"./plugins/media/api/adapters/local": {
|
|
428
|
+
"import": {
|
|
429
|
+
"types": "./dist/plugins/media/api/adapters/local.d.ts",
|
|
430
|
+
"default": "./dist/plugins/media/api/adapters/local.mjs"
|
|
431
|
+
},
|
|
432
|
+
"require": {
|
|
433
|
+
"types": "./dist/plugins/media/api/adapters/local.d.cts",
|
|
434
|
+
"default": "./dist/plugins/media/api/adapters/local.cjs"
|
|
435
|
+
}
|
|
436
|
+
},
|
|
427
437
|
"./plugins/media/api/adapters/s3": {
|
|
428
438
|
"import": {
|
|
429
439
|
"types": "./dist/plugins/media/api/adapters/s3.d.ts",
|
|
@@ -684,6 +694,9 @@
|
|
|
684
694
|
"plugins/media/api": [
|
|
685
695
|
"./dist/plugins/media/api/index.d.ts"
|
|
686
696
|
],
|
|
697
|
+
"plugins/media/api/adapters/local": [
|
|
698
|
+
"./dist/plugins/media/api/adapters/local.d.ts"
|
|
699
|
+
],
|
|
687
700
|
"plugins/media/api/adapters/s3": [
|
|
688
701
|
"./dist/plugins/media/api/adapters/s3.d.ts"
|
|
689
702
|
],
|
|
@@ -145,6 +145,17 @@ describe("localAdapter", () => {
|
|
|
145
145
|
const adapter = localAdapter();
|
|
146
146
|
expect(adapter.type).toBe("local");
|
|
147
147
|
});
|
|
148
|
+
|
|
149
|
+
it("throws when a URL contains a path traversal sequence", async () => {
|
|
150
|
+
const uploadDir = await makeTmpDir();
|
|
151
|
+
const adapter = localAdapter({ uploadDir, publicPath: "/uploads" });
|
|
152
|
+
|
|
153
|
+
// Simulate a tampered URL that would resolve outside uploadDir after decoding.
|
|
154
|
+
const maliciousUrl = "/uploads/..%2F..%2Fetc%2Fpasswd";
|
|
155
|
+
await expect(adapter.delete(maliciousUrl)).rejects.toThrow(
|
|
156
|
+
"Refusing to delete file outside upload directory",
|
|
157
|
+
);
|
|
158
|
+
});
|
|
148
159
|
});
|
|
149
160
|
|
|
150
161
|
// ── S3 adapter ────────────────────────────────────────────────────────────────
|
|
@@ -66,7 +66,16 @@ export function localAdapter(
|
|
|
66
66
|
if (!encodedFilename) return;
|
|
67
67
|
const filename = decodeURIComponent(encodedFilename);
|
|
68
68
|
|
|
69
|
-
const
|
|
69
|
+
const resolvedUploadDir = path.resolve(uploadDir);
|
|
70
|
+
const filePath = path.join(resolvedUploadDir, filename);
|
|
71
|
+
|
|
72
|
+
// Guard against path traversal: reject any path that escapes uploadDir.
|
|
73
|
+
if (!filePath.startsWith(resolvedUploadDir + path.sep)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Refusing to delete file outside upload directory: ${filePath}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
try {
|
|
71
80
|
await fs.unlink(filePath);
|
|
72
81
|
} catch (err: unknown) {
|
|
@@ -26,11 +26,6 @@ export { serializeAsset, serializeFolder } from "./serializers";
|
|
|
26
26
|
|
|
27
27
|
export { MEDIA_QUERY_KEYS, assetListDiscriminator } from "./query-key-defs";
|
|
28
28
|
|
|
29
|
-
export {
|
|
30
|
-
localAdapter,
|
|
31
|
-
type LocalStorageAdapterOptions,
|
|
32
|
-
} from "./adapters/local";
|
|
33
|
-
|
|
34
29
|
export type {
|
|
35
30
|
StorageAdapter,
|
|
36
31
|
DirectStorageAdapter,
|
|
@@ -240,6 +240,10 @@ export const mediaBackendPlugin = (config: MediaBackendConfig) =>
|
|
|
240
240
|
listAssets: (params?: Parameters<typeof listAssets>[1]) =>
|
|
241
241
|
listAssets(adapter, params),
|
|
242
242
|
getAssetById: (id: string) => getAssetById(adapter, id),
|
|
243
|
+
createAsset: (input: Parameters<typeof createAsset>[1]) =>
|
|
244
|
+
createAsset(adapter, input),
|
|
245
|
+
updateAsset: (id: string, input: Parameters<typeof updateAsset>[2]) =>
|
|
246
|
+
updateAsset(adapter, id, input),
|
|
243
247
|
listFolders: (params?: Parameters<typeof listFolders>[1]) =>
|
|
244
248
|
listFolders(adapter, params),
|
|
245
249
|
getFolderById: (id: string) => getFolderById(adapter, id),
|
|
@@ -248,6 +252,8 @@ export const mediaBackendPlugin = (config: MediaBackendConfig) =>
|
|
|
248
252
|
parentId?: string | null,
|
|
249
253
|
tenantId?: string,
|
|
250
254
|
) => getFolderByName(adapter, name, parentId, tenantId),
|
|
255
|
+
createFolder: (input: Parameters<typeof createFolder>[1]) =>
|
|
256
|
+
createFolder(adapter, input),
|
|
251
257
|
}),
|
|
252
258
|
|
|
253
259
|
routes: (adapter: Adapter) => {
|
|
@@ -8,11 +8,11 @@ import { QueryClient } from '@tanstack/react-query';
|
|
|
8
8
|
declare const createBoardSchema: z.ZodObject<{
|
|
9
9
|
description: z.ZodOptional<z.ZodString>;
|
|
10
10
|
name: z.ZodString;
|
|
11
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
12
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
11
13
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
14
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
13
15
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
14
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
15
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
declare const updateBoardSchema: z.ZodObject<{
|
|
18
18
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -26,9 +26,9 @@ declare const updateBoardSchema: z.ZodObject<{
|
|
|
26
26
|
}, z.core.$strip>;
|
|
27
27
|
declare const createColumnSchema: z.ZodObject<{
|
|
28
28
|
title: z.ZodString;
|
|
29
|
-
boardId: z.ZodString;
|
|
30
29
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
30
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
|
+
boardId: z.ZodString;
|
|
32
32
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
33
33
|
}, z.core.$strip>;
|
|
34
34
|
declare const updateColumnSchema: z.ZodObject<{
|
|
@@ -331,19 +331,19 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
331
331
|
body: better_call.StandardSchemaV1<{
|
|
332
332
|
name: string;
|
|
333
333
|
description?: string | undefined;
|
|
334
|
+
createdAt?: unknown;
|
|
335
|
+
updatedAt?: unknown;
|
|
334
336
|
slug?: string | undefined;
|
|
335
337
|
ownerId?: string | undefined;
|
|
336
338
|
organizationId?: string | undefined;
|
|
337
|
-
createdAt?: unknown;
|
|
338
|
-
updatedAt?: unknown;
|
|
339
339
|
}, {
|
|
340
340
|
name: string;
|
|
341
341
|
description?: string | undefined;
|
|
342
|
+
createdAt?: unknown;
|
|
343
|
+
updatedAt?: unknown;
|
|
342
344
|
slug?: string | undefined;
|
|
343
345
|
ownerId?: string | undefined;
|
|
344
346
|
organizationId?: string | undefined;
|
|
345
|
-
createdAt?: unknown;
|
|
346
|
-
updatedAt?: unknown;
|
|
347
347
|
}>;
|
|
348
348
|
}, {
|
|
349
349
|
columns: ColumnWithTasks[];
|
|
@@ -361,19 +361,19 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
361
361
|
body: better_call.StandardSchemaV1<{
|
|
362
362
|
description?: string | undefined;
|
|
363
363
|
name?: string | undefined;
|
|
364
|
+
createdAt?: unknown;
|
|
365
|
+
updatedAt?: unknown;
|
|
364
366
|
slug?: string | undefined;
|
|
365
367
|
ownerId?: string | undefined;
|
|
366
368
|
organizationId?: string | undefined;
|
|
367
|
-
createdAt?: unknown;
|
|
368
|
-
updatedAt?: unknown;
|
|
369
369
|
}, {
|
|
370
370
|
description?: string | undefined;
|
|
371
371
|
name?: string | undefined;
|
|
372
|
+
createdAt?: unknown;
|
|
373
|
+
updatedAt?: unknown;
|
|
372
374
|
slug?: string | undefined;
|
|
373
375
|
ownerId?: string | undefined;
|
|
374
376
|
organizationId?: string | undefined;
|
|
375
|
-
createdAt?: unknown;
|
|
376
|
-
updatedAt?: unknown;
|
|
377
377
|
}>;
|
|
378
378
|
}, Board>;
|
|
379
379
|
readonly deleteBoard: better_call.StrictEndpoint<"/boards/:id", {} & {
|
|
@@ -402,15 +402,15 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
402
402
|
method: "PUT";
|
|
403
403
|
body: better_call.StandardSchemaV1<{
|
|
404
404
|
title?: string | undefined;
|
|
405
|
-
boardId?: string | undefined;
|
|
406
405
|
createdAt?: unknown;
|
|
407
406
|
updatedAt?: unknown;
|
|
407
|
+
boardId?: string | undefined;
|
|
408
408
|
order?: number | undefined;
|
|
409
409
|
}, {
|
|
410
410
|
title?: string | undefined;
|
|
411
|
-
boardId?: string | undefined;
|
|
412
411
|
createdAt?: unknown;
|
|
413
412
|
updatedAt?: unknown;
|
|
413
|
+
boardId?: string | undefined;
|
|
414
414
|
order?: number | undefined;
|
|
415
415
|
}>;
|
|
416
416
|
}, Column>;
|
|
@@ -8,11 +8,11 @@ import { QueryClient } from '@tanstack/react-query';
|
|
|
8
8
|
declare const createBoardSchema: z.ZodObject<{
|
|
9
9
|
description: z.ZodOptional<z.ZodString>;
|
|
10
10
|
name: z.ZodString;
|
|
11
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
12
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
11
13
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
14
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
13
15
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
14
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
15
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
declare const updateBoardSchema: z.ZodObject<{
|
|
18
18
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -26,9 +26,9 @@ declare const updateBoardSchema: z.ZodObject<{
|
|
|
26
26
|
}, z.core.$strip>;
|
|
27
27
|
declare const createColumnSchema: z.ZodObject<{
|
|
28
28
|
title: z.ZodString;
|
|
29
|
-
boardId: z.ZodString;
|
|
30
29
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
30
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
|
+
boardId: z.ZodString;
|
|
32
32
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
33
33
|
}, z.core.$strip>;
|
|
34
34
|
declare const updateColumnSchema: z.ZodObject<{
|
|
@@ -331,19 +331,19 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
331
331
|
body: better_call.StandardSchemaV1<{
|
|
332
332
|
name: string;
|
|
333
333
|
description?: string | undefined;
|
|
334
|
+
createdAt?: unknown;
|
|
335
|
+
updatedAt?: unknown;
|
|
334
336
|
slug?: string | undefined;
|
|
335
337
|
ownerId?: string | undefined;
|
|
336
338
|
organizationId?: string | undefined;
|
|
337
|
-
createdAt?: unknown;
|
|
338
|
-
updatedAt?: unknown;
|
|
339
339
|
}, {
|
|
340
340
|
name: string;
|
|
341
341
|
description?: string | undefined;
|
|
342
|
+
createdAt?: unknown;
|
|
343
|
+
updatedAt?: unknown;
|
|
342
344
|
slug?: string | undefined;
|
|
343
345
|
ownerId?: string | undefined;
|
|
344
346
|
organizationId?: string | undefined;
|
|
345
|
-
createdAt?: unknown;
|
|
346
|
-
updatedAt?: unknown;
|
|
347
347
|
}>;
|
|
348
348
|
}, {
|
|
349
349
|
columns: ColumnWithTasks[];
|
|
@@ -361,19 +361,19 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
361
361
|
body: better_call.StandardSchemaV1<{
|
|
362
362
|
description?: string | undefined;
|
|
363
363
|
name?: string | undefined;
|
|
364
|
+
createdAt?: unknown;
|
|
365
|
+
updatedAt?: unknown;
|
|
364
366
|
slug?: string | undefined;
|
|
365
367
|
ownerId?: string | undefined;
|
|
366
368
|
organizationId?: string | undefined;
|
|
367
|
-
createdAt?: unknown;
|
|
368
|
-
updatedAt?: unknown;
|
|
369
369
|
}, {
|
|
370
370
|
description?: string | undefined;
|
|
371
371
|
name?: string | undefined;
|
|
372
|
+
createdAt?: unknown;
|
|
373
|
+
updatedAt?: unknown;
|
|
372
374
|
slug?: string | undefined;
|
|
373
375
|
ownerId?: string | undefined;
|
|
374
376
|
organizationId?: string | undefined;
|
|
375
|
-
createdAt?: unknown;
|
|
376
|
-
updatedAt?: unknown;
|
|
377
377
|
}>;
|
|
378
378
|
}, Board>;
|
|
379
379
|
readonly deleteBoard: better_call.StrictEndpoint<"/boards/:id", {} & {
|
|
@@ -402,15 +402,15 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
402
402
|
method: "PUT";
|
|
403
403
|
body: better_call.StandardSchemaV1<{
|
|
404
404
|
title?: string | undefined;
|
|
405
|
-
boardId?: string | undefined;
|
|
406
405
|
createdAt?: unknown;
|
|
407
406
|
updatedAt?: unknown;
|
|
407
|
+
boardId?: string | undefined;
|
|
408
408
|
order?: number | undefined;
|
|
409
409
|
}, {
|
|
410
410
|
title?: string | undefined;
|
|
411
|
-
boardId?: string | undefined;
|
|
412
411
|
createdAt?: unknown;
|
|
413
412
|
updatedAt?: unknown;
|
|
413
|
+
boardId?: string | undefined;
|
|
414
414
|
order?: number | undefined;
|
|
415
415
|
}>;
|
|
416
416
|
}, Column>;
|
|
@@ -8,11 +8,11 @@ import { QueryClient } from '@tanstack/react-query';
|
|
|
8
8
|
declare const createBoardSchema: z.ZodObject<{
|
|
9
9
|
description: z.ZodOptional<z.ZodString>;
|
|
10
10
|
name: z.ZodString;
|
|
11
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
12
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
11
13
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
14
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
13
15
|
organizationId: z.ZodOptional<z.ZodString>;
|
|
14
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
15
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
declare const updateBoardSchema: z.ZodObject<{
|
|
18
18
|
createdAt: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
@@ -26,9 +26,9 @@ declare const updateBoardSchema: z.ZodObject<{
|
|
|
26
26
|
}, z.core.$strip>;
|
|
27
27
|
declare const createColumnSchema: z.ZodObject<{
|
|
28
28
|
title: z.ZodString;
|
|
29
|
-
boardId: z.ZodString;
|
|
30
29
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
30
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
31
|
+
boardId: z.ZodString;
|
|
32
32
|
order: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
33
33
|
}, z.core.$strip>;
|
|
34
34
|
declare const updateColumnSchema: z.ZodObject<{
|
|
@@ -331,19 +331,19 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
331
331
|
body: better_call.StandardSchemaV1<{
|
|
332
332
|
name: string;
|
|
333
333
|
description?: string | undefined;
|
|
334
|
+
createdAt?: unknown;
|
|
335
|
+
updatedAt?: unknown;
|
|
334
336
|
slug?: string | undefined;
|
|
335
337
|
ownerId?: string | undefined;
|
|
336
338
|
organizationId?: string | undefined;
|
|
337
|
-
createdAt?: unknown;
|
|
338
|
-
updatedAt?: unknown;
|
|
339
339
|
}, {
|
|
340
340
|
name: string;
|
|
341
341
|
description?: string | undefined;
|
|
342
|
+
createdAt?: unknown;
|
|
343
|
+
updatedAt?: unknown;
|
|
342
344
|
slug?: string | undefined;
|
|
343
345
|
ownerId?: string | undefined;
|
|
344
346
|
organizationId?: string | undefined;
|
|
345
|
-
createdAt?: unknown;
|
|
346
|
-
updatedAt?: unknown;
|
|
347
347
|
}>;
|
|
348
348
|
}, {
|
|
349
349
|
columns: ColumnWithTasks[];
|
|
@@ -361,19 +361,19 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
361
361
|
body: better_call.StandardSchemaV1<{
|
|
362
362
|
description?: string | undefined;
|
|
363
363
|
name?: string | undefined;
|
|
364
|
+
createdAt?: unknown;
|
|
365
|
+
updatedAt?: unknown;
|
|
364
366
|
slug?: string | undefined;
|
|
365
367
|
ownerId?: string | undefined;
|
|
366
368
|
organizationId?: string | undefined;
|
|
367
|
-
createdAt?: unknown;
|
|
368
|
-
updatedAt?: unknown;
|
|
369
369
|
}, {
|
|
370
370
|
description?: string | undefined;
|
|
371
371
|
name?: string | undefined;
|
|
372
|
+
createdAt?: unknown;
|
|
373
|
+
updatedAt?: unknown;
|
|
372
374
|
slug?: string | undefined;
|
|
373
375
|
ownerId?: string | undefined;
|
|
374
376
|
organizationId?: string | undefined;
|
|
375
|
-
createdAt?: unknown;
|
|
376
|
-
updatedAt?: unknown;
|
|
377
377
|
}>;
|
|
378
378
|
}, Board>;
|
|
379
379
|
readonly deleteBoard: better_call.StrictEndpoint<"/boards/:id", {} & {
|
|
@@ -402,15 +402,15 @@ declare const kanbanBackendPlugin: (hooks?: KanbanBackendHooks) => _btst_stack_p
|
|
|
402
402
|
method: "PUT";
|
|
403
403
|
body: better_call.StandardSchemaV1<{
|
|
404
404
|
title?: string | undefined;
|
|
405
|
-
boardId?: string | undefined;
|
|
406
405
|
createdAt?: unknown;
|
|
407
406
|
updatedAt?: unknown;
|
|
407
|
+
boardId?: string | undefined;
|
|
408
408
|
order?: number | undefined;
|
|
409
409
|
}, {
|
|
410
410
|
title?: string | undefined;
|
|
411
|
-
boardId?: string | undefined;
|
|
412
411
|
createdAt?: unknown;
|
|
413
412
|
updatedAt?: unknown;
|
|
413
|
+
boardId?: string | undefined;
|
|
414
414
|
order?: number | undefined;
|
|
415
415
|
}>;
|
|
416
416
|
}, Column>;
|
|
@@ -35,6 +35,15 @@ interface SerializedTag extends Omit<Tag, "createdAt" | "updatedAt"> {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
declare const createPostSchema: z.ZodObject<{
|
|
38
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
39
|
+
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
40
|
+
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
41
|
+
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
42
|
+
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
43
|
+
title: z.ZodString;
|
|
44
|
+
content: z.ZodString;
|
|
45
|
+
excerpt: z.ZodString;
|
|
46
|
+
image: z.ZodOptional<z.ZodString>;
|
|
38
47
|
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
39
48
|
name: z.ZodString;
|
|
40
49
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -42,15 +51,6 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
42
51
|
name: z.ZodString;
|
|
43
52
|
slug: z.ZodString;
|
|
44
53
|
}, z.core.$strip>]>>>>;
|
|
45
|
-
title: z.ZodString;
|
|
46
|
-
slug: z.ZodOptional<z.ZodString>;
|
|
47
|
-
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
48
|
-
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
49
|
-
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
50
|
-
content: z.ZodString;
|
|
51
|
-
excerpt: z.ZodString;
|
|
52
|
-
image: z.ZodOptional<z.ZodString>;
|
|
53
|
-
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
declare const updatePostSchema: z.ZodObject<{
|
|
56
56
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|