@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
@@ -4,9 +4,15 @@ import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
4
4
  import execa from "execa";
5
5
  import { Listr } from "listr2";
6
6
  import { terminalLink } from "termi-link";
7
- import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
7
+ import { colors as c } from "@cedarjs/cli-helpers/colors";
8
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
9
+ import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
10
+ import {
11
+ addRootPackages,
12
+ addWorkspacePackages
13
+ } from "@cedarjs/cli-helpers/packageManager/packages";
14
+ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
8
15
  import { errorTelemetry } from "@cedarjs/telemetry";
9
- import c from "../../../../lib/colors.js";
10
16
  import { getPaths, usingVSCode } from "../../../../lib/index.js";
11
17
  const tailwindDirectives = [
12
18
  "@tailwind base;",
@@ -20,7 +26,7 @@ const tailwindImportsAndNotes = [
20
26
  "/**",
21
27
  " * START --- SETUP TAILWINDCSS EDIT",
22
28
  " *",
23
- " * `yarn cedar setup ui tailwindcss` placed these directives here",
29
+ ` * \`${formatCedarCommand(["setup", "ui", "tailwindcss"])}\` placed these directives here`,
24
30
  " * to inject Tailwind's styles into your CSS.",
25
31
  " * For more information, see: https://tailwindcss.com/docs/installation",
26
32
  " */",
@@ -69,17 +75,19 @@ async function recommendExtensionsToInstall() {
69
75
  });
70
76
  }
71
77
  }
72
- const handler = async ({ force, install }) => {
78
+ const handler = async ({
79
+ force,
80
+ install
81
+ }) => {
73
82
  recordTelemetryAttributes({
74
83
  command: "setup ui tailwindcss",
75
84
  force,
76
85
  install
77
86
  });
78
87
  const rwPaths = getPaths();
79
- const projectPackages = ["prettier-plugin-tailwindcss@^0.5.12"];
88
+ const projectPackages = ["prettier-plugin-tailwindcss@^0.8.0"];
80
89
  const webWorkspacePackages = [
81
90
  "postcss",
82
- "postcss-loader",
83
91
  "tailwindcss@^3.4.17",
84
92
  "autoprefixer"
85
93
  ];
@@ -94,8 +102,9 @@ const handler = async ({ force, install }) => {
94
102
  {
95
103
  title: `Install ${projectPackages.join(", ")}`,
96
104
  task: async () => {
97
- await execa("yarn", ["add", "-D", ...projectPackages], {
98
- cwd: rwPaths.base
105
+ await addRootPackages(projectPackages, {
106
+ cwd: rwPaths.base,
107
+ dev: true
99
108
  });
100
109
  }
101
110
  }
@@ -113,19 +122,16 @@ const handler = async ({ force, install }) => {
113
122
  {
114
123
  title: `Install ${webWorkspacePackages.join(", ")}`,
115
124
  task: async () => {
116
- await execa(
117
- "yarn",
118
- ["workspace", "web", "add", "-D", ...webWorkspacePackages],
119
- {
120
- cwd: rwPaths.base,
121
- env: {
122
- // For some reason yarn started installing deprecated
123
- // typescript types when installing tailwind. This
124
- // prevents it from happening.
125
- YARN_TS_ENABLE_AUTO_TYPES: "false"
126
- }
127
- }
128
- );
125
+ await addWorkspacePackages("web", webWorkspacePackages, {
126
+ cwd: rwPaths.base,
127
+ env: {
128
+ // For some reason yarn started installing deprecated
129
+ // typescript types when installing tailwind. This
130
+ // prevents it from happening. (yarn-only env var.)
131
+ YARN_TS_ENABLE_AUTO_TYPES: "false"
132
+ },
133
+ dev: true
134
+ });
129
135
  }
130
136
  }
131
137
  ],
@@ -170,7 +176,7 @@ const handler = async ({ force, install }) => {
170
176
  );
171
177
  }
172
178
  }
173
- await execa("yarn", ["tailwindcss", "init", tailwindConfigPath], {
179
+ await runBin("tailwindcss", ["init", tailwindConfigPath], {
174
180
  cwd: rwPaths.web.base
175
181
  });
176
182
  const tailwindConfig = fs.readFileSync(tailwindConfigPath, "utf-8");
@@ -235,7 +241,7 @@ const handler = async ({ force, install }) => {
235
241
  rwPaths.base,
236
242
  ".vscode/extensions.json"
237
243
  );
238
- let originalExtensionsJson = { recommendations: [] };
244
+ let originalExtensionsJson = {};
239
245
  if (fs.existsSync(VS_CODE_EXTENSIONS_PATH)) {
240
246
  const originalExtensionsFile = fs.readFileSync(
241
247
  VS_CODE_EXTENSIONS_PATH,
@@ -246,7 +252,7 @@ const handler = async ({ force, install }) => {
246
252
  const newExtensionsJson = {
247
253
  ...originalExtensionsJson,
248
254
  recommendations: [
249
- ...originalExtensionsJson.recommendations,
255
+ ...originalExtensionsJson.recommendations ?? [],
250
256
  ...recommendedVSCodeExtensions
251
257
  ]
252
258
  };
@@ -281,7 +287,10 @@ const handler = async ({ force, install }) => {
281
287
  const originalSettingsJson = JSON.parse(
282
288
  originalSettingsFile || "{}"
283
289
  );
284
- const originalTwClassAttributesJson = originalSettingsJson["tailwindCSS.classAttributes"] || [];
290
+ const existingAttributes = originalSettingsJson["tailwindCSS.classAttributes"];
291
+ const originalTwClassAttributesJson = Array.isArray(
292
+ existingAttributes
293
+ ) ? existingAttributes : [];
285
294
  const mergedClassAttributes = Array.from(
286
295
  /* @__PURE__ */ new Set([...classAttributes, ...originalTwClassAttributesJson])
287
296
  );
@@ -343,7 +352,7 @@ const handler = async ({ force, install }) => {
343
352
  const pluginsMatch = newPrettierConfig.match(
344
353
  /plugins: \[[\sa-z\(\)'\-,]*]/
345
354
  );
346
- const matched = pluginsMatch && pluginsMatch[0];
355
+ const matched = pluginsMatch != null ? pluginsMatch[0] : void 0;
347
356
  if (matched && (matched.includes("'prettier-plugin-tailwindcss'") || matched.includes('"prettier-plugin-tailwindcss"'))) {
348
357
  task.skip(
349
358
  "tailwindcss-plugin-prettier already required in plugins"
@@ -371,9 +380,11 @@ const handler = async ({ force, install }) => {
371
380
  await tasks.run();
372
381
  await recommendExtensionsToInstall();
373
382
  } catch (e) {
374
- errorTelemetry(process.argv, e.message);
375
- console.error(c.error(e.message));
376
- process.exit(e?.exitCode || 1);
383
+ const msg = e instanceof Error ? e.message : String(e);
384
+ const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
385
+ errorTelemetry(process.argv, msg);
386
+ console.error(c.error(msg));
387
+ process.exit(exitCode);
377
388
  }
378
389
  };
379
390
  export {
@@ -0,0 +1,41 @@
1
+ const UPLOAD_MODEL = `model Upload {
2
+ id String @id @default(cuid())
3
+ /// Name of the storage target, as configured in api/src/lib/uploads
4
+ target String
5
+ /// "pending" | "completed" | "failed"
6
+ status String @default("pending")
7
+ filename String
8
+ mimeType String
9
+ /// Bytes. BigInt because Int caps at 2 GB.
10
+ size BigInt
11
+ /// Provider-specific reference: S3 object key, filename on disk, or null
12
+ /// for files stored inline
13
+ storageKey String?
14
+ /// Inline bytes, only for DB targets
15
+ data Bytes?
16
+ /// The user the file belongs to, when it belongs to one
17
+ userId String?
18
+ /// Id of the upload token that created this row
19
+ tokenId String?
20
+ /// The organization the file belongs to, in multi-tenant apps
21
+ organizationId String?
22
+ createdAt DateTime @default(now())
23
+ updatedAt DateTime @updatedAt
24
+ }`;
25
+ function hasModel(schema, modelName) {
26
+ return new RegExp(`\\bmodel\\s+${modelName}\\s*\\{`).test(schema);
27
+ }
28
+ function addUploadModel(schema) {
29
+ if (hasModel(schema, "Upload")) {
30
+ return schema;
31
+ }
32
+ return `${schema.trimEnd()}
33
+
34
+ ${UPLOAD_MODEL}
35
+ `;
36
+ }
37
+ export {
38
+ UPLOAD_MODEL,
39
+ addUploadModel,
40
+ hasModel
41
+ };
@@ -0,0 +1,151 @@
1
+ const START_LINE = /^([ \t]*)await server\.start\(\)/m;
2
+ const FACTORY_IMPORT = /import\s*\{[^}]*\bcreateAuthDecoder\b[^}]*\}\s*from\s*['"](@cedarjs\/auth-[a-z0-9-]+-api)['"]/;
3
+ const DECODER_IMPORT = /import\s*\{[^}]*\bauthDecoder\b[^}]*\}\s*from\s*['"](@cedarjs\/auth-[a-z0-9-]+-api)['"]/;
4
+ function detectServerAuth(graphqlSource) {
5
+ const factory = FACTORY_IMPORT.exec(graphqlSource);
6
+ if (factory) {
7
+ return { decoderPackage: factory[1], usesFactory: true };
8
+ }
9
+ const decoder = DECODER_IMPORT.exec(graphqlSource);
10
+ if (decoder) {
11
+ return { decoderPackage: decoder[1], usesFactory: false };
12
+ }
13
+ return null;
14
+ }
15
+ function importedBindings(source) {
16
+ const names = /* @__PURE__ */ new Set();
17
+ const statements = source.matchAll(
18
+ /^import\s+(type\s+)?([^;]*?)\s+from\s+['"][^'"]+['"]/gm
19
+ );
20
+ for (const [, typeOnly, clause] of statements) {
21
+ if (typeOnly) {
22
+ continue;
23
+ }
24
+ const braces = /\{([^}]*)\}/.exec(clause);
25
+ const defaultOrNamespace = clause.replace(/\{[^}]*\}/, "");
26
+ for (const part of defaultOrNamespace.split(",")) {
27
+ const local = part.replace(/^\s*\*\s+as\s+/, "").trim();
28
+ if (local) {
29
+ names.add(local);
30
+ }
31
+ }
32
+ for (const specifier of braces?.[1].split(",") ?? []) {
33
+ const trimmed = specifier.trim();
34
+ if (!trimmed || trimmed.startsWith("type ")) {
35
+ continue;
36
+ }
37
+ const alias = / as (\w+)$/.exec(trimmed);
38
+ names.add(alias ? alias[1] : trimmed);
39
+ }
40
+ }
41
+ return names;
42
+ }
43
+ function hasBinding(source, name) {
44
+ const declared = new RegExp(
45
+ `^(?:export\\s+)?(?:const|let|var|function)\\s+${name}\\b`,
46
+ "m"
47
+ );
48
+ return importedBindings(source).has(name) || declared.test(source);
49
+ }
50
+ function uploadsServerImports(source, auth) {
51
+ const packageSpecs = [];
52
+ const srcSpecs = [];
53
+ if (auth) {
54
+ if (auth.usesFactory) {
55
+ if (!hasBinding(source, "authDecoder")) {
56
+ packageSpecs.push({
57
+ names: ["createAuthDecoder"],
58
+ from: auth.decoderPackage
59
+ });
60
+ }
61
+ } else {
62
+ packageSpecs.push({ names: ["authDecoder"], from: auth.decoderPackage });
63
+ }
64
+ }
65
+ packageSpecs.push({
66
+ names: auth ? ["cedarUploadsPlugin", "createUploadAuthenticator"] : ["cedarUploadsPlugin"],
67
+ from: "@cedarjs/uploads"
68
+ });
69
+ if (auth) {
70
+ const authNames = ["getCurrentUser"];
71
+ if (auth.usesFactory && !hasBinding(source, "authDecoder")) {
72
+ authNames.unshift("cookieName");
73
+ }
74
+ srcSpecs.push({ names: authNames, from: "src/lib/auth" });
75
+ }
76
+ srcSpecs.push({ names: ["db"], from: "src/lib/db" });
77
+ srcSpecs.push({ names: ["targets"], from: "src/lib/uploads" });
78
+ const render = (specs) => specs.map((spec) => ({
79
+ ...spec,
80
+ names: spec.names.filter((name) => !hasBinding(source, name))
81
+ })).filter((spec) => spec.names.length > 0).map((spec) => `import { ${spec.names.join(", ")} } from '${spec.from}'`);
82
+ const packageLines = render(packageSpecs);
83
+ const srcLines = render(srcSpecs);
84
+ if (packageLines.length > 0 && srcLines.length > 0) {
85
+ return [...packageLines, "", ...srcLines];
86
+ }
87
+ return [...packageLines, ...srcLines];
88
+ }
89
+ function uploadsServerRegistration(source, auth) {
90
+ if (!auth) {
91
+ return ` await server.register(cedarUploadsPlugin, {
92
+ tokenSecret: process.env.UPLOAD_TOKEN_SECRET,
93
+ targets,
94
+ db,
95
+ // Once the app has auth, bind upload tokens to the logged-in user:
96
+ //
97
+ // authenticate: createUploadAuthenticator({ authDecoder, getCurrentUser }),
98
+ })
99
+ `;
100
+ }
101
+ const decoder = auth.usesFactory && !hasBinding(source, "authDecoder") ? " const authDecoder = createAuthDecoder(cookieName)\n\n" : "";
102
+ return `${decoder} await server.register(cedarUploadsPlugin, {
103
+ tokenSecret: process.env.UPLOAD_TOKEN_SECRET,
104
+ targets,
105
+ db,
106
+ // Binds upload tokens to the logged-in user through the same auth
107
+ // pipeline the GraphQL server uses
108
+ authenticate: createUploadAuthenticator({ authDecoder, getCurrentUser }),
109
+ })
110
+ `;
111
+ }
112
+ function hasUploadsPlugin(source) {
113
+ return /^[ \t]*(?:(?:await|void)\s+|(?:const|let|var)\s+\w+\s*=\s*)?[\w.]+\.register\(\s*cedarUploadsPlugin\b/m.test(
114
+ source
115
+ );
116
+ }
117
+ function addUploadsPlugin(source, { auth = null } = {}) {
118
+ if (hasUploadsPlugin(source)) {
119
+ return source;
120
+ }
121
+ const start = START_LINE.exec(source);
122
+ if (!start) {
123
+ throw new Error("CEDAR_UPLOADS_ERR_NO_START");
124
+ }
125
+ const lines = source.split("\n");
126
+ let lastImport = -1;
127
+ for (const [index, line] of lines.entries()) {
128
+ if (/^import\s/.test(line)) {
129
+ lastImport = index;
130
+ }
131
+ }
132
+ const withImports = [
133
+ ...lines.slice(0, lastImport + 1),
134
+ ...uploadsServerImports(source, auth),
135
+ ...lines.slice(lastImport + 1)
136
+ ].join("\n");
137
+ return withImports.replace(
138
+ START_LINE,
139
+ (line) => `${uploadsServerRegistration(source, auth)}
140
+ ${line}`
141
+ );
142
+ }
143
+ export {
144
+ addUploadsPlugin,
145
+ detectServerAuth,
146
+ hasBinding,
147
+ hasUploadsPlugin,
148
+ importedBindings,
149
+ uploadsServerImports,
150
+ uploadsServerRegistration
151
+ };
@@ -0,0 +1,15 @@
1
+ import { createRequireUploadTokenDirective } from '@cedarjs/uploads'
2
+
3
+ /**
4
+ * Requires a valid upload token in the x-upload-token request header and
5
+ * makes its claims available to the resolver through
6
+ * `getUploadTokenPayload(context)`. The token must have been issued to the
7
+ * requesting user.
8
+ */
9
+ const requireUploadToken = createRequireUploadTokenDirective({
10
+ secret: process.env.UPLOAD_TOKEN_SECRET ?? '',
11
+ })
12
+
13
+ export const schema = requireUploadToken.schema
14
+
15
+ export default requireUploadToken
@@ -1,25 +1,24 @@
1
- import { createUploadsConfig, setupStorage } from '@cedarjs/storage'
2
- import { FileSystemStorage } from '@cedarjs/storage/FileSystemStorage'
3
- import { UrlSigner } from '@cedarjs/storage/UrlSigner'
1
+ __PATH_IMPORT____S3_IMPORTS__import {
2
+ __FS_IMPORT__
3
+ __DB_IMPORT__
4
+ __DB_MAX_IMPORT__
5
+ defineStorageTargets,
6
+ defineUploadProfiles,
7
+ } from '@cedarjs/uploads'
8
+ __GET_PATHS_IMPORT__
9
+ __S3_CLIENT__
10
+ /**
11
+ * Where files live. Each target is a provider instance; the Upload row
12
+ * records which target holds a file so it can be read, served, and deleted
13
+ * later. Look one up by name with `resolveTarget(targets, upload.target)`.
14
+ */
15
+ export const targets = defineStorageTargets({
16
+ __TARGETS__})
4
17
 
5
- const uploadsConfig = createUploadsConfig({
6
- // Configure your fields here
7
- // e.g. modelName: { fields: ['fieldWithUpload']}
8
- })
9
-
10
- export const fsStorage = new FileSystemStorage({
11
- baseDir: './uploads',
12
- })
13
-
14
- export const urlSigner = new UrlSigner({
15
- secret: process.env.UPLOADS_SECRET,
16
- endpoint: '/signedUrl',
17
- })
18
-
19
- const { saveFiles, storagePrismaExtension } = setupStorage({
20
- uploadsConfig,
21
- storageAdapter: fsStorage,
22
- urlSigner,
23
- })
24
-
25
- export { saveFiles, storagePrismaExtension }
18
+ /**
19
+ * What clients may upload. A profile names a target and the constraints the
20
+ * server signs into every upload token issued for it. The client never
21
+ * supplies constraints; it names a profile.
22
+ */
23
+ export const profiles = defineUploadProfiles({
24
+ __PROFILES__})
@@ -0,0 +1,79 @@
1
+ export const schema = gql`
2
+ type Upload {
3
+ id: String!
4
+ target: String!
5
+ status: String!
6
+ filename: String!
7
+ mimeType: String!
8
+ size: BigInt!
9
+ storageKey: String
10
+ userId: String
11
+ organizationId: String
12
+ createdAt: DateTime!
13
+ updatedAt: DateTime!
14
+ }
15
+
16
+ type UploadToken {
17
+ token: String!
18
+ """
19
+ The profile's constraints, echoed for client-side UX (file-picker
20
+ filters, pre-upload validation). The authoritative copy is inside the
21
+ signed token.
22
+ """
23
+ allowedMimeTypes: [String!]!
24
+ maxFileSize: BigInt!
25
+ maxFiles: Int!
26
+ }
27
+
28
+ type PresignedUploadUrl {
29
+ uploadId: String!
30
+ url: String!
31
+ method: String!
32
+ headers: JSON!
33
+ }
34
+
35
+ input CreatePresignedUploadUrlInput {
36
+ filename: String!
37
+ contentType: String!
38
+ size: BigInt!
39
+ }
40
+
41
+ input UploadFileInput {
42
+ filename: String!
43
+ mimeType: String!
44
+ """
45
+ The file's bytes, base64-encoded. Only for profiles whose target stores
46
+ files inline in the database.
47
+ """
48
+ data: String!
49
+ }
50
+
51
+ type Query {
52
+ """
53
+ Issues an upload token for a server-defined profile. The profile name
54
+ must match a key of \`profiles\` in api/src/lib/uploads.
55
+ """
56
+ requestUploadToken(profile: String!): UploadToken! @requireAuth
57
+ }
58
+
59
+ type Mutation {
60
+ """
61
+ Direct-to-storage uploads: returns a presigned URL for one file. Send the
62
+ upload token in the x-upload-token header.
63
+ """
64
+ createPresignedUploadUrl(
65
+ input: CreatePresignedUploadUrlInput!
66
+ ): PresignedUploadUrl! @requireAuth @requireUploadToken
67
+
68
+ """
69
+ Confirms a direct-to-storage upload once the client has PUT the bytes.
70
+ """
71
+ confirmUpload(uploadId: String!): Upload! @requireAuth
72
+
73
+ """
74
+ Stores a small file sent as base64, for profiles whose target keeps files
75
+ inline in the database.
76
+ """
77
+ uploadFile(profile: String!, input: UploadFileInput!): Upload! @requireAuth
78
+ }
79
+ `
@@ -0,0 +1,89 @@
1
+ import {
2
+ confirmUpload as confirmUploadRecord,
3
+ createPresignedUpload,
4
+ getUploadTokenPayload,
5
+ isMimeTypeAllowed,
6
+ issueUploadToken,
7
+ resolveProfile,
8
+ resolveTarget,
9
+ storeFile,
10
+ UploadError,
11
+ } from '@cedarjs/uploads'
12
+
13
+ import { db } from 'src/lib/db'
14
+ import { profiles, targets } from 'src/lib/uploads'
15
+
16
+ const secret = () => {
17
+ if (!process.env.UPLOAD_TOKEN_SECRET) {
18
+ throw new Error(
19
+ 'UPLOAD_TOKEN_SECRET is not set. Generate one with `yarn cedar generate secret` and add it to .env.',
20
+ )
21
+ }
22
+
23
+ return process.env.UPLOAD_TOKEN_SECRET
24
+ }
25
+
26
+ export const requestUploadToken = ({ profile }: { profile: string }) => {
27
+ return issueUploadToken({
28
+ profiles,
29
+ profile,
30
+ secret: secret(),
31
+ currentUser: context.currentUser,
32
+ })
33
+ }
34
+
35
+ export const createPresignedUploadUrl = ({
36
+ input,
37
+ }: {
38
+ input: { filename: string; contentType: string; size: bigint | number }
39
+ }) => {
40
+ return createPresignedUpload({
41
+ db,
42
+ targets,
43
+ tokenPayload: getUploadTokenPayload(context),
44
+ input,
45
+ })
46
+ }
47
+
48
+ export const confirmUpload = ({ uploadId }: { uploadId: string }) => {
49
+ return confirmUploadRecord({
50
+ db,
51
+ targets,
52
+ uploadId,
53
+ currentUser: context.currentUser,
54
+ })
55
+ }
56
+
57
+ export const uploadFile = async ({
58
+ profile: profileName,
59
+ input,
60
+ }: {
61
+ profile: string
62
+ input: { filename: string; mimeType: string; data: string }
63
+ }) => {
64
+ const profile = resolveProfile(profiles, profileName)
65
+ const target = resolveTarget(targets, profile.target)
66
+
67
+ if (target.providerType !== 'db') {
68
+ throw new UploadError(
69
+ 'NOT_SUPPORTED',
70
+ `Upload profile '${profile.name}' does not store files in the database. Use an upload token instead.`,
71
+ )
72
+ }
73
+
74
+ if (!isMimeTypeAllowed(profile.allowedMimeTypes, input.mimeType)) {
75
+ throw new UploadError(
76
+ 'MIME_TYPE_NOT_ALLOWED',
77
+ `File type '${input.mimeType}' is not allowed for upload profile '${profile.name}'.`,
78
+ )
79
+ }
80
+
81
+ return storeFile(target, {
82
+ db,
83
+ filename: input.filename,
84
+ mimeType: input.mimeType,
85
+ data: Buffer.from(input.data, 'base64'),
86
+ maxSize: profile.maxFileSize,
87
+ userId: context.currentUser ? String(context.currentUser.id) : undefined,
88
+ })
89
+ }
@@ -0,0 +1,14 @@
1
+ import { createWithDataUriDirective } from '@cedarjs/uploads'
2
+
3
+ import { db } from 'src/lib/db'
4
+ import { targets } from 'src/lib/uploads'
5
+
6
+ /**
7
+ * Resolves a field holding an Upload id to a base64 data: URI of the file.
8
+ * Every resolved field embeds the whole file, so use it for small files only.
9
+ */
10
+ const withDataUri = createWithDataUriDirective({ db, targets })
11
+
12
+ export const schema = withDataUri.schema
13
+
14
+ export default withDataUri
@@ -0,0 +1,16 @@
1
+ import { createWithSignedUrlDirective } from '@cedarjs/uploads'
2
+
3
+ import { db } from 'src/lib/db'
4
+ import { targets } from 'src/lib/uploads'
5
+
6
+ /**
7
+ * Resolves a field holding an Upload id to a time-limited URL for the file,
8
+ * from whichever storage target holds it. Files download by default; pass
9
+ * `disposition: 'inline'` to render them in the browser instead, and only
10
+ * for MIME types you trust.
11
+ */
12
+ const withSignedUrl = createWithSignedUrlDirective({ db, targets })
13
+
14
+ export const schema = withSignedUrl.schema
15
+
16
+ export default withSignedUrl