@cedarjs/storage 2.6.0 → 2.6.1-next.104
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.
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { PrismaClient } from '@prisma/client';
|
|
1
|
+
import type { PrismaClient } from '@prisma/client';
|
|
2
2
|
import type { Prisma } from '@prisma/client';
|
|
3
|
-
import type * as runtime from '@prisma/client/runtime/library';
|
|
4
3
|
import type { BaseStorageAdapter } from './adapters/BaseStorageAdapter.js';
|
|
5
4
|
import type { UrlSigner } from './UrlSigner.js';
|
|
6
5
|
type FilterOutDollarPrefixed<T> = T extends `$${string}` ? never : T extends symbol ? never : T;
|
|
@@ -15,7 +14,7 @@ export type UploadsConfig<MNames extends ModelNames = ModelNames> = {
|
|
|
15
14
|
type WithSignedUrlArgs = {
|
|
16
15
|
expiresIn?: number;
|
|
17
16
|
};
|
|
18
|
-
export declare const createUploadsExtension: <MNames extends ModelNames = ModelNames>(config: UploadsConfig<MNames>, storageAdapter: BaseStorageAdapter, urlSigner?: UrlSigner) => (client: any) => import("@prisma/client/extension").PrismaClientExtends<runtime.InternalArgs<{ [K in MNames]: {
|
|
17
|
+
export declare const createUploadsExtension: <MNames extends ModelNames = ModelNames>(config: UploadsConfig<MNames>, storageAdapter: BaseStorageAdapter, urlSigner?: UrlSigner) => (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/library").InternalArgs<{ [K in MNames]: {
|
|
19
18
|
withDataUri: {
|
|
20
19
|
needs: Record<string, boolean>;
|
|
21
20
|
compute: (modelData: Record<string, unknown>) => <T>(this: T) => Promise<T>;
|
|
@@ -24,6 +23,6 @@ export declare const createUploadsExtension: <MNames extends ModelNames = ModelN
|
|
|
24
23
|
needs: Record<string, boolean>;
|
|
25
24
|
compute: (modelData: Record<string, unknown>) => <T>(this: T, signArgs?: WithSignedUrlArgs) => T;
|
|
26
25
|
};
|
|
27
|
-
}; }, {}, {}, {}> & runtime.DefaultArgs>;
|
|
26
|
+
}; }, {}, {}, {}> & import("@prisma/client/runtime/library").DefaultArgs>;
|
|
28
27
|
export {};
|
|
29
28
|
//# sourceMappingURL=prismaExtension.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prismaExtension.d.ts","sourceRoot":"","sources":["../../src/prismaExtension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"prismaExtension.d.ts","sourceRoot":"","sources":["../../src/prismaExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAG5C,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,UAAU,GAAG,uBAAuB,CAAC,MAAM,YAAY,CAAC,CAAA;AAEpE,KAAK,iBAAiB,CAAC,KAAK,SAAS,UAAU,IAAI,MAAM,MAAM,CAAC,MAAM,CACpE,YAAY,CAAC,KAAK,CAAC,EACnB,GAAG,EACH,kBAAkB,CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,CAAC,gBAAgB,SAAS,UAAU,IAAI;IACtE,MAAM,EACF,iBAAiB,CAAC,gBAAgB,CAAC,GACnC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,UAAU,GAAG,UAAU,IAAI;KACjE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC;CACxC,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,MAAM,SAAS,UAAU,GAAG,UAAU,EAC3E,QAAQ,aAAa,CAAC,MAAM,CAAC,EAC7B,gBAAgB,kBAAkB,EAClC,YAAY,SAAS,sIAGlB,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;yEAoRN,CAAA"}
|
|
@@ -21,197 +21,182 @@ __export(prismaExtension_exports, {
|
|
|
21
21
|
createUploadsExtension: () => createUploadsExtension
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(prismaExtension_exports);
|
|
24
|
-
var import_client = require("@prisma/client");
|
|
25
24
|
var import_extension = require("@prisma/client/extension");
|
|
26
25
|
var import_fileToDataUri = require("./fileToDataUri.js");
|
|
27
26
|
const createUploadsExtension = (config, storageAdapter, urlSigner) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
const result = await query(args);
|
|
41
|
-
return result;
|
|
42
|
-
} catch (e) {
|
|
43
|
-
await removeUploadedFiles(
|
|
44
|
-
uploadFields,
|
|
45
|
-
args.data
|
|
46
|
-
);
|
|
47
|
-
throw e;
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
async createMany({ query, args }) {
|
|
51
|
-
try {
|
|
52
|
-
const result = await query(args);
|
|
53
|
-
return result;
|
|
54
|
-
} catch (e) {
|
|
55
|
-
const createDatas = args.data;
|
|
56
|
-
for (const createData of createDatas) {
|
|
57
|
-
await removeUploadedFiles(uploadFields, createData);
|
|
58
|
-
}
|
|
59
|
-
throw e;
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
async update({ query, model, args }) {
|
|
63
|
-
const uploadFieldsToUpdate = uploadFields.filter(
|
|
64
|
-
(field) => (
|
|
65
|
-
// All of this non-sense is to make typescript happy. I'm not sure how data could be anything but an object
|
|
66
|
-
typeof args.data === "object" && args.data !== null && field in args.data
|
|
67
|
-
)
|
|
68
|
-
);
|
|
69
|
-
if (uploadFieldsToUpdate.length == 0) {
|
|
70
|
-
return query(args);
|
|
71
|
-
} else {
|
|
72
|
-
const originalRecord = await prismaInstance[
|
|
73
|
-
model
|
|
74
|
-
// @ts-expect-error TS in strict mode will error due to union type. We cannot narrow it down here.
|
|
75
|
-
].findFirstOrThrow({
|
|
76
|
-
where: args.where
|
|
77
|
-
// @TODO: should we select here to reduce the amount of data we're handling
|
|
78
|
-
});
|
|
27
|
+
return import_extension.Prisma.defineExtension((client) => {
|
|
28
|
+
const queryExtends = {};
|
|
29
|
+
const resultExtends = {};
|
|
30
|
+
for (const modelName in config) {
|
|
31
|
+
const modelConfig = config[modelName];
|
|
32
|
+
if (!modelConfig) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const uploadFields = Array.isArray(modelConfig.fields) ? modelConfig.fields : [modelConfig.fields];
|
|
36
|
+
queryExtends[modelName] = {
|
|
37
|
+
async create({ query, args }) {
|
|
79
38
|
try {
|
|
80
39
|
const result = await query(args);
|
|
81
|
-
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
82
40
|
return result;
|
|
83
41
|
} catch (e) {
|
|
84
42
|
await removeUploadedFiles(
|
|
85
|
-
|
|
43
|
+
uploadFields,
|
|
86
44
|
args.data
|
|
87
45
|
);
|
|
88
46
|
throw e;
|
|
89
47
|
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async updateMany({ query, model, args }) {
|
|
93
|
-
const uploadFieldsToUpdate = uploadFields.filter(
|
|
94
|
-
(field) => (
|
|
95
|
-
// All of this non-sense is to make typescript happy. I'm not sure how data could be anything but an object
|
|
96
|
-
typeof args.data === "object" && args.data !== null && field in args.data
|
|
97
|
-
)
|
|
98
|
-
);
|
|
99
|
-
if (uploadFieldsToUpdate.length == 0) {
|
|
100
|
-
return query(args);
|
|
101
|
-
} else {
|
|
102
|
-
const originalRecords = await prismaInstance[
|
|
103
|
-
model
|
|
104
|
-
// @ts-expect-error TS in strict mode will error due to union type. We cannot narrow it down here.
|
|
105
|
-
].findMany({
|
|
106
|
-
where: args.where
|
|
107
|
-
// @TODO: should we select here to reduce the amount of data we're handling
|
|
108
|
-
});
|
|
48
|
+
},
|
|
49
|
+
async createMany({ query, args }) {
|
|
109
50
|
try {
|
|
110
51
|
const result = await query(args);
|
|
111
|
-
for await (const originalRecord of originalRecords) {
|
|
112
|
-
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
113
|
-
}
|
|
114
52
|
return result;
|
|
115
53
|
} catch (e) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
54
|
+
const createDatas = args.data;
|
|
55
|
+
for (const createData of createDatas) {
|
|
56
|
+
await removeUploadedFiles(uploadFields, createData);
|
|
57
|
+
}
|
|
120
58
|
throw e;
|
|
121
59
|
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
60
|
+
},
|
|
61
|
+
async update({ query, model, args }) {
|
|
62
|
+
const uploadFieldsToUpdate = uploadFields.filter((field) => {
|
|
63
|
+
return args.data && typeof args.data === "object" && field in args.data;
|
|
64
|
+
});
|
|
65
|
+
if (uploadFieldsToUpdate.length === 0) {
|
|
66
|
+
return query(args);
|
|
67
|
+
} else {
|
|
68
|
+
const originalRecord = await client[model].findFirstOrThrow({
|
|
69
|
+
where: args.where
|
|
70
|
+
// @TODO: should we select here to reduce the amount of data we're handling
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const result = await query(args);
|
|
74
|
+
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
75
|
+
return result;
|
|
76
|
+
} catch (e) {
|
|
77
|
+
await removeUploadedFiles(
|
|
78
|
+
uploadFieldsToUpdate,
|
|
79
|
+
args.data
|
|
80
|
+
);
|
|
81
|
+
throw e;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
async updateMany({ query, model, args }) {
|
|
86
|
+
const uploadFieldsToUpdate = uploadFields.filter((field) => {
|
|
87
|
+
return args.data && typeof args.data === "object" && field in args.data;
|
|
88
|
+
});
|
|
89
|
+
if (uploadFieldsToUpdate.length === 0) {
|
|
90
|
+
return query(args);
|
|
91
|
+
} else {
|
|
92
|
+
const originalRecords = await client[model].findMany({
|
|
136
93
|
where: args.where
|
|
94
|
+
// @TODO: should we select here to reduce the amount of data we're handling
|
|
137
95
|
});
|
|
138
|
-
|
|
96
|
+
try {
|
|
97
|
+
const result = await query(args);
|
|
98
|
+
for await (const originalRecord of originalRecords) {
|
|
99
|
+
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
} catch (e) {
|
|
103
|
+
await removeUploadedFiles(
|
|
104
|
+
uploadFieldsToUpdate,
|
|
105
|
+
args.data
|
|
106
|
+
);
|
|
107
|
+
throw e;
|
|
108
|
+
}
|
|
139
109
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
110
|
+
},
|
|
111
|
+
async upsert({ query, model, args }) {
|
|
112
|
+
let isUpdate;
|
|
113
|
+
const uploadFieldsToUpdate = uploadFields.filter(
|
|
114
|
+
(field) => typeof args.update === "object" && args.update !== null && field in args.update
|
|
115
|
+
);
|
|
116
|
+
try {
|
|
117
|
+
let existingRecord;
|
|
118
|
+
if (args.update) {
|
|
119
|
+
existingRecord = await client[model].findUnique({
|
|
120
|
+
where: args.where
|
|
121
|
+
});
|
|
122
|
+
isUpdate = !!existingRecord;
|
|
123
|
+
}
|
|
124
|
+
const result = await query(args);
|
|
125
|
+
if (isUpdate && existingRecord) {
|
|
126
|
+
await removeUploadedFiles(uploadFieldsToUpdate, existingRecord);
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
} catch (e) {
|
|
130
|
+
await removeUploadedFiles(
|
|
131
|
+
// Only delete files we're updating on update
|
|
132
|
+
isUpdate ? uploadFieldsToUpdate : uploadFields,
|
|
133
|
+
isUpdate ? args.update : args.create
|
|
134
|
+
);
|
|
135
|
+
throw e;
|
|
143
136
|
}
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
},
|
|
138
|
+
async delete({ query, args }) {
|
|
139
|
+
const deleteResult = await query(args);
|
|
146
140
|
await removeUploadedFiles(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
uploadFields,
|
|
142
|
+
// We don't know the exact type here
|
|
143
|
+
deleteResult
|
|
150
144
|
);
|
|
151
|
-
|
|
145
|
+
return deleteResult;
|
|
152
146
|
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
storageAdapter
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
// modelData is of type unknown at this point
|
|
179
|
-
...modelData,
|
|
180
|
-
...base64UploadFields
|
|
147
|
+
};
|
|
148
|
+
const needs = Object.fromEntries(
|
|
149
|
+
uploadFields.map((field) => [field, true])
|
|
150
|
+
);
|
|
151
|
+
resultExtends[modelName] = {
|
|
152
|
+
withDataUri: {
|
|
153
|
+
needs,
|
|
154
|
+
compute(modelData) {
|
|
155
|
+
return async () => {
|
|
156
|
+
const base64UploadFields = {};
|
|
157
|
+
for (const field of uploadFields) {
|
|
158
|
+
base64UploadFields[field] = await (0, import_fileToDataUri.fileToDataUri)(
|
|
159
|
+
modelData[field],
|
|
160
|
+
storageAdapter
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
// modelData is of type unknown at this point
|
|
165
|
+
...modelData,
|
|
166
|
+
...base64UploadFields
|
|
167
|
+
};
|
|
181
168
|
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
const signedUrlFields = {};
|
|
195
|
-
for (const field of uploadFields) {
|
|
196
|
-
if (!modelData[field]) {
|
|
197
|
-
continue;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
withSignedUrl: {
|
|
172
|
+
needs,
|
|
173
|
+
compute(modelData) {
|
|
174
|
+
return ({ expiresIn } = {}) => {
|
|
175
|
+
if (!urlSigner) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
"Please supply signed url settings in setupUpload()"
|
|
178
|
+
);
|
|
198
179
|
}
|
|
199
|
-
signedUrlFields
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
180
|
+
const signedUrlFields = {};
|
|
181
|
+
for (const field of uploadFields) {
|
|
182
|
+
if (!modelData[field]) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
signedUrlFields[field] = urlSigner.generateSignedUrl(
|
|
186
|
+
modelData[field],
|
|
187
|
+
expiresIn
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
// modelData is of type unknown at this point
|
|
192
|
+
...modelData,
|
|
193
|
+
...signedUrlFields
|
|
194
|
+
};
|
|
208
195
|
};
|
|
209
|
-
}
|
|
196
|
+
}
|
|
210
197
|
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return import_extension.Prisma.defineExtension((client) => {
|
|
198
|
+
};
|
|
199
|
+
}
|
|
215
200
|
return client.$extends({
|
|
216
201
|
name: "redwood-upload-prisma-plugin",
|
|
217
202
|
query: queryExtends,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { PrismaClient } from '@prisma/client';
|
|
1
|
+
import type { PrismaClient } from '@prisma/client';
|
|
2
2
|
import type { Prisma } from '@prisma/client';
|
|
3
|
-
import type * as runtime from '@prisma/client/runtime/library';
|
|
4
3
|
import type { BaseStorageAdapter } from './adapters/BaseStorageAdapter.js';
|
|
5
4
|
import type { UrlSigner } from './UrlSigner.js';
|
|
6
5
|
type FilterOutDollarPrefixed<T> = T extends `$${string}` ? never : T extends symbol ? never : T;
|
|
@@ -15,7 +14,7 @@ export type UploadsConfig<MNames extends ModelNames = ModelNames> = {
|
|
|
15
14
|
type WithSignedUrlArgs = {
|
|
16
15
|
expiresIn?: number;
|
|
17
16
|
};
|
|
18
|
-
export declare const createUploadsExtension: <MNames extends ModelNames = ModelNames>(config: UploadsConfig<MNames>, storageAdapter: BaseStorageAdapter, urlSigner?: UrlSigner) => (client: any) => import("@prisma/client/extension").PrismaClientExtends<runtime.InternalArgs<{ [K in MNames]: {
|
|
17
|
+
export declare const createUploadsExtension: <MNames extends ModelNames = ModelNames>(config: UploadsConfig<MNames>, storageAdapter: BaseStorageAdapter, urlSigner?: UrlSigner) => (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/library").InternalArgs<{ [K in MNames]: {
|
|
19
18
|
withDataUri: {
|
|
20
19
|
needs: Record<string, boolean>;
|
|
21
20
|
compute: (modelData: Record<string, unknown>) => <T>(this: T) => Promise<T>;
|
|
@@ -24,6 +23,6 @@ export declare const createUploadsExtension: <MNames extends ModelNames = ModelN
|
|
|
24
23
|
needs: Record<string, boolean>;
|
|
25
24
|
compute: (modelData: Record<string, unknown>) => <T>(this: T, signArgs?: WithSignedUrlArgs) => T;
|
|
26
25
|
};
|
|
27
|
-
}; }, {}, {}, {}> & runtime.DefaultArgs>;
|
|
26
|
+
}; }, {}, {}, {}> & import("@prisma/client/runtime/library").DefaultArgs>;
|
|
28
27
|
export {};
|
|
29
28
|
//# sourceMappingURL=prismaExtension.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prismaExtension.d.ts","sourceRoot":"","sources":["../src/prismaExtension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"prismaExtension.d.ts","sourceRoot":"","sources":["../src/prismaExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAG5C,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,UAAU,GAAG,uBAAuB,CAAC,MAAM,YAAY,CAAC,CAAA;AAEpE,KAAK,iBAAiB,CAAC,KAAK,SAAS,UAAU,IAAI,MAAM,MAAM,CAAC,MAAM,CACpE,YAAY,CAAC,KAAK,CAAC,EACnB,GAAG,EACH,kBAAkB,CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,CAAC,gBAAgB,SAAS,UAAU,IAAI;IACtE,MAAM,EACF,iBAAiB,CAAC,gBAAgB,CAAC,GACnC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,UAAU,GAAG,UAAU,IAAI;KACjE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC;CACxC,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,MAAM,SAAS,UAAU,GAAG,UAAU,EAC3E,QAAQ,aAAa,CAAC,MAAM,CAAC,EAC7B,gBAAgB,kBAAkB,EAClC,YAAY,SAAS,sIAGlB,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;yEAoRN,CAAA"}
|
package/dist/prismaExtension.js
CHANGED
|
@@ -1,194 +1,179 @@
|
|
|
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
|
-
for await (const originalRecord of originalRecords) {
|
|
89
|
-
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
90
|
-
}
|
|
91
29
|
return result;
|
|
92
30
|
} catch (e) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
31
|
+
const createDatas = args.data;
|
|
32
|
+
for (const createData of createDatas) {
|
|
33
|
+
await removeUploadedFiles(uploadFields, createData);
|
|
34
|
+
}
|
|
97
35
|
throw e;
|
|
98
36
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
+
// @TODO: should we select here to reduce the amount of data we're handling
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
const result = await query(args);
|
|
51
|
+
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
52
|
+
return result;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
await removeUploadedFiles(
|
|
55
|
+
uploadFieldsToUpdate,
|
|
56
|
+
args.data
|
|
57
|
+
);
|
|
58
|
+
throw e;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
async updateMany({ query, model, args }) {
|
|
63
|
+
const uploadFieldsToUpdate = uploadFields.filter((field) => {
|
|
64
|
+
return args.data && typeof args.data === "object" && field in args.data;
|
|
65
|
+
});
|
|
66
|
+
if (uploadFieldsToUpdate.length === 0) {
|
|
67
|
+
return query(args);
|
|
68
|
+
} else {
|
|
69
|
+
const originalRecords = await client[model].findMany({
|
|
113
70
|
where: args.where
|
|
71
|
+
// @TODO: should we select here to reduce the amount of data we're handling
|
|
114
72
|
});
|
|
115
|
-
|
|
73
|
+
try {
|
|
74
|
+
const result = await query(args);
|
|
75
|
+
for await (const originalRecord of originalRecords) {
|
|
76
|
+
await removeUploadedFiles(uploadFieldsToUpdate, originalRecord);
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
} catch (e) {
|
|
80
|
+
await removeUploadedFiles(
|
|
81
|
+
uploadFieldsToUpdate,
|
|
82
|
+
args.data
|
|
83
|
+
);
|
|
84
|
+
throw e;
|
|
85
|
+
}
|
|
116
86
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
87
|
+
},
|
|
88
|
+
async upsert({ query, model, args }) {
|
|
89
|
+
let isUpdate;
|
|
90
|
+
const uploadFieldsToUpdate = uploadFields.filter(
|
|
91
|
+
(field) => typeof args.update === "object" && args.update !== null && field in args.update
|
|
92
|
+
);
|
|
93
|
+
try {
|
|
94
|
+
let existingRecord;
|
|
95
|
+
if (args.update) {
|
|
96
|
+
existingRecord = await client[model].findUnique({
|
|
97
|
+
where: args.where
|
|
98
|
+
});
|
|
99
|
+
isUpdate = !!existingRecord;
|
|
100
|
+
}
|
|
101
|
+
const result = await query(args);
|
|
102
|
+
if (isUpdate && existingRecord) {
|
|
103
|
+
await removeUploadedFiles(uploadFieldsToUpdate, existingRecord);
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
} catch (e) {
|
|
107
|
+
await removeUploadedFiles(
|
|
108
|
+
// Only delete files we're updating on update
|
|
109
|
+
isUpdate ? uploadFieldsToUpdate : uploadFields,
|
|
110
|
+
isUpdate ? args.update : args.create
|
|
111
|
+
);
|
|
112
|
+
throw e;
|
|
120
113
|
}
|
|
121
|
-
|
|
122
|
-
|
|
114
|
+
},
|
|
115
|
+
async delete({ query, args }) {
|
|
116
|
+
const deleteResult = await query(args);
|
|
123
117
|
await removeUploadedFiles(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
118
|
+
uploadFields,
|
|
119
|
+
// We don't know the exact type here
|
|
120
|
+
deleteResult
|
|
127
121
|
);
|
|
128
|
-
|
|
122
|
+
return deleteResult;
|
|
129
123
|
}
|
|
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
|
|
124
|
+
};
|
|
125
|
+
const needs = Object.fromEntries(
|
|
126
|
+
uploadFields.map((field) => [field, true])
|
|
127
|
+
);
|
|
128
|
+
resultExtends[modelName] = {
|
|
129
|
+
withDataUri: {
|
|
130
|
+
needs,
|
|
131
|
+
compute(modelData) {
|
|
132
|
+
return async () => {
|
|
133
|
+
const base64UploadFields = {};
|
|
134
|
+
for (const field of uploadFields) {
|
|
135
|
+
base64UploadFields[field] = await fileToDataUri(
|
|
136
|
+
modelData[field],
|
|
137
|
+
storageAdapter
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
// modelData is of type unknown at this point
|
|
142
|
+
...modelData,
|
|
143
|
+
...base64UploadFields
|
|
144
|
+
};
|
|
158
145
|
};
|
|
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;
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
withSignedUrl: {
|
|
149
|
+
needs,
|
|
150
|
+
compute(modelData) {
|
|
151
|
+
return ({ expiresIn } = {}) => {
|
|
152
|
+
if (!urlSigner) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
"Please supply signed url settings in setupUpload()"
|
|
155
|
+
);
|
|
175
156
|
}
|
|
176
|
-
signedUrlFields
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
157
|
+
const signedUrlFields = {};
|
|
158
|
+
for (const field of uploadFields) {
|
|
159
|
+
if (!modelData[field]) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
signedUrlFields[field] = urlSigner.generateSignedUrl(
|
|
163
|
+
modelData[field],
|
|
164
|
+
expiresIn
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
// modelData is of type unknown at this point
|
|
169
|
+
...modelData,
|
|
170
|
+
...signedUrlFields
|
|
171
|
+
};
|
|
185
172
|
};
|
|
186
|
-
}
|
|
173
|
+
}
|
|
187
174
|
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return PrismaExtension.defineExtension((client) => {
|
|
175
|
+
};
|
|
176
|
+
}
|
|
192
177
|
return client.$extends({
|
|
193
178
|
name: "redwood-upload-prisma-plugin",
|
|
194
179
|
query: queryExtends,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/storage",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1-next.104+6be0fa58d",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/cedarjs/cedar.git",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"test:watch": "vitest watch"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@cedarjs/project-config": "2.6.
|
|
56
|
+
"@cedarjs/project-config": "2.6.1-next.104+6be0fa58d",
|
|
57
57
|
"mime-types": "2.1.35",
|
|
58
58
|
"ulid": "3.0.2"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@arethetypeswrong/cli": "0.18.2",
|
|
62
|
-
"@cedarjs/framework-tools": "
|
|
62
|
+
"@cedarjs/framework-tools": "2.6.1-next.104",
|
|
63
63
|
"@prisma/client": "6.19.2",
|
|
64
64
|
"@types/mime-types": "2.1.4",
|
|
65
65
|
"concurrently": "9.2.1",
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"publishConfig": {
|
|
74
74
|
"access": "public"
|
|
75
75
|
},
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "6be0fa58d21ad717026065445aab7117e39ee3eb"
|
|
77
77
|
}
|