@cedarjs/storage 9.0.0-canary.1784 → 9.0.0-canary.3124
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/README.md +6 -0
- package/dist/createSavers.d.ts +2 -2
- package/dist/createSavers.d.ts.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/prismaExtension.d.ts +9 -11
- package/dist/prismaExtension.d.ts.map +1 -1
- package/dist/prismaExtension.js +156 -162
- package/package.json +25 -36
- package/LICENSE +0 -21
- package/dist/cjs/UrlSigner.d.ts +0 -46
- package/dist/cjs/UrlSigner.d.ts.map +0 -1
- package/dist/cjs/UrlSigner.js +0 -142
- package/dist/cjs/adapters/BaseStorageAdapter.d.ts +0 -31
- package/dist/cjs/adapters/BaseStorageAdapter.d.ts.map +0 -1
- package/dist/cjs/adapters/BaseStorageAdapter.js +0 -53
- package/dist/cjs/adapters/FileSystemStorage/FileSystemStorage.d.ts +0 -16
- package/dist/cjs/adapters/FileSystemStorage/FileSystemStorage.d.ts.map +0 -1
- package/dist/cjs/adapters/FileSystemStorage/FileSystemStorage.js +0 -72
- package/dist/cjs/adapters/MemoryStorage/MemoryStorage.d.ts +0 -15
- package/dist/cjs/adapters/MemoryStorage/MemoryStorage.d.ts.map +0 -1
- package/dist/cjs/adapters/MemoryStorage/MemoryStorage.js +0 -67
- package/dist/cjs/createSavers.d.ts +0 -15
- package/dist/cjs/createSavers.d.ts.map +0 -1
- package/dist/cjs/createSavers.js +0 -75
- package/dist/cjs/fileToDataUri.d.ts +0 -3
- package/dist/cjs/fileToDataUri.d.ts.map +0 -1
- package/dist/cjs/fileToDataUri.js +0 -32
- package/dist/cjs/index.d.ts +0 -40
- package/dist/cjs/index.d.ts.map +0 -1
- package/dist/cjs/index.js +0 -50
- package/dist/cjs/package.json +0 -1
- package/dist/cjs/prismaExtension.d.ts +0 -29
- package/dist/cjs/prismaExtension.d.ts.map +0 -1
- package/dist/cjs/prismaExtension.js +0 -240
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# `@cedarjs/storage`
|
|
2
2
|
|
|
3
|
+
> **Deprecated.** `@cedarjs/storage` is superseded by
|
|
4
|
+
> [`@cedarjs/uploads`](../uploads/README.md), which replaces the Prisma
|
|
5
|
+
> extension and savers with explicit service calls, named storage targets, and
|
|
6
|
+
> token-gated upload routes. This package will be removed in a future major
|
|
7
|
+
> release. See the [migration guide](https://cedarjs.com/docs/uploads#migrating-from-cedarjsstorage).
|
|
8
|
+
|
|
3
9
|
This package houses
|
|
4
10
|
|
|
5
11
|
- Prisma extension for handling uploads. Currently
|
package/dist/createSavers.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { SaveOptionsOverride, BaseStorageAdapter } from './adapters/BaseStorageAdapter.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ModelNamesFor, UploadsConfig } from './prismaExtension.js';
|
|
3
3
|
type MakeFilesString<T> = {
|
|
4
4
|
[K in keyof T]: T[K] extends File ? string : T[K];
|
|
5
5
|
};
|
|
6
6
|
export declare const createFileListSaver: (storage: BaseStorageAdapter) => (files?: File[], pathOverrideOnly?: {
|
|
7
7
|
path?: string;
|
|
8
8
|
}) => Promise<string[]>;
|
|
9
|
-
export declare const createUploadSavers: <MNames extends
|
|
9
|
+
export declare const createUploadSavers: <TClient, MNames extends ModelNamesFor<TClient> = ModelNamesFor<TClient>>(uploadConfig: UploadsConfig<TClient, MNames>, storage: BaseStorageAdapter) => { [K in `for${Capitalize<string & MNames>}`]: <T extends Record<string, any>>(data: T, overrideSaveOptions?: SaveOptionsOverride) => Promise<MakeFilesString<T>>; } & {
|
|
10
10
|
inList: (files?: File[], pathOverrideOnly?: {
|
|
11
11
|
path?: string;
|
|
12
12
|
}) => Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSavers.d.ts","sourceRoot":"","sources":["../src/createSavers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"createSavers.d.ts","sourceRoot":"","sources":["../src/createSavers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGxE,KAAK,eAAe,CAAC,CAAC,IAAI;KACvB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;CAClD,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,SAAS,kBAAkB,MAC/C,QAAO,IAAI,EAAO,EAAE,mBAAmB;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,sBAUvE,CAAA;AAMD,eAAO,MAAM,kBAAkB,GAC7B,OAAO,EACP,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,EAE9D,cAAc,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,EAC5C,SAAS,kBAAkB,QAMxB,CAAC,2CAAwB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAC/C,CAAC,wBACe,mBAAmB,KACtC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;qBA9Bb,IAAI,EAAE,qBAA0B;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;CA8EvE,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { BaseStorageAdapter } from './adapters/BaseStorageAdapter.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ModelNamesFor, UploadConfigForModel, UploadsConfig } from './prismaExtension.js';
|
|
3
3
|
import type { UrlSigner } from './UrlSigner.js';
|
|
4
|
-
type SetupStorageOptions<MNames extends
|
|
5
|
-
uploadsConfig: UploadsConfig<MNames>;
|
|
4
|
+
type SetupStorageOptions<TClient, MNames extends ModelNamesFor<TClient> = ModelNamesFor<TClient>> = {
|
|
5
|
+
uploadsConfig: UploadsConfig<TClient, MNames>;
|
|
6
6
|
storageAdapter: BaseStorageAdapter;
|
|
7
7
|
urlSigner?: UrlSigner;
|
|
8
8
|
};
|
|
9
|
-
export declare const setupStorage: <MNames extends
|
|
10
|
-
storagePrismaExtension: (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/
|
|
9
|
+
export declare const setupStorage: <TClient, MNames extends ModelNamesFor<TClient> = ModelNamesFor<TClient>>({ uploadsConfig, storageAdapter, urlSigner, }: SetupStorageOptions<TClient, MNames>) => {
|
|
10
|
+
storagePrismaExtension: (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/client").InternalArgs<{ [K in MNames]: {
|
|
11
11
|
withDataUri: {
|
|
12
12
|
needs: Record<string, boolean>;
|
|
13
13
|
compute: (modelData: Record<string, unknown>) => <T>(this: T) => Promise<T>;
|
|
@@ -18,8 +18,8 @@ export declare const setupStorage: <MNames extends ModelNames>({ uploadsConfig,
|
|
|
18
18
|
expiresIn?: number;
|
|
19
19
|
}) => T;
|
|
20
20
|
};
|
|
21
|
-
}; }, {}, {}, {}> & import("@prisma/client/runtime/
|
|
22
|
-
saveFiles: { [K in `for${Capitalize<MNames>}`]: <T extends Record<string, any>>(data: T, overrideSaveOptions?: import("./adapters/BaseStorageAdapter.js").SaveOptionsOverride) => Promise<{ [K_2 in keyof T]: T[K_2] extends File ? string : T[K_2]; }>; } & {
|
|
21
|
+
}; }, {}, {}, {}> & import("@prisma/client/runtime/client").DefaultArgs>;
|
|
22
|
+
saveFiles: { [K in `for${Capitalize<string & MNames>}`]: <T extends Record<string, any>>(data: T, overrideSaveOptions?: import("./adapters/BaseStorageAdapter.js").SaveOptionsOverride) => Promise<{ [K_2 in keyof T]: T[K_2] extends File ? string : T[K_2]; }>; } & {
|
|
23
23
|
inList: (files?: File[], pathOverrideOnly?: {
|
|
24
24
|
path?: string;
|
|
25
25
|
}) => Promise<string[]>;
|
|
@@ -33,8 +33,8 @@ export declare const setupStorage: <MNames extends ModelNames>({ uploadsConfig,
|
|
|
33
33
|
* @param uploadsConfig The uploads configuration object.
|
|
34
34
|
* @returns The same uploads configuration object, but with filtered types
|
|
35
35
|
*/
|
|
36
|
-
export declare function createUploadsConfig<T extends Partial<{
|
|
37
|
-
[K in
|
|
36
|
+
export declare function createUploadsConfig<TClient, T extends Partial<{
|
|
37
|
+
[K in ModelNamesFor<TClient>]?: UploadConfigForModel<TClient, K>;
|
|
38
38
|
}>>(uploadsConfig: T): T;
|
|
39
|
-
export type {
|
|
39
|
+
export type { ModelNamesFor, UploadsConfig } from './prismaExtension.js';
|
|
40
40
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAE1E,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAE1E,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,aAAa,EACd,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAY/C,KAAK,mBAAmB,CACtB,OAAO,EACP,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,IAC5D;IACF,aAAa,EAAE,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC7C,cAAc,EAAE,kBAAkB,CAAA;IAClC,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,YAAY,GACvB,OAAO,EACP,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,EAC9D,+CAIC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;gBAzBE,CAAC;;;CAsCzC,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EACP,CAAC,SAAS,OAAO,CAAC;KACf,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC;CACjE,CAAC,EACF,aAAa,EAAE,CAAC,GAAG,CAAC,CAErB;AAED,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { createUploadSavers } from "./createSavers.js";
|
|
2
2
|
import { createUploadsExtension } from "./prismaExtension.js";
|
|
3
|
+
if (!process.env.CEDAR_SUPPRESS_STORAGE_DEPRECATION) {
|
|
4
|
+
console.warn(
|
|
5
|
+
"[@cedarjs/storage] This package is deprecated and will be removed in a future major release. Migrate to @cedarjs/uploads: https://cedarjs.com/docs/uploads#migrating-from-cedarjsstorage"
|
|
6
|
+
);
|
|
7
|
+
}
|
|
3
8
|
const setupStorage = ({
|
|
4
9
|
uploadsConfig,
|
|
5
10
|
storageAdapter,
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Prisma } from '@prisma/client';
|
|
3
|
-
import type * as runtime from '@prisma/client/runtime/library';
|
|
1
|
+
import { Prisma as PrismaExtension } from '@prisma/client/extension';
|
|
4
2
|
import type { BaseStorageAdapter } from './adapters/BaseStorageAdapter.js';
|
|
5
3
|
import type { UrlSigner } from './UrlSigner.js';
|
|
6
4
|
type FilterOutDollarPrefixed<T> = T extends `$${string}` ? never : T extends symbol ? never : T;
|
|
7
|
-
export type
|
|
8
|
-
type PrismaModelFields<MName extends
|
|
9
|
-
export type UploadConfigForModel<TPrismaModelName extends
|
|
10
|
-
fields: PrismaModelFields<TPrismaModelName> | PrismaModelFields<TPrismaModelName>[];
|
|
5
|
+
export type ModelNamesFor<TClient> = FilterOutDollarPrefixed<keyof TClient>;
|
|
6
|
+
type PrismaModelFields<TClient, MName extends ModelNamesFor<TClient>> = keyof PrismaExtension.Result<TClient[MName], any, 'findFirstOrThrow'>;
|
|
7
|
+
export type UploadConfigForModel<TClient, TPrismaModelName extends ModelNamesFor<TClient>> = {
|
|
8
|
+
fields: PrismaModelFields<TClient, TPrismaModelName> | PrismaModelFields<TClient, TPrismaModelName>[];
|
|
11
9
|
};
|
|
12
|
-
export type UploadsConfig<MNames extends
|
|
13
|
-
[K in MNames]?: UploadConfigForModel<K>;
|
|
10
|
+
export type UploadsConfig<TClient, MNames extends ModelNamesFor<TClient> = ModelNamesFor<TClient>> = {
|
|
11
|
+
[K in MNames]?: UploadConfigForModel<TClient, K>;
|
|
14
12
|
};
|
|
15
13
|
type WithSignedUrlArgs = {
|
|
16
14
|
expiresIn?: number;
|
|
17
15
|
};
|
|
18
|
-
export declare const createUploadsExtension: <MNames extends
|
|
16
|
+
export declare const createUploadsExtension: <TClient, MNames extends ModelNamesFor<TClient> = ModelNamesFor<TClient>>(config: UploadsConfig<TClient, MNames>, storageAdapter: BaseStorageAdapter, urlSigner?: UrlSigner) => (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/client").InternalArgs<{ [K in MNames]: {
|
|
19
17
|
withDataUri: {
|
|
20
18
|
needs: Record<string, boolean>;
|
|
21
19
|
compute: (modelData: Record<string, unknown>) => <T>(this: T) => Promise<T>;
|
|
@@ -24,6 +22,6 @@ export declare const createUploadsExtension: <MNames extends ModelNames = ModelN
|
|
|
24
22
|
needs: Record<string, boolean>;
|
|
25
23
|
compute: (modelData: Record<string, unknown>) => <T>(this: T, signArgs?: WithSignedUrlArgs) => T;
|
|
26
24
|
};
|
|
27
|
-
}; }, {}, {}, {}> & runtime.DefaultArgs>;
|
|
25
|
+
}; }, {}, {}, {}> & import("@prisma/client/runtime/client").DefaultArgs>;
|
|
28
26
|
export {};
|
|
29
27
|
//# sourceMappingURL=prismaExtension.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prismaExtension.d.ts","sourceRoot":"","sources":["../src/prismaExtension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"prismaExtension.d.ts","sourceRoot":"","sources":["../src/prismaExtension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAEpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAE1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,KAAK,uBAAuB,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,MAAM,EAAE,GACpD,KAAK,GACL,CAAC,SAAS,MAAM,GACd,KAAK,GACL,CAAC,CAAA;AAGP,MAAM,MAAM,aAAa,CAAC,OAAO,IAAI,uBAAuB,CAAC,MAAM,OAAO,CAAC,CAAA;AAE3E,KAAK,iBAAiB,CACpB,OAAO,EACP,KAAK,SAAS,aAAa,CAAC,OAAO,CAAC,IAClC,MAAM,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAA;AAEzE,MAAM,MAAM,oBAAoB,CAC9B,OAAO,EACP,gBAAgB,SAAS,aAAa,CAAC,OAAO,CAAC,IAC7C;IACF,MAAM,EACF,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,GAC5C,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,CAAA;CACnD,CAAA;AAED,MAAM,MAAM,aAAa,CACvB,OAAO,EACP,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,IAC5D;KACD,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC;CACjD,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,eAAO,MAAM,sBAAsB,GACjC,OAAO,EACP,MAAM,SAAS,aAAa,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,EAE9D,QAAQ,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,EACtC,gBAAgB,kBAAkB,EAClC,YAAY,SAAS,qIAGlB,CAAC;iBACa;QACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9B,OAAO,EAAE,CACP,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;KAChC;mBACc;QACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9B,OAAO,EAAE,CACP,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,iBAAiB,KAAK,CAAC,CAAA;KACrD;wEA+RN,CAAA"}
|
package/dist/prismaExtension.js
CHANGED
|
@@ -1,194 +1,188 @@
|
|
|
1
|
-
import { PrismaClient } from "@prisma/client";
|
|
2
1
|
import { Prisma as PrismaExtension } from "@prisma/client/extension";
|
|
3
2
|
import { fileToDataUri } from "./fileToDataUri.js";
|
|
4
3
|
const createUploadsExtension = (config, storageAdapter, urlSigner) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const result = await query(args);
|
|
18
|
-
return result;
|
|
19
|
-
} catch (e) {
|
|
20
|
-
await removeUploadedFiles(
|
|
21
|
-
uploadFields,
|
|
22
|
-
args.data
|
|
23
|
-
);
|
|
24
|
-
throw e;
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
async createMany({ query, args }) {
|
|
28
|
-
try {
|
|
29
|
-
const result = await query(args);
|
|
30
|
-
return result;
|
|
31
|
-
} catch (e) {
|
|
32
|
-
const createDatas = args.data;
|
|
33
|
-
for (const createData of createDatas) {
|
|
34
|
-
await removeUploadedFiles(uploadFields, createData);
|
|
35
|
-
}
|
|
36
|
-
throw e;
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
async update({ query, model, args }) {
|
|
40
|
-
const uploadFieldsToUpdate = uploadFields.filter(
|
|
41
|
-
(field) => (
|
|
42
|
-
// All of this non-sense is to make typescript happy. I'm not sure how data could be anything but an object
|
|
43
|
-
typeof args.data === "object" && args.data !== null && field in args.data
|
|
44
|
-
)
|
|
45
|
-
);
|
|
46
|
-
if (uploadFieldsToUpdate.length == 0) {
|
|
47
|
-
return query(args);
|
|
48
|
-
} else {
|
|
49
|
-
const originalRecord = await prismaInstance[
|
|
50
|
-
model
|
|
51
|
-
// @ts-expect-error TS in strict mode will error due to union type. We cannot narrow it down here.
|
|
52
|
-
].findFirstOrThrow({
|
|
53
|
-
where: args.where
|
|
54
|
-
// @TODO: should we select here to reduce the amount of data we're handling
|
|
55
|
-
});
|
|
4
|
+
return PrismaExtension.defineExtension((client) => {
|
|
5
|
+
const queryExtends = {};
|
|
6
|
+
const resultExtends = {};
|
|
7
|
+
for (const modelName in config) {
|
|
8
|
+
const modelConfig = config[modelName];
|
|
9
|
+
if (!modelConfig) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const uploadFields = Array.isArray(modelConfig.fields) ? modelConfig.fields : [modelConfig.fields];
|
|
13
|
+
queryExtends[modelName] = {
|
|
14
|
+
async create({ query, args }) {
|
|
56
15
|
try {
|
|
57
16
|
const result = await query(args);
|
|
58
|
-
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
59
17
|
return result;
|
|
60
18
|
} catch (e) {
|
|
61
19
|
await removeUploadedFiles(
|
|
62
|
-
|
|
20
|
+
uploadFields,
|
|
63
21
|
args.data
|
|
64
22
|
);
|
|
65
23
|
throw e;
|
|
66
24
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async updateMany({ query, model, args }) {
|
|
70
|
-
const uploadFieldsToUpdate = uploadFields.filter(
|
|
71
|
-
(field) => (
|
|
72
|
-
// All of this non-sense is to make typescript happy. I'm not sure how data could be anything but an object
|
|
73
|
-
typeof args.data === "object" && args.data !== null && field in args.data
|
|
74
|
-
)
|
|
75
|
-
);
|
|
76
|
-
if (uploadFieldsToUpdate.length == 0) {
|
|
77
|
-
return query(args);
|
|
78
|
-
} else {
|
|
79
|
-
const originalRecords = await prismaInstance[
|
|
80
|
-
model
|
|
81
|
-
// @ts-expect-error TS in strict mode will error due to union type. We cannot narrow it down here.
|
|
82
|
-
].findMany({
|
|
83
|
-
where: args.where
|
|
84
|
-
// @TODO: should we select here to reduce the amount of data we're handling
|
|
85
|
-
});
|
|
25
|
+
},
|
|
26
|
+
async createMany({ query, args }) {
|
|
86
27
|
try {
|
|
87
28
|
const result = await query(args);
|
|
88
|
-
|
|
29
|
+
return result;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
const createDatas = args.data;
|
|
32
|
+
for (const createData of createDatas) {
|
|
33
|
+
await removeUploadedFiles(uploadFields, createData);
|
|
34
|
+
}
|
|
35
|
+
throw e;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
async update({ query, model, args }) {
|
|
39
|
+
const uploadFieldsToUpdate = uploadFields.filter((field) => {
|
|
40
|
+
return args.data && typeof args.data === "object" && field in args.data;
|
|
41
|
+
});
|
|
42
|
+
if (uploadFieldsToUpdate.length === 0) {
|
|
43
|
+
return query(args);
|
|
44
|
+
} else {
|
|
45
|
+
const originalRecord = await client[model].findFirstOrThrow({
|
|
46
|
+
where: args.where,
|
|
47
|
+
select: Object.fromEntries(
|
|
48
|
+
uploadFieldsToUpdate.map((f) => [f, true])
|
|
49
|
+
)
|
|
50
|
+
});
|
|
51
|
+
try {
|
|
52
|
+
const result = await query(args);
|
|
89
53
|
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
54
|
+
return result;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
await removeUploadedFiles(
|
|
57
|
+
uploadFieldsToUpdate,
|
|
58
|
+
args.data
|
|
59
|
+
);
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
async updateMany({ query, model, args }) {
|
|
65
|
+
const uploadFieldsToUpdate = uploadFields.filter((field) => {
|
|
66
|
+
return args.data && typeof args.data === "object" && field in args.data;
|
|
67
|
+
});
|
|
68
|
+
if (uploadFieldsToUpdate.length === 0) {
|
|
69
|
+
return query(args);
|
|
70
|
+
} else {
|
|
71
|
+
const originalRecords = await client[model].findMany({
|
|
72
|
+
where: args.where,
|
|
73
|
+
select: Object.fromEntries(
|
|
74
|
+
uploadFieldsToUpdate.map((f) => [f, true])
|
|
75
|
+
)
|
|
76
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
const result = await query(args);
|
|
79
|
+
for await (const originalRecord of originalRecords) {
|
|
80
|
+
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
} catch (e) {
|
|
84
|
+
await removeUploadedFiles(
|
|
85
|
+
uploadFieldsToUpdate,
|
|
86
|
+
args.data
|
|
87
|
+
);
|
|
88
|
+
throw e;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
async upsert({ query, model, args }) {
|
|
93
|
+
let isUpdate;
|
|
94
|
+
const uploadFieldsToUpdate = uploadFields.filter(
|
|
95
|
+
(field) => typeof args.update === "object" && args.update !== null && field in args.update
|
|
96
|
+
);
|
|
97
|
+
try {
|
|
98
|
+
let existingRecord;
|
|
99
|
+
if (args.update) {
|
|
100
|
+
existingRecord = await client[model].findUnique({
|
|
101
|
+
where: args.where,
|
|
102
|
+
...uploadFieldsToUpdate.length > 0 ? {
|
|
103
|
+
select: Object.fromEntries(
|
|
104
|
+
uploadFieldsToUpdate.map((f) => [f, true])
|
|
105
|
+
)
|
|
106
|
+
} : {}
|
|
107
|
+
});
|
|
108
|
+
isUpdate = !!existingRecord;
|
|
109
|
+
}
|
|
110
|
+
const result = await query(args);
|
|
111
|
+
if (isUpdate && existingRecord) {
|
|
112
|
+
await removeUploadedFiles(uploadFieldsToUpdate, existingRecord);
|
|
90
113
|
}
|
|
91
114
|
return result;
|
|
92
115
|
} catch (e) {
|
|
93
116
|
await removeUploadedFiles(
|
|
94
|
-
|
|
95
|
-
|
|
117
|
+
// Only delete files we're updating on update
|
|
118
|
+
isUpdate ? uploadFieldsToUpdate : uploadFields,
|
|
119
|
+
isUpdate ? args.update : args.create
|
|
96
120
|
);
|
|
97
121
|
throw e;
|
|
98
122
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
let isUpdate;
|
|
103
|
-
const uploadFieldsToUpdate = uploadFields.filter(
|
|
104
|
-
(field) => typeof args.update === "object" && args.update !== null && field in args.update
|
|
105
|
-
);
|
|
106
|
-
try {
|
|
107
|
-
let existingRecord;
|
|
108
|
-
if (args.update) {
|
|
109
|
-
existingRecord = await prismaInstance[
|
|
110
|
-
model
|
|
111
|
-
// @ts-expect-error TS in strict mode will error due to union type. We cannot narrow it down here.
|
|
112
|
-
].findUnique({
|
|
113
|
-
where: args.where
|
|
114
|
-
});
|
|
115
|
-
isUpdate = !!existingRecord;
|
|
116
|
-
}
|
|
117
|
-
const result = await query(args);
|
|
118
|
-
if (isUpdate && existingRecord) {
|
|
119
|
-
await removeUploadedFiles(uploadFieldsToUpdate, existingRecord);
|
|
120
|
-
}
|
|
121
|
-
return result;
|
|
122
|
-
} catch (e) {
|
|
123
|
+
},
|
|
124
|
+
async delete({ query, args }) {
|
|
125
|
+
const deleteResult = await query(args);
|
|
123
126
|
await removeUploadedFiles(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
uploadFields,
|
|
128
|
+
// We don't know the exact type here
|
|
129
|
+
deleteResult
|
|
127
130
|
);
|
|
128
|
-
|
|
131
|
+
return deleteResult;
|
|
129
132
|
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
storageAdapter
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
return {
|
|
155
|
-
// modelData is of type unknown at this point
|
|
156
|
-
...modelData,
|
|
157
|
-
...base64UploadFields
|
|
133
|
+
};
|
|
134
|
+
const needs = Object.fromEntries(
|
|
135
|
+
uploadFields.map((field) => [field, true])
|
|
136
|
+
);
|
|
137
|
+
resultExtends[modelName] = {
|
|
138
|
+
withDataUri: {
|
|
139
|
+
needs,
|
|
140
|
+
compute(modelData) {
|
|
141
|
+
return async () => {
|
|
142
|
+
const base64UploadFields = {};
|
|
143
|
+
for (const field of uploadFields) {
|
|
144
|
+
base64UploadFields[field] = await fileToDataUri(
|
|
145
|
+
modelData[field],
|
|
146
|
+
storageAdapter
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
// modelData is of type unknown at this point
|
|
151
|
+
...modelData,
|
|
152
|
+
...base64UploadFields
|
|
153
|
+
};
|
|
158
154
|
};
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
const signedUrlFields = {};
|
|
172
|
-
for (const field of uploadFields) {
|
|
173
|
-
if (!modelData[field]) {
|
|
174
|
-
continue;
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
withSignedUrl: {
|
|
158
|
+
needs,
|
|
159
|
+
compute(modelData) {
|
|
160
|
+
return ({ expiresIn } = {}) => {
|
|
161
|
+
if (!urlSigner) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
"Please supply signed url settings in setupUpload()"
|
|
164
|
+
);
|
|
175
165
|
}
|
|
176
|
-
signedUrlFields
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
166
|
+
const signedUrlFields = {};
|
|
167
|
+
for (const field of uploadFields) {
|
|
168
|
+
if (!modelData[field]) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
signedUrlFields[field] = urlSigner.generateSignedUrl(
|
|
172
|
+
modelData[field],
|
|
173
|
+
expiresIn
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
// modelData is of type unknown at this point
|
|
178
|
+
...modelData,
|
|
179
|
+
...signedUrlFields
|
|
180
|
+
};
|
|
185
181
|
};
|
|
186
|
-
}
|
|
182
|
+
}
|
|
187
183
|
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return PrismaExtension.defineExtension((client) => {
|
|
184
|
+
};
|
|
185
|
+
}
|
|
192
186
|
return client.$extends({
|
|
193
187
|
name: "redwood-upload-prisma-plugin",
|
|
194
188
|
query: queryExtends,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/storage",
|
|
3
|
-
"version": "9.0.0-canary.
|
|
3
|
+
"version": "9.0.0-canary.3124",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/cedarjs/cedar.git",
|
|
@@ -10,68 +10,57 @@
|
|
|
10
10
|
"type": "module",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"
|
|
14
|
-
"types": "./dist/cjs/index.d.ts",
|
|
15
|
-
"default": "./dist/cjs/index.js"
|
|
16
|
-
},
|
|
17
|
-
"import": {
|
|
13
|
+
"default": {
|
|
18
14
|
"types": "./dist/index.d.ts",
|
|
19
15
|
"default": "./dist/index.js"
|
|
20
16
|
}
|
|
21
17
|
},
|
|
22
|
-
"./FileSystemStorage":
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"./MemoryStorage": {
|
|
27
|
-
"require": "./dist/cjs/adapters/MemoryStorage/MemoryStorage.js",
|
|
28
|
-
"import": "./dist/adapters/MemoryStorage/MemoryStorage.js"
|
|
29
|
-
},
|
|
30
|
-
"./BaseStorageAdapter": {
|
|
31
|
-
"require": "./dist/cjs/adapters/BaseStorageAdapter.js",
|
|
32
|
-
"import": "./dist/adapters/BaseStorageAdapter.js"
|
|
33
|
-
},
|
|
34
|
-
"./UrlSigner": {
|
|
35
|
-
"require": "./dist/cjs/UrlSigner.js",
|
|
36
|
-
"import": "./dist/UrlSigner.js"
|
|
37
|
-
}
|
|
18
|
+
"./FileSystemStorage": "./dist/adapters/FileSystemStorage/FileSystemStorage.js",
|
|
19
|
+
"./MemoryStorage": "./dist/adapters/MemoryStorage/MemoryStorage.js",
|
|
20
|
+
"./BaseStorageAdapter": "./dist/adapters/BaseStorageAdapter.js",
|
|
21
|
+
"./UrlSigner": "./dist/UrlSigner.js"
|
|
38
22
|
},
|
|
39
23
|
"files": [
|
|
40
24
|
"dist",
|
|
41
25
|
"!dist/**/*.test.d.*"
|
|
42
26
|
],
|
|
43
27
|
"scripts": {
|
|
44
|
-
"build": "
|
|
28
|
+
"build": "node ./build.mts",
|
|
45
29
|
"build:pack": "yarn pack -o cedarjs-storage.tgz",
|
|
46
30
|
"build:types": "tsc --build --verbose ./tsconfig.build.json",
|
|
47
|
-
"
|
|
48
|
-
"check:attw": "tsx attw.ts",
|
|
31
|
+
"check:attw": "yarn cedar-fwtools-attw",
|
|
49
32
|
"check:package": "concurrently npm:check:attw yarn publint",
|
|
50
|
-
"setup:test": "npx prisma db push --accept-data-loss --config ./src/__tests__/prisma.config.ts",
|
|
33
|
+
"setup:test": "npx prisma db push --accept-data-loss --config ./src/__tests__/prisma.config.ts && npx prisma generate --config ./src/__tests__/prisma.config.ts",
|
|
51
34
|
"test": "vitest run",
|
|
52
35
|
"test:types": "yarn setup:test && tstyche",
|
|
53
36
|
"test:watch": "vitest watch"
|
|
54
37
|
},
|
|
55
38
|
"dependencies": {
|
|
56
|
-
"@cedarjs/project-config": "9.0.0-canary.
|
|
39
|
+
"@cedarjs/project-config": "9.0.0-canary.3124",
|
|
57
40
|
"mime-types": "2.1.35",
|
|
58
41
|
"ulid": "3.0.2"
|
|
59
42
|
},
|
|
60
43
|
"devDependencies": {
|
|
61
|
-
"@arethetypeswrong/cli": "0.18.
|
|
62
|
-
"@cedarjs/framework-tools": "9.0.0-canary.
|
|
63
|
-
"@prisma/
|
|
44
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
45
|
+
"@cedarjs/framework-tools": "9.0.0-canary.3124",
|
|
46
|
+
"@prisma/adapter-better-sqlite3": "7.10.0",
|
|
47
|
+
"@prisma/client": "7.10.0",
|
|
48
|
+
"@types/better-sqlite3": "7.6.13",
|
|
64
49
|
"@types/mime-types": "2.1.4",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
50
|
+
"better-sqlite3": "12.11.1",
|
|
51
|
+
"concurrently": "9.2.4",
|
|
52
|
+
"esbuild": "0.28.2",
|
|
53
|
+
"prisma": "7.10.0",
|
|
54
|
+
"publint": "0.3.24",
|
|
68
55
|
"tstyche": "5.0.2",
|
|
69
|
-
"tsx": "4.21.0",
|
|
70
56
|
"typescript": "5.9.3",
|
|
71
|
-
"vitest": "
|
|
57
|
+
"vitest": "4.1.11"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=24"
|
|
72
61
|
},
|
|
73
62
|
"publishConfig": {
|
|
74
63
|
"access": "public"
|
|
75
64
|
},
|
|
76
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1"
|
|
77
66
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Cedar
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|