@cedarjs/cli 6.0.0-canary.2869 → 6.0.0-canary.2871
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.
|
@@ -23,6 +23,20 @@ const validateName = (name) => {
|
|
|
23
23
|
);
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
+
const SENSITIVE_FIELDS = [
|
|
27
|
+
"hashedPassword",
|
|
28
|
+
"salt",
|
|
29
|
+
"resetToken",
|
|
30
|
+
"resetTokenExpiresAt",
|
|
31
|
+
"webAuthnChallenge"
|
|
32
|
+
];
|
|
33
|
+
const redactedModelFields = (fieldNames) => {
|
|
34
|
+
const sensitive = fieldNames.filter((name) => SENSITIVE_FIELDS.includes(name));
|
|
35
|
+
if (sensitive.length === 1 && sensitive[0] === "salt") {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return sensitive;
|
|
39
|
+
};
|
|
26
40
|
const relationsForModel = (model) => {
|
|
27
41
|
return model?.fields.filter((f) => f.relationName).map((field) => {
|
|
28
42
|
return field.name;
|
|
@@ -60,11 +74,13 @@ const mapPrismaScalarToPagePropTsType = (scalarType) => {
|
|
|
60
74
|
return prismaScalarToTsType[scalarType] || "unknown";
|
|
61
75
|
};
|
|
62
76
|
export {
|
|
77
|
+
SENSITIVE_FIELDS,
|
|
63
78
|
forcePluralizeWord,
|
|
64
79
|
intForeignKeysForModel,
|
|
65
80
|
mapPrismaScalarToPagePropTsType,
|
|
66
81
|
mapRouteParamTypeToTsType,
|
|
67
82
|
pathName,
|
|
83
|
+
redactedModelFields,
|
|
68
84
|
relationsForModel,
|
|
69
85
|
removeGeneratorName,
|
|
70
86
|
validateName
|
|
@@ -30,12 +30,17 @@ import {
|
|
|
30
30
|
} from "../../../lib/rollback.js";
|
|
31
31
|
import { getSchema, verifyModelName } from "../../../lib/schemaHelpers.js";
|
|
32
32
|
import {
|
|
33
|
+
redactedModelFields,
|
|
33
34
|
relationsForModel,
|
|
34
35
|
intForeignKeysForModel,
|
|
35
36
|
mapPrismaScalarToPagePropTsType
|
|
36
37
|
} from "../helpers.js";
|
|
37
38
|
import { builder as sdlBuilder } from "../sdl/sdl.js";
|
|
38
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
files as sdlFiles,
|
|
41
|
+
printRedactedFieldsNote,
|
|
42
|
+
redactedSensitiveFields
|
|
43
|
+
} from "../sdl/sdlHandler.js";
|
|
39
44
|
import { writeFilesWithStubsTask } from "../sdl/stubFiles.js";
|
|
40
45
|
import { builder as serviceBuilder } from "../service/service.js";
|
|
41
46
|
import { files as serviceFiles } from "../service/serviceHandler.js";
|
|
@@ -273,7 +278,10 @@ const modelRelatedVariables = (model) => {
|
|
|
273
278
|
}
|
|
274
279
|
};
|
|
275
280
|
const relations = relationsForModel(model)?.map((relation) => relation);
|
|
276
|
-
const
|
|
281
|
+
const redactedFields = redactedModelFields(
|
|
282
|
+
model.fields.map((field) => field.name)
|
|
283
|
+
);
|
|
284
|
+
const columns = model.fields.filter((field) => field.kind !== "object").filter((field) => !redactedFields.includes(field.name)).map((column) => {
|
|
277
285
|
let validation;
|
|
278
286
|
const meta = componentMetadata[column.type];
|
|
279
287
|
const validationDef = meta?.validation;
|
|
@@ -716,6 +724,7 @@ const handler = async ({
|
|
|
716
724
|
prepareForRollback(t);
|
|
717
725
|
}
|
|
718
726
|
await t.run();
|
|
727
|
+
printRedactedFieldsNote(await redactedSensitiveFields([name]));
|
|
719
728
|
} catch (e) {
|
|
720
729
|
const message = e instanceof Error ? e.message : String(e);
|
|
721
730
|
const exitCode = e instanceof Error && "exitCode" in e ? e.exitCode ?? 1 : 1;
|
|
@@ -3,6 +3,7 @@ import boxen from "boxen";
|
|
|
3
3
|
import camelcase from "camelcase";
|
|
4
4
|
import { Listr } from "listr2";
|
|
5
5
|
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
6
|
+
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
6
7
|
import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
|
|
7
8
|
import { getConfig } from "@cedarjs/project-config";
|
|
8
9
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
getEnum,
|
|
18
19
|
verifyModelName
|
|
19
20
|
} from "../../../lib/schemaHelpers.js";
|
|
20
|
-
import { relationsForModel } from "../helpers.js";
|
|
21
|
+
import { redactedModelFields, relationsForModel } from "../helpers.js";
|
|
21
22
|
import { files as serviceFiles } from "../service/serviceHandler.js";
|
|
22
23
|
import { templateForFile } from "../yargsHandlerHelpers.js";
|
|
23
24
|
import {
|
|
@@ -68,11 +69,18 @@ const modelFieldToSDL = ({
|
|
|
68
69
|
return fieldContent;
|
|
69
70
|
}
|
|
70
71
|
};
|
|
72
|
+
const modelRedactedFields = (model) => {
|
|
73
|
+
return redactedModelFields(model.fields.map((field) => field.name));
|
|
74
|
+
};
|
|
71
75
|
const querySDL = (model, docs = false) => {
|
|
72
|
-
|
|
76
|
+
const redactedFields = modelRedactedFields(model);
|
|
77
|
+
return model.fields.filter((field) => !redactedFields.includes(field.name)).map((field) => modelFieldToSDL({ field, docs }));
|
|
73
78
|
};
|
|
74
79
|
const inputSDL = (model, required, docs = false) => {
|
|
75
|
-
const ignoredFields = [
|
|
80
|
+
const ignoredFields = [
|
|
81
|
+
...DEFAULT_IGNORE_FIELDS_FOR_INPUT,
|
|
82
|
+
...modelRedactedFields(model)
|
|
83
|
+
];
|
|
76
84
|
const idField = model.fields.find((field) => field.isId);
|
|
77
85
|
if (idField?.default !== void 0) {
|
|
78
86
|
ignoredFields.push(idField.name);
|
|
@@ -199,6 +207,35 @@ const stubFiles = async (models, generatedFor, { docs = false, typescript }) =>
|
|
|
199
207
|
}
|
|
200
208
|
return generatedFiles;
|
|
201
209
|
};
|
|
210
|
+
const redactedSensitiveFields = async (modelNames) => {
|
|
211
|
+
const redacted = [];
|
|
212
|
+
for (const modelName of modelNames) {
|
|
213
|
+
const model = await getSchema(modelName);
|
|
214
|
+
if (!model || !("fields" in model)) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
for (const fieldName of modelRedactedFields(model)) {
|
|
218
|
+
redacted.push(`${model.name}.${fieldName}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return redacted;
|
|
222
|
+
};
|
|
223
|
+
const printRedactedFieldsNote = (redactedFields) => {
|
|
224
|
+
if (redactedFields.length === 0) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
console.log();
|
|
228
|
+
console.log(
|
|
229
|
+
c.warning(
|
|
230
|
+
`The following fields were excluded from the generated SDL because they may contain sensitive data: ${redactedFields.join(", ")}`
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
console.log(
|
|
234
|
+
c.warning(
|
|
235
|
+
"If you want to expose any of them through your GraphQL API you can add them to the SDL file manually."
|
|
236
|
+
)
|
|
237
|
+
);
|
|
238
|
+
};
|
|
202
239
|
const handler = async ({
|
|
203
240
|
model,
|
|
204
241
|
crud,
|
|
@@ -223,6 +260,10 @@ const handler = async ({
|
|
|
223
260
|
try {
|
|
224
261
|
const { name } = await verifyModelName({ name: model });
|
|
225
262
|
const missingModels = await missingRelatedModels(name);
|
|
263
|
+
const redactedFields = await redactedSensitiveFields([
|
|
264
|
+
name,
|
|
265
|
+
...missingModels
|
|
266
|
+
]);
|
|
226
267
|
const tasks = new Listr(
|
|
227
268
|
[
|
|
228
269
|
{
|
|
@@ -273,9 +314,12 @@ const handler = async ({
|
|
|
273
314
|
);
|
|
274
315
|
console.log(c.info("To replace a stub with a full SDL and service, run"));
|
|
275
316
|
for (const stubModel of missingModels) {
|
|
276
|
-
console.log(
|
|
317
|
+
console.log(
|
|
318
|
+
c.info(` ${formatCedarCommand(["generate", "sdl", stubModel])}`)
|
|
319
|
+
);
|
|
277
320
|
}
|
|
278
321
|
}
|
|
322
|
+
printRedactedFieldsNote(redactedFields);
|
|
279
323
|
} catch (e) {
|
|
280
324
|
const message = e instanceof Error ? e.message : String(e);
|
|
281
325
|
const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
|
|
@@ -287,5 +331,7 @@ const handler = async ({
|
|
|
287
331
|
export {
|
|
288
332
|
files,
|
|
289
333
|
handler,
|
|
334
|
+
printRedactedFieldsNote,
|
|
335
|
+
redactedSensitiveFields,
|
|
290
336
|
stubFiles
|
|
291
337
|
};
|
|
@@ -3,7 +3,7 @@ import camelcase from "camelcase";
|
|
|
3
3
|
import { pluralize, singularize } from "@cedarjs/utils/cedarPluralize";
|
|
4
4
|
import { transformTSToJS } from "../../../lib/index.js";
|
|
5
5
|
import { getSchema, verifyModelName } from "../../../lib/schemaHelpers.js";
|
|
6
|
-
import { relationsForModel } from "../helpers.js";
|
|
6
|
+
import { redactedModelFields, relationsForModel } from "../helpers.js";
|
|
7
7
|
import { createHandler, templateForFile } from "../yargsHandlerHelpers.js";
|
|
8
8
|
function isServiceModel(schema) {
|
|
9
9
|
return typeof schema === "object" && schema !== null && "fields" in schema && "name" in schema;
|
|
@@ -32,7 +32,10 @@ const parseSchema = async (model) => {
|
|
|
32
32
|
return field.isRequired && !field.hasDefaultValue && // don't include fields that the database will default
|
|
33
33
|
!field.relationName;
|
|
34
34
|
});
|
|
35
|
-
|
|
35
|
+
const redactedFields = redactedModelFields(
|
|
36
|
+
schema.fields.map((field) => field.name)
|
|
37
|
+
);
|
|
38
|
+
return { scalarFields, relations, foreignKeys, redactedFields };
|
|
36
39
|
};
|
|
37
40
|
function scenarioFieldValue(field) {
|
|
38
41
|
const randFloat = Math.random() * 1e7;
|
|
@@ -145,9 +148,14 @@ const fieldTypes = async (model) => {
|
|
|
145
148
|
);
|
|
146
149
|
};
|
|
147
150
|
const fieldsToInput = async (model) => {
|
|
148
|
-
const { scalarFields, foreignKeys } = await parseSchema(model);
|
|
151
|
+
const { scalarFields, foreignKeys, redactedFields } = await parseSchema(model);
|
|
149
152
|
const modelName = camelcase(singularize(model));
|
|
150
153
|
const inputObj = {};
|
|
154
|
+
if (scalarFields.some(
|
|
155
|
+
(field) => redactedFields.includes(field.name)
|
|
156
|
+
)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
151
159
|
scalarFields.forEach((field) => {
|
|
152
160
|
if (foreignKeys.includes(field.name)) {
|
|
153
161
|
inputObj[field.name] = `scenario.${modelName}.two.${field.name}`;
|
|
@@ -162,14 +170,17 @@ const fieldsToInput = async (model) => {
|
|
|
162
170
|
}
|
|
163
171
|
};
|
|
164
172
|
const fieldsToUpdate = async (model) => {
|
|
165
|
-
const { scalarFields, relations, foreignKeys } = await parseSchema(model);
|
|
173
|
+
const { scalarFields, relations, foreignKeys, redactedFields } = await parseSchema(model);
|
|
166
174
|
const modelName = camelcase(singularize(model));
|
|
167
175
|
let field, newValue, fieldName;
|
|
168
|
-
|
|
176
|
+
const updatableFields = scalarFields.filter(
|
|
177
|
+
(scalar) => !redactedFields.includes(scalar.name)
|
|
178
|
+
);
|
|
179
|
+
field = updatableFields.find(
|
|
169
180
|
(scalar) => !foreignKeys.includes(scalar.name)
|
|
170
181
|
);
|
|
171
182
|
if (!field) {
|
|
172
|
-
field =
|
|
183
|
+
field = updatableFields[0];
|
|
173
184
|
}
|
|
174
185
|
if (!field) {
|
|
175
186
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/cli",
|
|
3
|
-
"version": "6.0.0-canary.
|
|
3
|
+
"version": "6.0.0-canary.2871",
|
|
4
4
|
"description": "The CedarJS Command Line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"@babel/preset-typescript": "7.29.7",
|
|
37
37
|
"@babel/traverse": "7.29.7",
|
|
38
38
|
"@babel/types": "7.29.7",
|
|
39
|
-
"@cedarjs/api-server": "6.0.0-canary.
|
|
40
|
-
"@cedarjs/babel-config": "6.0.0-canary.
|
|
41
|
-
"@cedarjs/cli-helpers": "6.0.0-canary.
|
|
42
|
-
"@cedarjs/internal": "6.0.0-canary.
|
|
43
|
-
"@cedarjs/prerender": "6.0.0-canary.
|
|
44
|
-
"@cedarjs/project-config": "6.0.0-canary.
|
|
45
|
-
"@cedarjs/structure": "6.0.0-canary.
|
|
46
|
-
"@cedarjs/telemetry": "6.0.0-canary.
|
|
47
|
-
"@cedarjs/utils": "6.0.0-canary.
|
|
48
|
-
"@cedarjs/vite": "6.0.0-canary.
|
|
49
|
-
"@cedarjs/web-server": "6.0.0-canary.
|
|
39
|
+
"@cedarjs/api-server": "6.0.0-canary.2871",
|
|
40
|
+
"@cedarjs/babel-config": "6.0.0-canary.2871",
|
|
41
|
+
"@cedarjs/cli-helpers": "6.0.0-canary.2871",
|
|
42
|
+
"@cedarjs/internal": "6.0.0-canary.2871",
|
|
43
|
+
"@cedarjs/prerender": "6.0.0-canary.2871",
|
|
44
|
+
"@cedarjs/project-config": "6.0.0-canary.2871",
|
|
45
|
+
"@cedarjs/structure": "6.0.0-canary.2871",
|
|
46
|
+
"@cedarjs/telemetry": "6.0.0-canary.2871",
|
|
47
|
+
"@cedarjs/utils": "6.0.0-canary.2871",
|
|
48
|
+
"@cedarjs/vite": "6.0.0-canary.2871",
|
|
49
|
+
"@cedarjs/web-server": "6.0.0-canary.2871",
|
|
50
50
|
"@listr2/prompt-adapter-enquirer": "4.3.0",
|
|
51
51
|
"@opentelemetry/api": "1.9.1",
|
|
52
52
|
"@opentelemetry/core": "1.30.1",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"yargs": "17.7.3"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@cedarjs/framework-tools": "6.0.0-canary.
|
|
97
|
+
"@cedarjs/framework-tools": "6.0.0-canary.2871",
|
|
98
98
|
"@prisma/dmmf": "7.8.0",
|
|
99
99
|
"@types/archiver": "^7.0.0",
|
|
100
100
|
"memfs": "4.64.0",
|