@cedarjs/vite 5.0.6 → 5.0.7-next.219

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/api/vite-plugin-cedar-vitest-api-preset.d.ts.map +1 -1
  2. package/dist/api/vite-plugin-cedar-vitest-api-preset.js +4 -0
  3. package/dist/apiDevMiddleware.d.ts.map +1 -1
  4. package/dist/apiDevMiddleware.js +117 -15
  5. package/dist/buildApp.d.ts.map +1 -1
  6. package/dist/buildApp.js +79 -18
  7. package/dist/buildRouteHooks.d.ts.map +1 -1
  8. package/dist/buildRouteHooks.js +36 -4
  9. package/dist/bundled/react-server-dom-webpack.server.js +192 -99
  10. package/dist/cedar-unified-dev.d.ts +18 -0
  11. package/dist/cedar-unified-dev.d.ts.map +1 -1
  12. package/dist/cedar-unified-dev.js +39 -5
  13. package/dist/devFeServer.js +3 -8
  14. package/dist/index.d.ts +11 -4
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +51 -19
  17. package/dist/lib/generateDiffSourceMap.d.ts +18 -0
  18. package/dist/lib/generateDiffSourceMap.d.ts.map +1 -0
  19. package/dist/lib/generateDiffSourceMap.js +151 -0
  20. package/dist/lib/getMergedConfig.d.ts.map +1 -1
  21. package/dist/lib/getMergedConfig.js +16 -6
  22. package/dist/lib/registerFwGlobalsAndShims.d.ts.map +1 -1
  23. package/dist/lib/registerFwGlobalsAndShims.js +14 -4
  24. package/dist/plugins/vite-plugin-cedar-api-import-guard.d.ts +13 -0
  25. package/dist/plugins/vite-plugin-cedar-api-import-guard.d.ts.map +1 -0
  26. package/dist/plugins/vite-plugin-cedar-api-import-guard.js +17 -0
  27. package/dist/plugins/vite-plugin-cedar-auto-import.d.ts +1 -1
  28. package/dist/plugins/vite-plugin-cedar-auto-import.d.ts.map +1 -1
  29. package/dist/plugins/vite-plugin-cedar-auto-import.js +8 -1
  30. package/dist/plugins/vite-plugin-cedar-cell.d.ts.map +1 -1
  31. package/dist/plugins/vite-plugin-cedar-cell.js +2 -1
  32. package/dist/plugins/vite-plugin-cedar-data-uri-shim.d.ts +3 -0
  33. package/dist/plugins/vite-plugin-cedar-data-uri-shim.d.ts.map +1 -0
  34. package/dist/plugins/vite-plugin-cedar-data-uri-shim.js +43 -0
  35. package/dist/plugins/vite-plugin-cedar-directory-named-import.d.ts +12 -0
  36. package/dist/plugins/vite-plugin-cedar-directory-named-import.d.ts.map +1 -0
  37. package/dist/plugins/vite-plugin-cedar-directory-named-import.js +35 -0
  38. package/dist/plugins/vite-plugin-cedar-gqlorm-inject.d.ts +29 -0
  39. package/dist/plugins/vite-plugin-cedar-gqlorm-inject.d.ts.map +1 -0
  40. package/dist/plugins/vite-plugin-cedar-gqlorm-inject.js +76 -0
  41. package/dist/plugins/vite-plugin-cedar-graphql-options-extract.d.ts +42 -0
  42. package/dist/plugins/vite-plugin-cedar-graphql-options-extract.d.ts.map +1 -0
  43. package/dist/plugins/vite-plugin-cedar-graphql-options-extract.js +103 -0
  44. package/dist/plugins/vite-plugin-cedar-import-dir.d.ts.map +1 -1
  45. package/dist/plugins/vite-plugin-cedar-import-dir.js +44 -31
  46. package/dist/plugins/vite-plugin-cedar-log-formatter-dev.d.ts +28 -0
  47. package/dist/plugins/vite-plugin-cedar-log-formatter-dev.d.ts.map +1 -0
  48. package/dist/plugins/vite-plugin-cedar-log-formatter-dev.js +67 -0
  49. package/dist/plugins/vite-plugin-cedar-mock-cell-data.d.ts +28 -0
  50. package/dist/plugins/vite-plugin-cedar-mock-cell-data.d.ts.map +1 -0
  51. package/dist/plugins/vite-plugin-cedar-mock-cell-data.js +247 -0
  52. package/dist/plugins/vite-plugin-cedar-otel-wrapping.d.ts +39 -0
  53. package/dist/plugins/vite-plugin-cedar-otel-wrapping.d.ts.map +1 -0
  54. package/dist/plugins/vite-plugin-cedar-otel-wrapping.js +200 -0
  55. package/dist/plugins/vite-plugin-cedar-universal-deploy.d.ts.map +1 -1
  56. package/dist/plugins/vite-plugin-cedar-universal-deploy.js +92 -90
  57. package/dist/plugins/vite-plugin-cedarjs-job-path-injector.d.ts +29 -0
  58. package/dist/plugins/vite-plugin-cedarjs-job-path-injector.d.ts.map +1 -1
  59. package/dist/plugins/vite-plugin-cedarjs-job-path-injector.js +63 -81
  60. package/dist/plugins/vite-plugin-cedarjs-resolve-cedar-style-imports.d.ts.map +1 -1
  61. package/dist/plugins/vite-plugin-cedarjs-resolve-cedar-style-imports.js +14 -0
  62. package/dist/plugins/{vite-plugin-cedar-context-wrapping.d.ts → vite-plugin-handler-als-wrapping.d.ts} +12 -12
  63. package/dist/plugins/vite-plugin-handler-als-wrapping.d.ts.map +1 -0
  64. package/dist/plugins/{vite-plugin-cedar-context-wrapping.js → vite-plugin-handler-als-wrapping.js} +16 -16
  65. package/dist/plugins/vite-plugin-swap-apollo-provider.d.ts +3 -0
  66. package/dist/plugins/vite-plugin-swap-apollo-provider.d.ts.map +1 -1
  67. package/dist/plugins/vite-plugin-swap-apollo-provider.js +2 -2
  68. package/dist/rsc/rscBuildForSsr.d.ts.map +1 -1
  69. package/dist/rsc/rscBuildForSsr.js +3 -5
  70. package/dist/streaming/buildForStreamingServer.d.ts.map +1 -1
  71. package/dist/streaming/buildForStreamingServer.js +3 -5
  72. package/package.json +41 -52
  73. package/dist/cjs/ClientRouter.d.ts +0 -1
  74. package/dist/cjs/api/vite-plugin-cedar-vitest-api-preset.js +0 -37
  75. package/dist/cjs/apiDevMiddleware.js +0 -371
  76. package/dist/cjs/build/build.d.ts +0 -1
  77. package/dist/cjs/build/build.js +0 -58
  78. package/dist/cjs/buildApp.js +0 -306
  79. package/dist/cjs/buildFeServer.d.ts +0 -1
  80. package/dist/cjs/buildFeServer.js +0 -63
  81. package/dist/cjs/buildRouteHooks.js +0 -80
  82. package/dist/cjs/buildRouteManifest.js +0 -92
  83. package/dist/cjs/buildRscClientAndServer.js +0 -54
  84. package/dist/cjs/cedar-unified-dev.js +0 -310
  85. package/dist/cjs/client.d.ts +0 -1
  86. package/dist/cjs/clientSsr.d.ts +0 -1
  87. package/dist/cjs/devFeServer.js +0 -157
  88. package/dist/cjs/index.d.ts +0 -1
  89. package/dist/cjs/index.js +0 -141
  90. package/dist/cjs/lib/StatusError.js +0 -37
  91. package/dist/cjs/lib/entries.js +0 -52
  92. package/dist/cjs/lib/getMergedConfig.js +0 -185
  93. package/dist/cjs/lib/onWarn.js +0 -36
  94. package/dist/cjs/lib/registerFwGlobalsAndShims.js +0 -102
  95. package/dist/cjs/lib/workspacePackageAliases.js +0 -107
  96. package/dist/cjs/middleware/index.js +0 -22
  97. package/dist/cjs/middleware/invokeMiddleware.js +0 -52
  98. package/dist/cjs/middleware/register.js +0 -105
  99. package/dist/cjs/middleware/types.js +0 -16
  100. package/dist/cjs/package.json +0 -1
  101. package/dist/cjs/plugins/vite-plugin-cedar-auto-import.js +0 -107
  102. package/dist/cjs/plugins/vite-plugin-cedar-cell.js +0 -183
  103. package/dist/cjs/plugins/vite-plugin-cedar-cjs-compat.js +0 -341
  104. package/dist/cjs/plugins/vite-plugin-cedar-context-wrapping.js +0 -95
  105. package/dist/cjs/plugins/vite-plugin-cedar-entry-injection.js +0 -107
  106. package/dist/cjs/plugins/vite-plugin-cedar-html-env.js +0 -67
  107. package/dist/cjs/plugins/vite-plugin-cedar-import-dir.js +0 -118
  108. package/dist/cjs/plugins/vite-plugin-cedar-node-polyfills.js +0 -43
  109. package/dist/cjs/plugins/vite-plugin-cedar-remove-dev-fatal-error-page.js +0 -61
  110. package/dist/cjs/plugins/vite-plugin-cedar-remove-from-bundle.js +0 -76
  111. package/dist/cjs/plugins/vite-plugin-cedar-routes-auto-loader.js +0 -126
  112. package/dist/cjs/plugins/vite-plugin-cedar-universal-deploy.js +0 -346
  113. package/dist/cjs/plugins/vite-plugin-cedar-wait-for-api-server.js +0 -134
  114. package/dist/cjs/plugins/vite-plugin-cedarjs-job-path-injector.js +0 -134
  115. package/dist/cjs/plugins/vite-plugin-cedarjs-resolve-cedar-style-imports.js +0 -106
  116. package/dist/cjs/plugins/vite-plugin-jsx-loader.js +0 -42
  117. package/dist/cjs/plugins/vite-plugin-merged-config.js +0 -39
  118. package/dist/cjs/plugins/vite-plugin-rsc-analyze.js +0 -104
  119. package/dist/cjs/plugins/vite-plugin-rsc-reload.js +0 -75
  120. package/dist/cjs/plugins/vite-plugin-rsc-routes-auto-loader.js +0 -159
  121. package/dist/cjs/plugins/vite-plugin-rsc-routes-imports.js +0 -125
  122. package/dist/cjs/plugins/vite-plugin-rsc-ssr-router-import.js +0 -75
  123. package/dist/cjs/plugins/vite-plugin-rsc-transform-client.js +0 -228
  124. package/dist/cjs/plugins/vite-plugin-rsc-transform-server.js +0 -398
  125. package/dist/cjs/plugins/vite-plugin-swap-apollo-provider.js +0 -46
  126. package/dist/cjs/rsc/rscBuildAnalyze.js +0 -126
  127. package/dist/cjs/rsc/rscBuildClient.js +0 -91
  128. package/dist/cjs/rsc/rscBuildCopyCssAssets.js +0 -56
  129. package/dist/cjs/rsc/rscBuildEntriesFile.js +0 -115
  130. package/dist/cjs/rsc/rscBuildForServer.js +0 -168
  131. package/dist/cjs/rsc/rscBuildForSsr.js +0 -173
  132. package/dist/cjs/rsc/rscBuildRwEnvVars.js +0 -56
  133. package/dist/cjs/rsc/rscRenderer.js +0 -165
  134. package/dist/cjs/rsc/rscRequestHandler.js +0 -162
  135. package/dist/cjs/rsc/rscStudioHandlers.js +0 -156
  136. package/dist/cjs/runFeServer.js +0 -165
  137. package/dist/cjs/streaming/buildForStreamingServer.js +0 -65
  138. package/dist/cjs/streaming/collectCss.js +0 -52
  139. package/dist/cjs/streaming/createReactStreamingHandler.js +0 -173
  140. package/dist/cjs/streaming/streamHelpers.js +0 -230
  141. package/dist/cjs/streaming/transforms/bufferedTransform.js +0 -61
  142. package/dist/cjs/streaming/transforms/cancelTimeoutTransform.js +0 -34
  143. package/dist/cjs/streaming/transforms/encode-decode.js +0 -36
  144. package/dist/cjs/streaming/transforms/serverInjectionTransform.js +0 -84
  145. package/dist/cjs/streaming/triggerRouteHooks.js +0 -96
  146. package/dist/cjs/types.js +0 -16
  147. package/dist/cjs/utils.js +0 -92
  148. package/dist/package.json +0 -1
  149. package/dist/plugins/vite-plugin-cedar-context-wrapping.d.ts.map +0 -1
  150. package/dist/plugins/vite-plugin-cedar-node-polyfills.d.ts +0 -3
  151. package/dist/plugins/vite-plugin-cedar-node-polyfills.d.ts.map +0 -1
  152. package/dist/plugins/vite-plugin-cedar-node-polyfills.js +0 -19
@@ -0,0 +1,247 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import babelGenerator from "@babel/generator";
4
+ import { parse as babelParse } from "@babel/parser";
5
+ import babelTraverse from "@babel/traverse";
6
+ import * as t from "@babel/types";
7
+ import fg from "fast-glob";
8
+ import { parse as graphqlParse, Kind } from "graphql";
9
+ const traverse = babelTraverse.default ?? babelTraverse;
10
+ const generate = babelGenerator.default ?? babelGenerator;
11
+ function cedarMockCellDataPlugin() {
12
+ return {
13
+ name: "cedar-mock-cell-data",
14
+ transform(code, id) {
15
+ if (!id.endsWith("Cell.mock.js") && !id.endsWith("Cell.mock.ts")) {
16
+ return null;
17
+ }
18
+ if (process.env.NODE_ENV === "production") {
19
+ return null;
20
+ }
21
+ const ast = parse(id, code);
22
+ if (!ast) {
23
+ return null;
24
+ }
25
+ let pathsToRemove = [];
26
+ const nodesToInsert = [];
27
+ const createVisitors = (addWatchFile) => ({
28
+ ExportNamedDeclaration(p) {
29
+ const d = p.node.declaration;
30
+ let mockFunction = null;
31
+ switch (d?.type) {
32
+ case "VariableDeclaration": {
33
+ const standardMockExport = d.declarations[0];
34
+ const exportId = standardMockExport.id;
35
+ const exportName = exportId?.name;
36
+ if (exportName !== "standard") {
37
+ return;
38
+ }
39
+ const mockFunctionMaybe = standardMockExport?.init;
40
+ if (!mockFunctionMaybe) {
41
+ return;
42
+ }
43
+ if (mockFunctionMaybe.type !== "ArrowFunctionExpression" && mockFunctionMaybe.type !== "FunctionExpression") {
44
+ throw new Error(
45
+ `
46
+
47
+ Mock Error: You must export your standard mock as a function
48
+
49
+ `
50
+ );
51
+ }
52
+ mockFunction = mockFunctionMaybe;
53
+ break;
54
+ }
55
+ case "FunctionDeclaration": {
56
+ const exportName = d.id?.name;
57
+ if (exportName !== "standard") {
58
+ return;
59
+ }
60
+ mockFunction = t.arrowFunctionExpression(d.params, d.body);
61
+ break;
62
+ }
63
+ default:
64
+ return;
65
+ }
66
+ const dirname = path.dirname(id);
67
+ const cellName = path.basename(dirname);
68
+ const [cellPath] = fg.sync(`${cellName}.{js,jsx,ts,tsx}`, {
69
+ cwd: dirname,
70
+ absolute: true,
71
+ ignore: ["node_modules"]
72
+ });
73
+ if (!cellPath) {
74
+ return;
75
+ }
76
+ addWatchFile?.(cellPath);
77
+ const cellMetadata = getCellMetadata(cellPath);
78
+ if (cellMetadata.hasDefaultExport || !cellMetadata.hasQueryExport) {
79
+ return;
80
+ }
81
+ if (!cellMetadata.operationName) {
82
+ console.warn(
83
+ `[cedar-mock-cell-data] Cell ${cellPath} has an unnamed GraphQL operation. The mock for ${id} will not work. Ensure the QUERY is named, e.g., "query GetUser { ... }"`
84
+ );
85
+ return;
86
+ }
87
+ const mockGraphQLCall = t.callExpression(
88
+ t.identifier("mockGraphQLQuery"),
89
+ [
90
+ t.stringLiteral(cellMetadata.operationName),
91
+ mockFunction
92
+ ]
93
+ );
94
+ pathsToRemove = [...pathsToRemove, p];
95
+ if (cellMetadata.hasAfterQueryExport) {
96
+ const importAfterQuery = t.importDeclaration(
97
+ [
98
+ t.importSpecifier(
99
+ t.identifier("afterQuery"),
100
+ t.identifier("afterQuery")
101
+ )
102
+ ],
103
+ t.stringLiteral(`./${path.basename(cellPath)}`)
104
+ );
105
+ nodesToInsert.push(
106
+ importAfterQuery,
107
+ createExportStandard(
108
+ t,
109
+ t.arrowFunctionExpression(
110
+ [],
111
+ t.callExpression(t.identifier("afterQuery"), [
112
+ t.callExpression(mockGraphQLCall, [])
113
+ ])
114
+ )
115
+ )
116
+ );
117
+ } else {
118
+ nodesToInsert.push(createExportStandard(t, mockGraphQLCall));
119
+ }
120
+ }
121
+ });
122
+ traverse(ast, createVisitors(this.addWatchFile?.bind(this)));
123
+ if (nodesToInsert.length === 0) {
124
+ return null;
125
+ }
126
+ for (const p of pathsToRemove) {
127
+ p.remove();
128
+ }
129
+ ;
130
+ ast.program.body.unshift(...nodesToInsert);
131
+ const result = generate(ast, { retainLines: false }, code);
132
+ return {
133
+ code: result.code,
134
+ map: result.map
135
+ };
136
+ }
137
+ };
138
+ }
139
+ function createExportStandard(babelTypes, ex) {
140
+ return babelTypes.exportNamedDeclaration(
141
+ babelTypes.variableDeclaration("const", [
142
+ babelTypes.variableDeclarator(babelTypes.identifier("standard"), ex)
143
+ ])
144
+ );
145
+ }
146
+ const getCellMetadata = (p) => {
147
+ const ast = getCellAst(p);
148
+ let hasDefaultExport = false;
149
+ const namedExports = [];
150
+ let operation;
151
+ traverse(ast, {
152
+ ExportDefaultDeclaration() {
153
+ hasDefaultExport = true;
154
+ },
155
+ ExportNamedDeclaration(path2) {
156
+ const specifiers = path2.node?.specifiers;
157
+ if (specifiers.length) {
158
+ for (const s of specifiers) {
159
+ const id = s.exported;
160
+ namedExports.push({
161
+ name: id.name,
162
+ type: "re-export"
163
+ });
164
+ }
165
+ return;
166
+ }
167
+ const declaration = path2.node.declaration;
168
+ if (!declaration) {
169
+ return;
170
+ }
171
+ if (declaration.type === "VariableDeclaration") {
172
+ const id = declaration.declarations[0].id;
173
+ namedExports.push({
174
+ name: id.name,
175
+ type: "variable"
176
+ });
177
+ } else if (declaration.type === "FunctionDeclaration") {
178
+ namedExports.push({
179
+ name: declaration?.id?.name,
180
+ type: "function"
181
+ });
182
+ } else if (declaration.type === "ClassDeclaration") {
183
+ namedExports.push({
184
+ name: declaration?.id?.name,
185
+ type: "class"
186
+ });
187
+ }
188
+ },
189
+ TaggedTemplateExpression(path2) {
190
+ if (path2.parent?.id?.name !== "QUERY") {
191
+ return;
192
+ }
193
+ operation = path2.node.quasi.quasis[0].value.raw;
194
+ }
195
+ });
196
+ const hasQueryExport = namedExports.find(({ name }) => name === "QUERY");
197
+ const hasAfterQueryExport = namedExports.find(
198
+ ({ name }) => name === "afterQuery"
199
+ );
200
+ let operationName = "";
201
+ if (operation) {
202
+ const document = graphqlParse(operation);
203
+ for (const definition of document.definitions) {
204
+ if (definition.kind === Kind.OPERATION_DEFINITION && definition.name?.value) {
205
+ operationName = definition.name.value;
206
+ }
207
+ }
208
+ }
209
+ return {
210
+ hasDefaultExport,
211
+ namedExports,
212
+ hasQueryExport,
213
+ hasAfterQueryExport,
214
+ operationName
215
+ };
216
+ };
217
+ function getCellAst(filePath) {
218
+ const code = fs.readFileSync(filePath, "utf-8");
219
+ const plugins = ["typescript", "jsx"].filter(Boolean);
220
+ try {
221
+ return babelParse(code, {
222
+ sourceType: "module",
223
+ plugins
224
+ });
225
+ } catch (e) {
226
+ console.error(`Error parsing: ${filePath}`);
227
+ console.error(e);
228
+ throw new Error(e?.message);
229
+ }
230
+ }
231
+ function parse(filePath, code) {
232
+ const plugins = ["typescript", "jsx"].filter(Boolean);
233
+ try {
234
+ return babelParse(code, {
235
+ sourceType: "module",
236
+ plugins
237
+ });
238
+ } catch (e) {
239
+ console.error(`Error parsing: ${filePath}`);
240
+ console.error(e);
241
+ return null;
242
+ }
243
+ }
244
+ export {
245
+ cedarMockCellDataPlugin,
246
+ getCellMetadata
247
+ };
@@ -0,0 +1,39 @@
1
+ import type { Plugin } from 'vite';
2
+ /**
3
+ * Vite plugin that wraps exported API functions with OpenTelemetry spans to
4
+ * provide automatic tracing in your Cedar API.
5
+ *
6
+ * For each `export const fn = (async?) (...) => {...}` declaration in an API
7
+ * file this plugin:
8
+ *
9
+ * 1. Adds an import at the top of the file:
10
+ * import { trace as OTEL_TRACE } from '@opentelemetry/api'
11
+ *
12
+ * 2. Wraps the original export with an OTel span:
13
+ * export const fn = (async?) (...params) => {
14
+ * const __fn = (async?) (...params) => { ...original body... }
15
+ * const OTEL_TRACER = OTEL_TRACE.getTracer('redwoodjs')
16
+ * const OTEL_RESULT = (await?) OTEL_TRACER.startActiveSpan(
17
+ * 'redwoodjs:api:<folder>:<fnName>',
18
+ * (async?) (span) => { ... }
19
+ * )
20
+ * return OTEL_RESULT
21
+ * }
22
+ *
23
+ * This replaces `babel-plugin-redwood-otel-wrapping` for all Vite and esbuild
24
+ * builds. The previous Babel plugin has been removed entirely; Jest transforms
25
+ * through the Vite SSR pipeline.
26
+ *
27
+ * NOTE: Known limitation. Spans will close before a Promise settles if a
28
+ * synchronous function returns a Promise. To trace async work correctly, mark
29
+ * the function as `async` if it returns or awaits Promises.
30
+ */
31
+ export declare function cedarOtelWrappingPlugin(): Plugin;
32
+ /**
33
+ * Applies OpenTelemetry span wrapping to API source files.
34
+ *
35
+ * Exported as a standalone function so it can be tested without a Vite context.
36
+ * Returns the transformed code string, or `null` if nothing was changed.
37
+ */
38
+ export declare function applyOtelWrapping(code: string, filename: string, apiFolder: string): string | null;
39
+ //# sourceMappingURL=vite-plugin-cedar-otel-wrapping.d.ts.map
@@ -0,0 +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;AAKlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAwBhD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CA+Ef"}
@@ -0,0 +1,200 @@
1
+ import { parseSync } from "oxc-parser";
2
+ import { normalizePath } from "vite";
3
+ import { getPaths } from "@cedarjs/project-config";
4
+ function cedarOtelWrappingPlugin() {
5
+ return {
6
+ name: "cedar-otel-wrapping",
7
+ transform(code, id) {
8
+ let apiSrc;
9
+ try {
10
+ apiSrc = normalizePath(getPaths().api.src);
11
+ } catch {
12
+ return null;
13
+ }
14
+ if (!normalizePath(id).startsWith(apiSrc + "/")) {
15
+ return null;
16
+ }
17
+ const relativePath = normalizePath(id).slice(apiSrc.length + 1);
18
+ const apiFolder = relativePath.split("/")[0] ?? "?";
19
+ const result = applyOtelWrapping(code, id, apiFolder);
20
+ return result ? { code: result, map: null } : null;
21
+ }
22
+ };
23
+ }
24
+ function applyOtelWrapping(code, filename, apiFolder) {
25
+ const parseResult = parseSync(filename, code, { sourceType: "module" });
26
+ const replacements = [];
27
+ for (const node of parseResult.program.body) {
28
+ if (node.type !== "ExportNamedDeclaration") {
29
+ continue;
30
+ }
31
+ const decl = node.declaration;
32
+ if (decl?.type !== "VariableDeclaration") {
33
+ continue;
34
+ }
35
+ const declarator = decl.declarations[0];
36
+ if (!declarator) {
37
+ continue;
38
+ }
39
+ const fn = declarator.init;
40
+ if (fn?.type !== "ArrowFunctionExpression") {
41
+ continue;
42
+ }
43
+ if (declarator.id.type !== "Identifier") {
44
+ continue;
45
+ }
46
+ const fnName = declarator.id.name;
47
+ const innerArgs = buildInnerArgs(fn.params);
48
+ if (innerArgs === null) {
49
+ continue;
50
+ }
51
+ const fnHeader = code.slice(fn.start, fn.body.start);
52
+ const originalFnSrc = code.slice(fn.start, fn.end);
53
+ const isAsync = fn.async;
54
+ const awaitKw = isAsync ? "await " : "";
55
+ const asyncKw = isAsync ? "async " : "";
56
+ replacements.push({
57
+ start: node.start,
58
+ end: node.end,
59
+ src: buildWrappedExport(
60
+ fnName,
61
+ fnHeader,
62
+ originalFnSrc,
63
+ innerArgs,
64
+ awaitKw,
65
+ asyncKw,
66
+ apiFolder,
67
+ filename
68
+ )
69
+ });
70
+ }
71
+ if (replacements.length === 0) {
72
+ return null;
73
+ }
74
+ let output = code;
75
+ for (let i = replacements.length - 1; i >= 0; i--) {
76
+ const r = replacements[i];
77
+ output = output.slice(0, r.start) + r.src + output.slice(r.end);
78
+ }
79
+ return `import { trace as OTEL_TRACE } from '@opentelemetry/api'
80
+ ` + output;
81
+ }
82
+ function buildInnerArgs(params) {
83
+ const args = [];
84
+ for (const param of params) {
85
+ if (param.type === "RestElement" || param.type === "ArrayPattern" || param.type === "TSParameterProperty") {
86
+ return null;
87
+ }
88
+ if (param.type === "Identifier") {
89
+ args.push(param.name);
90
+ continue;
91
+ }
92
+ if (param.type === "ObjectPattern") {
93
+ for (const prop of param.properties) {
94
+ if (prop.type === "RestElement") {
95
+ return null;
96
+ }
97
+ if (prop.key.type !== "Identifier") {
98
+ return null;
99
+ }
100
+ const value = prop.value;
101
+ if (value.type !== "Identifier" && value.type !== "AssignmentPattern" && value.type !== "ObjectPattern") {
102
+ return null;
103
+ }
104
+ if (value.type === "AssignmentPattern") {
105
+ if (value.left.type !== "Identifier" && value.left.type !== "ObjectPattern") {
106
+ return null;
107
+ }
108
+ }
109
+ }
110
+ const obj = buildObjectCallArg(param);
111
+ if (obj === null) {
112
+ return null;
113
+ }
114
+ args.push(obj);
115
+ continue;
116
+ }
117
+ if (param.type === "AssignmentPattern") {
118
+ const ap = param;
119
+ if (ap.left.type === "Identifier") {
120
+ args.push(ap.left.name);
121
+ } else if (ap.left.type === "ObjectPattern") {
122
+ const obj = buildObjectCallArg(ap.left);
123
+ if (obj === null) {
124
+ return null;
125
+ }
126
+ args.push(obj);
127
+ } else {
128
+ return null;
129
+ }
130
+ continue;
131
+ }
132
+ return null;
133
+ }
134
+ return args.join(", ");
135
+ }
136
+ function buildObjectCallArg(pattern) {
137
+ const keys = [];
138
+ for (const prop of pattern.properties) {
139
+ if (prop.type === "RestElement") {
140
+ return null;
141
+ }
142
+ if (prop.key.type !== "Identifier") {
143
+ return null;
144
+ }
145
+ const keyName = prop.key.name;
146
+ let valueName = null;
147
+ if (prop.value.type === "Identifier") {
148
+ valueName = prop.value.name;
149
+ } else if (prop.value.type === "AssignmentPattern") {
150
+ if (prop.value.left.type === "Identifier") {
151
+ valueName = prop.value.left.name;
152
+ } else {
153
+ return null;
154
+ }
155
+ } else {
156
+ return null;
157
+ }
158
+ if (valueName !== keyName) {
159
+ keys.push(`${keyName}: ${valueName}`);
160
+ } else {
161
+ keys.push(keyName);
162
+ }
163
+ }
164
+ return `{ ${keys.join(", ")} }`;
165
+ }
166
+ function buildWrappedExport(fnName, fnHeader, originalFnSrc, innerArgs, awaitKw, asyncKw, apiFolder, filename) {
167
+ const privateName = `__${fnName}`;
168
+ const spanName = `redwoodjs:api:${apiFolder}:${fnName}`;
169
+ return `export const ${fnName} = ${fnHeader}{
170
+ const ${privateName} = ${originalFnSrc}
171
+ const OTEL_TRACER = OTEL_TRACE.getTracer('redwoodjs')
172
+ const OTEL_RESULT = ${awaitKw}OTEL_TRACER.startActiveSpan(
173
+ '${spanName}',
174
+ ${asyncKw}(span) => {
175
+ span.setAttribute('code.function', '${fnName}')
176
+ span.setAttribute('code.filepath', ${JSON.stringify(filename)})
177
+ try {
178
+ const OTEL_INNER_RESULT = ${awaitKw}${privateName}(${innerArgs})
179
+ span.end()
180
+ return OTEL_INNER_RESULT
181
+ } catch (error) {
182
+ span.recordException(error)
183
+ span.setStatus({
184
+ code: 2,
185
+ message:
186
+ error?.message?.split('\\n')[0] ??
187
+ error?.toString()?.split('\\n')[0],
188
+ })
189
+ span.end()
190
+ throw error
191
+ }
192
+ }
193
+ )
194
+ return OTEL_RESULT
195
+ }`;
196
+ }
197
+ export {
198
+ applyOtelWrapping,
199
+ cedarOtelWrappingPlugin
200
+ };
@@ -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":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAMlC,MAAM,WAAW,iCAAiC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AA6GD,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,iCAAsC,GAC9C,MAAM,CA0GR"}
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;AAalC,MAAM,WAAW,iCAAiC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AA6GD,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,iCAAsC,GAC9C,MAAM,CA0GR"}
@@ -190,66 +190,15 @@ async function generateGraphQLModule(distPath) {
190
190
  include: ["__cedar_graphqlOptions"]
191
191
  });
192
192
  return `
193
- import { buildCedarContext, noopAuthDecoder, requestToLegacyEvent } from '@cedarjs/api/runtime';
193
+ import { buildCedarContext, requestToLegacyEvent } from '@cedarjs/api/runtime';
194
194
  import { createGraphQLYoga } from '@cedarjs/graphql-server';
195
195
 
196
196
  // Inlined bundle of ${path.basename(distPath)} (node_modules kept external)
197
197
  ${bundledCode}
198
198
 
199
- let yogaInitPromise = null;
199
+ ${createGraphQLFetch.toString()}
200
200
 
201
- function getYoga() {
202
- if (!yogaInitPromise) {
203
- yogaInitPromise = createGraphQLYoga(__cedar_graphqlOptions).then(
204
- ({ yoga }) => ({ yoga, graphqlOptions: __cedar_graphqlOptions })
205
- );
206
- }
207
- return yogaInitPromise;
208
- }
209
-
210
- export default {
211
- async fetch(request) {
212
- const { yoga, graphqlOptions } = await getYoga();
213
- const cedarContext = await buildCedarContext(request, {
214
- authDecoder: graphqlOptions?.authDecoder ?? noopAuthDecoder,
215
- });
216
- const event = await requestToLegacyEvent(request, cedarContext);
217
- // Wrap yoga.handle in an AsyncLocalStorage run so directive
218
- // validators can read from the global @cedarjs/context. Without
219
- // this, the auth plugin's setContext() call writes to a store
220
- // that's only visible inside the plugin's own callback \u2014 not
221
- // during directive validation.
222
- const { getAsyncStoreInstance } = await import('@cedarjs/context/dist/store')
223
- const store = getAsyncStoreInstance()
224
-
225
- return store.run(new Map(), () => {
226
- return yoga.handle(request, {
227
- request,
228
- cedarContext,
229
- event,
230
- requestContext: undefined,
231
- })
232
- }).then((response) => {
233
- // GraphQL Yoga returns a PonyfillResponse from @whatwg-node/fetch
234
- // which is not an instanceof the native Response class. Netlify's
235
- // bootstrap checks instanceof Response, so we wrap it.
236
- return new Response(response.body, {
237
- status: response.status,
238
- statusText: response.statusText,
239
- headers: response.headers,
240
- })
241
- }).catch((e) => {
242
- if (e?.code === 'ERR_STREAM_PREMATURE_CLOSE') {
243
- // Client disconnected while the request was being processed (e.g.,
244
- // page navigation, tab close). Return a 499 so the runtime doesn't
245
- // treat this as a 500.
246
- return new Response(null, { status: 499 })
247
- }
248
-
249
- throw e
250
- })
251
- }
252
- };
201
+ export default { fetch: createGraphQLFetch(__cedar_graphqlOptions) };
253
202
  `;
254
203
  }
255
204
  async function generateFunctionModule(distPath) {
@@ -263,50 +212,103 @@ async function generateFunctionModule(distPath) {
263
212
  // Inlined bundle of ${path.basename(distPath)} (node_modules kept external)
264
213
  ${bundledCode}
265
214
 
266
- const nativeHandler = (() => {
267
- // Prefer named handleRequest export
268
- if (typeof handleRequest !== 'undefined') { return handleRequest; }
269
- // Handle export default { handleRequest } pattern
270
- if (typeof __cedar_default !== 'undefined' && __cedar_default && typeof __cedar_default.handleRequest === 'function') {
271
- return __cedar_default.handleRequest;
272
- }
273
- // Handle plain default-exported async function: export default async (req) => Response
274
- if (typeof __cedar_default !== 'undefined' && typeof __cedar_default === 'function') {
275
- return __cedar_default;
276
- }
277
- return undefined;
278
- })();
215
+ ${resolveNativeHandler.toString()}
279
216
 
280
- const legacyFn = (() => {
281
- if (typeof handler !== 'undefined') { return handler; }
282
- if (typeof __cedar_default !== 'undefined' && __cedar_default && typeof __cedar_default.handler === 'function') {
283
- return __cedar_default.handler;
284
- }
285
- return undefined;
286
- })();
217
+ ${resolveLegacyHandler.toString()}
287
218
 
288
- if (!nativeHandler && !legacyFn) {
289
- throw new Error(${notFoundMsg});
290
- }
219
+ ${resolveCedarHandler.toString()}
291
220
 
292
- const _handler = nativeHandler ?? wrapLegacyHandler(legacyFn);
221
+ ${createFunctionFetch.toString()}
293
222
 
294
223
  export default {
295
- async fetch(request) {
296
- const ctx = await buildCedarContext(request);
297
- // Wrap the handler in an AsyncLocalStorage run so the global
298
- // @cedarjs/context is available inside it (and isolated per request).
299
- // Mirrors the GraphQL module above and the cedarContextWrappingPlugin
300
- // used for non-UD builds.
301
- const { getAsyncStoreInstance } = await import(
302
- '@cedarjs/context/dist/store'
303
- );
304
- const store = getAsyncStoreInstance();
305
- return store.run(new Map(), () => _handler(request, ctx));
306
- }
224
+ fetch: createFunctionFetch(resolveCedarHandler(${notFoundMsg})),
307
225
  };
308
226
  `;
309
227
  }
228
+ function resolveNativeHandler() {
229
+ if (typeof handleRequest !== "undefined") {
230
+ return handleRequest;
231
+ }
232
+ if (typeof __cedar_default === "undefined" || !__cedar_default) {
233
+ return void 0;
234
+ }
235
+ if (typeof __cedar_default === "object" && typeof __cedar_default.handleRequest === "function") {
236
+ return __cedar_default.handleRequest;
237
+ }
238
+ if (typeof __cedar_default === "function") {
239
+ return __cedar_default;
240
+ }
241
+ return void 0;
242
+ }
243
+ function resolveLegacyHandler() {
244
+ if (typeof handler !== "undefined") {
245
+ return handler;
246
+ }
247
+ if (typeof __cedar_default === "undefined" || !__cedar_default) {
248
+ return void 0;
249
+ }
250
+ if (typeof __cedar_default === "object" && typeof __cedar_default.handler === "function") {
251
+ return __cedar_default.handler;
252
+ }
253
+ return void 0;
254
+ }
255
+ function resolveCedarHandler(notFoundMessage) {
256
+ const nativeHandler = resolveNativeHandler();
257
+ if (nativeHandler) {
258
+ return nativeHandler;
259
+ }
260
+ const legacyFn = resolveLegacyHandler();
261
+ if (!legacyFn) {
262
+ throw new Error(notFoundMessage);
263
+ }
264
+ return wrapLegacyHandler(legacyFn);
265
+ }
266
+ function createFunctionFetch(cedarHandler) {
267
+ return async function fetch(request) {
268
+ const ctx = await buildCedarContext(request);
269
+ const { getAsyncStoreInstance } = await import("@cedarjs/context/dist/store");
270
+ const store = getAsyncStoreInstance();
271
+ return store.run(/* @__PURE__ */ new Map(), () => cedarHandler(request, ctx));
272
+ };
273
+ }
274
+ function createGraphQLFetch(graphqlOptions) {
275
+ let yogaInitPromise = null;
276
+ function getYoga() {
277
+ if (!yogaInitPromise) {
278
+ yogaInitPromise = createGraphQLYoga(graphqlOptions);
279
+ }
280
+ return yogaInitPromise;
281
+ }
282
+ return async function fetch(request) {
283
+ const { yoga } = await getYoga();
284
+ const cedarContext = await buildCedarContext(request, {
285
+ authDecoder: graphqlOptions?.authDecoder
286
+ });
287
+ const event = await requestToLegacyEvent(request, cedarContext);
288
+ const { getAsyncStoreInstance } = await import("@cedarjs/context/dist/store");
289
+ const store = getAsyncStoreInstance();
290
+ try {
291
+ const response = await store.run(/* @__PURE__ */ new Map(), () => {
292
+ return yoga.handle(request, {
293
+ request,
294
+ cedarContext,
295
+ event,
296
+ requestContext: void 0
297
+ });
298
+ });
299
+ return new Response(response.body, {
300
+ status: response.status,
301
+ statusText: response.statusText,
302
+ headers: response.headers
303
+ });
304
+ } catch (e) {
305
+ if (!!e && typeof e === "object" && "code" in e && e.code === "ERR_STREAM_PREMATURE_CLOSE") {
306
+ return new Response(null, { status: 499 });
307
+ }
308
+ throw e;
309
+ }
310
+ };
311
+ }
310
312
  export {
311
313
  cedarUniversalDeployPlugin
312
314
  };