@cedarjs/vite 7.0.1-next.333 → 7.0.1-next.467
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/apiDevMiddleware.d.ts.map +1 -1
- package/dist/apiDevMiddleware.js +12 -1
- package/dist/buildApp.d.ts.map +1 -1
- package/dist/buildApp.js +48 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/jobsDevMiddleware.d.ts.map +1 -1
- package/dist/jobsDevMiddleware.js +29 -2
- package/dist/lib/sandboxChildren.d.ts +58 -0
- package/dist/lib/sandboxChildren.d.ts.map +1 -0
- package/dist/lib/sandboxChildren.js +157 -0
- package/dist/plugins/vite-plugin-cedar-auto-import.d.ts.map +1 -1
- package/dist/plugins/vite-plugin-cedar-auto-import.js +14 -2
- package/dist/plugins/vite-plugin-cedar-import-dir.d.ts.map +1 -1
- package/dist/plugins/vite-plugin-cedar-import-dir.js +12 -1
- package/dist/plugins/vite-plugin-cedar-netlify-skew-protection.d.ts +73 -0
- package/dist/plugins/vite-plugin-cedar-netlify-skew-protection.d.ts.map +1 -0
- package/dist/plugins/vite-plugin-cedar-netlify-skew-protection.js +232 -0
- package/dist/plugins/vite-plugin-cedar-otel-wrapping.d.ts.map +1 -1
- package/dist/plugins/vite-plugin-cedar-otel-wrapping.js +12 -2
- package/dist/plugins/vite-plugin-cedar-sandbox-children.d.ts +20 -0
- package/dist/plugins/vite-plugin-cedar-sandbox-children.d.ts.map +1 -0
- package/dist/plugins/vite-plugin-cedar-sandbox-children.js +58 -0
- package/dist/plugins/vite-plugin-cedar-universal-deploy.d.ts +10 -0
- package/dist/plugins/vite-plugin-cedar-universal-deploy.d.ts.map +1 -1
- package/dist/plugins/vite-plugin-cedar-universal-deploy.js +5 -1
- package/dist/rsc/rscBuildClient.d.ts +1 -1
- package/dist/rsc/rscBuildForServer.d.ts +1 -1
- package/dist/rsc/rscBuildForSsr.d.ts +1 -1
- package/package.json +35 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiDevMiddleware.d.ts","sourceRoot":"","sources":["../src/apiDevMiddleware.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAsB,aAAa,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"apiDevMiddleware.d.ts","sourceRoot":"","sources":["../src/apiDevMiddleware.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAsB,aAAa,EAAE,MAAM,MAAM,CAAA;AAwE7D,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,aAAa,iBAe/D;AA8GD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAoNlE;AA0BD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,aAAa,GAAG,IAAI,CA0EhE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,KAIrB,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAiGnD;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IACrD,UAAU,EAAE,aAAa,CAAA;IACzB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACjD,CAAC,CAcD"}
|
package/dist/apiDevMiddleware.js
CHANGED
|
@@ -20,7 +20,11 @@ import {
|
|
|
20
20
|
import { getAsyncStoreInstance } from "@cedarjs/context/dist/store";
|
|
21
21
|
import { createGraphQLServer } from "@cedarjs/graphql-server";
|
|
22
22
|
import { applyGqlormInject } from "@cedarjs/internal/dist/build/api-graphql-transforms.js";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
createPrismaClientFileMatcher,
|
|
25
|
+
getConfig,
|
|
26
|
+
getPaths
|
|
27
|
+
} from "@cedarjs/project-config";
|
|
24
28
|
import { generateDiffSourceMap } from "./lib/generateDiffSourceMap.js";
|
|
25
29
|
import { getWorkspacePackageAliases } from "./lib/workspacePackageAliases.js";
|
|
26
30
|
import { cedarAutoImportsPlugin } from "./plugins/vite-plugin-cedar-auto-import.js";
|
|
@@ -145,6 +149,7 @@ async function createApiViteServer() {
|
|
|
145
149
|
const cedarPaths = getPaths();
|
|
146
150
|
const cedarConfig = getConfig();
|
|
147
151
|
const normalizedBase = normalizePath(cedarPaths.base);
|
|
152
|
+
const prismaClientFiles = createPrismaClientFileMatcher();
|
|
148
153
|
const babelPlugins = getApiSideBabelConfigPath() ? getApiSideBabelPluginsForVite() : null;
|
|
149
154
|
const workspacePkgSourceMap = Object.fromEntries(
|
|
150
155
|
Object.entries(getWorkspacePackageAliases(cedarPaths, cedarConfig)).map(
|
|
@@ -198,6 +203,9 @@ async function createApiViteServer() {
|
|
|
198
203
|
{
|
|
199
204
|
name: "cedar-api-babel-transform",
|
|
200
205
|
enforce: "pre",
|
|
206
|
+
async buildStart() {
|
|
207
|
+
await prismaClientFiles.load();
|
|
208
|
+
},
|
|
201
209
|
async transform(code, id) {
|
|
202
210
|
if (!/\.(ts|tsx|js|jsx)$/.test(id)) {
|
|
203
211
|
return null;
|
|
@@ -208,6 +216,9 @@ async function createApiViteServer() {
|
|
|
208
216
|
if (!id.startsWith(normalizedBase)) {
|
|
209
217
|
return null;
|
|
210
218
|
}
|
|
219
|
+
if (await prismaClientFiles.matches(id)) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
211
222
|
let sourceCode = code;
|
|
212
223
|
let sourceMap = null;
|
|
213
224
|
if (normalizePath(id).endsWith("/graphql.ts") || normalizePath(id).endsWith("/graphql.js")) {
|
package/dist/buildApp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildApp.d.ts","sourceRoot":"","sources":["../src/buildApp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildApp.d.ts","sourceRoot":"","sources":["../src/buildApp.ts"],"names":[],"mappings":"AAuEA,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,EAAE,CAAC,EAAE,OAAO,CAAA;CACb;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,EAClC,OAAe,EACf,SAA0B,EAC1B,EAAU,GACX,GAAE,oBAAyB,iBAyd3B"}
|
package/dist/buildApp.js
CHANGED
|
@@ -20,8 +20,17 @@ import {
|
|
|
20
20
|
applySrcAlias
|
|
21
21
|
} from "@cedarjs/internal/dist/build/api.js";
|
|
22
22
|
import { findApiFiles } from "@cedarjs/internal/dist/files.js";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
createPrismaClientFileMatcher,
|
|
25
|
+
getConfig,
|
|
26
|
+
getPaths
|
|
27
|
+
} from "@cedarjs/project-config";
|
|
24
28
|
import { generateDiffSourceMap } from "./lib/generateDiffSourceMap.js";
|
|
29
|
+
import {
|
|
30
|
+
copySandboxChildrenIntoVercelFunctions,
|
|
31
|
+
findSandboxChildScripts,
|
|
32
|
+
SANDBOX_CHILDREN_DIR
|
|
33
|
+
} from "./lib/sandboxChildren.js";
|
|
25
34
|
import { getWorkspacePackageAliases } from "./lib/workspacePackageAliases.js";
|
|
26
35
|
import { cedarAutoImportsPlugin } from "./plugins/vite-plugin-cedar-auto-import.js";
|
|
27
36
|
import { cedarDirectoryNamedImportPlugin } from "./plugins/vite-plugin-cedar-directory-named-import.js";
|
|
@@ -30,6 +39,7 @@ import { cedarGraphqlOptionsExtractPlugin } from "./plugins/vite-plugin-cedar-gr
|
|
|
30
39
|
import { cedarImportDirPlugin } from "./plugins/vite-plugin-cedar-import-dir.js";
|
|
31
40
|
import { cedarMockCellDataPlugin } from "./plugins/vite-plugin-cedar-mock-cell-data.js";
|
|
32
41
|
import { cedarOtelWrappingPlugin } from "./plugins/vite-plugin-cedar-otel-wrapping.js";
|
|
42
|
+
import { cedarSandboxChildrenPlugin } from "./plugins/vite-plugin-cedar-sandbox-children.js";
|
|
33
43
|
import { cedarjsJobPathInjectorPlugin } from "./plugins/vite-plugin-cedarjs-job-path-injector.js";
|
|
34
44
|
import { handlerAlsWrappingPlugin } from "./plugins/vite-plugin-handler-als-wrapping.js";
|
|
35
45
|
function resolveWithExtensions(id) {
|
|
@@ -52,6 +62,7 @@ async function buildCedarApp({
|
|
|
52
62
|
const cedarPaths = getPaths();
|
|
53
63
|
const cedarConfig = getConfig();
|
|
54
64
|
const environments = {};
|
|
65
|
+
let sandboxChildren = {};
|
|
55
66
|
if (workspace.includes("web")) {
|
|
56
67
|
environments.client = {
|
|
57
68
|
build: {
|
|
@@ -93,15 +104,16 @@ async function buildCedarApp({
|
|
|
93
104
|
}
|
|
94
105
|
};
|
|
95
106
|
if (ud) {
|
|
107
|
+
sandboxChildren = findSandboxChildScripts(cedarPaths.api.src);
|
|
96
108
|
environments["ssr"] = {
|
|
97
109
|
build: {
|
|
98
110
|
ssr: true,
|
|
99
111
|
outDir: path.join(cedarPaths.api.dist, "ud"),
|
|
100
112
|
emptyOutDir: true,
|
|
101
113
|
rollupOptions: {
|
|
102
|
-
input: catchAllEntry,
|
|
114
|
+
input: { index: catchAllEntry, ...sandboxChildren },
|
|
103
115
|
output: {
|
|
104
|
-
entryFileNames: "
|
|
116
|
+
entryFileNames: "[name].js"
|
|
105
117
|
},
|
|
106
118
|
external: (id) => {
|
|
107
119
|
if (id.startsWith("virtual:")) {
|
|
@@ -197,6 +209,12 @@ async function buildCedarApp({
|
|
|
197
209
|
];
|
|
198
210
|
if (ud) {
|
|
199
211
|
plugins.push(catchAll());
|
|
212
|
+
plugins.push(
|
|
213
|
+
cedarSandboxChildrenPlugin({
|
|
214
|
+
environment: "ssr",
|
|
215
|
+
children: sandboxChildren
|
|
216
|
+
})
|
|
217
|
+
);
|
|
200
218
|
plugins.push({
|
|
201
219
|
name: "cedar-ud-verify-routes",
|
|
202
220
|
configResolved() {
|
|
@@ -258,9 +276,13 @@ async function buildCedarApp({
|
|
|
258
276
|
}
|
|
259
277
|
plugins.push(cedarMockCellDataPlugin());
|
|
260
278
|
if (workspace.includes("api")) {
|
|
279
|
+
const prismaClientFiles = createPrismaClientFileMatcher();
|
|
261
280
|
plugins.push({
|
|
262
281
|
name: "cedar-vite-api-babel-transform",
|
|
263
282
|
enforce: "pre",
|
|
283
|
+
async buildStart() {
|
|
284
|
+
await prismaClientFiles.load();
|
|
285
|
+
},
|
|
264
286
|
async transform(code, id) {
|
|
265
287
|
if (!/\.(js|ts|tsx|jsx)$/.test(id)) {
|
|
266
288
|
return null;
|
|
@@ -271,6 +293,16 @@ async function buildCedarApp({
|
|
|
271
293
|
if (!normalizePath(id).startsWith(normalizePath(cedarPaths.api.base))) {
|
|
272
294
|
return null;
|
|
273
295
|
}
|
|
296
|
+
if (await prismaClientFiles.matches(id)) {
|
|
297
|
+
const rewrittenCode2 = applyImportExtensions(code, id);
|
|
298
|
+
if (rewrittenCode2 === code) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
code: rewrittenCode2,
|
|
303
|
+
map: generateDiffSourceMap(code, rewrittenCode2)
|
|
304
|
+
};
|
|
305
|
+
}
|
|
274
306
|
const babelPlugins = getApiSideBabelConfigPath() ? getApiSideBabelPluginsForVite() : null;
|
|
275
307
|
const fromDirRelativeToApiSrc = path.relative(
|
|
276
308
|
cedarPaths.api.src,
|
|
@@ -323,7 +355,19 @@ async function buildCedarApp({
|
|
|
323
355
|
},
|
|
324
356
|
plugins
|
|
325
357
|
});
|
|
326
|
-
|
|
358
|
+
await builder.buildApp();
|
|
359
|
+
const vercelNode = builder.environments["vercel_node"];
|
|
360
|
+
if (ud && vercelNode && Object.keys(sandboxChildren).length > 0) {
|
|
361
|
+
const outDir = path.resolve(
|
|
362
|
+
vercelNode.config.root,
|
|
363
|
+
vercelNode.config.build.outDir
|
|
364
|
+
);
|
|
365
|
+
copySandboxChildrenIntoVercelFunctions({
|
|
366
|
+
appRoot: cedarPaths.base,
|
|
367
|
+
childrenDir: path.join(cedarPaths.api.dist, "ud", SANDBOX_CHILDREN_DIR),
|
|
368
|
+
functionsDir: path.join(outDir, "functions")
|
|
369
|
+
});
|
|
370
|
+
}
|
|
327
371
|
}
|
|
328
372
|
export {
|
|
329
373
|
buildCedarApp
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { cedarjsJobPathInjectorPlugin } from './plugins/vite-plugin-cedarjs-job-
|
|
|
21
21
|
export { cedarMockCellDataPlugin } from './plugins/vite-plugin-cedar-mock-cell-data.js';
|
|
22
22
|
export { cedarParsedScalarsPlugin } from './plugins/vite-plugin-cedar-parsed-scalars.js';
|
|
23
23
|
export { cedarMergedConfig } from './plugins/vite-plugin-merged-config.js';
|
|
24
|
+
export { cedarNetlifySkewProtectionPlugin } from './plugins/vite-plugin-cedar-netlify-skew-protection.js';
|
|
24
25
|
export { cedarSwapApolloProvider } from './plugins/vite-plugin-swap-apollo-provider.js';
|
|
25
26
|
export { cedarUniversalDeployPlugin } from './plugins/vite-plugin-cedar-universal-deploy.js';
|
|
26
27
|
export { cedarWaitForApiServer } from './plugins/vite-plugin-cedar-wait-for-api-server.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAqCxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAA;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAA;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wDAAwD,CAAA;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,+CAA+C,CAAA;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAA;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uDAAuD,CAAA;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,4DAA4D,CAAA;AACzG,OAAO,EAAE,2BAA2B,EAAE,MAAM,mDAAmD,CAAA;AAC/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,qCAAqC,EAAE,MAAM,8DAA8D,CAAA;AACpH,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAA;AACjG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAA;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAA;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAA;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAA;AAE1F,KAAK,aAAa,GAAG;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAE,aAAkB,GAAG,YAAY,EAAE,CAgDzE;AAED,8DAA8D;AAC9D,eAAe,KAAK,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAqCxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAA;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAA;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wDAAwD,CAAA;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,+CAA+C,CAAA;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAA;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uDAAuD,CAAA;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,4DAA4D,CAAA;AACzG,OAAO,EAAE,2BAA2B,EAAE,MAAM,mDAAmD,CAAA;AAC/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,qCAAqC,EAAE,MAAM,8DAA8D,CAAA;AACpH,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAA;AACjG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAA;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAC1E,OAAO,EAAE,gCAAgC,EAAE,MAAM,wDAAwD,CAAA;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAA;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAA;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAA;AAE1F,KAAK,aAAa,GAAG;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAE,aAAkB,GAAG,YAAY,EAAE,CAgDzE;AAED,8DAA8D;AAC9D,eAAe,KAAK,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ import { cedarjsJobPathInjectorPlugin } from "./plugins/vite-plugin-cedarjs-job-
|
|
|
52
52
|
import { cedarMockCellDataPlugin as cedarMockCellDataPlugin2 } from "./plugins/vite-plugin-cedar-mock-cell-data.js";
|
|
53
53
|
import { cedarParsedScalarsPlugin as cedarParsedScalarsPlugin2 } from "./plugins/vite-plugin-cedar-parsed-scalars.js";
|
|
54
54
|
import { cedarMergedConfig as cedarMergedConfig2 } from "./plugins/vite-plugin-merged-config.js";
|
|
55
|
+
import { cedarNetlifySkewProtectionPlugin } from "./plugins/vite-plugin-cedar-netlify-skew-protection.js";
|
|
55
56
|
import { cedarSwapApolloProvider as cedarSwapApolloProvider2 } from "./plugins/vite-plugin-swap-apollo-provider.js";
|
|
56
57
|
import { cedarUniversalDeployPlugin } from "./plugins/vite-plugin-cedar-universal-deploy.js";
|
|
57
58
|
import { cedarWaitForApiServer as cedarWaitForApiServer2 } from "./plugins/vite-plugin-cedar-wait-for-api-server.js";
|
|
@@ -109,6 +110,7 @@ export {
|
|
|
109
110
|
cedarImportDirPlugin,
|
|
110
111
|
cedarMergedConfig2 as cedarMergedConfig,
|
|
111
112
|
cedarMockCellDataPlugin2 as cedarMockCellDataPlugin,
|
|
113
|
+
cedarNetlifySkewProtectionPlugin,
|
|
112
114
|
cedarOtelWrappingPlugin,
|
|
113
115
|
cedarParsedScalarsPlugin2 as cedarParsedScalarsPlugin,
|
|
114
116
|
cedarRemoveDevFatalErrorPage2 as cedarRemoveDevFatalErrorPage,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jobsDevMiddleware.d.ts","sourceRoot":"","sources":["../src/jobsDevMiddleware.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jobsDevMiddleware.d.ts","sourceRoot":"","sources":["../src/jobsDevMiddleware.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAsGzC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAKD,KAAK,eAAe,GAAG,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;AAE3D;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,eAAe,GAC1B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA6GhC"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
1
4
|
import { pathToFileURL } from "node:url";
|
|
2
5
|
import ansis from "ansis";
|
|
3
6
|
import {
|
|
7
|
+
isJobModuleFile,
|
|
4
8
|
JobNotFoundError,
|
|
5
9
|
JobsLibNotFoundError,
|
|
10
|
+
jobsFromModules,
|
|
6
11
|
setJobLoaderOverrides
|
|
7
12
|
} from "@cedarjs/jobs";
|
|
8
13
|
import { getPaths } from "@cedarjs/project-config";
|
|
@@ -40,10 +45,27 @@ async function loadJobViaVite(viteServer, { name: jobName, path: jobPath }) {
|
|
|
40
45
|
}
|
|
41
46
|
return mod[jobName];
|
|
42
47
|
}
|
|
48
|
+
async function loadAllJobsViaVite(viteServer) {
|
|
49
|
+
const jobsDir = getPaths().api.jobs;
|
|
50
|
+
if (!fs.existsSync(jobsDir)) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
const files = fs.readdirSync(jobsDir, { recursive: true, encoding: "utf-8" }).filter(isJobModuleFile).sort();
|
|
54
|
+
const modules = [];
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
modules.push(
|
|
57
|
+
await viteServer.ssrLoadModule(
|
|
58
|
+
pathToFileURL(path.join(jobsDir, file)).href
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return jobsFromModules(modules);
|
|
63
|
+
}
|
|
43
64
|
async function startJobsDevWorkers(viteServer) {
|
|
44
65
|
setJobLoaderOverrides({
|
|
45
66
|
loadJobsManager: () => loadJobsManagerViaVite(viteServer),
|
|
46
|
-
loadJob: (computedProperties) => loadJobViaVite(viteServer, computedProperties)
|
|
67
|
+
loadJob: (computedProperties) => loadJobViaVite(viteServer, computedProperties),
|
|
68
|
+
loadAllJobs: () => loadAllJobsViaVite(viteServer)
|
|
47
69
|
});
|
|
48
70
|
let jobsManager;
|
|
49
71
|
try {
|
|
@@ -61,12 +83,17 @@ async function startJobsDevWorkers(viteServer) {
|
|
|
61
83
|
setJobLoaderOverrides(void 0);
|
|
62
84
|
return null;
|
|
63
85
|
}
|
|
86
|
+
try {
|
|
87
|
+
await jobsManager.syncSchedules();
|
|
88
|
+
} catch (e) {
|
|
89
|
+
logger.error("[CedarJS Jobs] Could not sync the declared schedules", e);
|
|
90
|
+
}
|
|
64
91
|
logger.warn(
|
|
65
92
|
`[CedarJS Jobs] Starting ${numWorkers.length} worker(s) in-process (Unified Dev)...`
|
|
66
93
|
);
|
|
67
94
|
const workers = numWorkers.map(([index, id]) => {
|
|
68
95
|
const workerConfig = jobsManager.workers[index];
|
|
69
|
-
const processName = `ud-jobs.${[workerConfig.queue].flat().join("-")}.${id}`;
|
|
96
|
+
const processName = `ud-jobs.${[workerConfig.queue].flat().join("-")}.${id} host:${hostname()} pid:${process.pid}`;
|
|
70
97
|
return jobsManager.createWorker({
|
|
71
98
|
index,
|
|
72
99
|
clear: false,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The folder in `api/dist/ud` a bundled API build puts every sandboxed
|
|
3
|
+
* child script in, as `<name>.child.js`, with a `node_modules` holding the
|
|
4
|
+
* packages they import. `findChildScript()` in `@cedarjs/api/sandbox`
|
|
5
|
+
* looks for `api/dist/ud/sandbox-children` from its caller's folder up.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SANDBOX_CHILDREN_DIR = "sandbox-children";
|
|
8
|
+
/**
|
|
9
|
+
* Every sandboxed child script in `apiSrc` (`**\/*.child.{ts,js,mts,mjs}`),
|
|
10
|
+
* as `{ 'sandbox-children/<name>.child': file }`, for a bundled build's
|
|
11
|
+
* `input`. Throws when two have the same name: in a bundle they all go in
|
|
12
|
+
* one folder, and `findChildScript()` finds them by name.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findSandboxChildScripts(apiSrc: string): Record<string, string>;
|
|
15
|
+
export interface SandboxChildImports {
|
|
16
|
+
/** The child script's source file, which its imports resolve from */
|
|
17
|
+
source: string;
|
|
18
|
+
/** What it imports: package names and Node builtins */
|
|
19
|
+
imports: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Copies the packages the child scripts import, and everything those
|
|
23
|
+
* depend on, into `<childrenDir>/node_modules`, so the folder runs on its
|
|
24
|
+
* own wherever it's deployed: a serverless function's file tracing doesn't
|
|
25
|
+
* follow a child script (nothing imports it), and it would miss what
|
|
26
|
+
* native packages load at run time anyway (sharp's libvips).
|
|
27
|
+
*
|
|
28
|
+
* Follows each package's `dependencies`, and the `optionalDependencies`
|
|
29
|
+
* and `peerDependencies` that are installed, which is how native packages
|
|
30
|
+
* ship their platform's binaries (`@img/sharp-linux-x64`,
|
|
31
|
+
* `@img/sharp-libvips-linux-x64`).
|
|
32
|
+
*
|
|
33
|
+
* The copy keeps each package's choices, so it finds the same versions
|
|
34
|
+
* it does in the app: a dependency nested in a package's own
|
|
35
|
+
* `node_modules` is copied into the copy's `node_modules`; one beside it
|
|
36
|
+
* in a `node_modules` (pnpm's layout), or shadowed in the copy by another
|
|
37
|
+
* version, goes next to the dependent's copy; one in the app's own
|
|
38
|
+
* `node_modules` folders goes at the top. A package already reachable from
|
|
39
|
+
* the dependent's copy is reused. When two versions would still need the
|
|
40
|
+
* same place, it throws instead of letting one overwrite the other. So
|
|
41
|
+
* does a package or regular dependency that isn't installed: the child
|
|
42
|
+
* couldn't import it either.
|
|
43
|
+
*/
|
|
44
|
+
export declare function vendorSandboxChildPackages(childrenDir: string, children: SandboxChildImports[]): void;
|
|
45
|
+
/**
|
|
46
|
+
* Copies the bundled build's sandboxed children (and their `node_modules`)
|
|
47
|
+
* into every Node function in a Vercel Build Output API folder
|
|
48
|
+
* (`.vercel/output/functions/*.func`), at the same path as in the app
|
|
49
|
+
* (`api/dist/ud/sandbox-children`). Each Vercel function is a single
|
|
50
|
+
* bundled file with nothing else from the app, and `findChildScript()`
|
|
51
|
+
* looks for the children from the function's folder up.
|
|
52
|
+
*/
|
|
53
|
+
export declare function copySandboxChildrenIntoVercelFunctions({ appRoot, childrenDir, functionsDir, }: {
|
|
54
|
+
appRoot: string;
|
|
55
|
+
childrenDir: string;
|
|
56
|
+
functionsDir: string;
|
|
57
|
+
}): string[];
|
|
58
|
+
//# sourceMappingURL=sandboxChildren.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxChildren.d.ts","sourceRoot":"","sources":["../../src/lib/sandboxChildren.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,qBAAqB,CAAA;AAEtD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBxB;AA6CD,MAAM,WAAW,mBAAmB;IAClC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,mBAAmB,EAAE,QA+GhC;AAgBD;;;;;;;GAOG;AACH,wBAAgB,sCAAsC,CAAC,EACrD,OAAO,EACP,WAAW,EACX,YAAY,GACb,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB,YAgCA"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { isBuiltin } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fg from "fast-glob";
|
|
5
|
+
const SANDBOX_CHILDREN_DIR = "sandbox-children";
|
|
6
|
+
function findSandboxChildScripts(apiSrc) {
|
|
7
|
+
const files = fg.sync("**/*.child.{ts,js,mts,mjs}", {
|
|
8
|
+
cwd: apiSrc,
|
|
9
|
+
absolute: true,
|
|
10
|
+
ignore: ["**/node_modules/**", "**/__tests__/**"]
|
|
11
|
+
}).sort();
|
|
12
|
+
const entries = {};
|
|
13
|
+
for (const file of files) {
|
|
14
|
+
const name = path.basename(file).replace(/\.(ts|js|mts|mjs)$/, "");
|
|
15
|
+
const key = `${SANDBOX_CHILDREN_DIR}/${name}`;
|
|
16
|
+
if (entries[key]) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Two sandboxed child scripts are named ${name}: ${path.relative(apiSrc, entries[key])} and ${path.relative(apiSrc, file)}. A bundled build puts every child script in one folder, so their names must be unique.`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
entries[key] = path.normalize(file);
|
|
22
|
+
}
|
|
23
|
+
return entries;
|
|
24
|
+
}
|
|
25
|
+
const packageName = (specifier) => {
|
|
26
|
+
const parts = specifier.split("/");
|
|
27
|
+
return specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
28
|
+
};
|
|
29
|
+
const readPackageJson = (dir) => {
|
|
30
|
+
const parsed = JSON.parse(
|
|
31
|
+
fs.readFileSync(path.join(dir, "package.json"), "utf8")
|
|
32
|
+
);
|
|
33
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
34
|
+
};
|
|
35
|
+
const findPackage = (name, dir) => {
|
|
36
|
+
let current = dir;
|
|
37
|
+
for (; ; ) {
|
|
38
|
+
const candidate = path.join(current, "node_modules", name);
|
|
39
|
+
if (fs.existsSync(path.join(candidate, "package.json"))) {
|
|
40
|
+
return { realDir: fs.realpathSync(candidate), foundIn: current };
|
|
41
|
+
}
|
|
42
|
+
const parent = path.dirname(current);
|
|
43
|
+
if (parent === current) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
current = parent;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function vendorSandboxChildPackages(childrenDir, children) {
|
|
50
|
+
const copyOf = /* @__PURE__ */ new Map();
|
|
51
|
+
const occupied = /* @__PURE__ */ new Map();
|
|
52
|
+
const inNodeModules = (dir) => dir.split(path.sep).includes("node_modules");
|
|
53
|
+
const reachableFrom = (copy, name) => {
|
|
54
|
+
let dir = copy;
|
|
55
|
+
for (; ; ) {
|
|
56
|
+
const there = occupied.get(path.join(dir, "node_modules", name));
|
|
57
|
+
if (there || dir === childrenDir) {
|
|
58
|
+
return there?.realDir;
|
|
59
|
+
}
|
|
60
|
+
dir = path.dirname(dir);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const visit = (name, fromDir, dependentCopy, required, dependent) => {
|
|
64
|
+
const found = findPackage(name, fromDir);
|
|
65
|
+
if (!found) {
|
|
66
|
+
if (required) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Can't find package "${name}", which ${dependent} imports, in a node_modules folder above ${fromDir}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const { realDir, foundIn } = found;
|
|
74
|
+
const reachable = reachableFrom(dependentCopy, name);
|
|
75
|
+
if (reachable === realDir) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const copiedFolder = copyOf.get(foundIn);
|
|
79
|
+
const besideDependent = path.join(dependentCopy, "node_modules", name);
|
|
80
|
+
const target = copiedFolder ? path.join(copiedFolder, "node_modules", name) : inNodeModules(foundIn) || reachable ? besideDependent : path.join(childrenDir, "node_modules", name);
|
|
81
|
+
const there = occupied.get(target);
|
|
82
|
+
if (there) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Sandboxed child scripts need two versions of "${name}" in one place: ${there.realDir} (for ${there.neededBy}) and ${realDir} (for ${dependent}). Install a single version of it, or move the children so their imports resolve the same way.`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
occupied.set(target, { realDir, neededBy: dependent });
|
|
88
|
+
if (!copyOf.has(realDir)) {
|
|
89
|
+
copyOf.set(realDir, target);
|
|
90
|
+
}
|
|
91
|
+
fs.cpSync(realDir, target, {
|
|
92
|
+
recursive: true,
|
|
93
|
+
dereference: true,
|
|
94
|
+
// Its own node_modules are copied as dependencies, when they're needed
|
|
95
|
+
filter: (src) => src !== path.join(realDir, "node_modules")
|
|
96
|
+
});
|
|
97
|
+
const pkg = readPackageJson(realDir);
|
|
98
|
+
const optional = /* @__PURE__ */ new Set([
|
|
99
|
+
...Object.keys(pkg.optionalDependencies ?? {}),
|
|
100
|
+
...Object.keys(pkg.peerDependencies ?? {})
|
|
101
|
+
]);
|
|
102
|
+
for (const dep of Object.keys(pkg.dependencies ?? {})) {
|
|
103
|
+
visit(dep, realDir, target, !optional.has(dep), name);
|
|
104
|
+
}
|
|
105
|
+
for (const dep of optional) {
|
|
106
|
+
visit(dep, realDir, target, false, name);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
for (const { source, imports } of children) {
|
|
110
|
+
for (const specifier of imports) {
|
|
111
|
+
if (isBuiltin(specifier) || specifier.startsWith("#")) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
visit(
|
|
115
|
+
packageName(specifier),
|
|
116
|
+
fs.realpathSync(path.dirname(source)),
|
|
117
|
+
childrenDir,
|
|
118
|
+
true,
|
|
119
|
+
path.basename(source)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const findVercelFunctionDirs = (dir) => fs.existsSync(dir) ? fs.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).flatMap((entry) => {
|
|
125
|
+
const entryPath = path.join(dir, entry.name);
|
|
126
|
+
return entry.name.endsWith(".func") ? [entryPath] : findVercelFunctionDirs(entryPath);
|
|
127
|
+
}) : [];
|
|
128
|
+
function copySandboxChildrenIntoVercelFunctions({
|
|
129
|
+
appRoot,
|
|
130
|
+
childrenDir,
|
|
131
|
+
functionsDir
|
|
132
|
+
}) {
|
|
133
|
+
const childrenDirInApp = path.relative(appRoot, childrenDir);
|
|
134
|
+
if (!fs.existsSync(childrenDir)) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const functionDirs = findVercelFunctionDirs(functionsDir).filter((dir) => {
|
|
138
|
+
const config = path.join(dir, ".vc-config.json");
|
|
139
|
+
if (!fs.existsSync(config)) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const parsed = JSON.parse(fs.readFileSync(config, "utf8"));
|
|
143
|
+
return !!parsed && typeof parsed === "object" && "runtime" in parsed && typeof parsed.runtime === "string" && parsed.runtime.startsWith("nodejs");
|
|
144
|
+
});
|
|
145
|
+
for (const dir of functionDirs) {
|
|
146
|
+
fs.cpSync(childrenDir, path.join(dir, childrenDirInApp), {
|
|
147
|
+
recursive: true
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return functionDirs;
|
|
151
|
+
}
|
|
152
|
+
export {
|
|
153
|
+
SANDBOX_CHILDREN_DIR,
|
|
154
|
+
copySandboxChildrenIntoVercelFunctions,
|
|
155
|
+
findSandboxChildScripts,
|
|
156
|
+
vendorSandboxChildPackages
|
|
157
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-cedar-auto-import.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-auto-import.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vite-plugin-cedar-auto-import.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-auto-import.ts"],"names":[],"mappings":"AA2BA,wBAAgB,sBAAsB,UAyFrC"}
|
|
@@ -13,10 +13,15 @@ import {
|
|
|
13
13
|
getPaths,
|
|
14
14
|
importStatementPath
|
|
15
15
|
} from "@cedarjs/project-config";
|
|
16
|
+
function escapeRegExp(s) {
|
|
17
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18
|
+
}
|
|
16
19
|
function cedarAutoImportsPlugin() {
|
|
17
20
|
const config = getConfig();
|
|
18
21
|
const cedarPaths = getPaths();
|
|
19
22
|
const useTrustedDocumentsGqlTag = config?.graphql?.trustedDocuments;
|
|
23
|
+
const apiBase = cedarPaths.api.base.replace(/\\/g, "/");
|
|
24
|
+
const apiSrcPattern = new RegExp(`^${escapeRegExp(apiBase)}/.*\\.[tj]sx?$`);
|
|
20
25
|
return [
|
|
21
26
|
autoImport({
|
|
22
27
|
// targets to transform
|
|
@@ -44,7 +49,14 @@ function cedarAutoImportsPlugin() {
|
|
|
44
49
|
}),
|
|
45
50
|
autoImport({
|
|
46
51
|
// targets to transform
|
|
47
|
-
|
|
52
|
+
//
|
|
53
|
+
// This must stay scoped to api/ only. @cedarjs/context relies on
|
|
54
|
+
// Node's AsyncLocalStorage, which isn't available in the browser.
|
|
55
|
+
// If this ever matches web/ files too, an unrelated identifier
|
|
56
|
+
// named `context` in a web-side file (e.g. a function parameter)
|
|
57
|
+
// would get auto-imported from @cedarjs/context, pulling
|
|
58
|
+
// AsyncLocalStorage into the web build and breaking it. See #2892.
|
|
59
|
+
include: [apiSrcPattern],
|
|
48
60
|
// global imports to register
|
|
49
61
|
imports: [
|
|
50
62
|
{
|
|
@@ -56,7 +68,7 @@ function cedarAutoImportsPlugin() {
|
|
|
56
68
|
}),
|
|
57
69
|
autoImport({
|
|
58
70
|
// targets to transform
|
|
59
|
-
include: [
|
|
71
|
+
include: [apiSrcPattern],
|
|
60
72
|
// global imports to register
|
|
61
73
|
imports: [
|
|
62
74
|
// import gql from 'graphql-tag'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-cedar-import-dir.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-import-dir.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"vite-plugin-cedar-import-dir.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-import-dir.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAQlC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAqI7C"}
|
|
@@ -3,15 +3,26 @@ import path from "node:path";
|
|
|
3
3
|
import MagicString from "magic-string";
|
|
4
4
|
import { parseSync } from "oxc-parser";
|
|
5
5
|
import { normalizePath } from "vite";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
createPrismaClientFileMatcher,
|
|
8
|
+
importStatementPath,
|
|
9
|
+
getPaths
|
|
10
|
+
} from "@cedarjs/project-config";
|
|
7
11
|
function cedarImportDirPlugin() {
|
|
12
|
+
const prismaClientFiles = createPrismaClientFileMatcher();
|
|
8
13
|
return {
|
|
9
14
|
name: "vite-plugin-cedar-import-dir",
|
|
10
15
|
enforce: "pre",
|
|
16
|
+
async buildStart() {
|
|
17
|
+
await prismaClientFiles.load();
|
|
18
|
+
},
|
|
11
19
|
async transform(code, id) {
|
|
12
20
|
if (!code.includes("/**/")) {
|
|
13
21
|
return null;
|
|
14
22
|
}
|
|
23
|
+
if (await prismaClientFiles.matches(id)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
15
26
|
let program;
|
|
16
27
|
try {
|
|
17
28
|
program = parseSync(id, code).program;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Plugin, ResolvedConfig } from 'vite';
|
|
2
|
+
export interface CedarNetlifySkewProtectionPluginOptions {
|
|
3
|
+
headerName?: string;
|
|
4
|
+
queryName?: string;
|
|
5
|
+
cookieName?: string;
|
|
6
|
+
/**
|
|
7
|
+
* How long (in seconds) the skew-token cookie pins a client's asset and API
|
|
8
|
+
* requests to the deploy it last loaded a page from. Page loads are never
|
|
9
|
+
* pinned and always refresh the cookie, so a long value can't keep anyone
|
|
10
|
+
* on an old version; it only bounds how long an open tab can keep loading
|
|
11
|
+
* lazy chunks from the deploy it started on. Defaults to 24 hours.
|
|
12
|
+
*/
|
|
13
|
+
cookieMaxAge?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The paths Netlify should route to a client's pinned deploy, and the paths
|
|
17
|
+
* the edge function doesn't need to run on.
|
|
18
|
+
*/
|
|
19
|
+
export interface SkewProtectionPaths {
|
|
20
|
+
/** Regexes for Netlify's `skew-protection.json` `patterns` */
|
|
21
|
+
patterns: string[];
|
|
22
|
+
/** Globs for the edge function's `excludedPath` */
|
|
23
|
+
excludedPaths: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Pins hashed build assets (the lazy-loaded chunks an already-open tab
|
|
27
|
+
* requests after a new deploy) and Cedar's API routes (so an old client keeps
|
|
28
|
+
* talking to the API it was built against). Page loads are not pinned, so a
|
|
29
|
+
* reload or a fresh visit always gets the latest deploy.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getSkewProtectionPaths(config: Pick<ResolvedConfig, 'base' | 'build' | 'plugins'>): SkewProtectionPaths;
|
|
32
|
+
/**
|
|
33
|
+
* Generates Netlify's `.netlify/v1/skew-protection.json` build output, an
|
|
34
|
+
* edge function that stamps the skew-token cookie on static HTML, and wraps
|
|
35
|
+
* Universal Deploy's catch-all Fetchable so server-rendered HTML gets the
|
|
36
|
+
* same cookie.
|
|
37
|
+
*
|
|
38
|
+
* Background: https://docs.netlify.com/build/frameworks/frameworks-api/#netlifyv1skew-protectionjson
|
|
39
|
+
*
|
|
40
|
+
* How it works:
|
|
41
|
+
* - Every HTML response sets `Set-Cookie: <cookieName>=<deploy token>`.
|
|
42
|
+
* Netlify exposes the token at build time as `NETLIFY_SKEW_PROTECTION_TOKEN`
|
|
43
|
+
* and at runtime as `context.deploy.skewProtectionToken`.
|
|
44
|
+
* - Requests matching `patterns` (build assets and API routes, see
|
|
45
|
+
* `getSkewProtectionPaths`) that carry the cookie are served by the deploy
|
|
46
|
+
* the token belongs to. A tab that loaded an old build keeps loading its
|
|
47
|
+
* own lazy chunks after a new deploy, instead of getting 404s.
|
|
48
|
+
* - Page loads don't match `patterns`, so they're always served by the
|
|
49
|
+
* latest deploy, and its HTML sets the latest token. Reloading is therefore
|
|
50
|
+
* always enough to get the newest version.
|
|
51
|
+
* - Only HTML responses to page loads set the cookie. Responses to pinned
|
|
52
|
+
* asset and API requests can come from an old deploy and would otherwise
|
|
53
|
+
* renew the old token.
|
|
54
|
+
*
|
|
55
|
+
* The cookie is set in two places:
|
|
56
|
+
* - Static HTML (prerendered pages and the SPA shell) is served from
|
|
57
|
+
* Netlify's CDN and never reaches Cedar's server code. A framework-authored
|
|
58
|
+
* edge function (`.netlify/v1/edge-functions/`, registered automatically)
|
|
59
|
+
* stamps it using `context.deploy.skewProtectionToken`.
|
|
60
|
+
* - Server-rendered HTML comes from Universal Deploy's catch-all Fetchable.
|
|
61
|
+
* Fetchables are plain `(request: Request) => Response` functions that
|
|
62
|
+
* don't get Netlify's `context`, so the build-time token (identical to the
|
|
63
|
+
* runtime one, both describe the same deploy) is stamped into the SSR
|
|
64
|
+
* bundle as a virtual module, and the Fetchable is wrapped to set the
|
|
65
|
+
* cookie.
|
|
66
|
+
*
|
|
67
|
+
* Cookies are the only one of Netlify's three token sources (cookie, header,
|
|
68
|
+
* query) that browsers send automatically, so they're the only one Cedar
|
|
69
|
+
* sets. The header and query sources are registered so clients that can't
|
|
70
|
+
* use cookies can still pin requests by sending the token themselves.
|
|
71
|
+
*/
|
|
72
|
+
export declare function cedarNetlifySkewProtectionPlugin(options?: CedarNetlifySkewProtectionPluginOptions): Plugin;
|
|
73
|
+
//# sourceMappingURL=vite-plugin-cedar-netlify-skew-protection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin-cedar-netlify-skew-protection.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-netlify-skew-protection.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAOlD,MAAM,WAAW,uCAAuC;IACtD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,mDAAmD;IACnD,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB;AAoBD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GACzD,mBAAmB,CAgCrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,uCAA4C,GACpD,MAAM,CAwOR"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { catchAllEntry } from "@universal-deploy/store";
|
|
4
|
+
import { getPaths } from "@cedarjs/project-config";
|
|
5
|
+
import { CEDAR_UNIVERSAL_DEPLOY_PLUGIN_NAME } from "./vite-plugin-cedar-universal-deploy.js";
|
|
6
|
+
const VIRTUAL_SKEW_TOKEN_ID = "virtual:cedar-netlify-skew-token";
|
|
7
|
+
const RESOLVED_SKEW_TOKEN_ID = "\0" + VIRTUAL_SKEW_TOKEN_ID;
|
|
8
|
+
function escapeRegExp(value) {
|
|
9
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
+
}
|
|
11
|
+
function isUniversalDeployPluginApi(api) {
|
|
12
|
+
return typeof api === "object" && api !== null && "routes" in api && Array.isArray(api.routes);
|
|
13
|
+
}
|
|
14
|
+
function getSkewProtectionPaths(config) {
|
|
15
|
+
const patterns = [];
|
|
16
|
+
const excludedPaths = [];
|
|
17
|
+
const baseIsUrl = /^([a-z][a-z\d+.-]*:)?\/\//i.test(config.base);
|
|
18
|
+
if (!baseIsUrl) {
|
|
19
|
+
const basePath = config.base.startsWith("/") ? config.base : "/";
|
|
20
|
+
const assetsPath = path.posix.join(basePath, config.build.assetsDir);
|
|
21
|
+
patterns.push(`^${escapeRegExp(assetsPath)}/`);
|
|
22
|
+
excludedPaths.push(`${assetsPath}/*`);
|
|
23
|
+
}
|
|
24
|
+
const udApi = config.plugins.find(
|
|
25
|
+
(plugin) => plugin.name === CEDAR_UNIVERSAL_DEPLOY_PLUGIN_NAME
|
|
26
|
+
)?.api;
|
|
27
|
+
if (isUniversalDeployPluginApi(udApi)) {
|
|
28
|
+
for (const route of udApi.routes) {
|
|
29
|
+
if (route.path.includes("*")) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
patterns.push(`^${escapeRegExp(route.path)}(/.*)?$`);
|
|
33
|
+
excludedPaths.push(route.path, `${route.path}/*`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { patterns, excludedPaths };
|
|
37
|
+
}
|
|
38
|
+
function cedarNetlifySkewProtectionPlugin(options = {}) {
|
|
39
|
+
const {
|
|
40
|
+
headerName = "cedar-skew-token",
|
|
41
|
+
queryName = "skew",
|
|
42
|
+
cookieName = "cedar-skew-token",
|
|
43
|
+
cookieMaxAge = 60 * 60 * 24
|
|
44
|
+
} = options;
|
|
45
|
+
const skewToken = process.env.NETLIFY_SKEW_PROTECTION_TOKEN ?? "";
|
|
46
|
+
let skewProtectionPaths = {
|
|
47
|
+
patterns: [],
|
|
48
|
+
excludedPaths: []
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
name: "cedar-netlify-skew-protection",
|
|
52
|
+
apply: "build",
|
|
53
|
+
configResolved(config) {
|
|
54
|
+
skewProtectionPaths = getSkewProtectionPaths(config);
|
|
55
|
+
},
|
|
56
|
+
transform(code, id) {
|
|
57
|
+
if (this.environment?.name !== "ssr" || id !== catchAllEntry) {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
const wrappedCode = code.replace(
|
|
61
|
+
/^export default \{/m,
|
|
62
|
+
"const __cedarSkewCatchAllHandler = {"
|
|
63
|
+
);
|
|
64
|
+
if (wrappedCode === code) {
|
|
65
|
+
this.warn(
|
|
66
|
+
'cedar-netlify-skew-protection: expected "export default {" in the Universal Deploy catch-all entry but did not find it \u2014 skipping skew-token cookie stamping on server-rendered HTML. This likely means @universal-deploy/vite changed how it generates the catch-all entry.'
|
|
67
|
+
);
|
|
68
|
+
return void 0;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
code: [
|
|
72
|
+
`import { CEDAR_SKEW_TOKEN, CEDAR_SKEW_COOKIE_NAME } from ${JSON.stringify(VIRTUAL_SKEW_TOKEN_ID)}`,
|
|
73
|
+
wrappedCode,
|
|
74
|
+
"",
|
|
75
|
+
"const __cedarSkewPinnedPatterns = [",
|
|
76
|
+
...skewProtectionPaths.patterns.map(
|
|
77
|
+
(pattern) => ` new RegExp(${JSON.stringify(pattern)}),`
|
|
78
|
+
),
|
|
79
|
+
"]",
|
|
80
|
+
"",
|
|
81
|
+
"const __cedarSkewOriginalFetch =",
|
|
82
|
+
" __cedarSkewCatchAllHandler.fetch.bind(__cedarSkewCatchAllHandler)",
|
|
83
|
+
"",
|
|
84
|
+
"__cedarSkewCatchAllHandler.fetch = async (request, ...args) => {",
|
|
85
|
+
" const response = await __cedarSkewOriginalFetch(request, ...args)",
|
|
86
|
+
"",
|
|
87
|
+
" // Only HTML responses to page loads set the cookie (see",
|
|
88
|
+
" // vite-plugin-cedar-netlify-skew-protection.ts). Requests to pinned",
|
|
89
|
+
" // paths are never page loads, even if an API function returns",
|
|
90
|
+
" // HTML, and may be served by an old deploy. Nothing to stamp",
|
|
91
|
+
" // without a token (e.g. a local `cedar build --ud` run outside a",
|
|
92
|
+
" // Netlify build) or a response (an unmatched route). Statuses",
|
|
93
|
+
" // outside 200-599 (e.g. 101 for a WebSocket upgrade) make the",
|
|
94
|
+
" // Response constructor below throw, and 204/304 responses have no",
|
|
95
|
+
" // body worth re-wrapping. Responses that already set our cookie",
|
|
96
|
+
" // are left alone to avoid a duplicate.",
|
|
97
|
+
" if (",
|
|
98
|
+
" !CEDAR_SKEW_TOKEN ||",
|
|
99
|
+
" !response ||",
|
|
100
|
+
" response.status < 200 ||",
|
|
101
|
+
" response.status > 599 ||",
|
|
102
|
+
" response.status === 204 ||",
|
|
103
|
+
" response.status === 304 ||",
|
|
104
|
+
' !(response.headers.get("content-type") ?? "").includes("text/html") ||',
|
|
105
|
+
" __cedarSkewPinnedPatterns.some((pattern) =>",
|
|
106
|
+
" pattern.test(new URL(request.url).pathname),",
|
|
107
|
+
" ) ||",
|
|
108
|
+
' (response.headers.get("set-cookie") ?? "").includes(',
|
|
109
|
+
" `${CEDAR_SKEW_COOKIE_NAME}=`,",
|
|
110
|
+
" )",
|
|
111
|
+
" ) {",
|
|
112
|
+
" return response",
|
|
113
|
+
" }",
|
|
114
|
+
"",
|
|
115
|
+
" const headers = new Headers(response.headers)",
|
|
116
|
+
" headers.append(",
|
|
117
|
+
' "set-cookie",',
|
|
118
|
+
` \`\${CEDAR_SKEW_COOKIE_NAME}=\${CEDAR_SKEW_TOKEN}; Path=/; Max-Age=${cookieMaxAge}; HttpOnly; Secure; SameSite=Lax\`,`,
|
|
119
|
+
" )",
|
|
120
|
+
"",
|
|
121
|
+
" return new Response(response.body, {",
|
|
122
|
+
" status: response.status,",
|
|
123
|
+
" statusText: response.statusText,",
|
|
124
|
+
" headers,",
|
|
125
|
+
" })",
|
|
126
|
+
"}",
|
|
127
|
+
"",
|
|
128
|
+
"export default __cedarSkewCatchAllHandler"
|
|
129
|
+
].join("\n"),
|
|
130
|
+
map: null
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
resolveId(id) {
|
|
134
|
+
if (id === VIRTUAL_SKEW_TOKEN_ID) {
|
|
135
|
+
return RESOLVED_SKEW_TOKEN_ID;
|
|
136
|
+
}
|
|
137
|
+
return void 0;
|
|
138
|
+
},
|
|
139
|
+
load(id) {
|
|
140
|
+
if (id !== RESOLVED_SKEW_TOKEN_ID) {
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
143
|
+
return [
|
|
144
|
+
`export const CEDAR_SKEW_TOKEN = ${JSON.stringify(skewToken)}`,
|
|
145
|
+
`export const CEDAR_SKEW_HEADER_NAME = ${JSON.stringify(headerName)}`,
|
|
146
|
+
`export const CEDAR_SKEW_QUERY_NAME = ${JSON.stringify(queryName)}`,
|
|
147
|
+
`export const CEDAR_SKEW_COOKIE_NAME = ${JSON.stringify(cookieName)}`,
|
|
148
|
+
""
|
|
149
|
+
].join("\n");
|
|
150
|
+
},
|
|
151
|
+
writeBundle() {
|
|
152
|
+
if (this.environment?.name !== "client") {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!skewToken) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const netlifyV1Dir = path.join(getPaths().web.base, ".netlify", "v1");
|
|
159
|
+
fs.mkdirSync(netlifyV1Dir, { recursive: true });
|
|
160
|
+
const manifest = {
|
|
161
|
+
patterns: skewProtectionPaths.patterns,
|
|
162
|
+
sources: [
|
|
163
|
+
{ type: "header", name: headerName },
|
|
164
|
+
{ type: "query", name: queryName },
|
|
165
|
+
{ type: "cookie", name: cookieName }
|
|
166
|
+
]
|
|
167
|
+
};
|
|
168
|
+
fs.writeFileSync(
|
|
169
|
+
path.join(netlifyV1Dir, "skew-protection.json"),
|
|
170
|
+
JSON.stringify(manifest, null, 2) + "\n"
|
|
171
|
+
);
|
|
172
|
+
const edgeFunctionsDir = path.join(netlifyV1Dir, "edge-functions");
|
|
173
|
+
fs.mkdirSync(edgeFunctionsDir, { recursive: true });
|
|
174
|
+
fs.writeFileSync(
|
|
175
|
+
path.join(edgeFunctionsDir, "cedar-skew-cookie.js"),
|
|
176
|
+
[
|
|
177
|
+
"// Generated by @cedarjs/vite. Stamps the skew-protection cookie on",
|
|
178
|
+
"// static HTML served from Netlify's CDN. See",
|
|
179
|
+
"// vite-plugin-cedar-netlify-skew-protection.ts for the full picture.",
|
|
180
|
+
"export default async (request, context) => {",
|
|
181
|
+
" const response = await context.next()",
|
|
182
|
+
"",
|
|
183
|
+
` const cookieName = ${JSON.stringify(cookieName)}`,
|
|
184
|
+
"",
|
|
185
|
+
" // Only HTML responses set the cookie. Statuses outside 200-599",
|
|
186
|
+
" // (e.g. 101 for a WebSocket upgrade) make the Response",
|
|
187
|
+
" // constructor below throw, and 204/304 responses have no body",
|
|
188
|
+
" // worth re-wrapping. Responses that already set our cookie (from",
|
|
189
|
+
" // the Universal Deploy wrapper) are left alone.",
|
|
190
|
+
" if (",
|
|
191
|
+
" response.status < 200 ||",
|
|
192
|
+
" response.status > 599 ||",
|
|
193
|
+
" response.status === 204 ||",
|
|
194
|
+
" response.status === 304 ||",
|
|
195
|
+
' !(response.headers.get("content-type") ?? "").includes("text/html") ||',
|
|
196
|
+
' (response.headers.get("set-cookie") ?? "").includes(`${cookieName}=`)',
|
|
197
|
+
" ) {",
|
|
198
|
+
" return response",
|
|
199
|
+
" }",
|
|
200
|
+
"",
|
|
201
|
+
" const token = context.deploy?.skewProtectionToken",
|
|
202
|
+
" if (!token) {",
|
|
203
|
+
" return response",
|
|
204
|
+
" }",
|
|
205
|
+
"",
|
|
206
|
+
" const headers = new Headers(response.headers)",
|
|
207
|
+
" headers.append(",
|
|
208
|
+
' "set-cookie",',
|
|
209
|
+
` \`\${cookieName}=\${token}; Path=/; Max-Age=${cookieMaxAge}; HttpOnly; Secure; SameSite=Lax\`,`,
|
|
210
|
+
" )",
|
|
211
|
+
"",
|
|
212
|
+
" return new Response(response.body, {",
|
|
213
|
+
" status: response.status,",
|
|
214
|
+
" statusText: response.statusText,",
|
|
215
|
+
" headers,",
|
|
216
|
+
" })",
|
|
217
|
+
"}",
|
|
218
|
+
"",
|
|
219
|
+
"export const config = {",
|
|
220
|
+
' path: "/*",',
|
|
221
|
+
` excludedPath: ${JSON.stringify(skewProtectionPaths.excludedPaths)},`,
|
|
222
|
+
"}",
|
|
223
|
+
""
|
|
224
|
+
].join("\n")
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
export {
|
|
230
|
+
cedarNetlifySkewProtectionPlugin,
|
|
231
|
+
getSkewProtectionPaths
|
|
232
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-cedar-otel-wrapping.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-otel-wrapping.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"vite-plugin-cedar-otel-wrapping.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-otel-wrapping.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAQlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAkChD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CA+Ef"}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { parseSync } from "oxc-parser";
|
|
2
2
|
import { normalizePath } from "vite";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createPrismaClientFileMatcher,
|
|
5
|
+
getPaths
|
|
6
|
+
} from "@cedarjs/project-config";
|
|
4
7
|
function cedarOtelWrappingPlugin() {
|
|
8
|
+
const prismaClientFiles = createPrismaClientFileMatcher();
|
|
5
9
|
return {
|
|
6
10
|
name: "cedar-otel-wrapping",
|
|
7
|
-
|
|
11
|
+
async buildStart() {
|
|
12
|
+
await prismaClientFiles.load();
|
|
13
|
+
},
|
|
14
|
+
async transform(code, id) {
|
|
8
15
|
let apiSrc;
|
|
9
16
|
try {
|
|
10
17
|
apiSrc = normalizePath(getPaths().api.src);
|
|
@@ -14,6 +21,9 @@ function cedarOtelWrappingPlugin() {
|
|
|
14
21
|
if (!normalizePath(id).startsWith(apiSrc + "/")) {
|
|
15
22
|
return null;
|
|
16
23
|
}
|
|
24
|
+
if (await prismaClientFiles.matches(id)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
17
27
|
const relativePath = normalizePath(id).slice(apiSrc.length + 1);
|
|
18
28
|
const apiFolder = relativePath.split("/")[0] ?? "?";
|
|
19
29
|
const result = applyOtelWrapping(code, id, apiFolder);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* For the bundled API build (`cedar build --ud`): the sandboxed child
|
|
4
|
+
* scripts in api/src are extra entries of the build (see
|
|
5
|
+
* `findSandboxChildScripts()`), so each comes out as
|
|
6
|
+
* `sandbox-children/<name>.child.js`. This plugin checks that each child
|
|
7
|
+
* stands alone, importing only packages and Node builtins (it can read
|
|
8
|
+
* nothing of the app), and then copies the packages they import into
|
|
9
|
+
* `sandbox-children/node_modules`.
|
|
10
|
+
*
|
|
11
|
+
* `findChildScript()` from `@cedarjs/api/sandbox` finds the children there
|
|
12
|
+
* from code in the bundle.
|
|
13
|
+
*/
|
|
14
|
+
export declare function cedarSandboxChildrenPlugin({ environment, children, }: {
|
|
15
|
+
/** The bundled build's environment */
|
|
16
|
+
environment: string;
|
|
17
|
+
/** The child scripts' entries: `{ 'sandbox-children/x.child': file }` */
|
|
18
|
+
children: Record<string, string>;
|
|
19
|
+
}): Plugin;
|
|
20
|
+
//# sourceMappingURL=vite-plugin-cedar-sandbox-children.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin-cedar-sandbox-children.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-sandbox-children.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AASlC;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,WAAW,EACX,QAAQ,GACT,EAAE;IACD,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC,GAAG,MAAM,CAmDT"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { normalizePath } from "vite";
|
|
3
|
+
import {
|
|
4
|
+
SANDBOX_CHILDREN_DIR,
|
|
5
|
+
vendorSandboxChildPackages
|
|
6
|
+
} from "../lib/sandboxChildren.js";
|
|
7
|
+
function cedarSandboxChildrenPlugin({
|
|
8
|
+
environment,
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
11
|
+
const sources = new Set(
|
|
12
|
+
Object.values(children).map((file) => normalizePath(file))
|
|
13
|
+
);
|
|
14
|
+
let imports = [];
|
|
15
|
+
return {
|
|
16
|
+
name: "cedar-sandbox-children",
|
|
17
|
+
apply: "build",
|
|
18
|
+
applyToEnvironment(env) {
|
|
19
|
+
return env.name === environment;
|
|
20
|
+
},
|
|
21
|
+
generateBundle(_options, bundle) {
|
|
22
|
+
imports = [];
|
|
23
|
+
for (const chunk of Object.values(bundle)) {
|
|
24
|
+
if (chunk.type !== "chunk" || !chunk.facadeModuleId) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const source = normalizePath(chunk.facadeModuleId);
|
|
28
|
+
if (!sources.has(source)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const bundled = [...chunk.imports, ...chunk.dynamicImports].filter(
|
|
32
|
+
(id) => id in bundle
|
|
33
|
+
);
|
|
34
|
+
if (bundled.length > 0) {
|
|
35
|
+
this.error(
|
|
36
|
+
`${path.basename(source)} imports your app's own code (${bundled.join(", ")}). A sandboxed child script may import only packages and Node builtins: it runs in a process that can't read the rest of your app.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
imports.push({
|
|
40
|
+
source,
|
|
41
|
+
imports: [...chunk.imports, ...chunk.dynamicImports]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
writeBundle(options) {
|
|
46
|
+
if (imports.length === 0 || !options.dir) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
vendorSandboxChildPackages(
|
|
50
|
+
path.join(options.dir, SANDBOX_CHILDREN_DIR),
|
|
51
|
+
imports
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
cedarSandboxChildrenPlugin
|
|
58
|
+
};
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
|
+
import type { CedarRouteRecord } from '@cedarjs/api/runtime';
|
|
2
3
|
export interface CedarUniversalDeployPluginOptions {
|
|
3
4
|
apiRootPath?: string;
|
|
4
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Exposed as the plugin's `api` property so other plugins (e.g.
|
|
8
|
+
* `cedarNetlifySkewProtectionPlugin`) can find the API routes this plugin
|
|
9
|
+
* registers.
|
|
10
|
+
*/
|
|
11
|
+
export interface CedarUniversalDeployPluginApi {
|
|
12
|
+
routes: CedarRouteRecord[];
|
|
13
|
+
}
|
|
14
|
+
export declare const CEDAR_UNIVERSAL_DEPLOY_PLUGIN_NAME = "cedar-universal-deploy";
|
|
5
15
|
export declare function cedarUniversalDeployPlugin(options?: CedarUniversalDeployPluginOptions): Plugin;
|
|
6
16
|
//# sourceMappingURL=vite-plugin-cedar-universal-deploy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-cedar-universal-deploy.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-universal-deploy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"vite-plugin-cedar-universal-deploy.d.ts","sourceRoot":"","sources":["../../src/plugins/vite-plugin-cedar-universal-deploy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAGlC,OAAO,KAAK,EAEV,gBAAgB,EAEjB,MAAM,sBAAsB,CAAA;AAS7B,MAAM,WAAW,iCAAiC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAC3B;AAED,eAAO,MAAM,kCAAkC,2BAA2B,CAAA;AA6G1E,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,iCAAsC,GAC9C,MAAM,CA6GR"}
|
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { addEntry } from "@universal-deploy/store";
|
|
3
3
|
import { findApiServerFunctions } from "@cedarjs/internal/dist/files.js";
|
|
4
4
|
import { getPaths } from "@cedarjs/project-config";
|
|
5
|
+
const CEDAR_UNIVERSAL_DEPLOY_PLUGIN_NAME = "cedar-universal-deploy";
|
|
5
6
|
const VIRTUAL_CEDAR_FN_PREFIX = "virtual:cedar-api:fn:";
|
|
6
7
|
const RESOLVED_CEDAR_FN_PREFIX = "\0virtual:cedar-api:fn:";
|
|
7
8
|
const GRAPHQL_METHODS = ["GET", "POST", "OPTIONS"];
|
|
@@ -66,9 +67,11 @@ function toEntryMeta(route) {
|
|
|
66
67
|
function cedarUniversalDeployPlugin(options = {}) {
|
|
67
68
|
const effectiveApiRootPath = process.env.CEDAR_API_ROOT_PATH ?? options.apiRootPath;
|
|
68
69
|
const routes = discoverCedarRoutes(effectiveApiRootPath ?? "/");
|
|
70
|
+
const api = { routes };
|
|
69
71
|
return {
|
|
70
|
-
name:
|
|
72
|
+
name: CEDAR_UNIVERSAL_DEPLOY_PLUGIN_NAME,
|
|
71
73
|
apply: "build",
|
|
74
|
+
api,
|
|
72
75
|
config: {
|
|
73
76
|
order: "pre",
|
|
74
77
|
handler() {
|
|
@@ -308,5 +311,6 @@ function createGraphQLFetch(graphqlOptions) {
|
|
|
308
311
|
};
|
|
309
312
|
}
|
|
310
313
|
export {
|
|
314
|
+
CEDAR_UNIVERSAL_DEPLOY_PLUGIN_NAME,
|
|
311
315
|
cedarUniversalDeployPlugin
|
|
312
316
|
};
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* buildFeServer -> buildRscFeServer -> rscBuildClient
|
|
4
4
|
* Generate the client bundle
|
|
5
5
|
*/
|
|
6
|
-
export declare function rscBuildClient(clientEntryFiles: Record<string, string>): Promise<[import("rollup").OutputChunk, ...(import("rollup").
|
|
6
|
+
export declare function rscBuildClient(clientEntryFiles: Record<string, string>): Promise<[import("rollup").OutputChunk, ...(import("rollup").OutputAsset | import("rollup").OutputChunk)[]]>;
|
|
7
7
|
//# sourceMappingURL=rscBuildClient.d.ts.map
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* buildFeServer -> buildRscFeServer -> rscBuildForServer
|
|
4
4
|
* Generate the output to be used by the rsc worker (not the actual server!)
|
|
5
5
|
*/
|
|
6
|
-
export declare function rscBuildForServer(clientEntryFiles: Record<string, string>, serverEntryFiles: Record<string, string>, customModules: Record<string, string>): Promise<[import("rollup").OutputChunk, ...(import("rollup").
|
|
6
|
+
export declare function rscBuildForServer(clientEntryFiles: Record<string, string>, serverEntryFiles: Record<string, string>, customModules: Record<string, string>): Promise<[import("rollup").OutputChunk, ...(import("rollup").OutputAsset | import("rollup").OutputChunk)[]]>;
|
|
7
7
|
//# sourceMappingURL=rscBuildForServer.d.ts.map
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
export declare function rscBuildForSsr({ clientEntryFiles, verbose, }: {
|
|
6
6
|
clientEntryFiles: Record<string, string>;
|
|
7
7
|
verbose?: boolean;
|
|
8
|
-
}): Promise<[import("rollup").OutputChunk, ...(import("rollup").
|
|
8
|
+
}): Promise<[import("rollup").OutputChunk, ...(import("rollup").OutputAsset | import("rollup").OutputChunk)[]]>;
|
|
9
9
|
//# sourceMappingURL=rscBuildForSsr.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/vite",
|
|
3
|
-
"version": "7.0.1-next.
|
|
3
|
+
"version": "7.0.1-next.467",
|
|
4
4
|
"description": "Vite configuration package for CedarJS",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -52,41 +52,41 @@
|
|
|
52
52
|
"@babel/generator": "7.29.8",
|
|
53
53
|
"@babel/parser": "7.29.9",
|
|
54
54
|
"@babel/preset-typescript": "7.29.7",
|
|
55
|
-
"@babel/traverse": "7.29.
|
|
55
|
+
"@babel/traverse": "7.29.10",
|
|
56
56
|
"@babel/types": "7.29.8",
|
|
57
|
-
"@cedarjs/api": "7.0.1-next.
|
|
58
|
-
"@cedarjs/api-server": "7.0.1-next.
|
|
59
|
-
"@cedarjs/babel-config": "7.0.1-next.
|
|
60
|
-
"@cedarjs/context": "7.0.1-next.
|
|
61
|
-
"@cedarjs/graphql-server": "7.0.1-next.
|
|
62
|
-
"@cedarjs/internal": "7.0.1-next.
|
|
63
|
-
"@cedarjs/jobs": "7.0.1-next.
|
|
64
|
-
"@cedarjs/project-config": "7.0.1-next.
|
|
65
|
-
"@cedarjs/server-store": "7.0.1-next.
|
|
66
|
-
"@cedarjs/structure": "7.0.1-next.
|
|
67
|
-
"@cedarjs/testing": "7.0.1-next.
|
|
68
|
-
"@swc/core": "1.16.
|
|
69
|
-
"@universal-deploy/store": "^0.
|
|
70
|
-
"@universal-deploy/vite": "^0.
|
|
57
|
+
"@cedarjs/api": "7.0.1-next.467",
|
|
58
|
+
"@cedarjs/api-server": "7.0.1-next.467",
|
|
59
|
+
"@cedarjs/babel-config": "7.0.1-next.467",
|
|
60
|
+
"@cedarjs/context": "7.0.1-next.467",
|
|
61
|
+
"@cedarjs/graphql-server": "7.0.1-next.467",
|
|
62
|
+
"@cedarjs/internal": "7.0.1-next.467",
|
|
63
|
+
"@cedarjs/jobs": "7.0.1-next.467",
|
|
64
|
+
"@cedarjs/project-config": "7.0.1-next.467",
|
|
65
|
+
"@cedarjs/server-store": "7.0.1-next.467",
|
|
66
|
+
"@cedarjs/structure": "7.0.1-next.467",
|
|
67
|
+
"@cedarjs/testing": "7.0.1-next.467",
|
|
68
|
+
"@swc/core": "1.16.18",
|
|
69
|
+
"@universal-deploy/store": "^0.3.0",
|
|
70
|
+
"@universal-deploy/vite": "^0.2.0",
|
|
71
71
|
"@vitejs/plugin-react": "4.7.0",
|
|
72
|
-
"@whatwg-node/fetch": "0.12.
|
|
72
|
+
"@whatwg-node/fetch": "0.12.1",
|
|
73
73
|
"@whatwg-node/server": "0.13.0",
|
|
74
|
-
"acorn": "8.
|
|
74
|
+
"acorn": "8.19.0",
|
|
75
75
|
"acorn-loose": "8.5.2",
|
|
76
76
|
"ansis": "4.4.0",
|
|
77
77
|
"busboy": "^1.6.0",
|
|
78
78
|
"dotenv-defaults": "5.0.2",
|
|
79
|
-
"express": "5.
|
|
79
|
+
"express": "5.3.0",
|
|
80
80
|
"fast-glob": "3.3.3",
|
|
81
|
-
"find-my-way": "9.
|
|
81
|
+
"find-my-way": "9.10.0",
|
|
82
82
|
"http-proxy-middleware": "3.0.7",
|
|
83
83
|
"isbot": "5.2.2",
|
|
84
84
|
"magic-string": "0.30.21",
|
|
85
|
-
"oxc-parser": "0.
|
|
85
|
+
"oxc-parser": "0.153.0",
|
|
86
86
|
"react-server-dom-webpack": "19.3.0",
|
|
87
87
|
"unimport": "5.7.0",
|
|
88
88
|
"unplugin-auto-import": "19.3.0",
|
|
89
|
-
"vite": "7.3.
|
|
89
|
+
"vite": "7.3.7",
|
|
90
90
|
"vite-plugin-cjs-interop": "2.4.4",
|
|
91
91
|
"vite-plugin-graphql-tag": "0.1.1",
|
|
92
92
|
"vite-tsconfig-paths": "^6.1.1",
|
|
@@ -94,34 +94,34 @@
|
|
|
94
94
|
"yargs-parser": "21.1.1"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@cedarjs/auth": "7.0.1-next.
|
|
98
|
-
"@cedarjs/framework-tools": "7.0.1-next.
|
|
99
|
-
"@cedarjs/router": "7.0.1-next.
|
|
100
|
-
"@cedarjs/web": "7.0.1-next.
|
|
97
|
+
"@cedarjs/auth": "7.0.1-next.467",
|
|
98
|
+
"@cedarjs/framework-tools": "7.0.1-next.467",
|
|
99
|
+
"@cedarjs/router": "7.0.1-next.467",
|
|
100
|
+
"@cedarjs/web": "7.0.1-next.467",
|
|
101
101
|
"@dr.pogodin/react-helmet": "2.0.4",
|
|
102
102
|
"@hyrious/esbuild-plugin-commonjs": "0.2.6",
|
|
103
103
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
104
|
-
"@oxc-project/types": "^0.
|
|
105
|
-
"@types/aws-lambda": "8.10.
|
|
104
|
+
"@oxc-project/types": "^0.153.0",
|
|
105
|
+
"@types/aws-lambda": "8.10.164",
|
|
106
106
|
"@types/busboy": "^1",
|
|
107
107
|
"@types/express": "5.0.6",
|
|
108
108
|
"@types/react": "^19.2.0",
|
|
109
109
|
"@types/ws": "^8",
|
|
110
110
|
"@types/yargs-parser": "21.0.3",
|
|
111
|
-
"concurrently": "9.2.
|
|
112
|
-
"memfs": "4.
|
|
113
|
-
"publint": "0.3.
|
|
111
|
+
"concurrently": "9.2.5",
|
|
112
|
+
"memfs": "4.80.0",
|
|
113
|
+
"publint": "0.3.25",
|
|
114
114
|
"react": "19.3.0",
|
|
115
115
|
"react-dom": "19.3.0",
|
|
116
|
-
"rollup": "4.
|
|
116
|
+
"rollup": "4.64.5",
|
|
117
117
|
"ts-dedent": "2.3.0",
|
|
118
118
|
"typescript": "5.9.3",
|
|
119
119
|
"vitest": "4.1.11"
|
|
120
120
|
},
|
|
121
121
|
"peerDependencies": {
|
|
122
|
-
"@cedarjs/auth": "7.0.1-next.
|
|
123
|
-
"@cedarjs/router": "7.0.1-next.
|
|
124
|
-
"@cedarjs/web": "7.0.1-next.
|
|
122
|
+
"@cedarjs/auth": "7.0.1-next.467",
|
|
123
|
+
"@cedarjs/router": "7.0.1-next.467",
|
|
124
|
+
"@cedarjs/web": "7.0.1-next.467",
|
|
125
125
|
"react": "19.3.0",
|
|
126
126
|
"react-dom": "19.3.0"
|
|
127
127
|
},
|