@cedarjs/cli 9.0.0-canary.1784 → 9.0.0-canary.3124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/README.md +7 -10
  2. package/dist/cfw.js +10 -6
  3. package/dist/commands/build/buildHandler.js +220 -45
  4. package/dist/commands/build/buildPackagesTask.js +21 -20
  5. package/dist/commands/build.js +13 -2
  6. package/dist/commands/check.js +4 -6
  7. package/dist/commands/console.js +6 -4
  8. package/dist/commands/deploy/baremetal/SshExecutor.js +13 -4
  9. package/dist/commands/deploy/baremetal/baremetalHandler.js +116 -50
  10. package/dist/commands/deploy/baremetal.js +11 -4
  11. package/dist/commands/deploy/flightcontrolHandler.js +28 -15
  12. package/dist/commands/deploy/helpers/deployHandler.js +11 -6
  13. package/dist/commands/deploy/netlify.js +1 -1
  14. package/dist/commands/deploy/packing/nft.js +1 -2
  15. package/dist/commands/deploy/render.js +1 -1
  16. package/dist/commands/deploy/renderHandler.js +24 -13
  17. package/dist/commands/deploy/serverlessHandler.js +69 -27
  18. package/dist/commands/deploy/vercel.js +1 -1
  19. package/dist/commands/destroy/component/component.js +2 -3
  20. package/dist/commands/destroy/directive/directive.js +1 -3
  21. package/dist/commands/destroy/directive/directiveHandler.js +2 -4
  22. package/dist/commands/destroy/function/function.js +1 -3
  23. package/dist/commands/destroy/handlerHelpers.js +17 -17
  24. package/dist/commands/destroy/helpers.js +8 -2
  25. package/dist/commands/destroy/layout/layout.js +1 -2
  26. package/dist/commands/destroy/page/pageHandler.js +3 -3
  27. package/dist/commands/destroy/scaffold/scaffoldHandler.js +31 -12
  28. package/dist/commands/destroy/sdl/sdlHandler.js +3 -3
  29. package/dist/commands/dev/apiDebugFlag.js +5 -4
  30. package/dist/commands/dev/devHandler.js +219 -68
  31. package/dist/commands/dev/packageWatchCommands.js +8 -3
  32. package/dist/commands/dev.js +16 -6
  33. package/dist/commands/execHandler.js +49 -29
  34. package/dist/commands/experimental/live-queries/liveQueries.js +32 -0
  35. package/dist/commands/experimental/live-queries/liveQueriesHandler.js +448 -0
  36. package/dist/commands/experimental/live-queries/templates/liveQueriesListener.ts.template +153 -0
  37. package/dist/commands/experimental/live-queries/templates/migration.sql.template +100 -0
  38. package/dist/commands/experimental/setupInngest.js +2 -2
  39. package/dist/commands/experimental/setupInngestHandler.js +13 -12
  40. package/dist/commands/experimental/setupOpentelemetry.js +2 -2
  41. package/dist/commands/experimental/setupOpentelemetryHandler.js +14 -10
  42. package/dist/commands/experimental/setupReactCompiler.js +2 -2
  43. package/dist/commands/experimental/setupReactCompilerHandler.js +48 -33
  44. package/dist/commands/experimental/setupRsc.js +1 -1
  45. package/dist/commands/experimental/setupRscHandler.js +20 -16
  46. package/dist/commands/experimental/setupStreamingSsr.js +2 -2
  47. package/dist/commands/experimental/setupStreamingSsrHandler.js +49 -34
  48. package/dist/commands/experimental/templates/opentelemetry.ts.template +2 -1
  49. package/dist/commands/experimental/templates/rsc/Document.tsx.template +1 -1
  50. package/dist/commands/experimental/templates/rsc/entry.client.tsx.template +8 -8
  51. package/dist/commands/experimental/templates/streamingSsr/Document.tsx.template +1 -1
  52. package/dist/commands/experimental/templates/streamingSsr/entry.client.tsx.template +6 -6
  53. package/dist/commands/experimental/templates/streamingSsr/tsconfig.json.template +6 -6
  54. package/dist/commands/experimental/util.js +27 -25
  55. package/dist/commands/experimental.js +3 -2
  56. package/dist/commands/generate/cell/cell.js +20 -0
  57. package/dist/commands/generate/cell/cellHandler.js +89 -40
  58. package/dist/commands/generate/cell/templates/cell.tsx.template +21 -2
  59. package/dist/commands/generate/cell/templates/cellFragment.tsx.template +43 -0
  60. package/dist/commands/generate/cell/templates/cellList.tsx.template +21 -2
  61. package/dist/commands/generate/cell/templates/storiesFragment.tsx.template +23 -0
  62. package/dist/commands/generate/cell/templates/test.js.template +1 -1
  63. package/dist/commands/generate/cell/templates/testFragment.js.template +30 -0
  64. package/dist/commands/generate/component/componentHandler.js +14 -16
  65. package/dist/commands/generate/dataMigration/dataMigration.js +36 -18
  66. package/dist/commands/generate/dataMigration/templates/dataMigration.js.template +1 -1
  67. package/dist/commands/generate/dataMigration/templates/dataMigration.ts.template +1 -1
  68. package/dist/commands/generate/dbAuth/dbAuth.js +1 -0
  69. package/dist/commands/generate/dbAuth/dbAuthHandler.js +63 -34
  70. package/dist/commands/generate/dbAuth/templates/login.oauth.tsx.template +164 -0
  71. package/dist/commands/generate/dbAuth/templates/signup.oauth.tsx.template +147 -0
  72. package/dist/commands/generate/directive/directiveHandler.js +14 -16
  73. package/dist/commands/generate/function/function.js +1 -0
  74. package/dist/commands/generate/function/functionHandler.js +14 -19
  75. package/dist/commands/generate/helpers.js +34 -18
  76. package/dist/commands/generate/job/job.js +1 -0
  77. package/dist/commands/generate/job/jobHandler.js +20 -24
  78. package/dist/commands/generate/layout/layoutHandler.js +13 -16
  79. package/dist/commands/generate/model/model.js +1 -0
  80. package/dist/commands/generate/model/modelHandler.js +11 -5
  81. package/dist/commands/generate/ogImage/ogImage.js +1 -0
  82. package/dist/commands/generate/ogImage/ogImageHandler.js +18 -11
  83. package/dist/commands/generate/package/filesTask.js +9 -0
  84. package/dist/commands/generate/package/packageHandler.js +50 -61
  85. package/dist/commands/generate/package/templates/test.ts.template +2 -2
  86. package/dist/commands/generate/package/templates/vitest.config.ts.template +9 -0
  87. package/dist/commands/generate/page/pageHandler.js +27 -24
  88. package/dist/commands/generate/realtime/realtime.js +2 -2
  89. package/dist/commands/generate/realtime/realtimeHandler.js +51 -32
  90. package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.ts.template +1 -1
  91. package/dist/commands/generate/scaffold/scaffold.js +1 -0
  92. package/dist/commands/generate/scaffold/scaffoldHandler.js +176 -49
  93. package/dist/commands/generate/scaffold/templates/lib/formatters.tsx.template +1 -1
  94. package/dist/commands/generate/script/script.js +1 -0
  95. package/dist/commands/generate/script/scriptHandler.js +10 -6
  96. package/dist/commands/generate/script/templates/script.ts.template +9 -4
  97. package/dist/commands/generate/script/templates/tsconfig.json.template +16 -2
  98. package/dist/commands/generate/sdl/sdl.js +4 -3
  99. package/dist/commands/generate/sdl/sdlHandler.js +135 -46
  100. package/dist/commands/generate/sdl/stubFiles.js +132 -0
  101. package/dist/commands/generate/sdl/templates/sdl.js.template +2 -1
  102. package/dist/commands/generate/sdl/templates/sdl.ts.template +2 -1
  103. package/dist/commands/generate/secret/secret.js +20 -20
  104. package/dist/commands/generate/service/service.js +5 -5
  105. package/dist/commands/generate/service/serviceHandler.js +126 -61
  106. package/dist/commands/generate/service/templates/scenarios.ts.template +4 -2
  107. package/dist/commands/generate/service/templates/service.ts.template +22 -8
  108. package/dist/commands/generate/service/templates/test.ts.template +2 -2
  109. package/dist/commands/generate/yargsCommandHelpers.js +7 -2
  110. package/dist/commands/generate/yargsHandlerHelpers.js +20 -18
  111. package/dist/commands/generate.js +4 -4
  112. package/dist/commands/info.js +2 -2
  113. package/dist/commands/jobsHandler.js +7 -4
  114. package/dist/commands/lint.js +26 -69
  115. package/dist/commands/prerenderHandler.js +95 -58
  116. package/dist/commands/prismaHandler.js +51 -26
  117. package/dist/commands/record/init.js +2 -2
  118. package/dist/commands/record.js +4 -3
  119. package/dist/commands/serve.js +245 -31
  120. package/dist/commands/serveApiHandler.js +7 -6
  121. package/dist/commands/serveBothHandler.js +22 -13
  122. package/dist/commands/serveWebHandler.js +3 -2
  123. package/dist/commands/setup/auth/auth.js +15 -11
  124. package/dist/commands/setup/cache/cache.js +1 -1
  125. package/dist/commands/setup/cache/cacheHandler.js +15 -9
  126. package/dist/commands/setup/database/database.js +15 -0
  127. package/dist/commands/setup/database/postgres.js +19 -0
  128. package/dist/commands/setup/database/postgresHandler.js +196 -0
  129. package/dist/commands/setup/database/templates/db.ts.template +32 -0
  130. package/dist/commands/setup/deploy/deploy.js +4 -3
  131. package/dist/commands/setup/deploy/helpers/helpers.js +5 -1
  132. package/dist/commands/setup/deploy/helpers/index.js +132 -6
  133. package/dist/commands/setup/deploy/providers/baremetalHandler.js +28 -6
  134. package/dist/commands/setup/deploy/providers/coherence.js +1 -1
  135. package/dist/commands/setup/deploy/providers/coherenceHandler.js +60 -31
  136. package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +69 -51
  137. package/dist/commands/setup/deploy/providers/netlify.js +6 -0
  138. package/dist/commands/setup/deploy/providers/netlifyHandler.js +114 -13
  139. package/dist/commands/setup/deploy/providers/renderHandler.js +44 -41
  140. package/dist/commands/setup/deploy/providers/serverlessHandler.js +7 -5
  141. package/dist/commands/setup/deploy/providers/universal-deploy.js +11 -0
  142. package/dist/commands/setup/deploy/providers/universalDeployHandler.js +186 -0
  143. package/dist/commands/setup/deploy/providers/vercel.js +6 -0
  144. package/dist/commands/setup/deploy/providers/vercelHandler.js +115 -14
  145. package/dist/commands/setup/deploy/templates/baremetal.js +3 -2
  146. package/dist/commands/setup/deploy/templates/flightcontrol.js +60 -49
  147. package/dist/commands/setup/deploy/templates/netlify.js +2 -1
  148. package/dist/commands/setup/deploy/templates/netlifyUD.js +31 -0
  149. package/dist/commands/setup/deploy/templates/render.js +32 -17
  150. package/dist/commands/setup/docker/docker.js +2 -2
  151. package/dist/commands/setup/docker/dockerHandler.js +74 -39
  152. package/dist/commands/setup/docker/templates/Dockerfile.npm +119 -0
  153. package/dist/commands/setup/docker/templates/Dockerfile.pnpm +112 -0
  154. package/dist/commands/setup/docker/templates/{Dockerfile → Dockerfile.yarn} +4 -7
  155. package/dist/commands/setup/docker/templates/docker-compose.dev.yml +3 -3
  156. package/dist/commands/setup/docker/templates/docker-compose.prod.yml +2 -5
  157. package/dist/commands/setup/docker/templates/dockerignore +1 -0
  158. package/dist/commands/setup/generator/generator.js +1 -1
  159. package/dist/commands/setup/generator/generatorHandler.js +5 -4
  160. package/dist/commands/setup/graphql/features/fragments/appGqlConfigTransform.js +6 -3
  161. package/dist/commands/setup/graphql/features/fragments/fragments.js +1 -1
  162. package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +5 -7
  163. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocuments.js +1 -1
  164. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +4 -3
  165. package/dist/commands/setup/i18n/i18n.js +1 -1
  166. package/dist/commands/setup/i18n/i18nHandler.js +21 -17
  167. package/dist/commands/setup/jobs/jobs.js +1 -1
  168. package/dist/commands/setup/jobs/jobsHandler.js +17 -12
  169. package/dist/commands/setup/mailer/mailer.js +1 -1
  170. package/dist/commands/setup/mailer/mailerHandler.js +13 -11
  171. package/dist/commands/setup/middleware/ogImage/ogImage.js +1 -1
  172. package/dist/commands/setup/middleware/ogImage/ogImageHandler.js +2 -1
  173. package/dist/commands/setup/monitoring/sentry/sentry.js +1 -1
  174. package/dist/commands/setup/monitoring/sentry/sentryHandler.js +18 -12
  175. package/dist/commands/setup/neon/neon.js +35 -0
  176. package/dist/commands/setup/neon/neonHandler.js +264 -0
  177. package/dist/commands/setup/package/package.js +1 -1
  178. package/dist/commands/setup/package/packageHandler.js +18 -14
  179. package/dist/commands/setup/realtime/addRealtimeToGraphql.js +1 -1
  180. package/dist/commands/setup/realtime/realtime.js +1 -1
  181. package/dist/commands/setup/realtime/realtimeHandler.js +26 -37
  182. package/dist/commands/setup/realtime/templates/realtime.ts.template +1 -1
  183. package/dist/commands/setup/realtime/templates/subscriptions/countdown/countdown.ts.template +1 -1
  184. package/dist/commands/setup/realtime/templates/subscriptions/newMessage/newMessage.ts.template +1 -1
  185. package/dist/commands/setup/server-file/serverFile.js +1 -1
  186. package/dist/commands/setup/server-file/serverFileHandler.js +18 -10
  187. package/dist/commands/setup/tenancy/authCodemod.js +66 -0
  188. package/dist/commands/setup/tenancy/dbCodemod.js +64 -0
  189. package/dist/commands/setup/tenancy/graphqlCodemod.js +88 -0
  190. package/dist/commands/setup/tenancy/preflight.js +49 -0
  191. package/dist/commands/setup/tenancy/schemaPrisma.js +81 -0
  192. package/dist/commands/setup/tenancy/signupCodemod.js +153 -0
  193. package/dist/commands/setup/tenancy/templates/InvitePage.tsx.template +63 -0
  194. package/dist/commands/setup/tenancy/templates/OrgScope.tsx.template +40 -0
  195. package/dist/commands/setup/tenancy/templates/ensureDefaultOrganizations.dataMigration.ts.template +39 -0
  196. package/dist/commands/setup/tenancy/templates/organizations.scenarios.ts.template +59 -0
  197. package/dist/commands/setup/tenancy/templates/organizations.sdl.ts.template +89 -0
  198. package/dist/commands/setup/tenancy/templates/organizations.test.ts.template +389 -0
  199. package/dist/commands/setup/tenancy/templates/organizations.ts.template +394 -0
  200. package/dist/commands/setup/tenancy/templates/requireMembership.test.ts.template +35 -0
  201. package/dist/commands/setup/tenancy/templates/requireMembership.ts.template +25 -0
  202. package/dist/commands/setup/tenancy/tenancy.js +30 -0
  203. package/dist/commands/setup/tenancy/tenancyHandler.js +425 -0
  204. package/dist/commands/setup/ui/helpers/helpers.js +5 -1
  205. package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +16 -8
  206. package/dist/commands/setup/ui/libraries/mantineHandler.js +26 -16
  207. package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +40 -29
  208. package/dist/commands/setup/uploads/schemaPrisma.js +41 -0
  209. package/dist/commands/setup/uploads/serverFile.js +151 -0
  210. package/dist/commands/setup/uploads/templates/requireUploadToken.ts.template +15 -0
  211. package/dist/commands/setup/uploads/templates/srcLibUploads.ts.template +23 -24
  212. package/dist/commands/setup/uploads/templates/uploads.sdl.ts.template +79 -0
  213. package/dist/commands/setup/uploads/templates/uploads.ts.template +89 -0
  214. package/dist/commands/setup/uploads/templates/withDataUri.ts.template +14 -0
  215. package/dist/commands/setup/uploads/templates/withSignedUrl.ts.template +16 -0
  216. package/dist/commands/setup/uploads/uploads.js +49 -7
  217. package/dist/commands/setup/uploads/uploadsHandler.js +266 -72
  218. package/dist/commands/setup.js +5 -4
  219. package/dist/commands/studio.js +1 -1
  220. package/dist/commands/studioHandler.js +2 -2
  221. package/dist/commands/test/datasourceWarning.js +42 -0
  222. package/dist/commands/test/testHandler.js +104 -0
  223. package/dist/commands/test/viteVersionCheck.js +75 -0
  224. package/dist/commands/test.js +16 -19
  225. package/dist/commands/type-check.js +2 -1
  226. package/dist/commands/type-checkHandler.js +25 -18
  227. package/dist/commands/upgrade/preUpgradeScripts.js +11 -11
  228. package/dist/commands/upgrade/upgrade.js +4 -2
  229. package/dist/commands/upgrade/upgradeHandler.js +97 -73
  230. package/dist/index.js +15 -11
  231. package/dist/lib/background.js +22 -1
  232. package/dist/lib/configureStorybook.js +2 -2
  233. package/dist/lib/exec.js +68 -63
  234. package/dist/lib/exit.js +20 -5
  235. package/dist/lib/extendFile.js +23 -13
  236. package/dist/lib/generatePrismaClient.js +48 -12
  237. package/dist/lib/index.js +137 -106
  238. package/dist/lib/loadEnvFiles.js +1 -1
  239. package/dist/lib/locking.js +8 -4
  240. package/dist/lib/merge/algorithms.js +4 -1
  241. package/dist/lib/merge/index.js +78 -41
  242. package/dist/lib/merge/semanticIdentity.js +18 -6
  243. package/dist/lib/merge/strategy.js +86 -36
  244. package/dist/lib/packages.js +23 -13
  245. package/dist/lib/plugin.js +13 -7
  246. package/dist/lib/pluralHelpers.js +6 -2
  247. package/dist/lib/project.js +3 -1
  248. package/dist/lib/rollback.js +7 -7
  249. package/dist/lib/schemaHelpers.js +16 -19
  250. package/dist/lib/test.js +20 -5
  251. package/dist/lib/updateCheck.js +47 -18
  252. package/dist/middleware/checkNodeVersion.js +9 -4
  253. package/dist/middleware/{detectProjectRxVersion.js → detectProjectCedarVersion.js} +2 -2
  254. package/dist/plugin.js +18 -12
  255. package/dist/telemetry/exporter.js +12 -5
  256. package/dist/telemetry/index.js +4 -3
  257. package/dist/telemetry/resource.js +9 -12
  258. package/dist/telemetry/send.js +14 -10
  259. package/dist/testLib/cells.js +5 -3
  260. package/package.json +44 -41
  261. package/LICENSE +0 -21
  262. package/dist/commands/consoleHandler.js +0 -68
  263. package/dist/commands/setup/tsconfig/tsconfig.js +0 -25
  264. package/dist/commands/setup/tsconfig/tsconfigHandler.js +0 -59
  265. package/dist/commands/setup/uploads/dbCodemod.js +0 -28
  266. package/dist/commands/setup/uploads/templates/signedUrl.ts.template +0 -21
  267. package/dist/commands/setup/vite/templates/vite.config.ts.template +0 -19
  268. package/dist/commands/setup/vite/vite.js +0 -38
  269. package/dist/commands/setup/vite/viteHandler.js +0 -83
  270. package/dist/commands/testEsm.js +0 -36
  271. package/dist/commands/testHandler.js +0 -137
  272. package/dist/commands/testHandlerEsm.js +0 -85
  273. package/dist/commands/ts-to-js.js +0 -20
  274. package/dist/lib/cedarPluralize.js +0 -56
  275. package/dist/lib/colors.js +0 -18
  276. package/dist/testLib/getFilesWithPattern.js +0 -21
  277. /package/dist/{index.d.js → global.d.js} +0 -0
@@ -1,16 +1,25 @@
1
1
  import path from "node:path";
2
2
  import camelcase from "camelcase";
3
- import { pluralize, singularize } from "../../../lib/cedarPluralize.js";
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
+ function isServiceModel(schema) {
9
+ return typeof schema === "object" && schema !== null && "fields" in schema && "name" in schema;
10
+ }
8
11
  const DEFAULT_SCENARIO_NAMES = ["one", "two"];
9
12
  const parseSchema = async (model) => {
10
- const schema = await getSchema(model);
13
+ const schemaResult = await getSchema(model);
14
+ if (!isServiceModel(schemaResult)) {
15
+ throw new Error(
16
+ `No schema definition found for \`${model}\` in schema.prisma file`
17
+ );
18
+ }
19
+ const schema = schemaResult;
11
20
  const relations = {};
12
21
  let foreignKeys = [];
13
- let scalarFields = schema.fields.filter((field) => {
22
+ const scalarFields = schema.fields.filter((field) => {
14
23
  if (field.relationFromFields) {
15
24
  if (field.isRequired && field.relationFromFields.length !== 0) {
16
25
  relations[field.name] = {
@@ -23,15 +32,18 @@ const parseSchema = async (model) => {
23
32
  return field.isRequired && !field.hasDefaultValue && // don't include fields that the database will default
24
33
  !field.relationName;
25
34
  });
26
- return { scalarFields, relations, foreignKeys };
35
+ const redactedFields = redactedModelFields(
36
+ schema.fields.map((field) => field.name)
37
+ );
38
+ return { scalarFields, relations, foreignKeys, redactedFields };
27
39
  };
28
40
  function scenarioFieldValue(field) {
29
41
  const randFloat = Math.random() * 1e7;
30
- const randInt = parseInt(Math.random() * 1e7);
42
+ const randInt = parseInt(String(Math.random() * 1e7));
31
43
  const randIntArray = [
32
- parseInt(Math.random() * 300),
33
- parseInt(Math.random() * 300),
34
- parseInt(Math.random() * 300)
44
+ parseInt(String(Math.random() * 300)),
45
+ parseInt(String(Math.random() * 300)),
46
+ parseInt(String(Math.random() * 300))
35
47
  ];
36
48
  switch (field.type) {
37
49
  case "BigInt":
@@ -55,11 +67,12 @@ function scenarioFieldValue(field) {
55
67
  case "Bytes":
56
68
  return `new Uint8Array([${randIntArray}])`;
57
69
  default: {
58
- if (field.kind === "enum" && field.enumValues[0]) {
70
+ if (field.kind === "enum" && field.enumValues?.[0]) {
59
71
  return field.enumValues[0].dbName || field.enumValues[0].name;
60
72
  }
61
73
  }
62
74
  }
75
+ return void 0;
63
76
  }
64
77
  const fieldsToScenario = async (scalarFields, relations, foreignKeys) => {
65
78
  const data = {};
@@ -126,15 +139,23 @@ const buildStringifiedScenario = async (model) => {
126
139
  };
127
140
  const fieldTypes = async (model) => {
128
141
  const { scalarFields } = await parseSchema(model);
129
- return scalarFields.reduce((acc, value) => {
130
- acc[value.name] = value.type;
131
- return acc;
132
- }, {});
142
+ return scalarFields.reduce(
143
+ (acc, value) => {
144
+ acc[value.name] = value.type;
145
+ return acc;
146
+ },
147
+ {}
148
+ );
133
149
  };
134
150
  const fieldsToInput = async (model) => {
135
- const { scalarFields, foreignKeys } = await parseSchema(model);
151
+ const { scalarFields, foreignKeys, redactedFields } = await parseSchema(model);
136
152
  const modelName = camelcase(singularize(model));
137
- let inputObj = {};
153
+ const inputObj = {};
154
+ if (scalarFields.some(
155
+ (field) => redactedFields.includes(field.name)
156
+ )) {
157
+ return false;
158
+ }
138
159
  scalarFields.forEach((field) => {
139
160
  if (foreignKeys.includes(field.name)) {
140
161
  inputObj[field.name] = `scenario.${modelName}.two.${field.name}`;
@@ -149,12 +170,17 @@ const fieldsToInput = async (model) => {
149
170
  }
150
171
  };
151
172
  const fieldsToUpdate = async (model) => {
152
- const { scalarFields, relations, foreignKeys } = await parseSchema(model);
173
+ const { scalarFields, relations, foreignKeys, redactedFields } = await parseSchema(model);
153
174
  const modelName = camelcase(singularize(model));
154
175
  let field, newValue, fieldName;
155
- field = scalarFields.find((scalar) => !foreignKeys.includes(scalar.name));
176
+ const updatableFields = scalarFields.filter(
177
+ (scalar) => !redactedFields.includes(scalar.name)
178
+ );
179
+ field = updatableFields.find(
180
+ (scalar) => !foreignKeys.includes(scalar.name)
181
+ );
156
182
  if (!field) {
157
- field = scalarFields[0];
183
+ field = updatableFields[0];
158
184
  }
159
185
  if (!field) {
160
186
  return false;
@@ -168,25 +194,31 @@ const fieldsToUpdate = async (model) => {
168
194
  newValue = value;
169
195
  switch (field.type) {
170
196
  case "BigInt":
171
- newValue = `${newValue + 1n}`;
197
+ if (typeof value === "bigint") {
198
+ newValue = `${value + 1n}`;
199
+ }
172
200
  break;
173
201
  case "Boolean": {
174
202
  newValue = !value;
175
203
  break;
176
204
  }
177
205
  case "DateTime": {
178
- let date = /* @__PURE__ */ new Date();
206
+ const date = /* @__PURE__ */ new Date();
179
207
  date.setDate(date.getDate() + 1);
180
208
  newValue = date;
181
209
  break;
182
210
  }
183
211
  case "Decimal":
184
212
  case "Float": {
185
- newValue = newValue + 1.1;
213
+ if (typeof value === "number") {
214
+ newValue = value + 1.1;
215
+ }
186
216
  break;
187
217
  }
188
218
  case "Int": {
189
- newValue = newValue + 1;
219
+ if (typeof value === "number") {
220
+ newValue = value + 1;
221
+ }
190
222
  break;
191
223
  }
192
224
  case "Json": {
@@ -194,11 +226,13 @@ const fieldsToUpdate = async (model) => {
194
226
  break;
195
227
  }
196
228
  case "String": {
197
- newValue = newValue + "2";
229
+ if (typeof value === "string") {
230
+ newValue = value + "2";
231
+ }
198
232
  break;
199
233
  }
200
234
  default: {
201
- if (field.kind === "enum" && field.enumValues[field.enumValues.length - 1]) {
235
+ if (field.kind === "enum" && field.enumValues?.[field.enumValues.length - 1]) {
202
236
  const enumVal = field.enumValues[field.enumValues.length - 1];
203
237
  newValue = enumVal.dbName || enumVal.name;
204
238
  }
@@ -206,11 +240,21 @@ const fieldsToUpdate = async (model) => {
206
240
  }
207
241
  }
208
242
  }
243
+ if (Array.isArray(fieldName)) {
244
+ return Object.fromEntries(fieldName.map((key) => [key, newValue]));
245
+ }
209
246
  return { [fieldName]: newValue };
210
247
  };
211
248
  const getIdName = async (model) => {
212
- const schema = await getSchema(model);
213
- return schema.fields.find((field) => field.isId)?.name;
249
+ const schemaResult = await getSchema(model);
250
+ if (!isServiceModel(schemaResult)) {
251
+ return void 0;
252
+ }
253
+ if (schemaResult.primaryKey?.fields.length) {
254
+ const { fields, name } = schemaResult.primaryKey;
255
+ return { fields, whereArg: name || fields.join("_") };
256
+ }
257
+ return schemaResult.fields.find((field) => field.isId)?.name;
214
258
  };
215
259
  const files = async ({
216
260
  name,
@@ -222,7 +266,21 @@ const files = async ({
222
266
  const componentName = camelcase(pluralize(name));
223
267
  const model = name;
224
268
  const idName = await getIdName(model);
225
- const modelRelations = relations || relationsForModel(await getSchema(model));
269
+ if (tests && rest.crud && idName !== void 0 && typeof idName !== "string") {
270
+ throw new Error(
271
+ `Cannot generate CRUD tests for "${model}": it has a compound primary key (@@id([${idName.fields.join(", ")}])), which isn't supported by the generated test file yet. Re-run with \`--tests=false\`.`
272
+ );
273
+ }
274
+ const prismaImportSource = "src/lib/db";
275
+ let modelRelations;
276
+ if (relations) {
277
+ modelRelations = relations;
278
+ } else {
279
+ const schemaResult = await getSchema(model);
280
+ if (isServiceModel(schemaResult)) {
281
+ modelRelations = relationsForModel(schemaResult);
282
+ }
283
+ }
226
284
  const serviceFile = await templateForFile({
227
285
  name,
228
286
  side: "api",
@@ -230,46 +288,53 @@ const files = async ({
230
288
  generator: "service",
231
289
  outputPath: path.join(componentName, componentName + ".ts"),
232
290
  templatePath: "service.ts.template",
233
- templateVars: { relations: modelRelations, idName, ...rest }
234
- });
235
- const testFile = await templateForFile({
236
- name,
237
- side: "api",
238
- sidePathSection: "services",
239
- generator: "service",
240
- outputPath: path.join(componentName, componentName + ".test.ts"),
241
- templatePath: "test.ts.template",
242
291
  templateVars: {
243
- relations: relations || [],
244
- create: await fieldsToInput(model),
245
- update: await fieldsToUpdate(model),
246
- types: await fieldTypes(model),
247
- prismaImport: (await parseSchema(model)).scalarFields.some(
248
- (field) => field.type === "Decimal"
249
- ),
250
- prismaModel: model,
251
- idName,
252
- ...rest
253
- }
254
- });
255
- const scenariosFile = await templateForFile({
256
- name,
257
- side: "api",
258
- sidePathSection: "services",
259
- generator: "service",
260
- outputPath: path.join(componentName, componentName + ".scenarios.ts"),
261
- templatePath: "scenarios.ts.template",
262
- templateVars: {
263
- scenario: await buildScenario(model),
264
- stringifiedScenario: await buildStringifiedScenario(model),
265
- prismaModel: model,
266
- idName,
267
292
  relations: modelRelations,
293
+ idName,
294
+ prismaImportSource,
268
295
  ...rest
269
296
  }
270
297
  });
271
298
  const files2 = [serviceFile];
272
299
  if (tests) {
300
+ const testFile = await templateForFile({
301
+ name,
302
+ side: "api",
303
+ sidePathSection: "services",
304
+ generator: "service",
305
+ outputPath: path.join(componentName, componentName + ".test.ts"),
306
+ templatePath: "test.ts.template",
307
+ templateVars: {
308
+ relations: relations || [],
309
+ create: await fieldsToInput(model),
310
+ update: await fieldsToUpdate(model),
311
+ types: await fieldTypes(model),
312
+ prismaImport: (await parseSchema(model)).scalarFields.some(
313
+ (field) => field.type === "Decimal"
314
+ ),
315
+ prismaModel: model,
316
+ idName,
317
+ prismaImportSource,
318
+ ...rest
319
+ }
320
+ });
321
+ const scenariosFile = await templateForFile({
322
+ name,
323
+ side: "api",
324
+ sidePathSection: "services",
325
+ generator: "service",
326
+ outputPath: path.join(componentName, componentName + ".scenarios.ts"),
327
+ templatePath: "scenarios.ts.template",
328
+ templateVars: {
329
+ scenario: await buildScenario(model),
330
+ stringifiedScenario: await buildStringifiedScenario(model),
331
+ prismaModel: model,
332
+ idName,
333
+ relations: modelRelations,
334
+ prismaImportSource,
335
+ ...rest
336
+ }
337
+ });
273
338
  files2.push(testFile);
274
339
  files2.push(scenariosFile);
275
340
  }
@@ -1,6 +1,8 @@
1
- import type { Prisma, ${prismaModel} } from '@prisma/client'
1
+ <% if (prismaImportSource === 'src/lib/db') { %>import type { ScenarioData } from '@cedarjs/testing/api'
2
2
 
3
- import type { ScenarioData } from '@cedarjs/testing/api'
3
+ import type { Prisma, ${prismaModel} } from '${prismaImportSource}'<% } else { %>import type { Prisma, ${prismaModel} } from '${prismaImportSource}'
4
+
5
+ import type { ScenarioData } from '@cedarjs/testing/api'<% } %>
4
6
 
5
7
  export const standard = defineScenario<Prisma.${prismaModel}CreateArgs>(${stringifiedScenario})
6
8
 
@@ -1,14 +1,28 @@
1
1
  import type { QueryResolvers<% if (crud) { %>, MutationResolvers<% } %><% if (relations.length) { %>, ${singularPascalName}RelationResolvers<% } %> } from 'types/graphql'
2
2
 
3
3
  import { db } from 'src/lib/db'
4
-
4
+ <%
5
+ // A compound `@@id([...])` key comes through as `{ fields, whereArg }`
6
+ // instead of a single field name -- build the destructure/where-clause
7
+ // snippets for both shapes here so the rest of the template can stay
8
+ // shape-agnostic.
9
+ const idIsComposite = idName != null && typeof idName === 'object'
10
+ const idFields = idIsComposite ? idName.fields : [idName]
11
+ const idArgs = idFields.join(', ')
12
+ const idWhere = idIsComposite
13
+ ? `${idName.whereArg}: { ${idFields.join(', ')} }`
14
+ : idName
15
+ const idWhereFromRoot = idIsComposite
16
+ ? `${idName.whereArg}: { ${idFields.map((f) => `${f}: root?.${f}`).join(', ')} }`
17
+ : `${idName}: root?.${idName}`
18
+ %>
5
19
  export const ${pluralCamelName}: QueryResolvers['${pluralCamelName}'] = () => {
6
20
  return db.${singularCamelName}.findMany()
7
21
  }<% if (crud || relations.length) { %>
8
22
 
9
- export const ${singularCamelName}: QueryResolvers['${singularCamelName}'] = ({ ${idName} }) => {
23
+ export const ${singularCamelName}: QueryResolvers['${singularCamelName}'] = ({ ${idArgs} }) => {
10
24
  return db.${singularCamelName}.findUnique({
11
- where: { ${idName} },
25
+ where: { ${idWhere} },
12
26
  })
13
27
  }<% } %><% if (crud) { %>
14
28
 
@@ -18,21 +32,21 @@ export const create${singularPascalName}: MutationResolvers['create${singularPas
18
32
  })
19
33
  }
20
34
 
21
- export const update${singularPascalName}: MutationResolvers['update${singularPascalName}'] = ({ ${idName}, input }) => {
35
+ export const update${singularPascalName}: MutationResolvers['update${singularPascalName}'] = ({ ${idArgs}, input }) => {
22
36
  return db.${singularCamelName}.update({
23
37
  data: input,
24
- where: { ${idName} },
38
+ where: { ${idWhere} },
25
39
  })
26
40
  }
27
41
 
28
- export const delete${singularPascalName}: MutationResolvers['delete${singularPascalName}'] = ({ ${idName} }) => {
42
+ export const delete${singularPascalName}: MutationResolvers['delete${singularPascalName}'] = ({ ${idArgs} }) => {
29
43
  return db.${singularCamelName}.delete({
30
- where: { ${idName} },
44
+ where: { ${idWhere} },
31
45
  })
32
46
  }<% } %><% if (relations.length) { %>
33
47
 
34
48
  export const ${singularPascalName}: ${singularPascalName}RelationResolvers = {<% relations.forEach(relation => { %>
35
49
  ${relation}: (_obj, { root }) => {
36
- return db.${singularCamelName}.findUnique({ where: { ${idName}: root?.${idName} } }).${relation}()
50
+ return db.${singularCamelName}.findUnique({ where: { ${idWhereFromRoot} } }).${relation}()
37
51
  },<% }) %>
38
52
  }<% } %>
@@ -31,7 +31,7 @@
31
31
  // Not all values can be represented as JSON, like function invocations
32
32
  return jsonString.replace(/"new Uint8Array\(([^)]+)\)"/g, 'new Uint8Array($1)')
33
33
  } %>
34
- <% if (prismaImport) { %>import { Prisma, ${prismaModel} } from '@prisma/client'<% } else { %>import type { ${prismaModel} } from '@prisma/client'<% } %>
34
+ <% if (prismaImport) { %>import { Prisma, ${prismaModel} } from '${prismaImportSource}'<% } else { %>import type { ${prismaModel} } from '${prismaImportSource}'<% } %>
35
35
 
36
36
  import { ${pluralCamelName}<% if (crud) { %>,${singularCamelName}, create${singularPascalName}, update${singularPascalName}, delete${singularPascalName}<% } %> } from './${pluralCamelName}.js'
37
37
  import type { StandardScenario } from './${pluralCamelName}.scenarios.js'
@@ -40,7 +40,7 @@ import type { StandardScenario } from './${pluralCamelName}.scenarios.js'
40
40
  // and can fail without adjustments, e.g. Float.
41
41
  // Please refer to the RedwoodJS Testing Docs:
42
42
  // https://cedarjs.com/docs/testing#testing-services
43
- // https://cedarjs.com/docs/testing#jest-expect-type-considerations
43
+ // https://cedarjs.com/docs/testing#expect-type-considerations
44
44
 
45
45
  describe('${pluralCamelName}', () => {
46
46
  scenario('returns all ${pluralCamelName}', async (scenario: StandardScenario) => {
@@ -1,5 +1,5 @@
1
1
  import { terminalLink } from "termi-link";
2
- import { isTypeScriptProject } from "@cedarjs/cli-helpers";
2
+ import { isTypeScriptProject } from "@cedarjs/cli-helpers/project";
3
3
  function getYargsDefaults() {
4
4
  return {
5
5
  force: {
@@ -70,11 +70,16 @@ function createBuilder({
70
70
  Object.entries(opts).forEach(([option, config]) => {
71
71
  yargs.option(option, config);
72
72
  });
73
+ return yargs;
73
74
  };
74
75
  }
75
76
  function createHandler(componentName) {
76
77
  return async function handler(argv) {
77
- const { handler: importedHandler } = await import(`./${componentName}/${componentName}Handler.js`);
78
+ const { existsSync } = await import("node:fs");
79
+ const tsPath = `./${componentName}/${componentName}Handler.ts`;
80
+ const jsPath = `./${componentName}/${componentName}Handler.js`;
81
+ const resolvedPath = existsSync(new URL(tsPath, import.meta.url)) ? tsPath : jsPath;
82
+ const { handler: importedHandler } = await import(resolvedPath);
78
83
  return importedHandler(argv);
79
84
  };
80
85
  }
@@ -3,10 +3,10 @@ import path from "node:path";
3
3
  import { camelCase } from "change-case";
4
4
  import { Listr } from "listr2";
5
5
  import pascalcase from "pascalcase";
6
- import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
6
+ import { colors as c } from "@cedarjs/cli-helpers/colors";
7
+ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
7
8
  import { ensurePosixPath, getConfig } from "@cedarjs/project-config";
8
9
  import { errorTelemetry } from "@cedarjs/telemetry";
9
- import c from "../../lib/colors.js";
10
10
  import { generateTemplate, getPaths, writeFilesTask } from "../../lib/index.js";
11
11
  import { prepareForRollback } from "../../lib/rollback.js";
12
12
  import {
@@ -31,14 +31,8 @@ const customOrDefaultTemplatePath = ({
31
31
  generator,
32
32
  templatePath
33
33
  );
34
- const deprecatedCustomPath = getPaths()[side].generators ? path.join(getPaths()[side].generators, generator, templatePath) : void 0;
35
34
  if (fs.existsSync(customPath)) {
36
35
  return customPath;
37
- } else if (deprecatedCustomPath && fs.existsSync(deprecatedCustomPath)) {
38
- console.log(
39
- `Having generator templates in ${getPaths()[side].generators} has been deprecated. Please move them to ${getPaths().generatorTemplates}.`
40
- );
41
- return deprecatedCustomPath;
42
36
  } else {
43
37
  return defaultPath;
44
38
  }
@@ -52,7 +46,11 @@ const templateForFile = async ({
52
46
  templatePath,
53
47
  templateVars
54
48
  }) => {
55
- const basePath = sidePathSection ? getPaths()[side][sidePathSection] : getPaths()[side];
49
+ const paths = getPaths();
50
+ const basePath = side === "scripts" ? paths.scripts : side === "web" ? sidePathSection ? paths.web[sidePathSection] : paths.web.base : side === "packages" ? paths.packages : sidePathSection ? paths.api[sidePathSection] : paths.api.base;
51
+ if (typeof basePath !== "string") {
52
+ throw new Error(`Invalid path section: "${sidePathSection}"`);
53
+ }
56
54
  const fullOutputPath = path.join(basePath, outputPath);
57
55
  const fullTemplatePath = customOrDefaultTemplatePath({
58
56
  generator,
@@ -127,6 +125,10 @@ function createHandler({
127
125
  validateName(argv.name);
128
126
  try {
129
127
  argv = await preTasksFn(argv);
128
+ const listrOptions = {
129
+ exitOnError: true,
130
+ ...argv.verbose ? { renderer: "verbose" } : { rendererOptions: { collapseSubtasks: false } }
131
+ };
130
132
  const tasks = new Listr(
131
133
  [
132
134
  {
@@ -138,28 +140,28 @@ function createHandler({
138
140
  },
139
141
  ...includeAdditionalTasks(argv)
140
142
  ],
141
- {
142
- rendererOptions: { collapseSubtasks: false },
143
- exitOnError: true,
144
- renderer: argv.verbose && "verbose"
145
- }
143
+ listrOptions
146
144
  );
147
145
  if (argv.rollback && !argv.force) {
148
146
  prepareForRollback(tasks);
149
147
  }
150
148
  await tasks.run();
151
149
  } catch (e) {
152
- errorTelemetry(process.argv, e.message);
153
- console.error(c.error(e.message));
154
- process.exit(e?.exitCode || 1);
150
+ const message = e instanceof Error ? e.message : String(e);
151
+ errorTelemetry(process.argv, message);
152
+ console.error(c.error(message));
153
+ process.exit(errorExitCode(e));
155
154
  }
156
155
  };
157
156
  }
157
+ function errorExitCode(e) {
158
+ return typeof e === "object" && e !== null && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
159
+ }
158
160
  const createYargsForComponentGeneration = ({
159
161
  componentName,
160
162
  preTasksFn = (options) => options,
161
163
  /** filesFn is not used if generator implements its own `handler` */
162
- filesFn = () => ({}),
164
+ filesFn = async () => ({}),
163
165
  optionsObj,
164
166
  positionalsObj = {},
165
167
  /** function that takes the options object and returns an array of listr tasks */
@@ -1,6 +1,6 @@
1
- import execa from "execa";
2
1
  import { terminalLink } from "termi-link";
3
- import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
2
+ import { runBinSync } from "@cedarjs/cli-helpers/packageManager/exec";
3
+ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
4
4
  import * as generateCell from "./generate/cell/cell.js";
5
5
  import * as generateComponent from "./generate/component/component.js";
6
6
  import * as generateDataMigration from "./generate/dataMigration/dataMigration.js";
@@ -25,9 +25,9 @@ const description = "Generate boilerplate code and type definitions";
25
25
  const builder = (yargs) => yargs.command("types", "Generate supplementary code", {}, () => {
26
26
  recordTelemetryAttributes({ command: "generate types" });
27
27
  try {
28
- execa.sync("yarn", ["rw-gen"], { stdio: "inherit" });
28
+ runBinSync("cedar-gen", [], { stdio: "inherit" });
29
29
  } catch (error) {
30
- process.exitCode = error.exitCode ?? 1;
30
+ process.exitCode = typeof error === "object" && error !== null && "exitCode" in error && typeof error.exitCode === "number" ? error.exitCode : 1;
31
31
  }
32
32
  }).command(generateCell).command(generateComponent).command(generateDataMigration).command(generateDbAuth).command(generateDirective).command(generateFunction).command(generateJob).command(generateLayout).command(generateModel).command(generateOgImage).command(generatePackage).command(generatePage).command(generateRealtime).command(generateScaffold).command(generateScript).command(generateSdl).command(generateSecret).command(generateService).demandCommand().epilogue(
33
33
  `Also see the ${terminalLink(
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import envinfo from "envinfo";
4
4
  import { terminalLink } from "termi-link";
5
- import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
5
+ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
6
6
  import { getConfigPath } from "@cedarjs/project-config";
7
7
  const command = "info";
8
8
  const description = "Print your system environment information";
@@ -28,7 +28,7 @@ const handler = async () => {
28
28
  const tomlContent = fs.readFileSync(configTomlPath, "utf8");
29
29
  console.log(
30
30
  output + ` ${path.basename(configTomlPath)}:
31
- ` + tomlContent.split("\n").filter((line) => line.trim().length > 0).filter((line) => !/^#/.test(line)).map((line) => ` ${line}`).join("\n")
31
+ ` + tomlContent.split("\n").filter((line) => line.trim().length > 0).filter((line) => !line.startsWith("#")).map((line) => ` ${line}`).join("\n")
32
32
  );
33
33
  };
34
34
  export {
@@ -1,4 +1,5 @@
1
1
  import execa from "execa";
2
+ import { formatRunBinCommand } from "@cedarjs/cli-helpers/packageManager/display";
2
3
  import { getPaths } from "../lib/index.js";
3
4
  const handler = async ({
4
5
  _,
@@ -6,16 +7,18 @@ const handler = async ({
6
7
  commands: _commands,
7
8
  ...options
8
9
  }) => {
9
- const args = [_.pop()];
10
+ const positionalArgs = Array.isArray(_) ? [..._] : [];
11
+ const commandArg = positionalArgs.pop();
12
+ const args = [commandArg == null ? "" : String(commandArg)];
10
13
  for (const [name, value] of Object.entries(options)) {
11
14
  args.push(name.length > 1 ? `--${name}` : `-${name}`);
12
- args.push(value);
15
+ args.push(String(value));
13
16
  }
14
- let command = `yarn rw-jobs ${args.join(" ")}`;
17
+ let command = formatRunBinCommand("cedar-jobs", args);
15
18
  const originalLogLevel = process.env.LOG_LEVEL;
16
19
  process.env.LOG_LEVEL = originalLogLevel || "warn";
17
20
  if (process.env.NODE_ENV !== "production") {
18
- command += " | yarn rw-log-formatter";
21
+ command += ` | ${formatRunBinCommand("cedar-log-formatter")}`;
19
22
  process.env.LOG_LEVEL = originalLogLevel || "debug";
20
23
  }
21
24
  execa.commandSync(command, {