@cedarjs/cli 7.1.0 → 7.1.1-next.468
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/build/buildHandler.js +2 -1
- package/dist/commands/build.js +1 -1
- package/dist/commands/check.js +2 -1
- package/dist/commands/deploy/baremetal/baremetalHandler.js +364 -73
- package/dist/commands/deploy/baremetal/monitors.js +66 -0
- package/dist/commands/deploy/baremetal.js +7 -1
- package/dist/commands/deploy/flightcontrolHandler.js +1 -1
- package/dist/commands/deploy/helpers/deployHandler.js +1 -1
- package/dist/commands/deploy/netlify.js +1 -1
- package/dist/commands/deploy/renderHandler.js +1 -1
- package/dist/commands/deploy/serverlessHandler.js +2 -1
- package/dist/commands/deploy/vercel.js +1 -1
- package/dist/commands/destroy/handlerHelpers.js +1 -1
- package/dist/commands/destroy/page/pageHandler.js +2 -1
- package/dist/commands/destroy/scaffold/scaffoldHandler.js +65 -26
- package/dist/commands/destroy/sdl/sdlHandler.js +2 -1
- package/dist/commands/dev/devHandler.js +3 -4
- package/dist/commands/dev/packageWatchCommands.js +8 -3
- package/dist/commands/dev.js +1 -1
- package/dist/commands/execHandler.js +2 -1
- package/dist/commands/experimental/live-queries/liveQueries.js +1 -1
- package/dist/commands/experimental/live-queries/liveQueriesHandler.js +3 -3
- package/dist/commands/experimental/setupInngest.js +1 -1
- package/dist/commands/experimental/setupInngestHandler.js +1 -1
- package/dist/commands/experimental/setupOpentelemetry.js +1 -1
- package/dist/commands/experimental/setupOpentelemetryHandler.js +2 -1
- package/dist/commands/experimental/setupReactCompiler.js +1 -1
- package/dist/commands/experimental/setupReactCompilerHandler.js +4 -4
- package/dist/commands/experimental/setupRsc.js +1 -1
- package/dist/commands/experimental/setupRscHandler.js +2 -1
- package/dist/commands/experimental/setupStreamingSsr.js +1 -1
- package/dist/commands/experimental/setupStreamingSsrHandler.js +3 -2
- package/dist/commands/generate/cell/cell.js +20 -0
- package/dist/commands/generate/cell/cellHandler.js +68 -20
- package/dist/commands/generate/cell/templates/cell.tsx.template +21 -2
- package/dist/commands/generate/cell/templates/cellFragment.tsx.template +43 -0
- package/dist/commands/generate/cell/templates/cellList.tsx.template +21 -2
- package/dist/commands/generate/cell/templates/storiesFragment.tsx.template +23 -0
- package/dist/commands/generate/cell/templates/test.js.template +1 -1
- package/dist/commands/generate/cell/templates/testFragment.js.template +30 -0
- package/dist/commands/generate/dataMigration/dataMigration.js +2 -1
- package/dist/commands/generate/dbAuth/dbAuth.js +6 -2
- package/dist/commands/generate/dbAuth/dbAuthHandler.js +80 -17
- package/dist/commands/generate/dbAuth/templates/changePassword.tsx.template +131 -0
- package/dist/commands/generate/dbAuth/templates/login.oauth.tsx.template +164 -0
- package/dist/commands/generate/dbAuth/templates/login.webAuthn.tsx.template +20 -12
- package/dist/commands/generate/dbAuth/templates/signup.oauth.tsx.template +147 -0
- package/dist/commands/generate/directive/directiveHandler.js +2 -1
- package/dist/commands/generate/function/functionHandler.js +2 -1
- package/dist/commands/generate/helpers.js +26 -0
- package/dist/commands/generate/job/jobHandler.js +2 -1
- package/dist/commands/generate/model/modelHandler.js +2 -1
- package/dist/commands/generate/ogImage/ogImageHandler.js +2 -1
- package/dist/commands/generate/ogImage/templates/ogImage.og.tsx.template +1 -1
- package/dist/commands/generate/package/filesTask.js +9 -12
- package/dist/commands/generate/package/packageHandler.js +3 -4
- package/dist/commands/generate/package/templates/tsconfig.json.template +1 -0
- package/dist/commands/generate/page/pageHandler.js +2 -1
- package/dist/commands/generate/realtime/realtime.js +1 -1
- package/dist/commands/generate/realtime/realtimeHandler.js +2 -9
- package/dist/commands/generate/realtime/templates/liveQueries/blank/blank.service.ts.template +12 -4
- package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.service.ts.template +2 -2
- package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.ts.template +4 -4
- package/dist/commands/generate/scaffold/scaffold.js +1 -1
- package/dist/commands/generate/scaffold/scaffoldHandler.js +93 -49
- package/dist/commands/generate/scaffold/templates/assets/scaffold.tailwind.css.template +12 -7
- package/dist/commands/generate/scaffold/templates/components/EditNameCell.tsx.template +5 -7
- package/dist/commands/generate/scaffold/templates/components/NameForm.tsx.template +10 -9
- package/dist/commands/generate/scaffold/templates/layouts/NamesScaffoldLayout.tsx.template +18 -0
- package/dist/commands/generate/scaffold/templates/lib/formatters.test.tsx.template +11 -0
- package/dist/commands/generate/scaffold/templates/lib/formatters.tsx.template +16 -4
- package/dist/commands/generate/script/scriptHandler.js +2 -1
- package/dist/commands/generate/script/templates/tsconfig.json.template +1 -0
- package/dist/commands/generate/sdl/sdlHandler.js +10 -4
- package/dist/commands/generate/secret/secret.js +1 -1
- package/dist/commands/generate/service/serviceHandler.js +79 -49
- package/dist/commands/generate/service/templates/service.ts.template +40 -13
- package/dist/commands/generate/service/templates/test.ts.template +8 -6
- package/dist/commands/generate/yargsCommandHelpers.js +1 -1
- package/dist/commands/generate/yargsHandlerHelpers.js +2 -1
- package/dist/commands/generate.js +1 -1
- package/dist/commands/info.js +1 -1
- package/dist/commands/jobsHandler.js +5 -3
- package/dist/commands/lint.js +1 -1
- package/dist/commands/prerenderHandler.js +11 -4
- package/dist/commands/prismaHandler.js +7 -2
- package/dist/commands/record/init.js +1 -1
- package/dist/commands/serve.js +2 -1
- package/dist/commands/setup/auth/auth.js +2 -4
- package/dist/commands/setup/cache/cache.js +1 -1
- package/dist/commands/setup/cache/cacheHandler.js +2 -1
- package/dist/commands/setup/cache/templates/memcached.ts.template +14 -17
- package/dist/commands/setup/cache/templates/redis.ts.template +12 -20
- package/dist/commands/setup/database/postgres.js +1 -1
- package/dist/commands/setup/database/postgresHandler.js +3 -1
- package/dist/commands/setup/deploy/providers/baremetal.js +7 -0
- package/dist/commands/setup/deploy/providers/baremetalHandler.js +130 -21
- package/dist/commands/setup/deploy/providers/coherence.js +1 -1
- package/dist/commands/setup/deploy/providers/coherenceHandler.js +7 -6
- package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +2 -1
- package/dist/commands/setup/deploy/providers/netlifyHandler.js +2 -1
- package/dist/commands/setup/deploy/providers/renderHandler.js +2 -1
- package/dist/commands/setup/deploy/providers/serverlessHandler.js +2 -1
- package/dist/commands/setup/deploy/providers/universalDeployHandler.js +4 -6
- package/dist/commands/setup/deploy/providers/vercelHandler.js +2 -1
- package/dist/commands/setup/deploy/templates/baremetal.js +119 -9
- package/dist/commands/setup/deploy/templates/netlifyUD.js +3 -0
- package/dist/commands/setup/docker/docker.js +1 -1
- package/dist/commands/setup/docker/dockerHandler.js +2 -1
- package/dist/commands/setup/generator/generator.js +1 -1
- package/dist/commands/setup/generator/generatorHandler.js +1 -1
- package/dist/commands/setup/graphql/features/fragments/fragments.js +1 -1
- package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +3 -5
- package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocuments.js +1 -1
- package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +2 -1
- package/dist/commands/setup/i18n/i18n.js +1 -1
- package/dist/commands/setup/i18n/i18nHandler.js +1 -1
- package/dist/commands/setup/jobs/jobs.js +1 -1
- package/dist/commands/setup/jobs/jobsHandler.js +4 -1
- package/dist/commands/setup/mailer/mailer.js +1 -1
- package/dist/commands/setup/mailer/mailerHandler.js +2 -1
- package/dist/commands/setup/middleware/ogImage/ogImage.js +1 -1
- package/dist/commands/setup/middleware/ogImage/ogImageHandler.js +2 -1
- package/dist/commands/setup/monitoring/sentry/sentry.js +1 -1
- package/dist/commands/setup/monitoring/sentry/sentryHandler.js +13 -9
- package/dist/commands/setup/monitoring/sentry/templates/sentryApi.ts.template +1 -4
- package/dist/commands/setup/monitoring/sentry/templates/sentryWeb.ts.template +7 -4
- package/dist/commands/setup/neon/neon.js +1 -1
- package/dist/commands/setup/neon/neonHandler.js +5 -9
- package/dist/commands/setup/package/package.js +1 -1
- package/dist/commands/setup/package/packageHandler.js +4 -4
- package/dist/commands/setup/realtime/addRealtimeToGraphql.js +1 -1
- package/dist/commands/setup/realtime/realtime.js +1 -1
- package/dist/commands/setup/realtime/realtimeHandler.js +4 -16
- package/dist/commands/setup/realtime/templates/defer/fastAndSlowFields/fastAndSlowFields.ts.template +4 -1
- package/dist/commands/setup/realtime/templates/liveQueries/auctions/auctions.ts.template +12 -4
- package/dist/commands/setup/realtime/templates/subscriptions/countdown/countdown.ts.template +1 -1
- package/dist/commands/setup/realtime/templates/subscriptions/newMessage/newMessage.ts.template +2 -2
- package/dist/commands/setup/server-file/serverFile.js +1 -1
- package/dist/commands/setup/server-file/serverFileHandler.js +2 -1
- package/dist/commands/setup/tenancy/authCodemod.js +66 -0
- package/dist/commands/setup/tenancy/dbCodemod.js +64 -0
- package/dist/commands/setup/tenancy/graphqlCodemod.js +88 -0
- package/dist/commands/setup/tenancy/preflight.js +49 -0
- package/dist/commands/setup/tenancy/schemaPrisma.js +81 -0
- package/dist/commands/setup/tenancy/signupCodemod.js +154 -0
- package/dist/commands/setup/tenancy/templates/InvitePage.tsx.template +72 -0
- package/dist/commands/setup/tenancy/templates/OrgScope.tsx.template +40 -0
- package/dist/commands/setup/tenancy/templates/ensureDefaultOrganizations.dataMigration.ts.template +39 -0
- package/dist/commands/setup/tenancy/templates/organizations.scenarios.ts.template +57 -0
- package/dist/commands/setup/tenancy/templates/organizations.sdl.ts.template +89 -0
- package/dist/commands/setup/tenancy/templates/organizations.test.ts.template +381 -0
- package/dist/commands/setup/tenancy/templates/organizations.ts.template +394 -0
- package/dist/commands/setup/tenancy/templates/requireMembership.test.ts.template +35 -0
- package/dist/commands/setup/tenancy/templates/requireMembership.ts.template +25 -0
- package/dist/commands/setup/tenancy/tenancy.js +30 -0
- package/dist/commands/setup/tenancy/tenancyHandler.js +425 -0
- package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +2 -1
- package/dist/commands/setup/ui/libraries/mantineHandler.js +2 -1
- package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +63 -82
- package/dist/commands/setup/uploads/gitignore.js +17 -0
- package/dist/commands/setup/uploads/schemaPrisma.js +41 -0
- package/dist/commands/setup/uploads/serverFile.js +217 -0
- package/dist/commands/setup/uploads/templates/requireUploadToken.ts.template +15 -0
- package/dist/commands/setup/uploads/templates/srcLibUploads.ts.template +23 -24
- package/dist/commands/setup/uploads/templates/uploads.sdl.ts.template +79 -0
- package/dist/commands/setup/uploads/templates/uploads.ts.template +98 -0
- package/dist/commands/setup/uploads/templates/withDataUri.ts.template +14 -0
- package/dist/commands/setup/uploads/templates/withSignedUrl.ts.template +16 -0
- package/dist/commands/setup/uploads/uploads.js +49 -7
- package/dist/commands/setup/uploads/uploadsHandler.js +277 -69
- package/dist/commands/setup.js +2 -1
- package/dist/commands/studio.js +1 -1
- package/dist/commands/test/testHandler.js +25 -71
- package/dist/commands/test/viteVersionCheck.js +75 -0
- package/dist/commands/test.js +10 -18
- package/dist/commands/type-checkHandler.js +1 -1
- package/dist/commands/upgrade/preUpgradeScripts.js +3 -3
- package/dist/commands/upgrade/upgrade.js +1 -1
- package/dist/commands/upgrade/upgradeHandler.js +2 -1
- package/dist/index.js +5 -8
- package/dist/lib/exit.js +1 -1
- package/dist/lib/index.js +16 -31
- package/dist/lib/loadEnvFiles.js +1 -1
- package/dist/lib/plugin.js +1 -1
- package/dist/lib/test.js +1 -1
- package/dist/lib/updateCheck.js +4 -4
- package/dist/middleware/checkNodeVersion.js +4 -4
- package/package.json +27 -27
- package/dist/commands/setup/ui/templates/postcss.config.cjs.template +0 -9
- package/dist/commands/setup/uploads/dbCodemod.js +0 -28
- package/dist/commands/setup/uploads/templates/signedUrl.ts.template +0 -21
- package/dist/commands/test/testHandlerEsm.js +0 -109
- package/dist/commands/testEsm.js +0 -41
|
@@ -4,45 +4,33 @@ 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 {
|
|
7
|
+
import { colors as c } from "@cedarjs/cli-helpers/colors";
|
|
8
8
|
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
9
|
-
import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
10
9
|
import {
|
|
11
10
|
addRootPackages,
|
|
12
11
|
addWorkspacePackages
|
|
13
12
|
} from "@cedarjs/cli-helpers/packageManager/packages";
|
|
13
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
14
14
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
15
15
|
import { getPaths, usingVSCode } from "../../../../lib/index.js";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
];
|
|
21
|
-
const tailwindDirectivesExist = (indexCSS) => tailwindDirectives.every(
|
|
22
|
-
(tailwindDirective) => indexCSS.includes(tailwindDirective)
|
|
23
|
-
);
|
|
24
|
-
const tailwindImportsAndNotes = [
|
|
16
|
+
import { insertPluginsBeforeCedar } from "../../deploy/helpers/index.js";
|
|
17
|
+
const tailwindImport = "@import 'tailwindcss';";
|
|
18
|
+
const tailwindImportRegExp = /@import\s+['"]tailwindcss['"]/;
|
|
19
|
+
const tailwindImportAndNotes = [
|
|
25
20
|
"/**",
|
|
26
21
|
" * START --- SETUP TAILWINDCSS EDIT",
|
|
27
22
|
" *",
|
|
28
|
-
` * \`${formatCedarCommand(["setup", "ui", "tailwindcss"])}\` placed
|
|
23
|
+
` * \`${formatCedarCommand(["setup", "ui", "tailwindcss"])}\` placed this import here`,
|
|
29
24
|
" * to inject Tailwind's styles into your CSS.",
|
|
30
25
|
" * For more information, see: https://tailwindcss.com/docs/installation",
|
|
31
26
|
" */",
|
|
32
|
-
|
|
27
|
+
tailwindImport,
|
|
33
28
|
"/**",
|
|
34
29
|
" * END --- SETUP TAILWINDCSS EDIT",
|
|
35
30
|
" */\n"
|
|
36
31
|
];
|
|
37
|
-
const recommendedVSCodeExtensions = [
|
|
38
|
-
"csstools.postcss",
|
|
39
|
-
"bradlc.vscode-tailwindcss"
|
|
40
|
-
];
|
|
32
|
+
const recommendedVSCodeExtensions = ["bradlc.vscode-tailwindcss"];
|
|
41
33
|
const recommendationTexts = {
|
|
42
|
-
"csstools.postcss": terminalLink(
|
|
43
|
-
"PostCSS Language Support",
|
|
44
|
-
"https://marketplace.visualstudio.com/items?itemName=csstools.postcss"
|
|
45
|
-
),
|
|
46
34
|
"bradlc.vscode-tailwindcss": terminalLink(
|
|
47
35
|
"Tailwind CSS IntelliSense",
|
|
48
36
|
"https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss"
|
|
@@ -86,9 +74,8 @@ const handler = async ({
|
|
|
86
74
|
const rwPaths = getPaths();
|
|
87
75
|
const projectPackages = ["prettier-plugin-tailwindcss@^0.8.0"];
|
|
88
76
|
const webWorkspacePackages = [
|
|
89
|
-
"
|
|
90
|
-
"tailwindcss@^3.
|
|
91
|
-
"autoprefixer"
|
|
77
|
+
"tailwindcss@^4.3.3",
|
|
78
|
+
"@tailwindcss/vite@^4.3.3"
|
|
92
79
|
];
|
|
93
80
|
const tasks = new Listr(
|
|
94
81
|
[
|
|
@@ -139,62 +126,45 @@ const handler = async ({
|
|
|
139
126
|
}
|
|
140
127
|
},
|
|
141
128
|
{
|
|
142
|
-
title: "
|
|
143
|
-
task: () => {
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
129
|
+
title: "Adding the Tailwind CSS plugin to the Vite config...",
|
|
130
|
+
task: (_ctx, task) => {
|
|
131
|
+
const viteConfigPath = rwPaths.web.viteConfig;
|
|
132
|
+
if (!viteConfigPath || !fs.existsSync(viteConfigPath)) {
|
|
133
|
+
throw new Error("Could not find web/vite.config.{ts,js}");
|
|
134
|
+
}
|
|
135
|
+
const viteConfig = fs.readFileSync(viteConfigPath, "utf-8");
|
|
136
|
+
if (viteConfig.includes("@tailwindcss/vite")) {
|
|
137
|
+
task.skip("The Tailwind CSS Vite plugin is already configured");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const viteConfigWithPlugin = insertPluginsBeforeCedar({
|
|
141
|
+
content: viteConfig,
|
|
142
|
+
pluginCodes: ["tailwindcss()"]
|
|
143
|
+
});
|
|
144
|
+
if (!viteConfigWithPlugin) {
|
|
146
145
|
throw new Error(
|
|
147
|
-
|
|
146
|
+
`Could not find \`cedar()\` in the plugins array in ${viteConfigPath}.
|
|
147
|
+
Add \`import tailwindcss from '@tailwindcss/vite'\` to the top of the file and \`tailwindcss()\` to the plugins array yourself, and then run this command again.`
|
|
148
148
|
);
|
|
149
|
-
} else {
|
|
150
|
-
const postCSSConfig = fs.readFileSync(
|
|
151
|
-
path.join(
|
|
152
|
-
import.meta.dirname,
|
|
153
|
-
"../templates/postcss.config.cjs.template"
|
|
154
|
-
),
|
|
155
|
-
"utf-8"
|
|
156
|
-
);
|
|
157
|
-
fs.mkdirSync(path.dirname(postCSSConfigPath), { recursive: true });
|
|
158
|
-
return fs.writeFileSync(postCSSConfigPath, postCSSConfig);
|
|
159
149
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
rwPaths.web.config,
|
|
167
|
-
"tailwind.config.cjs"
|
|
150
|
+
const tailwindPluginImport = "import tailwindcss from '@tailwindcss/vite'\n";
|
|
151
|
+
const importAnchor = /^import .* from ['"]vite['"]/m.exec(viteConfigWithPlugin) ?? /^import /m.exec(viteConfigWithPlugin);
|
|
152
|
+
const insertAt = importAnchor?.index ?? 0;
|
|
153
|
+
fs.writeFileSync(
|
|
154
|
+
viteConfigPath,
|
|
155
|
+
viteConfigWithPlugin.slice(0, insertAt) + tailwindPluginImport + viteConfigWithPlugin.slice(insertAt)
|
|
168
156
|
);
|
|
169
|
-
if (fs.existsSync(tailwindConfigPath)) {
|
|
170
|
-
if (force) {
|
|
171
|
-
fs.unlinkSync(tailwindConfigPath);
|
|
172
|
-
} else {
|
|
173
|
-
throw new Error(
|
|
174
|
-
"Tailwind CSS config already exists.\nUse --force to override existing config."
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
await runBin("tailwindcss", ["init", tailwindConfigPath], {
|
|
179
|
-
cwd: rwPaths.web.base
|
|
180
|
-
});
|
|
181
|
-
const tailwindConfig = fs.readFileSync(tailwindConfigPath, "utf-8");
|
|
182
|
-
const newTailwindConfig = 'const { join } = require("node:path");\n\n' + tailwindConfig.replace(
|
|
183
|
-
"content: []",
|
|
184
|
-
"content: [join(__dirname, '../src/**/*.{js,jsx,ts,tsx}')]"
|
|
185
|
-
).replace("export default {", "module.exports = {");
|
|
186
|
-
fs.writeFileSync(tailwindConfigPath, newTailwindConfig);
|
|
187
157
|
}
|
|
188
158
|
},
|
|
189
159
|
{
|
|
190
|
-
title: "Adding
|
|
160
|
+
title: "Adding Tailwind CSS import to index.css...",
|
|
191
161
|
task: (_ctx, task) => {
|
|
192
162
|
const INDEX_CSS_PATH = path.join(rwPaths.web.src, "index.css");
|
|
193
163
|
const indexCSS = fs.readFileSync(INDEX_CSS_PATH, "utf-8");
|
|
194
|
-
if (
|
|
195
|
-
task.skip("
|
|
164
|
+
if (tailwindImportRegExp.test(indexCSS)) {
|
|
165
|
+
task.skip("Tailwind CSS import already exists in index.css");
|
|
196
166
|
} else {
|
|
197
|
-
const newIndexCSS =
|
|
167
|
+
const newIndexCSS = tailwindImportAndNotes.join("\n") + indexCSS;
|
|
198
168
|
fs.writeFileSync(INDEX_CSS_PATH, newIndexCSS);
|
|
199
169
|
}
|
|
200
170
|
}
|
|
@@ -275,7 +245,9 @@ const handler = async ({
|
|
|
275
245
|
"activeClassName",
|
|
276
246
|
"errorClassName"
|
|
277
247
|
];
|
|
248
|
+
const fileAssociations = { "*.css": "tailwindcss" };
|
|
278
249
|
let newSettingsJson = {
|
|
250
|
+
["files.associations"]: fileAssociations,
|
|
279
251
|
["tailwindCSS.classAttributes"]: classAttributes
|
|
280
252
|
};
|
|
281
253
|
if (fs.existsSync(VS_CODE_SETTINGS_PATH)) {
|
|
@@ -293,8 +265,13 @@ const handler = async ({
|
|
|
293
265
|
const mergedClassAttributes = Array.from(
|
|
294
266
|
/* @__PURE__ */ new Set([...classAttributes, ...originalTwClassAttributesJson])
|
|
295
267
|
);
|
|
268
|
+
const existingAssociations = originalSettingsJson["files.associations"];
|
|
296
269
|
newSettingsJson = {
|
|
297
270
|
...originalSettingsJson,
|
|
271
|
+
["files.associations"]: {
|
|
272
|
+
...existingAssociations && typeof existingAssociations === "object" && !Array.isArray(existingAssociations) ? existingAssociations : {},
|
|
273
|
+
...fileAssociations
|
|
274
|
+
},
|
|
298
275
|
["tailwindCSS.classAttributes"]: mergedClassAttributes
|
|
299
276
|
};
|
|
300
277
|
}
|
|
@@ -305,34 +282,38 @@ const handler = async ({
|
|
|
305
282
|
}
|
|
306
283
|
},
|
|
307
284
|
{
|
|
308
|
-
title: "Adding tailwind
|
|
285
|
+
title: "Adding tailwind stylesheet entry in prettier...",
|
|
309
286
|
task: async (_ctx) => {
|
|
310
287
|
const prettierConfigPath = path.join(
|
|
311
288
|
rwPaths.base,
|
|
312
289
|
"prettier.config.cjs"
|
|
313
290
|
);
|
|
314
291
|
const prettierConfig = fs.readFileSync(prettierConfigPath, "utf-8");
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
path.posix.join(rwPaths.web.config, "tailwind.config.cjs")
|
|
318
|
-
).replaceAll("\\", "/");
|
|
292
|
+
const tailwindStylesheetPath = path.relative(rwPaths.base, path.join(rwPaths.web.src, "index.css")).replaceAll("\\", "/");
|
|
293
|
+
const tailwindStylesheetEntry = `tailwindStylesheet: './${tailwindStylesheetPath}',`;
|
|
319
294
|
let newPrettierConfig = prettierConfig;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
295
|
+
const stringEntryRegExp = /tailwindStylesheet:\s*(['"`])[^'"`\n]*\1,?/;
|
|
296
|
+
if (newPrettierConfig.includes("tailwindStylesheet")) {
|
|
297
|
+
if (!force) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
"tailwindStylesheet setting already exists in prettier configuration.\nUse --force to override existing config."
|
|
325
300
|
);
|
|
326
|
-
}
|
|
301
|
+
}
|
|
302
|
+
if (!stringEntryRegExp.test(newPrettierConfig)) {
|
|
327
303
|
throw new Error(
|
|
328
|
-
|
|
304
|
+
`Could not update the tailwindStylesheet setting in ${prettierConfigPath}.
|
|
305
|
+
Set it to './${tailwindStylesheetPath}' yourself.`
|
|
329
306
|
);
|
|
330
307
|
}
|
|
308
|
+
newPrettierConfig = newPrettierConfig.replace(
|
|
309
|
+
stringEntryRegExp,
|
|
310
|
+
tailwindStylesheetEntry
|
|
311
|
+
);
|
|
331
312
|
} else {
|
|
332
313
|
newPrettierConfig = newPrettierConfig.replace(
|
|
333
314
|
/,(\n\s*)(\}\n?)$/,
|
|
334
315
|
`,
|
|
335
|
-
|
|
316
|
+
${tailwindStylesheetEntry}$1$2`
|
|
336
317
|
);
|
|
337
318
|
}
|
|
338
319
|
fs.writeFileSync(prettierConfigPath, newPrettierConfig);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const UPLOADS_GITIGNORE_ENTRY = "api/.uploads";
|
|
2
|
+
function transformGitignore(source) {
|
|
3
|
+
const activeLines = source.split("\n").map((line) => line.trimEnd()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
4
|
+
if (activeLines.includes(UPLOADS_GITIGNORE_ENTRY)) {
|
|
5
|
+
return source;
|
|
6
|
+
}
|
|
7
|
+
if (/^dev\.db\*$/m.test(source)) {
|
|
8
|
+
return source.replace(/^(dev\.db\*)$/m, `$1
|
|
9
|
+
${UPLOADS_GITIGNORE_ENTRY}`);
|
|
10
|
+
}
|
|
11
|
+
const prefix = source === "" || source.endsWith("\n") ? source : source + "\n";
|
|
12
|
+
return prefix + UPLOADS_GITIGNORE_ENTRY + "\n";
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
UPLOADS_GITIGNORE_ENTRY,
|
|
16
|
+
transformGitignore
|
|
17
|
+
};
|
|
@@ -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,217 @@
|
|
|
1
|
+
import { isBuiltin } from "node:module";
|
|
2
|
+
const START_LINE = /^([ \t]*)await server\.start\(\)/m;
|
|
3
|
+
const FACTORY_IMPORT = /import\s*\{[^}]*\bcreateAuthDecoder\b[^}]*\}\s*from\s*['"](@cedarjs\/auth-[a-z0-9-]+-api)['"]/;
|
|
4
|
+
const DECODER_IMPORT = /import\s*\{[^}]*\bauthDecoder\b[^}]*\}\s*from\s*['"](@cedarjs\/auth-[a-z0-9-]+-api)['"]/;
|
|
5
|
+
function detectServerAuth(graphqlSource) {
|
|
6
|
+
const factory = FACTORY_IMPORT.exec(graphqlSource);
|
|
7
|
+
if (factory) {
|
|
8
|
+
return { decoderPackage: factory[1], usesFactory: true };
|
|
9
|
+
}
|
|
10
|
+
const decoder = DECODER_IMPORT.exec(graphqlSource);
|
|
11
|
+
if (decoder) {
|
|
12
|
+
return { decoderPackage: decoder[1], usesFactory: false };
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function importedBindings(source) {
|
|
17
|
+
const names = /* @__PURE__ */ new Set();
|
|
18
|
+
const statements = source.matchAll(
|
|
19
|
+
/^import\s+(type\s+)?([^;]*?)\s+from\s+['"][^'"]+['"]/gm
|
|
20
|
+
);
|
|
21
|
+
for (const [, typeOnly, clause] of statements) {
|
|
22
|
+
if (typeOnly) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const braces = /\{([^}]*)\}/.exec(clause);
|
|
26
|
+
const defaultOrNamespace = clause.replace(/\{[^}]*\}/, "");
|
|
27
|
+
for (const part of defaultOrNamespace.split(",")) {
|
|
28
|
+
const local = part.replace(/^\s*\*\s+as\s+/, "").trim();
|
|
29
|
+
if (local) {
|
|
30
|
+
names.add(local);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const specifier of braces?.[1].split(",") ?? []) {
|
|
34
|
+
const trimmed = specifier.trim();
|
|
35
|
+
if (!trimmed || trimmed.startsWith("type ")) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const alias = / as (\w+)$/.exec(trimmed);
|
|
39
|
+
names.add(alias ? alias[1] : trimmed);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return names;
|
|
43
|
+
}
|
|
44
|
+
function hasBinding(source, name) {
|
|
45
|
+
const declared = new RegExp(
|
|
46
|
+
`^(?:export\\s+)?(?:const|let|var|function)\\s+${name}\\b`,
|
|
47
|
+
"m"
|
|
48
|
+
);
|
|
49
|
+
return importedBindings(source).has(name) || declared.test(source);
|
|
50
|
+
}
|
|
51
|
+
function uploadsServerImports(source, auth) {
|
|
52
|
+
const specs = [];
|
|
53
|
+
if (auth) {
|
|
54
|
+
if (auth.usesFactory) {
|
|
55
|
+
if (!hasBinding(source, "authDecoder")) {
|
|
56
|
+
specs.push({
|
|
57
|
+
names: ["createAuthDecoder"],
|
|
58
|
+
from: auth.decoderPackage
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
specs.push({ names: ["authDecoder"], from: auth.decoderPackage });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
specs.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
|
+
specs.push({ names: authNames, from: "src/lib/auth" });
|
|
75
|
+
}
|
|
76
|
+
specs.push({ names: ["db"], from: "src/lib/db" });
|
|
77
|
+
specs.push({ names: ["targets"], from: "src/lib/uploads" });
|
|
78
|
+
return specs.map((spec) => ({
|
|
79
|
+
...spec,
|
|
80
|
+
names: spec.names.filter((name) => !hasBinding(source, name))
|
|
81
|
+
})).filter((spec) => spec.names.length > 0).map((spec) => ({
|
|
82
|
+
line: `import { ${spec.names.join(", ")} } from '${spec.from}'`,
|
|
83
|
+
from: spec.from
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
function findImports(lines) {
|
|
87
|
+
const imports = [];
|
|
88
|
+
for (let start = 0; start < lines.length; start++) {
|
|
89
|
+
if (!/^import\b/.test(lines[start])) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const sideEffect = /^import\s*['"]([^'"]+)['"]/.exec(lines[start]);
|
|
93
|
+
if (sideEffect) {
|
|
94
|
+
imports.push({ start, end: start, from: sideEffect[1] });
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
for (let end = start; end < lines.length; end++) {
|
|
98
|
+
const from = /\bfrom\s*['"]([^'"]+)['"]/.exec(lines[end]);
|
|
99
|
+
if (from) {
|
|
100
|
+
imports.push({ start, end, from: from[1] });
|
|
101
|
+
start = end;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return imports;
|
|
107
|
+
}
|
|
108
|
+
function importGroup(from) {
|
|
109
|
+
if (isBuiltin(from)) {
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
if (from === "react") {
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
if (from.startsWith("@cedarjs/")) {
|
|
116
|
+
return 3;
|
|
117
|
+
}
|
|
118
|
+
if (from.startsWith("src/")) {
|
|
119
|
+
return /^src\/[^/]+\/.+\.(?:sdl\.)?(?:js|ts)$/.test(from) ? 4 : 5;
|
|
120
|
+
}
|
|
121
|
+
if (from === ".." || from.startsWith("../")) {
|
|
122
|
+
return 6;
|
|
123
|
+
}
|
|
124
|
+
if (/^\.\/?(?:index(?:\.[jt]sx?)?)?$/.test(from)) {
|
|
125
|
+
return 8;
|
|
126
|
+
}
|
|
127
|
+
if (from.startsWith("./")) {
|
|
128
|
+
return 7;
|
|
129
|
+
}
|
|
130
|
+
return 2;
|
|
131
|
+
}
|
|
132
|
+
function compareSpecifiers(a, b) {
|
|
133
|
+
const segmentsA = a.toLowerCase().split("/");
|
|
134
|
+
const segmentsB = b.toLowerCase().split("/");
|
|
135
|
+
for (let i = 0; i < Math.min(segmentsA.length, segmentsB.length); i++) {
|
|
136
|
+
if (segmentsA[i] !== segmentsB[i]) {
|
|
137
|
+
return segmentsA[i] < segmentsB[i] ? -1 : 1;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return segmentsA.length - segmentsB.length;
|
|
141
|
+
}
|
|
142
|
+
function insertImport(lines, serverImport) {
|
|
143
|
+
const imports = findImports(lines);
|
|
144
|
+
const group = importGroup(serverImport.from);
|
|
145
|
+
const sameGroup = imports.filter((i) => importGroup(i.from) === group);
|
|
146
|
+
if (sameGroup.length > 0) {
|
|
147
|
+
const next = sameGroup.find(
|
|
148
|
+
(i) => compareSpecifiers(i.from, serverImport.from) > 0
|
|
149
|
+
);
|
|
150
|
+
const at2 = next ? next.start : sameGroup[sameGroup.length - 1].end + 1;
|
|
151
|
+
return [...lines.slice(0, at2), serverImport.line, ...lines.slice(at2)];
|
|
152
|
+
}
|
|
153
|
+
const earlier = imports.filter((i) => importGroup(i.from) < group);
|
|
154
|
+
if (earlier.length > 0) {
|
|
155
|
+
const at2 = Math.max(...earlier.map((i) => i.end)) + 1;
|
|
156
|
+
const inserted = ["", serverImport.line];
|
|
157
|
+
if (at2 < lines.length && lines[at2].trim() !== "") {
|
|
158
|
+
inserted.push("");
|
|
159
|
+
}
|
|
160
|
+
return [...lines.slice(0, at2), ...inserted, ...lines.slice(at2)];
|
|
161
|
+
}
|
|
162
|
+
const later = imports.find((i) => importGroup(i.from) > group);
|
|
163
|
+
const at = later ? later.start : 0;
|
|
164
|
+
return [...lines.slice(0, at), serverImport.line, "", ...lines.slice(at)];
|
|
165
|
+
}
|
|
166
|
+
function uploadsServerRegistration(source, auth) {
|
|
167
|
+
if (!auth) {
|
|
168
|
+
return ` await server.register(cedarUploadsPlugin, {
|
|
169
|
+
tokenSecret: process.env.UPLOAD_TOKEN_SECRET,
|
|
170
|
+
targets,
|
|
171
|
+
db,
|
|
172
|
+
// Once the app has auth, bind upload tokens to the logged-in user:
|
|
173
|
+
//
|
|
174
|
+
// authenticate: createUploadAuthenticator({ authDecoder, getCurrentUser }),
|
|
175
|
+
})
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
const decoder = auth.usesFactory && !hasBinding(source, "authDecoder") ? " const authDecoder = createAuthDecoder(cookieName)\n\n" : "";
|
|
179
|
+
return `${decoder} await server.register(cedarUploadsPlugin, {
|
|
180
|
+
tokenSecret: process.env.UPLOAD_TOKEN_SECRET,
|
|
181
|
+
targets,
|
|
182
|
+
db,
|
|
183
|
+
// Binds upload tokens to the logged-in user through the same auth
|
|
184
|
+
// pipeline the GraphQL server uses
|
|
185
|
+
authenticate: createUploadAuthenticator({ authDecoder, getCurrentUser }),
|
|
186
|
+
})
|
|
187
|
+
`;
|
|
188
|
+
}
|
|
189
|
+
function hasUploadsPlugin(source) {
|
|
190
|
+
return /^[ \t]*(?:(?:await|void)\s+|(?:const|let|var)\s+\w+\s*=\s*)?[\w.]+\.register\(\s*cedarUploadsPlugin\b/m.test(
|
|
191
|
+
source
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
function addUploadsPlugin(source, { auth = null } = {}) {
|
|
195
|
+
if (hasUploadsPlugin(source)) {
|
|
196
|
+
return source;
|
|
197
|
+
}
|
|
198
|
+
const start = START_LINE.exec(source);
|
|
199
|
+
if (!start) {
|
|
200
|
+
throw new Error("CEDAR_UPLOADS_ERR_NO_START");
|
|
201
|
+
}
|
|
202
|
+
const withImports = uploadsServerImports(source, auth).reduce(insertImport, source.split("\n")).join("\n");
|
|
203
|
+
return withImports.replace(
|
|
204
|
+
START_LINE,
|
|
205
|
+
(line) => `${uploadsServerRegistration(source, auth)}
|
|
206
|
+
${line}`
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
export {
|
|
210
|
+
addUploadsPlugin,
|
|
211
|
+
detectServerAuth,
|
|
212
|
+
hasBinding,
|
|
213
|
+
hasUploadsPlugin,
|
|
214
|
+
importedBindings,
|
|
215
|
+
uploadsServerImports,
|
|
216
|
+
uploadsServerRegistration
|
|
217
|
+
};
|
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export const
|
|
11
|
-
|
|
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
|
+
`
|