@cedarjs/internal 4.2.0 → 4.2.1-next.258
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/build/api.d.ts +1 -0
- package/dist/build/api.d.ts.map +1 -1
- package/dist/build/api.js +59 -5
- package/dist/cjs/build/api.d.ts +1 -0
- package/dist/cjs/build/api.d.ts.map +1 -1
- package/dist/cjs/build/api.js +60 -5
- package/dist/cjs/generate/gqlormSchema.d.ts +2 -0
- package/dist/cjs/generate/gqlormSchema.d.ts.map +1 -1
- package/dist/cjs/generate/gqlormSchema.js +325 -1
- package/dist/cjs/generate/plugins/rw-typescript-resolvers/visitor.d.ts.map +1 -1
- package/dist/cjs/generate/typeDefinitions.js +5 -8
- package/dist/cjs/validateSchema.js +2 -2
- package/dist/generate/gqlormSchema.d.ts +2 -0
- package/dist/generate/gqlormSchema.d.ts.map +1 -1
- package/dist/generate/gqlormSchema.js +325 -1
- package/dist/generate/plugins/rw-typescript-resolvers/visitor.d.ts.map +1 -1
- package/dist/generate/typeDefinitions.js +5 -8
- package/dist/validateSchema.js +2 -2
- package/package.json +19 -12
package/dist/build/api.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ export declare const buildApi: () => Promise<import("esbuild").BuildResult<Build
|
|
|
3
3
|
export declare const rebuildApi: () => Promise<import("esbuild").BuildResult<BuildOptions>>;
|
|
4
4
|
export declare const cleanApiBuild: () => Promise<void>;
|
|
5
5
|
export declare const buildApiWithVite: () => Promise<import("rollup").RollupOutput | import("rollup").RollupOutput[] | import("rollup").RollupWatcher>;
|
|
6
|
+
export declare function fixSourceMaps(distDir: string, srcDir: string): Promise<void>;
|
|
6
7
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/build/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/build/api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,YAAY,EAAe,MAAM,SAAS,CAAA;AAetE,eAAO,MAAM,QAAQ,4DAIpB,CAAA;AAED,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/build/api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,YAAY,EAAe,MAAM,SAAS,CAAA;AAetE,eAAO,MAAM,QAAQ,4DAIpB,CAAA;AAED,eAAO,MAAM,UAAU,4DAStB,CAAA;AAED,eAAO,MAAM,aAAa,qBAGzB,CAAA;AA0ED,eAAO,MAAM,gBAAgB,iHAqD5B,CAAA;AAcD,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAoDf"}
|
package/dist/build/api.js
CHANGED
|
@@ -19,7 +19,10 @@ const rebuildApi = async () => {
|
|
|
19
19
|
if (!BUILD_CTX) {
|
|
20
20
|
BUILD_CTX = await context(getEsbuildOptions(apiFiles));
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
const result = await BUILD_CTX.rebuild();
|
|
23
|
+
const cedarPaths = getPaths();
|
|
24
|
+
await fixSourceMaps(cedarPaths.api.dist, cedarPaths.api.src);
|
|
25
|
+
return result;
|
|
23
26
|
};
|
|
24
27
|
const cleanApiBuild = async () => {
|
|
25
28
|
const cedarPaths = getPaths();
|
|
@@ -30,7 +33,9 @@ const runCedarBabelTransformsPlugin = {
|
|
|
30
33
|
setup(build2) {
|
|
31
34
|
const cedarConfig = getConfig();
|
|
32
35
|
build2.onLoad({ filter: /\.(js|ts|tsx|jsx)$/ }, async (args) => {
|
|
36
|
+
const fileContents = await fs.promises.readFile(args.path, "utf-8");
|
|
33
37
|
const transformedCode = await transformWithBabel(
|
|
38
|
+
fileContents,
|
|
34
39
|
args.path,
|
|
35
40
|
getApiSideBabelPlugins({
|
|
36
41
|
openTelemetry: cedarConfig.experimental.opentelemetry.enabled && cedarConfig.experimental.opentelemetry.wrapApi,
|
|
@@ -52,7 +57,8 @@ function createCedarViteApiPlugin() {
|
|
|
52
57
|
const isEsm = projectSideIsEsm("api");
|
|
53
58
|
return {
|
|
54
59
|
name: "cedar-vite-api-babel-transform",
|
|
55
|
-
|
|
60
|
+
enforce: "pre",
|
|
61
|
+
async transform(code, id) {
|
|
56
62
|
if (!/\.(js|ts|tsx|jsx)$/.test(id)) {
|
|
57
63
|
return null;
|
|
58
64
|
}
|
|
@@ -64,11 +70,13 @@ function createCedarViteApiPlugin() {
|
|
|
64
70
|
return null;
|
|
65
71
|
}
|
|
66
72
|
const transformedCode = await transformWithBabel(
|
|
73
|
+
code,
|
|
67
74
|
id,
|
|
68
75
|
getApiSideBabelPlugins({
|
|
69
76
|
openTelemetry: cedarConfig.experimental.opentelemetry.enabled && cedarConfig.experimental.opentelemetry.wrapApi,
|
|
70
77
|
projectIsEsm: isEsm
|
|
71
|
-
})
|
|
78
|
+
}),
|
|
79
|
+
true
|
|
72
80
|
);
|
|
73
81
|
if (transformedCode?.code) {
|
|
74
82
|
return {
|
|
@@ -103,7 +111,11 @@ const buildApiWithVite = async () => {
|
|
|
103
111
|
format,
|
|
104
112
|
preserveModules: true,
|
|
105
113
|
preserveModulesRoot: cedarPaths.api.src,
|
|
106
|
-
entryFileNames: "[name].js"
|
|
114
|
+
entryFileNames: "[name].js",
|
|
115
|
+
// Directives (and other entry modules) intentionally use both named
|
|
116
|
+
// and default exports (e.g. `export const schema` + `export default`).
|
|
117
|
+
// Tell Rollup to expect this so it doesn't warn about mixed exports.
|
|
118
|
+
exports: "named"
|
|
107
119
|
},
|
|
108
120
|
external: (id) => {
|
|
109
121
|
if (id.startsWith("node:")) {
|
|
@@ -120,8 +132,49 @@ const buildApiWithVite = async () => {
|
|
|
120
132
|
});
|
|
121
133
|
};
|
|
122
134
|
const transpileApi = async (files) => {
|
|
123
|
-
|
|
135
|
+
const result = await build(getEsbuildOptions(files));
|
|
136
|
+
const cedarPaths = getPaths();
|
|
137
|
+
await fixSourceMaps(cedarPaths.api.dist, cedarPaths.api.src);
|
|
138
|
+
return result;
|
|
124
139
|
};
|
|
140
|
+
async function fixSourceMaps(distDir, srcDir) {
|
|
141
|
+
let entries;
|
|
142
|
+
try {
|
|
143
|
+
entries = await fs.promises.readdir(distDir, {
|
|
144
|
+
recursive: true,
|
|
145
|
+
withFileTypes: true
|
|
146
|
+
});
|
|
147
|
+
} catch {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const mapFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".js.map")).map((e) => path.join(e.parentPath ?? e.path, e.name));
|
|
151
|
+
await Promise.all(
|
|
152
|
+
mapFiles.map(async (mapFile) => {
|
|
153
|
+
try {
|
|
154
|
+
const raw = await fs.promises.readFile(mapFile, "utf8");
|
|
155
|
+
const map = JSON.parse(raw);
|
|
156
|
+
if (!Array.isArray(map.sources) || map.sources.length === 0) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const jsFile = mapFile.slice(0, -4);
|
|
160
|
+
const baseName = path.relative(distDir, jsFile).replace(/\.js$/, "");
|
|
161
|
+
const srcFile = [".ts", ".tsx", ".jsx", ".js"].map((ext) => path.join(srcDir, baseName + ext)).find((f) => fs.existsSync(f));
|
|
162
|
+
if (!srcFile) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const correctRelPath = normalizePath(
|
|
166
|
+
path.relative(path.dirname(mapFile), srcFile)
|
|
167
|
+
);
|
|
168
|
+
if (map.sources[0] === correctRelPath) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
map.sources = [correctRelPath];
|
|
172
|
+
await fs.promises.writeFile(mapFile, JSON.stringify(map), "utf8");
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
);
|
|
177
|
+
}
|
|
125
178
|
function getEsbuildOptions(files) {
|
|
126
179
|
const cedarPaths = getPaths();
|
|
127
180
|
const format = projectSideIsEsm("api") ? "esm" : "cjs";
|
|
@@ -145,5 +198,6 @@ export {
|
|
|
145
198
|
buildApi,
|
|
146
199
|
buildApiWithVite,
|
|
147
200
|
cleanApiBuild,
|
|
201
|
+
fixSourceMaps,
|
|
148
202
|
rebuildApi
|
|
149
203
|
};
|
package/dist/cjs/build/api.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ export declare const buildApi: () => Promise<import("esbuild").BuildResult<Build
|
|
|
3
3
|
export declare const rebuildApi: () => Promise<import("esbuild").BuildResult<BuildOptions>>;
|
|
4
4
|
export declare const cleanApiBuild: () => Promise<void>;
|
|
5
5
|
export declare const buildApiWithVite: () => Promise<import("rollup").RollupOutput | import("rollup").RollupOutput[] | import("rollup").RollupWatcher>;
|
|
6
|
+
export declare function fixSourceMaps(distDir: string, srcDir: string): Promise<void>;
|
|
6
7
|
//# sourceMappingURL=api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/build/api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,YAAY,EAAe,MAAM,SAAS,CAAA;AAetE,eAAO,MAAM,QAAQ,4DAIpB,CAAA;AAED,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/build/api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,YAAY,EAAe,MAAM,SAAS,CAAA;AAetE,eAAO,MAAM,QAAQ,4DAIpB,CAAA;AAED,eAAO,MAAM,UAAU,4DAStB,CAAA;AAED,eAAO,MAAM,aAAa,qBAGzB,CAAA;AA0ED,eAAO,MAAM,gBAAgB,iHAqD5B,CAAA;AAcD,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAoDf"}
|
package/dist/cjs/build/api.js
CHANGED
|
@@ -31,6 +31,7 @@ __export(api_exports, {
|
|
|
31
31
|
buildApi: () => buildApi,
|
|
32
32
|
buildApiWithVite: () => buildApiWithVite,
|
|
33
33
|
cleanApiBuild: () => cleanApiBuild,
|
|
34
|
+
fixSourceMaps: () => fixSourceMaps,
|
|
34
35
|
rebuildApi: () => rebuildApi
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(api_exports);
|
|
@@ -52,7 +53,10 @@ const rebuildApi = async () => {
|
|
|
52
53
|
if (!BUILD_CTX) {
|
|
53
54
|
BUILD_CTX = await (0, import_esbuild.context)(getEsbuildOptions(apiFiles));
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
const result = await BUILD_CTX.rebuild();
|
|
57
|
+
const cedarPaths = (0, import_project_config.getPaths)();
|
|
58
|
+
await fixSourceMaps(cedarPaths.api.dist, cedarPaths.api.src);
|
|
59
|
+
return result;
|
|
56
60
|
};
|
|
57
61
|
const cleanApiBuild = async () => {
|
|
58
62
|
const cedarPaths = (0, import_project_config.getPaths)();
|
|
@@ -63,7 +67,9 @@ const runCedarBabelTransformsPlugin = {
|
|
|
63
67
|
setup(build2) {
|
|
64
68
|
const cedarConfig = (0, import_project_config.getConfig)();
|
|
65
69
|
build2.onLoad({ filter: /\.(js|ts|tsx|jsx)$/ }, async (args) => {
|
|
70
|
+
const fileContents = await import_node_fs.default.promises.readFile(args.path, "utf-8");
|
|
66
71
|
const transformedCode = await (0, import_babel_config.transformWithBabel)(
|
|
72
|
+
fileContents,
|
|
67
73
|
args.path,
|
|
68
74
|
(0, import_babel_config.getApiSideBabelPlugins)({
|
|
69
75
|
openTelemetry: cedarConfig.experimental.opentelemetry.enabled && cedarConfig.experimental.opentelemetry.wrapApi,
|
|
@@ -85,7 +91,8 @@ function createCedarViteApiPlugin() {
|
|
|
85
91
|
const isEsm = (0, import_project_config.projectSideIsEsm)("api");
|
|
86
92
|
return {
|
|
87
93
|
name: "cedar-vite-api-babel-transform",
|
|
88
|
-
|
|
94
|
+
enforce: "pre",
|
|
95
|
+
async transform(code, id) {
|
|
89
96
|
if (!/\.(js|ts|tsx|jsx)$/.test(id)) {
|
|
90
97
|
return null;
|
|
91
98
|
}
|
|
@@ -97,11 +104,13 @@ function createCedarViteApiPlugin() {
|
|
|
97
104
|
return null;
|
|
98
105
|
}
|
|
99
106
|
const transformedCode = await (0, import_babel_config.transformWithBabel)(
|
|
107
|
+
code,
|
|
100
108
|
id,
|
|
101
109
|
(0, import_babel_config.getApiSideBabelPlugins)({
|
|
102
110
|
openTelemetry: cedarConfig.experimental.opentelemetry.enabled && cedarConfig.experimental.opentelemetry.wrapApi,
|
|
103
111
|
projectIsEsm: isEsm
|
|
104
|
-
})
|
|
112
|
+
}),
|
|
113
|
+
true
|
|
105
114
|
);
|
|
106
115
|
if (transformedCode?.code) {
|
|
107
116
|
return {
|
|
@@ -136,7 +145,11 @@ const buildApiWithVite = async () => {
|
|
|
136
145
|
format,
|
|
137
146
|
preserveModules: true,
|
|
138
147
|
preserveModulesRoot: cedarPaths.api.src,
|
|
139
|
-
entryFileNames: "[name].js"
|
|
148
|
+
entryFileNames: "[name].js",
|
|
149
|
+
// Directives (and other entry modules) intentionally use both named
|
|
150
|
+
// and default exports (e.g. `export const schema` + `export default`).
|
|
151
|
+
// Tell Rollup to expect this so it doesn't warn about mixed exports.
|
|
152
|
+
exports: "named"
|
|
140
153
|
},
|
|
141
154
|
external: (id) => {
|
|
142
155
|
if (id.startsWith("node:")) {
|
|
@@ -153,8 +166,49 @@ const buildApiWithVite = async () => {
|
|
|
153
166
|
});
|
|
154
167
|
};
|
|
155
168
|
const transpileApi = async (files) => {
|
|
156
|
-
|
|
169
|
+
const result = await (0, import_esbuild.build)(getEsbuildOptions(files));
|
|
170
|
+
const cedarPaths = (0, import_project_config.getPaths)();
|
|
171
|
+
await fixSourceMaps(cedarPaths.api.dist, cedarPaths.api.src);
|
|
172
|
+
return result;
|
|
157
173
|
};
|
|
174
|
+
async function fixSourceMaps(distDir, srcDir) {
|
|
175
|
+
let entries;
|
|
176
|
+
try {
|
|
177
|
+
entries = await import_node_fs.default.promises.readdir(distDir, {
|
|
178
|
+
recursive: true,
|
|
179
|
+
withFileTypes: true
|
|
180
|
+
});
|
|
181
|
+
} catch {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const mapFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".js.map")).map((e) => import_node_path.default.join(e.parentPath ?? e.path, e.name));
|
|
185
|
+
await Promise.all(
|
|
186
|
+
mapFiles.map(async (mapFile) => {
|
|
187
|
+
try {
|
|
188
|
+
const raw = await import_node_fs.default.promises.readFile(mapFile, "utf8");
|
|
189
|
+
const map = JSON.parse(raw);
|
|
190
|
+
if (!Array.isArray(map.sources) || map.sources.length === 0) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const jsFile = mapFile.slice(0, -4);
|
|
194
|
+
const baseName = import_node_path.default.relative(distDir, jsFile).replace(/\.js$/, "");
|
|
195
|
+
const srcFile = [".ts", ".tsx", ".jsx", ".js"].map((ext) => import_node_path.default.join(srcDir, baseName + ext)).find((f) => import_node_fs.default.existsSync(f));
|
|
196
|
+
if (!srcFile) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const correctRelPath = (0, import_vite.normalizePath)(
|
|
200
|
+
import_node_path.default.relative(import_node_path.default.dirname(mapFile), srcFile)
|
|
201
|
+
);
|
|
202
|
+
if (map.sources[0] === correctRelPath) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
map.sources = [correctRelPath];
|
|
206
|
+
await import_node_fs.default.promises.writeFile(mapFile, JSON.stringify(map), "utf8");
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
);
|
|
211
|
+
}
|
|
158
212
|
function getEsbuildOptions(files) {
|
|
159
213
|
const cedarPaths = (0, import_project_config.getPaths)();
|
|
160
214
|
const format = (0, import_project_config.projectSideIsEsm)("api") ? "esm" : "cjs";
|
|
@@ -179,5 +233,6 @@ function getEsbuildOptions(files) {
|
|
|
179
233
|
buildApi,
|
|
180
234
|
buildApiWithVite,
|
|
181
235
|
cleanApiBuild,
|
|
236
|
+
fixSourceMaps,
|
|
182
237
|
rebuildApi
|
|
183
238
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gqlormSchema.d.ts","sourceRoot":"","sources":["../../../src/generate/gqlormSchema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,IAAI,MAAM,cAAc,CAAA;AA8BzC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAE3C,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAA;CAC5B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"gqlormSchema.d.ts","sourceRoot":"","sources":["../../../src/generate/gqlormSchema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,IAAI,MAAM,cAAc,CAAA;AA8BzC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAE3C,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAA;CAC5B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,eAAe,EAAE,OAAO,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,gBAAgB,EAAE,CAAA;IAC1B,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAAA;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,OAAO,CAAA;CAC/B;AA6DD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvE;AAoGD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAClB,iBAAiB,EAAE,CAiDrB;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,iBAAiB,EAAE,GAC1B,MAAM,CA2CR;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,WAAW,CAkDjE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,gBAAgB,EAAE,CA6D7E;AAkBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CA6BvE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,gBAAgB,EAAE,EAC1B,MAAM,GAAE,mBAAmD,GAC1D,MAAM,CA+rBR;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IACvD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CAC9C,CAAC,CAkID"}
|
|
@@ -308,7 +308,9 @@ function buildBackendModelInfo(dmmf) {
|
|
|
308
308
|
name: field.name,
|
|
309
309
|
graphqlType: mapDmmfTypeToGraphql(field.type, field.kind),
|
|
310
310
|
isRequired: field.isRequired,
|
|
311
|
-
isId: field.isId
|
|
311
|
+
isId: field.isId,
|
|
312
|
+
hasDefaultValue: field.hasDefaultValue,
|
|
313
|
+
isUpdatedAt: field.isUpdatedAt ?? false
|
|
312
314
|
});
|
|
313
315
|
}
|
|
314
316
|
if (fields.length > 0) {
|
|
@@ -423,6 +425,46 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
423
425
|
lines.push(" where: Record<string, unknown>");
|
|
424
426
|
lines.push(" }): Promise<Record<string, unknown> | null>");
|
|
425
427
|
}
|
|
428
|
+
lines.push(" create(args: {");
|
|
429
|
+
lines.push(" data: Record<string, unknown>");
|
|
430
|
+
lines.push(` select: { ${selectType} }`);
|
|
431
|
+
lines.push(" }): Promise<{");
|
|
432
|
+
for (const field of model.fields) {
|
|
433
|
+
const tsType = graphqlTypeToTsInterfaceType(
|
|
434
|
+
field.graphqlType,
|
|
435
|
+
field.isRequired
|
|
436
|
+
);
|
|
437
|
+
lines.push(` ${field.name}: ${tsType}`);
|
|
438
|
+
}
|
|
439
|
+
lines.push(" }>");
|
|
440
|
+
if (model.idField) {
|
|
441
|
+
const idTsType = graphqlTypeToTsType(model.idField.graphqlType);
|
|
442
|
+
lines.push(" update(args: {");
|
|
443
|
+
lines.push(` where: { ${model.idField.name}: ${idTsType} }`);
|
|
444
|
+
lines.push(" data: Record<string, unknown>");
|
|
445
|
+
lines.push(` select: { ${selectType} }`);
|
|
446
|
+
lines.push(" }): Promise<{");
|
|
447
|
+
for (const field of model.fields) {
|
|
448
|
+
const tsType = graphqlTypeToTsInterfaceType(
|
|
449
|
+
field.graphqlType,
|
|
450
|
+
field.isRequired
|
|
451
|
+
);
|
|
452
|
+
lines.push(` ${field.name}: ${tsType}`);
|
|
453
|
+
}
|
|
454
|
+
lines.push(" }>");
|
|
455
|
+
lines.push(" delete(args: {");
|
|
456
|
+
lines.push(` where: { ${model.idField.name}: ${idTsType} }`);
|
|
457
|
+
lines.push(` select: { ${selectType} }`);
|
|
458
|
+
lines.push(" }): Promise<{");
|
|
459
|
+
for (const field of model.fields) {
|
|
460
|
+
const tsType = graphqlTypeToTsInterfaceType(
|
|
461
|
+
field.graphqlType,
|
|
462
|
+
field.isRequired
|
|
463
|
+
);
|
|
464
|
+
lines.push(` ${field.name}: ${tsType}`);
|
|
465
|
+
}
|
|
466
|
+
lines.push(" }>");
|
|
467
|
+
}
|
|
426
468
|
lines.push(" }");
|
|
427
469
|
}
|
|
428
470
|
const membershipAlreadyInModels = models.some(
|
|
@@ -454,6 +496,26 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
454
496
|
}
|
|
455
497
|
lines.push(" }");
|
|
456
498
|
lines.push("");
|
|
499
|
+
if (!model.idField) {
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
const writableFields = model.fields.filter(
|
|
503
|
+
(field) => !field.isId && !field.isUpdatedAt && field.name !== config.membershipUserField
|
|
504
|
+
);
|
|
505
|
+
lines.push(` input Create${model.modelName}Input {`);
|
|
506
|
+
for (const field of writableFields) {
|
|
507
|
+
const isClientRequired = field.isRequired && !field.hasDefaultValue;
|
|
508
|
+
const nullMark = isClientRequired ? "!" : "";
|
|
509
|
+
lines.push(` ${field.name}: ${field.graphqlType}${nullMark}`);
|
|
510
|
+
}
|
|
511
|
+
lines.push(" }");
|
|
512
|
+
lines.push("");
|
|
513
|
+
lines.push(` input Update${model.modelName}Input {`);
|
|
514
|
+
for (const field of writableFields) {
|
|
515
|
+
lines.push(` ${field.name}: ${field.graphqlType}`);
|
|
516
|
+
}
|
|
517
|
+
lines.push(" }");
|
|
518
|
+
lines.push("");
|
|
457
519
|
}
|
|
458
520
|
lines.push(" type Query {");
|
|
459
521
|
for (const model of models) {
|
|
@@ -477,6 +539,32 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
477
539
|
}
|
|
478
540
|
}
|
|
479
541
|
lines.push(" }");
|
|
542
|
+
lines.push("");
|
|
543
|
+
lines.push(" type Mutation {");
|
|
544
|
+
for (const model of models) {
|
|
545
|
+
if (model.idField) {
|
|
546
|
+
const hasUserField = model.fields.some(
|
|
547
|
+
(f) => f.name === config.membershipUserField
|
|
548
|
+
);
|
|
549
|
+
const hasOrgField = model.fields.some(
|
|
550
|
+
(f) => f.name === config.membershipOrganizationField
|
|
551
|
+
);
|
|
552
|
+
const isMembershipModel = model.camelName === config.membershipModelCamel;
|
|
553
|
+
const needsAuth = hasUserField || hasOrgField && config.membershipModelExists && !isMembershipModel;
|
|
554
|
+
const authDirective = needsAuth ? "@requireAuth" : "@skipAuth";
|
|
555
|
+
const idNullMark = model.idField.isRequired ? "!" : "";
|
|
556
|
+
lines.push(
|
|
557
|
+
` create${model.modelName}(input: Create${model.modelName}Input!): ${model.modelName}! ${authDirective}`
|
|
558
|
+
);
|
|
559
|
+
lines.push(
|
|
560
|
+
` update${model.modelName}(${model.idField.name}: ${model.idField.graphqlType}${idNullMark}, input: Update${model.modelName}Input!): ${model.modelName}! ${authDirective}`
|
|
561
|
+
);
|
|
562
|
+
lines.push(
|
|
563
|
+
` delete${model.modelName}(${model.idField.name}: ${model.idField.graphqlType}${idNullMark}): ${model.modelName}! ${authDirective}`
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
lines.push(" }");
|
|
480
568
|
lines.push("`");
|
|
481
569
|
lines.push("");
|
|
482
570
|
lines.push(
|
|
@@ -625,6 +713,242 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
625
713
|
}
|
|
626
714
|
}
|
|
627
715
|
lines.push(" },");
|
|
716
|
+
lines.push(" Mutation: {");
|
|
717
|
+
for (const model of models) {
|
|
718
|
+
if (!model.idField) {
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
const selectObj = model.fields.map((f) => `${f.name}: true`).join(", ");
|
|
722
|
+
const hasUserField = model.fields.some(
|
|
723
|
+
(f) => f.name === config.membershipUserField
|
|
724
|
+
);
|
|
725
|
+
const hasOrgField = model.fields.some(
|
|
726
|
+
(f) => f.name === config.membershipOrganizationField
|
|
727
|
+
);
|
|
728
|
+
const isMembershipModel = model.camelName === config.membershipModelCamel;
|
|
729
|
+
const useOrgScoping = hasOrgField && config.membershipModelExists && !isMembershipModel;
|
|
730
|
+
const idFieldName = model.idField.name;
|
|
731
|
+
const idTsType = graphqlTypeToTsType(model.idField.graphqlType);
|
|
732
|
+
lines.push(
|
|
733
|
+
` create${model.modelName}: async (_root: unknown, { input }: { input: Record<string, unknown> }, ${hasUserField || useOrgScoping ? "context" : "_context"}: GqlormContext) => {`
|
|
734
|
+
);
|
|
735
|
+
if (hasUserField || useOrgScoping) {
|
|
736
|
+
lines.push(" if (!context.currentUser) {");
|
|
737
|
+
lines.push(
|
|
738
|
+
` throw new AuthenticationError("You don't have permission to do that.")`
|
|
739
|
+
);
|
|
740
|
+
lines.push(" }");
|
|
741
|
+
lines.push(" const currentUserId = context.currentUser['id']");
|
|
742
|
+
lines.push(
|
|
743
|
+
" if (currentUserId === undefined || currentUserId === null) {"
|
|
744
|
+
);
|
|
745
|
+
lines.push(
|
|
746
|
+
` throw new AuthenticationError("Could not determine the current user's ID.")`
|
|
747
|
+
);
|
|
748
|
+
lines.push(" }");
|
|
749
|
+
}
|
|
750
|
+
lines.push(" const data: Record<string, unknown> = { ...input }");
|
|
751
|
+
if (hasUserField) {
|
|
752
|
+
lines.push(
|
|
753
|
+
` data['${config.membershipUserField}'] = currentUserId`
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
if (useOrgScoping) {
|
|
757
|
+
lines.push(
|
|
758
|
+
` const organizationId = data['${config.membershipOrganizationField}']`
|
|
759
|
+
);
|
|
760
|
+
lines.push(
|
|
761
|
+
" if (organizationId === undefined || organizationId === null) {"
|
|
762
|
+
);
|
|
763
|
+
lines.push(
|
|
764
|
+
` throw new ForbiddenError('Organization membership is required for this operation')`
|
|
765
|
+
);
|
|
766
|
+
lines.push(" }");
|
|
767
|
+
lines.push(
|
|
768
|
+
` const membership = await db.${config.membershipModelCamel}.findFirst({`
|
|
769
|
+
);
|
|
770
|
+
lines.push(" where: {");
|
|
771
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
772
|
+
lines.push(
|
|
773
|
+
` ${config.membershipOrganizationField}: organizationId,`
|
|
774
|
+
);
|
|
775
|
+
lines.push(" },");
|
|
776
|
+
lines.push(" })");
|
|
777
|
+
lines.push(" if (!membership) {");
|
|
778
|
+
lines.push(
|
|
779
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
780
|
+
);
|
|
781
|
+
lines.push(" }");
|
|
782
|
+
}
|
|
783
|
+
lines.push(` return db.${model.camelName}.create({`);
|
|
784
|
+
lines.push(" data,");
|
|
785
|
+
lines.push(` select: { ${selectObj} },`);
|
|
786
|
+
lines.push(" })");
|
|
787
|
+
lines.push(" },");
|
|
788
|
+
lines.push(
|
|
789
|
+
` update${model.modelName}: async (_root: unknown, { ${idFieldName}, input }: { ${idFieldName}: ${idTsType}; input: Record<string, unknown> }, ${hasUserField || useOrgScoping ? "context" : "_context"}: GqlormContext) => {`
|
|
790
|
+
);
|
|
791
|
+
if (hasUserField || useOrgScoping) {
|
|
792
|
+
lines.push(" if (!context.currentUser) {");
|
|
793
|
+
lines.push(
|
|
794
|
+
` throw new AuthenticationError("You don't have permission to do that.")`
|
|
795
|
+
);
|
|
796
|
+
lines.push(" }");
|
|
797
|
+
lines.push(" const currentUserId = context.currentUser['id']");
|
|
798
|
+
lines.push(
|
|
799
|
+
" if (currentUserId === undefined || currentUserId === null) {"
|
|
800
|
+
);
|
|
801
|
+
lines.push(
|
|
802
|
+
` throw new AuthenticationError("Could not determine the current user's ID.")`
|
|
803
|
+
);
|
|
804
|
+
lines.push(" }");
|
|
805
|
+
lines.push(
|
|
806
|
+
` const existingRecord = await db.${model.camelName}.findUnique({`
|
|
807
|
+
);
|
|
808
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
809
|
+
lines.push(` select: { ${selectObj} },`);
|
|
810
|
+
lines.push(" })");
|
|
811
|
+
lines.push(" if (!existingRecord) {");
|
|
812
|
+
lines.push(
|
|
813
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
814
|
+
);
|
|
815
|
+
lines.push(" }");
|
|
816
|
+
lines.push(" const data: Record<string, unknown> = { ...input }");
|
|
817
|
+
if (hasUserField) {
|
|
818
|
+
lines.push(
|
|
819
|
+
` if (existingRecord.${config.membershipUserField} !== currentUserId) {`
|
|
820
|
+
);
|
|
821
|
+
lines.push(
|
|
822
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
823
|
+
);
|
|
824
|
+
lines.push(" }");
|
|
825
|
+
lines.push(` delete data['${config.membershipUserField}']`);
|
|
826
|
+
}
|
|
827
|
+
if (useOrgScoping) {
|
|
828
|
+
lines.push(
|
|
829
|
+
` const currentOrganizationId = existingRecord.${config.membershipOrganizationField}`
|
|
830
|
+
);
|
|
831
|
+
lines.push(
|
|
832
|
+
` const currentOrganizationMembership = await db.${config.membershipModelCamel}.findFirst({`
|
|
833
|
+
);
|
|
834
|
+
lines.push(" where: {");
|
|
835
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
836
|
+
lines.push(
|
|
837
|
+
` ${config.membershipOrganizationField}: currentOrganizationId,`
|
|
838
|
+
);
|
|
839
|
+
lines.push(" },");
|
|
840
|
+
lines.push(" })");
|
|
841
|
+
lines.push(" if (!currentOrganizationMembership) {");
|
|
842
|
+
lines.push(
|
|
843
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
844
|
+
);
|
|
845
|
+
lines.push(" }");
|
|
846
|
+
lines.push(
|
|
847
|
+
` const requestedOrganizationId = input['${config.membershipOrganizationField}'] ?? currentOrganizationId`
|
|
848
|
+
);
|
|
849
|
+
lines.push(
|
|
850
|
+
` const requestedOrganizationMembership = await db.${config.membershipModelCamel}.findFirst({`
|
|
851
|
+
);
|
|
852
|
+
lines.push(" where: {");
|
|
853
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
854
|
+
lines.push(
|
|
855
|
+
` ${config.membershipOrganizationField}: requestedOrganizationId,`
|
|
856
|
+
);
|
|
857
|
+
lines.push(" },");
|
|
858
|
+
lines.push(" })");
|
|
859
|
+
lines.push(" if (!requestedOrganizationMembership) {");
|
|
860
|
+
lines.push(
|
|
861
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
862
|
+
);
|
|
863
|
+
lines.push(" }");
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
if (!(hasUserField || useOrgScoping)) {
|
|
867
|
+
lines.push(
|
|
868
|
+
` const existingRecord = await db.${model.camelName}.findUnique({`
|
|
869
|
+
);
|
|
870
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
871
|
+
lines.push(` select: { ${selectObj} },`);
|
|
872
|
+
lines.push(" })");
|
|
873
|
+
lines.push(" if (!existingRecord) {");
|
|
874
|
+
lines.push(
|
|
875
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
876
|
+
);
|
|
877
|
+
lines.push(" }");
|
|
878
|
+
lines.push(" const data: Record<string, unknown> = { ...input }");
|
|
879
|
+
}
|
|
880
|
+
lines.push(` return db.${model.camelName}.update({`);
|
|
881
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
882
|
+
lines.push(" data,");
|
|
883
|
+
lines.push(` select: { ${selectObj} },`);
|
|
884
|
+
lines.push(" })");
|
|
885
|
+
lines.push(" },");
|
|
886
|
+
lines.push(
|
|
887
|
+
` delete${model.modelName}: async (_root: unknown, { ${idFieldName} }: { ${idFieldName}: ${idTsType} }, ${hasUserField || useOrgScoping ? "context" : "_context"}: GqlormContext) => {`
|
|
888
|
+
);
|
|
889
|
+
lines.push(
|
|
890
|
+
` const existingRecord = await db.${model.camelName}.findUnique({`
|
|
891
|
+
);
|
|
892
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
893
|
+
lines.push(` select: { ${selectObj} },`);
|
|
894
|
+
lines.push(" })");
|
|
895
|
+
lines.push(" if (!existingRecord) {");
|
|
896
|
+
lines.push(
|
|
897
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
898
|
+
);
|
|
899
|
+
lines.push(" }");
|
|
900
|
+
if (hasUserField || useOrgScoping) {
|
|
901
|
+
lines.push(" if (!context.currentUser) {");
|
|
902
|
+
lines.push(
|
|
903
|
+
` throw new AuthenticationError("You don't have permission to do that.")`
|
|
904
|
+
);
|
|
905
|
+
lines.push(" }");
|
|
906
|
+
lines.push(" const currentUserId = context.currentUser['id']");
|
|
907
|
+
lines.push(
|
|
908
|
+
" if (currentUserId === undefined || currentUserId === null) {"
|
|
909
|
+
);
|
|
910
|
+
lines.push(
|
|
911
|
+
` throw new AuthenticationError("Could not determine the current user's ID.")`
|
|
912
|
+
);
|
|
913
|
+
lines.push(" }");
|
|
914
|
+
if (hasUserField) {
|
|
915
|
+
lines.push(
|
|
916
|
+
` if (existingRecord.${config.membershipUserField} !== currentUserId) {`
|
|
917
|
+
);
|
|
918
|
+
lines.push(
|
|
919
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
920
|
+
);
|
|
921
|
+
lines.push(" }");
|
|
922
|
+
}
|
|
923
|
+
if (useOrgScoping) {
|
|
924
|
+
lines.push(
|
|
925
|
+
` const membership = await db.${config.membershipModelCamel}.findFirst({`
|
|
926
|
+
);
|
|
927
|
+
lines.push(" where: {");
|
|
928
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
929
|
+
lines.push(
|
|
930
|
+
` ${config.membershipOrganizationField}: existingRecord.${config.membershipOrganizationField},`
|
|
931
|
+
);
|
|
932
|
+
lines.push(" },");
|
|
933
|
+
lines.push(" })");
|
|
934
|
+
lines.push(" if (!membership) {");
|
|
935
|
+
lines.push(
|
|
936
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
937
|
+
);
|
|
938
|
+
lines.push(" }");
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
lines.push(` return db.${model.camelName}.delete({`);
|
|
942
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
943
|
+
lines.push(` select: { ${selectObj} },`);
|
|
944
|
+
lines.push(" })");
|
|
945
|
+
lines.push(" },");
|
|
946
|
+
lines.push("");
|
|
947
|
+
}
|
|
948
|
+
while (lines[lines.length - 1] === "") {
|
|
949
|
+
lines.pop();
|
|
950
|
+
}
|
|
951
|
+
lines.push(" },");
|
|
628
952
|
lines.push(" }");
|
|
629
953
|
lines.push("}");
|
|
630
954
|
lines.push("");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../../../../src/generate/plugins/rw-typescript-resolvers/visitor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../../../../src/generate/plugins/rw-typescript-resolvers/visitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAA;AAC5F,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAElF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AACnF,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,wBAAwB,EACzB,MAAM,SAAS,CAAA;AAEhB,qBAAa,4BAA6B,SAAQ,0BAA0B;gBAExE,YAAY,EAAE,+BAA+B,EAC7C,MAAM,EAAE,aAAa;IAMvB,eAAe,CACb,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,MAAM,EAAE,GAAG,GACV,qBAAqB;IAgCxB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM,GAAG,IAAI;CA6FpE"}
|
|
@@ -320,9 +320,9 @@ const generateTypeDefGlobalContext = () => {
|
|
|
320
320
|
};
|
|
321
321
|
const generateViteClientTypesDirective = () => {
|
|
322
322
|
const viteClientDirective = `/// <reference types="vite/client" />`;
|
|
323
|
-
const
|
|
323
|
+
const cedarProjectPaths = (0, import_project_config.getPaths)();
|
|
324
324
|
const viteClientDirectivePath = import_path.default.join(
|
|
325
|
-
|
|
325
|
+
cedarProjectPaths.generated.types.includes,
|
|
326
326
|
"web-vite-client.d.ts"
|
|
327
327
|
);
|
|
328
328
|
import_node_fs.default.writeFileSync(viteClientDirectivePath, viteClientDirective);
|
|
@@ -334,12 +334,9 @@ function generateStubStorybookTypes() {
|
|
|
334
334
|
export type StoryObj<T = any> = any
|
|
335
335
|
}
|
|
336
336
|
`;
|
|
337
|
-
const
|
|
337
|
+
const cedarProjectPaths = (0, import_project_config.getPaths)();
|
|
338
338
|
const packageJson = JSON.parse(
|
|
339
|
-
import_node_fs.default.readFileSync(
|
|
340
|
-
import_path.default.join(redwoodProjectPaths.base, "package.json"),
|
|
341
|
-
"utf-8"
|
|
342
|
-
)
|
|
339
|
+
import_node_fs.default.readFileSync(import_path.default.join(cedarProjectPaths.base, "package.json"), "utf-8")
|
|
343
340
|
);
|
|
344
341
|
const hasCliStorybookVite = Object.keys(
|
|
345
342
|
packageJson["devDependencies"]
|
|
@@ -348,7 +345,7 @@ function generateStubStorybookTypes() {
|
|
|
348
345
|
return [];
|
|
349
346
|
}
|
|
350
347
|
const stubStorybookTypesFilePath = import_path.default.join(
|
|
351
|
-
|
|
348
|
+
cedarProjectPaths.generated.types.includes,
|
|
352
349
|
"web-storybook.d.ts"
|
|
353
350
|
);
|
|
354
351
|
import_node_fs.default.writeFileSync(stubStorybookTypesFilePath, stubStorybookTypesFileContent);
|
|
@@ -79,11 +79,11 @@ function validateSchema(schemaDocumentNode, typesToCheck = ["Query", "Mutation"]
|
|
|
79
79
|
for (const field of typeNode.fields || []) {
|
|
80
80
|
const fieldName = field.name.value;
|
|
81
81
|
const fieldTypeName = typeNode.name.value;
|
|
82
|
-
const
|
|
82
|
+
const isLegacyRedwoodQuery = fieldName === "redwood" && fieldTypeName === "Query";
|
|
83
83
|
const isCedarQuery = fieldName === "cedar" && fieldTypeName === "Query" || // TODO: Remove this when I remove the root schema
|
|
84
84
|
fieldName === "cedarjs" && fieldTypeName === "Query";
|
|
85
85
|
const isCurrentUserQuery = fieldName === "currentUser" && fieldTypeName === "Query";
|
|
86
|
-
if (!(
|
|
86
|
+
if (!(isCedarQuery || isCurrentUserQuery || isLegacyRedwoodQuery)) {
|
|
87
87
|
const hasDirective = field.directives?.length;
|
|
88
88
|
if (!hasDirective) {
|
|
89
89
|
validationOutput.push(`${fieldName} ${fieldTypeName}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gqlormSchema.d.ts","sourceRoot":"","sources":["../../src/generate/gqlormSchema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,IAAI,MAAM,cAAc,CAAA;AA8BzC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAE3C,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAA;CAC5B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"gqlormSchema.d.ts","sourceRoot":"","sources":["../../src/generate/gqlormSchema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,IAAI,MAAM,cAAc,CAAA;AA8BzC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAE3C,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAA;CAC5B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,eAAe,EAAE,OAAO,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,gBAAgB,EAAE,CAAA;IAC1B,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAAA;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,OAAO,CAAA;CAC/B;AA6DD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvE;AAoGD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAClB,iBAAiB,EAAE,CAiDrB;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,iBAAiB,EAAE,GAC1B,MAAM,CA2CR;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,WAAW,CAkDjE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,gBAAgB,EAAE,CA6D7E;AAkBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CA6BvE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,gBAAgB,EAAE,EAC1B,MAAM,GAAE,mBAAmD,GAC1D,MAAM,CA+rBR;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IACvD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CAC9C,CAAC,CAkID"}
|
|
@@ -268,7 +268,9 @@ function buildBackendModelInfo(dmmf) {
|
|
|
268
268
|
name: field.name,
|
|
269
269
|
graphqlType: mapDmmfTypeToGraphql(field.type, field.kind),
|
|
270
270
|
isRequired: field.isRequired,
|
|
271
|
-
isId: field.isId
|
|
271
|
+
isId: field.isId,
|
|
272
|
+
hasDefaultValue: field.hasDefaultValue,
|
|
273
|
+
isUpdatedAt: field.isUpdatedAt ?? false
|
|
272
274
|
});
|
|
273
275
|
}
|
|
274
276
|
if (fields.length > 0) {
|
|
@@ -383,6 +385,46 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
383
385
|
lines.push(" where: Record<string, unknown>");
|
|
384
386
|
lines.push(" }): Promise<Record<string, unknown> | null>");
|
|
385
387
|
}
|
|
388
|
+
lines.push(" create(args: {");
|
|
389
|
+
lines.push(" data: Record<string, unknown>");
|
|
390
|
+
lines.push(` select: { ${selectType} }`);
|
|
391
|
+
lines.push(" }): Promise<{");
|
|
392
|
+
for (const field of model.fields) {
|
|
393
|
+
const tsType = graphqlTypeToTsInterfaceType(
|
|
394
|
+
field.graphqlType,
|
|
395
|
+
field.isRequired
|
|
396
|
+
);
|
|
397
|
+
lines.push(` ${field.name}: ${tsType}`);
|
|
398
|
+
}
|
|
399
|
+
lines.push(" }>");
|
|
400
|
+
if (model.idField) {
|
|
401
|
+
const idTsType = graphqlTypeToTsType(model.idField.graphqlType);
|
|
402
|
+
lines.push(" update(args: {");
|
|
403
|
+
lines.push(` where: { ${model.idField.name}: ${idTsType} }`);
|
|
404
|
+
lines.push(" data: Record<string, unknown>");
|
|
405
|
+
lines.push(` select: { ${selectType} }`);
|
|
406
|
+
lines.push(" }): Promise<{");
|
|
407
|
+
for (const field of model.fields) {
|
|
408
|
+
const tsType = graphqlTypeToTsInterfaceType(
|
|
409
|
+
field.graphqlType,
|
|
410
|
+
field.isRequired
|
|
411
|
+
);
|
|
412
|
+
lines.push(` ${field.name}: ${tsType}`);
|
|
413
|
+
}
|
|
414
|
+
lines.push(" }>");
|
|
415
|
+
lines.push(" delete(args: {");
|
|
416
|
+
lines.push(` where: { ${model.idField.name}: ${idTsType} }`);
|
|
417
|
+
lines.push(` select: { ${selectType} }`);
|
|
418
|
+
lines.push(" }): Promise<{");
|
|
419
|
+
for (const field of model.fields) {
|
|
420
|
+
const tsType = graphqlTypeToTsInterfaceType(
|
|
421
|
+
field.graphqlType,
|
|
422
|
+
field.isRequired
|
|
423
|
+
);
|
|
424
|
+
lines.push(` ${field.name}: ${tsType}`);
|
|
425
|
+
}
|
|
426
|
+
lines.push(" }>");
|
|
427
|
+
}
|
|
386
428
|
lines.push(" }");
|
|
387
429
|
}
|
|
388
430
|
const membershipAlreadyInModels = models.some(
|
|
@@ -414,6 +456,26 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
414
456
|
}
|
|
415
457
|
lines.push(" }");
|
|
416
458
|
lines.push("");
|
|
459
|
+
if (!model.idField) {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
const writableFields = model.fields.filter(
|
|
463
|
+
(field) => !field.isId && !field.isUpdatedAt && field.name !== config.membershipUserField
|
|
464
|
+
);
|
|
465
|
+
lines.push(` input Create${model.modelName}Input {`);
|
|
466
|
+
for (const field of writableFields) {
|
|
467
|
+
const isClientRequired = field.isRequired && !field.hasDefaultValue;
|
|
468
|
+
const nullMark = isClientRequired ? "!" : "";
|
|
469
|
+
lines.push(` ${field.name}: ${field.graphqlType}${nullMark}`);
|
|
470
|
+
}
|
|
471
|
+
lines.push(" }");
|
|
472
|
+
lines.push("");
|
|
473
|
+
lines.push(` input Update${model.modelName}Input {`);
|
|
474
|
+
for (const field of writableFields) {
|
|
475
|
+
lines.push(` ${field.name}: ${field.graphqlType}`);
|
|
476
|
+
}
|
|
477
|
+
lines.push(" }");
|
|
478
|
+
lines.push("");
|
|
417
479
|
}
|
|
418
480
|
lines.push(" type Query {");
|
|
419
481
|
for (const model of models) {
|
|
@@ -437,6 +499,32 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
437
499
|
}
|
|
438
500
|
}
|
|
439
501
|
lines.push(" }");
|
|
502
|
+
lines.push("");
|
|
503
|
+
lines.push(" type Mutation {");
|
|
504
|
+
for (const model of models) {
|
|
505
|
+
if (model.idField) {
|
|
506
|
+
const hasUserField = model.fields.some(
|
|
507
|
+
(f) => f.name === config.membershipUserField
|
|
508
|
+
);
|
|
509
|
+
const hasOrgField = model.fields.some(
|
|
510
|
+
(f) => f.name === config.membershipOrganizationField
|
|
511
|
+
);
|
|
512
|
+
const isMembershipModel = model.camelName === config.membershipModelCamel;
|
|
513
|
+
const needsAuth = hasUserField || hasOrgField && config.membershipModelExists && !isMembershipModel;
|
|
514
|
+
const authDirective = needsAuth ? "@requireAuth" : "@skipAuth";
|
|
515
|
+
const idNullMark = model.idField.isRequired ? "!" : "";
|
|
516
|
+
lines.push(
|
|
517
|
+
` create${model.modelName}(input: Create${model.modelName}Input!): ${model.modelName}! ${authDirective}`
|
|
518
|
+
);
|
|
519
|
+
lines.push(
|
|
520
|
+
` update${model.modelName}(${model.idField.name}: ${model.idField.graphqlType}${idNullMark}, input: Update${model.modelName}Input!): ${model.modelName}! ${authDirective}`
|
|
521
|
+
);
|
|
522
|
+
lines.push(
|
|
523
|
+
` delete${model.modelName}(${model.idField.name}: ${model.idField.graphqlType}${idNullMark}): ${model.modelName}! ${authDirective}`
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
lines.push(" }");
|
|
440
528
|
lines.push("`");
|
|
441
529
|
lines.push("");
|
|
442
530
|
lines.push(
|
|
@@ -585,6 +673,242 @@ function generateGqlormBackendContent(models, config = DEFAULT_GQLORM_BACKEND_CO
|
|
|
585
673
|
}
|
|
586
674
|
}
|
|
587
675
|
lines.push(" },");
|
|
676
|
+
lines.push(" Mutation: {");
|
|
677
|
+
for (const model of models) {
|
|
678
|
+
if (!model.idField) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
const selectObj = model.fields.map((f) => `${f.name}: true`).join(", ");
|
|
682
|
+
const hasUserField = model.fields.some(
|
|
683
|
+
(f) => f.name === config.membershipUserField
|
|
684
|
+
);
|
|
685
|
+
const hasOrgField = model.fields.some(
|
|
686
|
+
(f) => f.name === config.membershipOrganizationField
|
|
687
|
+
);
|
|
688
|
+
const isMembershipModel = model.camelName === config.membershipModelCamel;
|
|
689
|
+
const useOrgScoping = hasOrgField && config.membershipModelExists && !isMembershipModel;
|
|
690
|
+
const idFieldName = model.idField.name;
|
|
691
|
+
const idTsType = graphqlTypeToTsType(model.idField.graphqlType);
|
|
692
|
+
lines.push(
|
|
693
|
+
` create${model.modelName}: async (_root: unknown, { input }: { input: Record<string, unknown> }, ${hasUserField || useOrgScoping ? "context" : "_context"}: GqlormContext) => {`
|
|
694
|
+
);
|
|
695
|
+
if (hasUserField || useOrgScoping) {
|
|
696
|
+
lines.push(" if (!context.currentUser) {");
|
|
697
|
+
lines.push(
|
|
698
|
+
` throw new AuthenticationError("You don't have permission to do that.")`
|
|
699
|
+
);
|
|
700
|
+
lines.push(" }");
|
|
701
|
+
lines.push(" const currentUserId = context.currentUser['id']");
|
|
702
|
+
lines.push(
|
|
703
|
+
" if (currentUserId === undefined || currentUserId === null) {"
|
|
704
|
+
);
|
|
705
|
+
lines.push(
|
|
706
|
+
` throw new AuthenticationError("Could not determine the current user's ID.")`
|
|
707
|
+
);
|
|
708
|
+
lines.push(" }");
|
|
709
|
+
}
|
|
710
|
+
lines.push(" const data: Record<string, unknown> = { ...input }");
|
|
711
|
+
if (hasUserField) {
|
|
712
|
+
lines.push(
|
|
713
|
+
` data['${config.membershipUserField}'] = currentUserId`
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
if (useOrgScoping) {
|
|
717
|
+
lines.push(
|
|
718
|
+
` const organizationId = data['${config.membershipOrganizationField}']`
|
|
719
|
+
);
|
|
720
|
+
lines.push(
|
|
721
|
+
" if (organizationId === undefined || organizationId === null) {"
|
|
722
|
+
);
|
|
723
|
+
lines.push(
|
|
724
|
+
` throw new ForbiddenError('Organization membership is required for this operation')`
|
|
725
|
+
);
|
|
726
|
+
lines.push(" }");
|
|
727
|
+
lines.push(
|
|
728
|
+
` const membership = await db.${config.membershipModelCamel}.findFirst({`
|
|
729
|
+
);
|
|
730
|
+
lines.push(" where: {");
|
|
731
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
732
|
+
lines.push(
|
|
733
|
+
` ${config.membershipOrganizationField}: organizationId,`
|
|
734
|
+
);
|
|
735
|
+
lines.push(" },");
|
|
736
|
+
lines.push(" })");
|
|
737
|
+
lines.push(" if (!membership) {");
|
|
738
|
+
lines.push(
|
|
739
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
740
|
+
);
|
|
741
|
+
lines.push(" }");
|
|
742
|
+
}
|
|
743
|
+
lines.push(` return db.${model.camelName}.create({`);
|
|
744
|
+
lines.push(" data,");
|
|
745
|
+
lines.push(` select: { ${selectObj} },`);
|
|
746
|
+
lines.push(" })");
|
|
747
|
+
lines.push(" },");
|
|
748
|
+
lines.push(
|
|
749
|
+
` update${model.modelName}: async (_root: unknown, { ${idFieldName}, input }: { ${idFieldName}: ${idTsType}; input: Record<string, unknown> }, ${hasUserField || useOrgScoping ? "context" : "_context"}: GqlormContext) => {`
|
|
750
|
+
);
|
|
751
|
+
if (hasUserField || useOrgScoping) {
|
|
752
|
+
lines.push(" if (!context.currentUser) {");
|
|
753
|
+
lines.push(
|
|
754
|
+
` throw new AuthenticationError("You don't have permission to do that.")`
|
|
755
|
+
);
|
|
756
|
+
lines.push(" }");
|
|
757
|
+
lines.push(" const currentUserId = context.currentUser['id']");
|
|
758
|
+
lines.push(
|
|
759
|
+
" if (currentUserId === undefined || currentUserId === null) {"
|
|
760
|
+
);
|
|
761
|
+
lines.push(
|
|
762
|
+
` throw new AuthenticationError("Could not determine the current user's ID.")`
|
|
763
|
+
);
|
|
764
|
+
lines.push(" }");
|
|
765
|
+
lines.push(
|
|
766
|
+
` const existingRecord = await db.${model.camelName}.findUnique({`
|
|
767
|
+
);
|
|
768
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
769
|
+
lines.push(` select: { ${selectObj} },`);
|
|
770
|
+
lines.push(" })");
|
|
771
|
+
lines.push(" if (!existingRecord) {");
|
|
772
|
+
lines.push(
|
|
773
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
774
|
+
);
|
|
775
|
+
lines.push(" }");
|
|
776
|
+
lines.push(" const data: Record<string, unknown> = { ...input }");
|
|
777
|
+
if (hasUserField) {
|
|
778
|
+
lines.push(
|
|
779
|
+
` if (existingRecord.${config.membershipUserField} !== currentUserId) {`
|
|
780
|
+
);
|
|
781
|
+
lines.push(
|
|
782
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
783
|
+
);
|
|
784
|
+
lines.push(" }");
|
|
785
|
+
lines.push(` delete data['${config.membershipUserField}']`);
|
|
786
|
+
}
|
|
787
|
+
if (useOrgScoping) {
|
|
788
|
+
lines.push(
|
|
789
|
+
` const currentOrganizationId = existingRecord.${config.membershipOrganizationField}`
|
|
790
|
+
);
|
|
791
|
+
lines.push(
|
|
792
|
+
` const currentOrganizationMembership = await db.${config.membershipModelCamel}.findFirst({`
|
|
793
|
+
);
|
|
794
|
+
lines.push(" where: {");
|
|
795
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
796
|
+
lines.push(
|
|
797
|
+
` ${config.membershipOrganizationField}: currentOrganizationId,`
|
|
798
|
+
);
|
|
799
|
+
lines.push(" },");
|
|
800
|
+
lines.push(" })");
|
|
801
|
+
lines.push(" if (!currentOrganizationMembership) {");
|
|
802
|
+
lines.push(
|
|
803
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
804
|
+
);
|
|
805
|
+
lines.push(" }");
|
|
806
|
+
lines.push(
|
|
807
|
+
` const requestedOrganizationId = input['${config.membershipOrganizationField}'] ?? currentOrganizationId`
|
|
808
|
+
);
|
|
809
|
+
lines.push(
|
|
810
|
+
` const requestedOrganizationMembership = await db.${config.membershipModelCamel}.findFirst({`
|
|
811
|
+
);
|
|
812
|
+
lines.push(" where: {");
|
|
813
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
814
|
+
lines.push(
|
|
815
|
+
` ${config.membershipOrganizationField}: requestedOrganizationId,`
|
|
816
|
+
);
|
|
817
|
+
lines.push(" },");
|
|
818
|
+
lines.push(" })");
|
|
819
|
+
lines.push(" if (!requestedOrganizationMembership) {");
|
|
820
|
+
lines.push(
|
|
821
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
822
|
+
);
|
|
823
|
+
lines.push(" }");
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
if (!(hasUserField || useOrgScoping)) {
|
|
827
|
+
lines.push(
|
|
828
|
+
` const existingRecord = await db.${model.camelName}.findUnique({`
|
|
829
|
+
);
|
|
830
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
831
|
+
lines.push(` select: { ${selectObj} },`);
|
|
832
|
+
lines.push(" })");
|
|
833
|
+
lines.push(" if (!existingRecord) {");
|
|
834
|
+
lines.push(
|
|
835
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
836
|
+
);
|
|
837
|
+
lines.push(" }");
|
|
838
|
+
lines.push(" const data: Record<string, unknown> = { ...input }");
|
|
839
|
+
}
|
|
840
|
+
lines.push(` return db.${model.camelName}.update({`);
|
|
841
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
842
|
+
lines.push(" data,");
|
|
843
|
+
lines.push(` select: { ${selectObj} },`);
|
|
844
|
+
lines.push(" })");
|
|
845
|
+
lines.push(" },");
|
|
846
|
+
lines.push(
|
|
847
|
+
` delete${model.modelName}: async (_root: unknown, { ${idFieldName} }: { ${idFieldName}: ${idTsType} }, ${hasUserField || useOrgScoping ? "context" : "_context"}: GqlormContext) => {`
|
|
848
|
+
);
|
|
849
|
+
lines.push(
|
|
850
|
+
` const existingRecord = await db.${model.camelName}.findUnique({`
|
|
851
|
+
);
|
|
852
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
853
|
+
lines.push(` select: { ${selectObj} },`);
|
|
854
|
+
lines.push(" })");
|
|
855
|
+
lines.push(" if (!existingRecord) {");
|
|
856
|
+
lines.push(
|
|
857
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
858
|
+
);
|
|
859
|
+
lines.push(" }");
|
|
860
|
+
if (hasUserField || useOrgScoping) {
|
|
861
|
+
lines.push(" if (!context.currentUser) {");
|
|
862
|
+
lines.push(
|
|
863
|
+
` throw new AuthenticationError("You don't have permission to do that.")`
|
|
864
|
+
);
|
|
865
|
+
lines.push(" }");
|
|
866
|
+
lines.push(" const currentUserId = context.currentUser['id']");
|
|
867
|
+
lines.push(
|
|
868
|
+
" if (currentUserId === undefined || currentUserId === null) {"
|
|
869
|
+
);
|
|
870
|
+
lines.push(
|
|
871
|
+
` throw new AuthenticationError("Could not determine the current user's ID.")`
|
|
872
|
+
);
|
|
873
|
+
lines.push(" }");
|
|
874
|
+
if (hasUserField) {
|
|
875
|
+
lines.push(
|
|
876
|
+
` if (existingRecord.${config.membershipUserField} !== currentUserId) {`
|
|
877
|
+
);
|
|
878
|
+
lines.push(
|
|
879
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
880
|
+
);
|
|
881
|
+
lines.push(" }");
|
|
882
|
+
}
|
|
883
|
+
if (useOrgScoping) {
|
|
884
|
+
lines.push(
|
|
885
|
+
` const membership = await db.${config.membershipModelCamel}.findFirst({`
|
|
886
|
+
);
|
|
887
|
+
lines.push(" where: {");
|
|
888
|
+
lines.push(` ${config.membershipUserField}: currentUserId,`);
|
|
889
|
+
lines.push(
|
|
890
|
+
` ${config.membershipOrganizationField}: existingRecord.${config.membershipOrganizationField},`
|
|
891
|
+
);
|
|
892
|
+
lines.push(" },");
|
|
893
|
+
lines.push(" })");
|
|
894
|
+
lines.push(" if (!membership) {");
|
|
895
|
+
lines.push(
|
|
896
|
+
` throw new ForbiddenError('Not authorized to access this resource')`
|
|
897
|
+
);
|
|
898
|
+
lines.push(" }");
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
lines.push(` return db.${model.camelName}.delete({`);
|
|
902
|
+
lines.push(` where: { ${idFieldName} },`);
|
|
903
|
+
lines.push(` select: { ${selectObj} },`);
|
|
904
|
+
lines.push(" })");
|
|
905
|
+
lines.push(" },");
|
|
906
|
+
lines.push("");
|
|
907
|
+
}
|
|
908
|
+
while (lines[lines.length - 1] === "") {
|
|
909
|
+
lines.pop();
|
|
910
|
+
}
|
|
911
|
+
lines.push(" },");
|
|
588
912
|
lines.push(" }");
|
|
589
913
|
lines.push("}");
|
|
590
914
|
lines.push("");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../../../src/generate/plugins/rw-typescript-resolvers/visitor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../../../src/generate/plugins/rw-typescript-resolvers/visitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAA;AAC5F,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAElF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AACnF,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,wBAAwB,EACzB,MAAM,SAAS,CAAA;AAEhB,qBAAa,4BAA6B,SAAQ,0BAA0B;gBAExE,YAAY,EAAE,+BAA+B,EAC7C,MAAM,EAAE,aAAa;IAMvB,eAAe,CACb,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,MAAM,EAAE,GAAG,GACV,qBAAqB;IAgCxB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM,GAAG,IAAI;CA6FpE"}
|
|
@@ -280,9 +280,9 @@ const generateTypeDefGlobalContext = () => {
|
|
|
280
280
|
};
|
|
281
281
|
const generateViteClientTypesDirective = () => {
|
|
282
282
|
const viteClientDirective = `/// <reference types="vite/client" />`;
|
|
283
|
-
const
|
|
283
|
+
const cedarProjectPaths = getPaths();
|
|
284
284
|
const viteClientDirectivePath = path.join(
|
|
285
|
-
|
|
285
|
+
cedarProjectPaths.generated.types.includes,
|
|
286
286
|
"web-vite-client.d.ts"
|
|
287
287
|
);
|
|
288
288
|
fs.writeFileSync(viteClientDirectivePath, viteClientDirective);
|
|
@@ -294,12 +294,9 @@ function generateStubStorybookTypes() {
|
|
|
294
294
|
export type StoryObj<T = any> = any
|
|
295
295
|
}
|
|
296
296
|
`;
|
|
297
|
-
const
|
|
297
|
+
const cedarProjectPaths = getPaths();
|
|
298
298
|
const packageJson = JSON.parse(
|
|
299
|
-
fs.readFileSync(
|
|
300
|
-
path.join(redwoodProjectPaths.base, "package.json"),
|
|
301
|
-
"utf-8"
|
|
302
|
-
)
|
|
299
|
+
fs.readFileSync(path.join(cedarProjectPaths.base, "package.json"), "utf-8")
|
|
303
300
|
);
|
|
304
301
|
const hasCliStorybookVite = Object.keys(
|
|
305
302
|
packageJson["devDependencies"]
|
|
@@ -308,7 +305,7 @@ function generateStubStorybookTypes() {
|
|
|
308
305
|
return [];
|
|
309
306
|
}
|
|
310
307
|
const stubStorybookTypesFilePath = path.join(
|
|
311
|
-
|
|
308
|
+
cedarProjectPaths.generated.types.includes,
|
|
312
309
|
"web-storybook.d.ts"
|
|
313
310
|
);
|
|
314
311
|
fs.writeFileSync(stubStorybookTypesFilePath, stubStorybookTypesFileContent);
|
package/dist/validateSchema.js
CHANGED
|
@@ -52,11 +52,11 @@ function validateSchema(schemaDocumentNode, typesToCheck = ["Query", "Mutation"]
|
|
|
52
52
|
for (const field of typeNode.fields || []) {
|
|
53
53
|
const fieldName = field.name.value;
|
|
54
54
|
const fieldTypeName = typeNode.name.value;
|
|
55
|
-
const
|
|
55
|
+
const isLegacyRedwoodQuery = fieldName === "redwood" && fieldTypeName === "Query";
|
|
56
56
|
const isCedarQuery = fieldName === "cedar" && fieldTypeName === "Query" || // TODO: Remove this when I remove the root schema
|
|
57
57
|
fieldName === "cedarjs" && fieldTypeName === "Query";
|
|
58
58
|
const isCurrentUserQuery = fieldName === "currentUser" && fieldTypeName === "Query";
|
|
59
|
-
if (!(
|
|
59
|
+
if (!(isCedarQuery || isCurrentUserQuery || isLegacyRedwoodQuery)) {
|
|
60
60
|
const hasDirective = field.directives?.length;
|
|
61
61
|
if (!hasDirective) {
|
|
62
62
|
validationOutput.push(`${fieldName} ${fieldTypeName}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/internal",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.1-next.258",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/cedarjs/cedar.git",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"build:types": "tsc --build --verbose ./tsconfig.build.json",
|
|
147
147
|
"build:types-cjs": "tsc --build --verbose ./tsconfig.cjs.json",
|
|
148
148
|
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
|
|
149
|
-
"check:attw": "yarn attw
|
|
149
|
+
"check:attw": "yarn cedar-fwtools-attw",
|
|
150
150
|
"check:package": "concurrently npm:check:attw yarn:publint",
|
|
151
151
|
"fix:permissions": "chmod +x dist/generate/generate.js dist/generate/watch.js",
|
|
152
152
|
"prepublishOnly": "NODE_ENV=production yarn build",
|
|
@@ -155,10 +155,10 @@
|
|
|
155
155
|
},
|
|
156
156
|
"dependencies": {
|
|
157
157
|
"@babel/core": "^7.26.10",
|
|
158
|
-
"@babel/parser": "7.29.
|
|
159
|
-
"@babel/plugin-transform-react-jsx": "7.
|
|
158
|
+
"@babel/parser": "7.29.7",
|
|
159
|
+
"@babel/plugin-transform-react-jsx": "7.29.7",
|
|
160
160
|
"@babel/plugin-transform-typescript": "^7.26.8",
|
|
161
|
-
"@babel/traverse": "7.29.
|
|
161
|
+
"@babel/traverse": "7.29.7",
|
|
162
162
|
"@cedarjs/babel-config": "4.2.0",
|
|
163
163
|
"@cedarjs/cli-helpers": "4.2.0",
|
|
164
164
|
"@cedarjs/graphql-server": "4.2.0",
|
|
@@ -171,40 +171,47 @@
|
|
|
171
171
|
"@graphql-codegen/client-preset": "5.3.0",
|
|
172
172
|
"@graphql-codegen/core": "5.0.2",
|
|
173
173
|
"@graphql-codegen/fragment-matcher": "6.0.1",
|
|
174
|
+
"@graphql-codegen/plugin-helpers": "6.3.0",
|
|
174
175
|
"@graphql-codegen/schema-ast": "5.0.2",
|
|
175
176
|
"@graphql-codegen/typed-document-node": "6.1.8",
|
|
176
177
|
"@graphql-codegen/typescript": "5.0.10",
|
|
177
178
|
"@graphql-codegen/typescript-operations": "5.1.0",
|
|
178
179
|
"@graphql-codegen/typescript-react-apollo": "4.4.2",
|
|
179
180
|
"@graphql-codegen/typescript-resolvers": "5.1.8",
|
|
181
|
+
"@graphql-codegen/visitor-plugin-common": "6.3.0",
|
|
182
|
+
"@graphql-tools/code-file-loader": "8.1.29",
|
|
180
183
|
"@graphql-tools/documents": "1.0.1",
|
|
184
|
+
"@graphql-tools/graphql-file-loader": "8.1.12",
|
|
185
|
+
"@graphql-tools/load": "8.1.8",
|
|
186
|
+
"@graphql-tools/merge": "9.1.9",
|
|
181
187
|
"@prisma/dmmf": "7.8.0",
|
|
182
188
|
"@prisma/internals": "7.8.0",
|
|
183
189
|
"@sdl-codegen/node": "2.0.1",
|
|
184
190
|
"ansis": "4.2.0",
|
|
185
191
|
"deepmerge": "4.3.1",
|
|
186
192
|
"esbuild": "0.27.7",
|
|
193
|
+
"execa": "5.1.1",
|
|
187
194
|
"fast-glob": "3.3.3",
|
|
188
195
|
"graphql": "16.13.2",
|
|
189
196
|
"kill-port": "1.6.1",
|
|
190
|
-
"prettier": "3.8.
|
|
197
|
+
"prettier": "3.8.4",
|
|
191
198
|
"rimraf": "6.1.3",
|
|
192
199
|
"source-map": "0.7.6",
|
|
193
200
|
"string-env-interpolation": "1.0.1",
|
|
194
|
-
"systeminformation": "5.31.
|
|
201
|
+
"systeminformation": "5.31.7",
|
|
195
202
|
"termi-link": "1.1.0",
|
|
196
203
|
"ts-node": "10.9.2",
|
|
197
204
|
"typescript": "5.9.3",
|
|
198
|
-
"vite": "7.3.
|
|
205
|
+
"vite": "7.3.5"
|
|
199
206
|
},
|
|
200
207
|
"devDependencies": {
|
|
201
|
-
"@arethetypeswrong/cli": "0.18.
|
|
208
|
+
"@arethetypeswrong/cli": "0.18.4",
|
|
202
209
|
"@cedarjs/framework-tools": "4.2.0",
|
|
203
210
|
"concurrently": "9.2.1",
|
|
204
211
|
"graphql-tag": "2.12.6",
|
|
205
|
-
"publint": "0.3.
|
|
206
|
-
"tsx": "4.
|
|
207
|
-
"vitest": "3.2.
|
|
212
|
+
"publint": "0.3.21",
|
|
213
|
+
"tsx": "4.22.4",
|
|
214
|
+
"vitest": "3.2.6"
|
|
208
215
|
},
|
|
209
216
|
"engines": {
|
|
210
217
|
"node": ">=24"
|