@superblocksteam/sdk 2.0.0-next.63 → 2.0.0-next.69
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/application-build.d.mts +12 -0
- package/dist/application-build.d.mts.map +1 -0
- package/dist/application-build.mjs +113 -0
- package/dist/application-build.mjs.map +1 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -5
- package/dist/client.js.map +1 -1
- package/dist/dev-utils/vite-plugin-react-transform.d.mts.map +1 -1
- package/dist/dev-utils/vite-plugin-react-transform.mjs +1 -0
- package/dist/dev-utils/vite-plugin-react-transform.mjs.map +1 -1
- package/dist/dev-utils/vite-plugin-sb-cdn.d.mts.map +1 -1
- package/dist/dev-utils/vite-plugin-sb-cdn.mjs +28 -7
- package/dist/dev-utils/vite-plugin-sb-cdn.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/vite-plugin-inject-sb-ids-transform.d.mts +15 -0
- package/dist/vite-plugin-inject-sb-ids-transform.d.mts.map +1 -0
- package/dist/vite-plugin-inject-sb-ids-transform.mjs +86 -0
- package/dist/vite-plugin-inject-sb-ids-transform.mjs.map +1 -0
- package/package.json +12 -4
- package/src/application-build.mts +160 -0
- package/src/client.ts +13 -4
- package/src/dev-utils/vite-plugin-react-transform.mts +1 -0
- package/src/dev-utils/vite-plugin-sb-cdn.mts +35 -7
- package/src/index.ts +2 -0
- package/src/vite-plugin-inject-sb-ids-transform.mts +104 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import babelGenerate from "@babel/generator";
|
|
3
|
+
import { parse } from "@babel/parser";
|
|
4
|
+
import { supplementElementIds, generateRootSource, } from "@superblocksteam/vite-plugin-file-sync";
|
|
5
|
+
import { yellow, red } from "colorette";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import { createLogger } from "vite";
|
|
8
|
+
import { getLogger } from "./dev-utils/dev-logger.mjs";
|
|
9
|
+
const routesFileBaseName = "routes.json";
|
|
10
|
+
/**
|
|
11
|
+
* Creates a Vite plugin that injects Superblocks IDs into the application.
|
|
12
|
+
* This will primarily be used during builds, as the dev server leverages the
|
|
13
|
+
* file sync manager to inject and keep the IDs up to date.
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Injects the root component with the routes data
|
|
17
|
+
* - Injects Superblocks IDs into all components
|
|
18
|
+
*
|
|
19
|
+
* @param root - The root directory of the application
|
|
20
|
+
* @returns A Vite plugin that injects Superblocks IDs into the application's components
|
|
21
|
+
*/
|
|
22
|
+
export async function injectSuperblocksIdsPlugin(root) {
|
|
23
|
+
const viteLogger = createLogger();
|
|
24
|
+
const logger = getLogger();
|
|
25
|
+
viteLogger.info = logger.info;
|
|
26
|
+
viteLogger.warn = (msg) => {
|
|
27
|
+
logger.warn(yellow(msg));
|
|
28
|
+
};
|
|
29
|
+
viteLogger.warnOnce = (msg) => {
|
|
30
|
+
logger.warn(yellow(msg));
|
|
31
|
+
};
|
|
32
|
+
viteLogger.error = (msg) => {
|
|
33
|
+
logger.error(red(msg));
|
|
34
|
+
};
|
|
35
|
+
viteLogger.clearScreen = () => { };
|
|
36
|
+
const routes = await getRoutes(root, viteLogger);
|
|
37
|
+
return {
|
|
38
|
+
name: "sb-inject-superblocks-ids",
|
|
39
|
+
enforce: "pre",
|
|
40
|
+
transform(code, id) {
|
|
41
|
+
const relativePath = path.relative(root, id);
|
|
42
|
+
if (relativePath === "root.tsx") {
|
|
43
|
+
const source = generateRootSource(code, routes);
|
|
44
|
+
return {
|
|
45
|
+
code: source,
|
|
46
|
+
map: null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
else if (id.endsWith(".tsx")) {
|
|
50
|
+
const ast = parse(code, {
|
|
51
|
+
sourceType: "module",
|
|
52
|
+
sourceFilename: id,
|
|
53
|
+
plugins: ["jsx"],
|
|
54
|
+
});
|
|
55
|
+
supplementElementIds({
|
|
56
|
+
fileName: id,
|
|
57
|
+
ast,
|
|
58
|
+
shouldModifyAst: true,
|
|
59
|
+
});
|
|
60
|
+
const result = babelGenerate.default(ast);
|
|
61
|
+
return result.code;
|
|
62
|
+
}
|
|
63
|
+
return code;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function getRoutes(root, logger) {
|
|
68
|
+
const routesFile = path.join(root, routesFileBaseName);
|
|
69
|
+
if (!(await fs.pathExists(routesFile))) {
|
|
70
|
+
logger.warn(`routes file not found at expected location: ${routesFile}`);
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const routesData = await fs.readFile(routesFile, "utf-8");
|
|
75
|
+
const routes = JSON.parse(routesData);
|
|
76
|
+
return Object.entries(routes).map(([path, { file }]) => ({
|
|
77
|
+
path,
|
|
78
|
+
component: file,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
logger.error(`error reading routes file: ${routesFile}. error=[${JSON.stringify(err)}]`);
|
|
83
|
+
}
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=vite-plugin-inject-sb-ids-transform.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin-inject-sb-ids-transform.mjs","sourceRoot":"","sources":["../src/vite-plugin-inject-sb-ids-transform.mts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EACL,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAIvD,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,IAAY;IAC3D,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAC9B,UAAU,CAAC,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;QAChC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,UAAU,CAAC,QAAQ,GAAG,CAAC,GAAW,EAAE,EAAE;QACpC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,UAAU,CAAC,KAAK,GAAG,CAAC,GAAW,EAAE,EAAE;QACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,UAAU,CAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IAElC,MAAM,MAAM,GAAoB,MAAM,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAElE,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,OAAO,EAAE,KAAK;QAEd,SAAS,CAAC,IAAI,EAAE,EAAE;YAChB,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAE7C,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,OAAO;oBACL,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,IAAI;iBACV,CAAC;YACJ,CAAC;iBAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE;oBACtB,UAAU,EAAE,QAAQ;oBACpB,cAAc,EAAE,EAAE;oBAClB,OAAO,EAAE,CAAC,KAAK,CAAC;iBACjB,CAAC,CAAC;gBAEH,oBAAoB,CAAC;oBACnB,QAAQ,EAAE,EAAE;oBACZ,GAAG;oBACH,eAAe,EAAE,IAAI;iBACtB,CAAC,CAAC;gBAEH,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC1C,OAAO,MAAM,CAAC,IAAI,CAAC;YACrB,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;KACQ,CAAC;AACd,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,MAAc;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IACvD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,+CAA+C,UAAU,EAAE,CAAC,CAAC;QACzE,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAqC,CAAC;QAE1E,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACvD,IAAI;YACJ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CACV,8BAA8B,UAAU,YAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAC3E,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superblocksteam/sdk",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.69",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Superblocks JS SDK",
|
|
6
6
|
"homepage": "https://www.superblocks.com",
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@babel/core": "7.24.0",
|
|
20
|
+
"@babel/generator": "^7.25.7",
|
|
21
|
+
"@babel/parser": "^7.25.8",
|
|
22
|
+
"@babel/traverse": "^7.25.7",
|
|
19
23
|
"@opentelemetry/api": "^1.9.0",
|
|
20
24
|
"@opentelemetry/context-async-hooks": "^2.0.1",
|
|
21
25
|
"@opentelemetry/exporter-trace-otlp-http": "^0.55.0",
|
|
@@ -25,10 +29,10 @@
|
|
|
25
29
|
"@opentelemetry/sdk-node": "^0.55.0",
|
|
26
30
|
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
27
31
|
"@rollup/wasm-node": "^4.35.0",
|
|
28
|
-
"@superblocksteam/bucketeer-sdk": "0.
|
|
32
|
+
"@superblocksteam/bucketeer-sdk": "0.5.0",
|
|
29
33
|
"@superblocksteam/shared": "0.9146.0",
|
|
30
|
-
"@superblocksteam/util": "2.0.0-next.
|
|
31
|
-
"@superblocksteam/vite-plugin-file-sync": "2.0.0-next.
|
|
34
|
+
"@superblocksteam/util": "2.0.0-next.69",
|
|
35
|
+
"@superblocksteam/vite-plugin-file-sync": "2.0.0-next.69",
|
|
32
36
|
"@vitejs/plugin-react": "^4.3.4",
|
|
33
37
|
"axios": "^1.4.0",
|
|
34
38
|
"chokidar": "^4.0.3",
|
|
@@ -56,7 +60,11 @@
|
|
|
56
60
|
"yaml": "^2.4.2"
|
|
57
61
|
},
|
|
58
62
|
"devDependencies": {
|
|
63
|
+
"@babel/types": "^7.25.8",
|
|
59
64
|
"@eslint/js": "^9.16.0",
|
|
65
|
+
"@types/babel__core": "^7.20.5",
|
|
66
|
+
"@types/babel__generator": "^7.6.8",
|
|
67
|
+
"@types/babel__traverse": "^7.20.6",
|
|
60
68
|
"@types/chai": "^4",
|
|
61
69
|
"@types/chai-as-promised": "^8.0.2",
|
|
62
70
|
"@types/common-tags": "^1.8.4",
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { injectIndexVitePlugin } from "@superblocksteam/vite-plugin-file-sync/inject-index";
|
|
3
|
+
import react from "@vitejs/plugin-react";
|
|
4
|
+
import { yellow, red } from "colorette";
|
|
5
|
+
import fs from "fs-extra";
|
|
6
|
+
import { build, createLogger } from "vite";
|
|
7
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
8
|
+
import { customComponentsPlugin } from "./dev-utils/custom-build.mjs";
|
|
9
|
+
import { getLogger } from "./dev-utils/dev-logger.mjs";
|
|
10
|
+
import { ddRumPlugin } from "./dev-utils/vite-plugin-dd-rum.mjs";
|
|
11
|
+
import { superblocksCdnPlugin } from "./dev-utils/vite-plugin-sb-cdn.mjs";
|
|
12
|
+
import { injectSuperblocksIdsPlugin } from "./vite-plugin-inject-sb-ids-transform.mjs";
|
|
13
|
+
import type { Plugin } from "vite";
|
|
14
|
+
|
|
15
|
+
export async function buildApplication({
|
|
16
|
+
root,
|
|
17
|
+
dest,
|
|
18
|
+
mode,
|
|
19
|
+
libraryUrl,
|
|
20
|
+
assetsCdnUrl,
|
|
21
|
+
ddClientToken,
|
|
22
|
+
ddApplicationId,
|
|
23
|
+
ddEnv,
|
|
24
|
+
ddVersion,
|
|
25
|
+
}: {
|
|
26
|
+
root: string;
|
|
27
|
+
dest: string;
|
|
28
|
+
mode: string;
|
|
29
|
+
libraryUrl: string;
|
|
30
|
+
assetsCdnUrl?: string;
|
|
31
|
+
ddClientToken?: string;
|
|
32
|
+
ddApplicationId?: string;
|
|
33
|
+
ddEnv?: string;
|
|
34
|
+
ddVersion?: string;
|
|
35
|
+
}) {
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
try {
|
|
38
|
+
// Ensure the root directory exists and change execution context to it
|
|
39
|
+
if (!(await fs.pathExists(root))) {
|
|
40
|
+
throw new Error(`Root directory "${root}" does not exist`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
process.chdir(root);
|
|
44
|
+
await buildWithVite({
|
|
45
|
+
root: fs.realpathSync(root),
|
|
46
|
+
dest: fs.realpathSync(dest),
|
|
47
|
+
mode,
|
|
48
|
+
libraryUrl,
|
|
49
|
+
assetsCdnUrl,
|
|
50
|
+
ddClientToken,
|
|
51
|
+
ddApplicationId,
|
|
52
|
+
ddEnv,
|
|
53
|
+
ddVersion,
|
|
54
|
+
});
|
|
55
|
+
} finally {
|
|
56
|
+
// Restore the original working directory before returning
|
|
57
|
+
process.chdir(cwd);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function buildWithVite({
|
|
62
|
+
root,
|
|
63
|
+
dest,
|
|
64
|
+
mode,
|
|
65
|
+
libraryUrl,
|
|
66
|
+
assetsCdnUrl,
|
|
67
|
+
ddClientToken,
|
|
68
|
+
ddApplicationId,
|
|
69
|
+
ddEnv,
|
|
70
|
+
ddVersion,
|
|
71
|
+
}: {
|
|
72
|
+
root: string;
|
|
73
|
+
dest: string;
|
|
74
|
+
mode: string;
|
|
75
|
+
libraryUrl: string;
|
|
76
|
+
assetsCdnUrl?: string;
|
|
77
|
+
ddClientToken?: string;
|
|
78
|
+
ddApplicationId?: string;
|
|
79
|
+
ddEnv?: string;
|
|
80
|
+
ddVersion?: string;
|
|
81
|
+
}) {
|
|
82
|
+
const viteLogger = createLogger();
|
|
83
|
+
const logger = getLogger();
|
|
84
|
+
viteLogger.info = logger.info;
|
|
85
|
+
viteLogger.warn = (msg: string) => {
|
|
86
|
+
logger.warn(yellow(msg));
|
|
87
|
+
};
|
|
88
|
+
viteLogger.warnOnce = (msg: string) => {
|
|
89
|
+
logger.warn(yellow(msg));
|
|
90
|
+
};
|
|
91
|
+
viteLogger.error = (msg: string) => {
|
|
92
|
+
logger.error(red(msg));
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
viteLogger.clearScreen = () => {};
|
|
96
|
+
|
|
97
|
+
const customFolder = path.join(root, "custom");
|
|
98
|
+
|
|
99
|
+
await build({
|
|
100
|
+
root,
|
|
101
|
+
mode,
|
|
102
|
+
appType: "spa",
|
|
103
|
+
resolve: {
|
|
104
|
+
alias: {
|
|
105
|
+
"react-router": "@superblocksteam/library",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
clearScreen: true,
|
|
109
|
+
optimizeDeps: {
|
|
110
|
+
include: ["lodash", "react-is"],
|
|
111
|
+
exclude: [],
|
|
112
|
+
},
|
|
113
|
+
build: {
|
|
114
|
+
outDir: dest,
|
|
115
|
+
emptyOutDir: true,
|
|
116
|
+
write: true,
|
|
117
|
+
commonjsOptions: {
|
|
118
|
+
include: ["react-is"],
|
|
119
|
+
transformMixedEsModules: true,
|
|
120
|
+
},
|
|
121
|
+
rollupOptions: {
|
|
122
|
+
external: [
|
|
123
|
+
`${customFolder}/**/*`,
|
|
124
|
+
"react",
|
|
125
|
+
"react-dom",
|
|
126
|
+
"react/jsx-runtime",
|
|
127
|
+
"react/jsx-dev-runtime",
|
|
128
|
+
],
|
|
129
|
+
preserveEntrySignatures: "allow-extension",
|
|
130
|
+
output: { format: "esm" },
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
logLevel: "info",
|
|
134
|
+
plugins: [
|
|
135
|
+
tsconfigPaths(),
|
|
136
|
+
injectIndexVitePlugin({ assetsCdnUrl, logger }) as Plugin,
|
|
137
|
+
customComponentsPlugin(),
|
|
138
|
+
injectSuperblocksIdsPlugin(root),
|
|
139
|
+
superblocksCdnPlugin({
|
|
140
|
+
imports: {
|
|
141
|
+
"@superblocksteam/library": `${libraryUrl}/index.js`,
|
|
142
|
+
"react/jsx-runtime": "https://esm.sh/react@18.2.0/jsx-runtime.mjs",
|
|
143
|
+
"react/jsx-dev-runtime":
|
|
144
|
+
"https://esm.sh/react@18.2.0/jsx-dev-runtime.mjs",
|
|
145
|
+
},
|
|
146
|
+
cssImports: {
|
|
147
|
+
"@superblocksteam/library/index.css": `${libraryUrl}/index.css`,
|
|
148
|
+
},
|
|
149
|
+
}),
|
|
150
|
+
react(),
|
|
151
|
+
|
|
152
|
+
ddRumPlugin({
|
|
153
|
+
clientToken: ddClientToken ?? "",
|
|
154
|
+
applicationId: ddApplicationId ?? "",
|
|
155
|
+
env: ddEnv ?? "prod",
|
|
156
|
+
version: ddVersion ?? "1.0.0",
|
|
157
|
+
}),
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
import { Bucketeer, FileDescriptor } from "@superblocksteam/bucketeer-sdk";
|
|
3
4
|
import { ExportViewMode } from "@superblocksteam/shared";
|
|
4
5
|
import {
|
|
@@ -1269,13 +1270,15 @@ export async function uploadApplication({
|
|
|
1269
1270
|
scopedJwt,
|
|
1270
1271
|
url,
|
|
1271
1272
|
cliVersion,
|
|
1273
|
+
appRoot,
|
|
1272
1274
|
}: {
|
|
1273
1275
|
files: string[];
|
|
1274
1276
|
scopedJwt: string;
|
|
1275
1277
|
url: string;
|
|
1276
1278
|
cliVersion: string;
|
|
1279
|
+
appRoot?: string;
|
|
1277
1280
|
}) {
|
|
1278
|
-
const fds = filesToFileDescriptors(files);
|
|
1281
|
+
const fds = filesToFileDescriptors(files, appRoot);
|
|
1279
1282
|
const bucketeer = new Bucketeer({
|
|
1280
1283
|
token: scopedJwt,
|
|
1281
1284
|
baseUrl: url,
|
|
@@ -1285,9 +1288,15 @@ export async function uploadApplication({
|
|
|
1285
1288
|
await bucketeer.uploadApplication(fds);
|
|
1286
1289
|
}
|
|
1287
1290
|
|
|
1288
|
-
function filesToFileDescriptors(files: string[]) {
|
|
1291
|
+
function filesToFileDescriptors(files: string[], appRoot?: string) {
|
|
1289
1292
|
const fds = files.map((file) => {
|
|
1290
|
-
|
|
1293
|
+
const relativePath = appRoot ? path.relative(appRoot, file) : undefined;
|
|
1294
|
+
return new FileDescriptor(
|
|
1295
|
+
file,
|
|
1296
|
+
fs.createReadStream(file),
|
|
1297
|
+
undefined,
|
|
1298
|
+
relativePath,
|
|
1299
|
+
);
|
|
1291
1300
|
});
|
|
1292
1301
|
return fds;
|
|
1293
1302
|
}
|
|
@@ -11,6 +11,7 @@ export function reactTransformPlugin(): Plugin {
|
|
|
11
11
|
return {
|
|
12
12
|
name: "vite-plugin-react-transform",
|
|
13
13
|
enforce: "pre", // Run before other plugins
|
|
14
|
+
apply: "serve",
|
|
14
15
|
async transform(code, id) {
|
|
15
16
|
// Check for React modules
|
|
16
17
|
if (id.includes("node_modules/.vite/deps/react.js")) {
|
|
@@ -469,6 +469,16 @@ async function extractNeededExports(
|
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
const wellKnownPackages = new Map<string, string>([
|
|
473
|
+
["react", "https://esm.sh/react@18.2.0"],
|
|
474
|
+
["react-dom", "https://esm.sh/react-dom@18.2.0"],
|
|
475
|
+
["react/jsx-runtime", "https://esm.sh/react@18.2.0/jsx-runtime"],
|
|
476
|
+
["react/jsx-dev-runtime", "https://esm.sh/react@18.2.0/jsx-dev-runtime"],
|
|
477
|
+
]);
|
|
478
|
+
|
|
479
|
+
const react18CdnUrl = "https://esm.sh/react@18.2.0";
|
|
480
|
+
const reactDom18CdnUrl = "https://esm.sh/react-dom@18.2.0";
|
|
481
|
+
|
|
472
482
|
/**
|
|
473
483
|
* Creates a Vite plugin that injects an import map into the HTML.
|
|
474
484
|
* It analyzes remote modules to find their imports and maps them to local Vite modules.
|
|
@@ -558,7 +568,14 @@ export async function superblocksCdnPlugin(
|
|
|
558
568
|
const modulePreloadData = modulesToPreload.get(importUrl);
|
|
559
569
|
if (modulePreloadData) {
|
|
560
570
|
modulePreloadData.content = content;
|
|
561
|
-
|
|
571
|
+
|
|
572
|
+
// Don't calculate integrity for react 18 CDN modules
|
|
573
|
+
if (
|
|
574
|
+
!importUrl.startsWith(react18CdnUrl) &&
|
|
575
|
+
!importUrl.startsWith(reactDom18CdnUrl)
|
|
576
|
+
) {
|
|
577
|
+
modulePreloadData.integrity = await calculateIntegrity(binary);
|
|
578
|
+
}
|
|
562
579
|
}
|
|
563
580
|
|
|
564
581
|
// Process all discovered modules and add them to the preload list
|
|
@@ -570,8 +587,15 @@ export async function superblocksCdnPlugin(
|
|
|
570
587
|
if (moduleUrl.startsWith(baseUrl)) {
|
|
571
588
|
// Add the module to preload if not already added
|
|
572
589
|
if (!modulesToPreload.has(moduleUrl)) {
|
|
573
|
-
// Calculate the integrity hash
|
|
574
|
-
|
|
590
|
+
// Calculate the integrity hash for non-react 18 CDN modules
|
|
591
|
+
let integrity: string | undefined;
|
|
592
|
+
if (
|
|
593
|
+
!moduleUrl.startsWith(react18CdnUrl) &&
|
|
594
|
+
!moduleUrl.startsWith(reactDom18CdnUrl)
|
|
595
|
+
) {
|
|
596
|
+
integrity = await calculateIntegrity(moduleData.binary);
|
|
597
|
+
}
|
|
598
|
+
|
|
575
599
|
modulesToPreload.set(moduleUrl, {
|
|
576
600
|
url: moduleUrl,
|
|
577
601
|
content: moduleData.content,
|
|
@@ -802,10 +826,12 @@ export async function superblocksCdnPlugin(
|
|
|
802
826
|
const importMap = {
|
|
803
827
|
imports: {
|
|
804
828
|
...Object.fromEntries(
|
|
805
|
-
Object.entries(initialImportMap).map(([module, url]) =>
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
829
|
+
Object.entries(initialImportMap).map(([module, url]) => {
|
|
830
|
+
if (wellKnownPackages.has(module)) {
|
|
831
|
+
return [module, wellKnownPackages.get(module)!];
|
|
832
|
+
}
|
|
833
|
+
return [`${isDevMode ? "/@id/" : ""}cdn:${module}`, url];
|
|
834
|
+
}),
|
|
809
835
|
),
|
|
810
836
|
},
|
|
811
837
|
// Scopes apply to specific URL prefixes for more granular control
|
|
@@ -871,6 +897,8 @@ export async function superblocksCdnPlugin(
|
|
|
871
897
|
const chunkPath = importToChunkMap.get(moduleName);
|
|
872
898
|
if (chunkPath) {
|
|
873
899
|
dependencyChunkUrl = `${base}${chunkPath}`;
|
|
900
|
+
} else if (wellKnownPackages.has(moduleName)) {
|
|
901
|
+
dependencyChunkUrl = wellKnownPackages.get(moduleName)!;
|
|
874
902
|
}
|
|
875
903
|
}
|
|
876
904
|
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import babelGenerate from "@babel/generator";
|
|
3
|
+
import { parse } from "@babel/parser";
|
|
4
|
+
import {
|
|
5
|
+
supplementElementIds,
|
|
6
|
+
generateRootSource,
|
|
7
|
+
} from "@superblocksteam/vite-plugin-file-sync";
|
|
8
|
+
import { yellow, red } from "colorette";
|
|
9
|
+
import fs from "fs-extra";
|
|
10
|
+
import { createLogger } from "vite";
|
|
11
|
+
import { getLogger } from "./dev-utils/dev-logger.mjs";
|
|
12
|
+
import type { HydratedRoute } from "@superblocksteam/vite-plugin-file-sync";
|
|
13
|
+
import type { Logger, Plugin } from "vite";
|
|
14
|
+
|
|
15
|
+
const routesFileBaseName = "routes.json";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates a Vite plugin that injects Superblocks IDs into the application.
|
|
19
|
+
* This will primarily be used during builds, as the dev server leverages the
|
|
20
|
+
* file sync manager to inject and keep the IDs up to date.
|
|
21
|
+
*
|
|
22
|
+
* Features:
|
|
23
|
+
* - Injects the root component with the routes data
|
|
24
|
+
* - Injects Superblocks IDs into all components
|
|
25
|
+
*
|
|
26
|
+
* @param root - The root directory of the application
|
|
27
|
+
* @returns A Vite plugin that injects Superblocks IDs into the application's components
|
|
28
|
+
*/
|
|
29
|
+
export async function injectSuperblocksIdsPlugin(root: string) {
|
|
30
|
+
const viteLogger = createLogger();
|
|
31
|
+
const logger = getLogger();
|
|
32
|
+
viteLogger.info = logger.info;
|
|
33
|
+
viteLogger.warn = (msg: string) => {
|
|
34
|
+
logger.warn(yellow(msg));
|
|
35
|
+
};
|
|
36
|
+
viteLogger.warnOnce = (msg: string) => {
|
|
37
|
+
logger.warn(yellow(msg));
|
|
38
|
+
};
|
|
39
|
+
viteLogger.error = (msg: string) => {
|
|
40
|
+
logger.error(red(msg));
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
viteLogger.clearScreen = () => {};
|
|
44
|
+
|
|
45
|
+
const routes: HydratedRoute[] = await getRoutes(root, viteLogger);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
name: "sb-inject-superblocks-ids",
|
|
49
|
+
enforce: "pre",
|
|
50
|
+
|
|
51
|
+
transform(code, id) {
|
|
52
|
+
const relativePath = path.relative(root, id);
|
|
53
|
+
|
|
54
|
+
if (relativePath === "root.tsx") {
|
|
55
|
+
const source = generateRootSource(code, routes);
|
|
56
|
+
return {
|
|
57
|
+
code: source,
|
|
58
|
+
map: null,
|
|
59
|
+
};
|
|
60
|
+
} else if (id.endsWith(".tsx")) {
|
|
61
|
+
const ast = parse(code, {
|
|
62
|
+
sourceType: "module",
|
|
63
|
+
sourceFilename: id,
|
|
64
|
+
plugins: ["jsx"],
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
supplementElementIds({
|
|
68
|
+
fileName: id,
|
|
69
|
+
ast,
|
|
70
|
+
shouldModifyAst: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const result = babelGenerate.default(ast);
|
|
74
|
+
return result.code;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return code;
|
|
78
|
+
},
|
|
79
|
+
} as Plugin;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function getRoutes(root: string, logger: Logger) {
|
|
83
|
+
const routesFile = path.join(root, routesFileBaseName);
|
|
84
|
+
if (!(await fs.pathExists(routesFile))) {
|
|
85
|
+
logger.warn(`routes file not found at expected location: ${routesFile}`);
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const routesData = await fs.readFile(routesFile, "utf-8");
|
|
91
|
+
const routes = JSON.parse(routesData) as Record<string, { file: string }>;
|
|
92
|
+
|
|
93
|
+
return Object.entries(routes).map(([path, { file }]) => ({
|
|
94
|
+
path,
|
|
95
|
+
component: file,
|
|
96
|
+
}));
|
|
97
|
+
} catch (err) {
|
|
98
|
+
logger.error(
|
|
99
|
+
`error reading routes file: ${routesFile}. error=[${JSON.stringify(err)}]`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return [];
|
|
104
|
+
}
|