@cedarjs/cli 6.0.0-canary.2869 → 6.0.0-canary.2870

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 { files as sdlFiles } from "../sdl/sdlHandler.js";
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 columns = model.fields.filter((field) => field.kind !== "object").map((column) => {
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;
@@ -17,7 +17,7 @@ import {
17
17
  getEnum,
18
18
  verifyModelName
19
19
  } from "../../../lib/schemaHelpers.js";
20
- import { relationsForModel } from "../helpers.js";
20
+ import { redactedModelFields, relationsForModel } from "../helpers.js";
21
21
  import { files as serviceFiles } from "../service/serviceHandler.js";
22
22
  import { templateForFile } from "../yargsHandlerHelpers.js";
23
23
  import {
@@ -68,11 +68,18 @@ const modelFieldToSDL = ({
68
68
  return fieldContent;
69
69
  }
70
70
  };
71
+ const modelRedactedFields = (model) => {
72
+ return redactedModelFields(model.fields.map((field) => field.name));
73
+ };
71
74
  const querySDL = (model, docs = false) => {
72
- return model.fields.map((field) => modelFieldToSDL({ field, docs }));
75
+ const redactedFields = modelRedactedFields(model);
76
+ return model.fields.filter((field) => !redactedFields.includes(field.name)).map((field) => modelFieldToSDL({ field, docs }));
73
77
  };
74
78
  const inputSDL = (model, required, docs = false) => {
75
- const ignoredFields = [...DEFAULT_IGNORE_FIELDS_FOR_INPUT];
79
+ const ignoredFields = [
80
+ ...DEFAULT_IGNORE_FIELDS_FOR_INPUT,
81
+ ...modelRedactedFields(model)
82
+ ];
76
83
  const idField = model.fields.find((field) => field.isId);
77
84
  if (idField?.default !== void 0) {
78
85
  ignoredFields.push(idField.name);
@@ -199,6 +206,35 @@ const stubFiles = async (models, generatedFor, { docs = false, typescript }) =>
199
206
  }
200
207
  return generatedFiles;
201
208
  };
209
+ const redactedSensitiveFields = async (modelNames) => {
210
+ const redacted = [];
211
+ for (const modelName of modelNames) {
212
+ const model = await getSchema(modelName);
213
+ if (!model || !("fields" in model)) {
214
+ continue;
215
+ }
216
+ for (const fieldName of modelRedactedFields(model)) {
217
+ redacted.push(`${model.name}.${fieldName}`);
218
+ }
219
+ }
220
+ return redacted;
221
+ };
222
+ const printRedactedFieldsNote = (redactedFields) => {
223
+ if (redactedFields.length === 0) {
224
+ return;
225
+ }
226
+ console.log();
227
+ console.log(
228
+ c.warning(
229
+ `The following fields were excluded from the generated SDL because they may contain sensitive data: ${redactedFields.join(", ")}`
230
+ )
231
+ );
232
+ console.log(
233
+ c.warning(
234
+ "If you want to expose any of them through your GraphQL API you can add them to the SDL file manually."
235
+ )
236
+ );
237
+ };
202
238
  const handler = async ({
203
239
  model,
204
240
  crud,
@@ -223,6 +259,10 @@ const handler = async ({
223
259
  try {
224
260
  const { name } = await verifyModelName({ name: model });
225
261
  const missingModels = await missingRelatedModels(name);
262
+ const redactedFields = await redactedSensitiveFields([
263
+ name,
264
+ ...missingModels
265
+ ]);
226
266
  const tasks = new Listr(
227
267
  [
228
268
  {
@@ -276,6 +316,7 @@ const handler = async ({
276
316
  console.log(c.info(` yarn cedar generate sdl ${stubModel}`));
277
317
  }
278
318
  }
319
+ printRedactedFieldsNote(redactedFields);
279
320
  } catch (e) {
280
321
  const message = e instanceof Error ? e.message : String(e);
281
322
  const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
@@ -287,5 +328,7 @@ const handler = async ({
287
328
  export {
288
329
  files,
289
330
  handler,
331
+ printRedactedFieldsNote,
332
+ redactedSensitiveFields,
290
333
  stubFiles
291
334
  };
@@ -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
- return { scalarFields, relations, foreignKeys };
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
- field = scalarFields.find(
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 = scalarFields[0];
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.2869",
3
+ "version": "6.0.0-canary.2870",
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.2869",
40
- "@cedarjs/babel-config": "6.0.0-canary.2869",
41
- "@cedarjs/cli-helpers": "6.0.0-canary.2869",
42
- "@cedarjs/internal": "6.0.0-canary.2869",
43
- "@cedarjs/prerender": "6.0.0-canary.2869",
44
- "@cedarjs/project-config": "6.0.0-canary.2869",
45
- "@cedarjs/structure": "6.0.0-canary.2869",
46
- "@cedarjs/telemetry": "6.0.0-canary.2869",
47
- "@cedarjs/utils": "6.0.0-canary.2869",
48
- "@cedarjs/vite": "6.0.0-canary.2869",
49
- "@cedarjs/web-server": "6.0.0-canary.2869",
39
+ "@cedarjs/api-server": "6.0.0-canary.2870",
40
+ "@cedarjs/babel-config": "6.0.0-canary.2870",
41
+ "@cedarjs/cli-helpers": "6.0.0-canary.2870",
42
+ "@cedarjs/internal": "6.0.0-canary.2870",
43
+ "@cedarjs/prerender": "6.0.0-canary.2870",
44
+ "@cedarjs/project-config": "6.0.0-canary.2870",
45
+ "@cedarjs/structure": "6.0.0-canary.2870",
46
+ "@cedarjs/telemetry": "6.0.0-canary.2870",
47
+ "@cedarjs/utils": "6.0.0-canary.2870",
48
+ "@cedarjs/vite": "6.0.0-canary.2870",
49
+ "@cedarjs/web-server": "6.0.0-canary.2870",
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.2869",
97
+ "@cedarjs/framework-tools": "6.0.0-canary.2870",
98
98
  "@prisma/dmmf": "7.8.0",
99
99
  "@types/archiver": "^7.0.0",
100
100
  "memfs": "4.64.0",