-
-
Notifications
You must be signed in to change notification settings - Fork 871
Expand file tree
/
Copy pathinit-loaders.js
More file actions
executable file
·154 lines (129 loc) · 4.77 KB
/
Copy pathinit-loaders.js
File metadata and controls
executable file
·154 lines (129 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// This script was created to initialize and create the loaders for the Plone registry.
// Nowadays it is not used in the build process, but it's still needed for initialize
// the unit tests before they run.
// It was used when React Router was evaluating `routes.ts` before running vite build.
// See https://github.com/remix-run/react-router/issues/13078#issuecomment-2863445977
import fs from 'fs';
import path from 'path';
import cryptoRandomString from 'crypto-random-string';
import { createServer } from 'vite';
import { pathToFileURL } from 'node:url';
import { AddonRegistry } from '@plone/registry/addon-registry';
import { createAddonsLoader } from '@plone/registry/create-addons-loader';
import { createAddonsServerLoader } from '@plone/registry/create-addons-loader-server';
import { createAddonsStyleLoader } from '@plone/registry/create-addons-styles-loader';
import { createAddonsLocalesLoader } from '@plone/registry/create-addons-locales-loader';
import { PloneRegistryVitePlugin } from '@plone/registry/vite-plugin';
import config from '@plone/registry';
import { buildSlotTree } from './slot-tree.js';
const titleCase = (w) => w.slice(0, 1).toUpperCase() + w.slice(1, w.length);
function nameFromPath(filePath) {
const normalizedPath =
filePath.replace(/[@~./\\:\s-]/gi, '') ||
cryptoRandomString({ length: 10, characters: 'abcdefghijk' });
return normalizedPath
.split('-')
.map((w, i) => (i > 0 ? titleCase(w) : w))
.join('');
}
function getAddonViteExtenders(registry) {
return registry
.getAddons()
.map((addon) => {
const base = path.dirname(addon.packageJson);
const viteExtendJs = path.resolve(`${base}/vite.extend.js`);
const viteExtendTs = path.resolve(`${base}/vite.extend.ts`);
if (fs.existsSync(viteExtendJs)) return viteExtendJs;
if (fs.existsSync(viteExtendTs)) return viteExtendTs;
return null;
})
.filter(Boolean);
}
function createViteLoader(extenders) {
const viteLoaderPath = path.join(process.cwd(), '.plone', 'vite.loader.js');
let code = `/*
Don't change this file manually.
It is autogenerated by @plone/registry.
Instead, change the "addons" registration in the app.
*/\n`;
const extendersToLoad = [];
extenders.forEach((extenderPath) => {
const defaultImport = nameFromPath(extenderPath);
const fileUrl = pathToFileURL(extenderPath).href;
code += `import ${defaultImport} from '${fileUrl}';\n`;
extendersToLoad.push(defaultImport);
});
code += `
const safeWrapper = (func) => (config, context) => {
const res = func(config, context);
if (typeof res === 'undefined') {
throw new Error("Vite extension function doesn't return config");
}
return res;
};
const load = (config, context = {}) => {
const addonLoaders = [${extendersToLoad.join(', ')}];
if (!addonLoaders.every((el) => typeof el === 'function')) {
throw new TypeError(
'Each addon has to provide a function applying its Vite extension to the app configuration.',
);
}
return addonLoaders.reduce(
(acc, apply) => safeWrapper(apply)(acc, context),
config,
);
};
export default load;
`;
fs.writeFileSync(viteLoaderPath, code);
return viteLoaderPath;
}
async function evaluateAddons(addonsLoaderPath) {
const projectRootPath = path.resolve('.');
const ploneDir = path.join(projectRootPath, '.plone');
const server = await createServer({
root: projectRootPath,
configFile: false,
server: { middlewareMode: true },
plugins: [PloneRegistryVitePlugin()],
});
try {
const { default: loader, addonsInfo } =
await server.ssrLoadModule(addonsLoaderPath);
const populatedConfig = loader(config);
fs.writeFileSync(
path.join(ploneDir, 'registry.routes.json'),
JSON.stringify(populatedConfig.routes, null, 2),
);
fs.writeFileSync(
path.join(ploneDir, 'registry.addonsInfo.json'),
JSON.stringify(addonsInfo, null, 2),
);
await buildSlotTree(populatedConfig, ploneDir, server);
} finally {
await server.close();
}
}
async function initPloneRegistryLoaders() {
const projectRootPath = path.resolve('.');
const { registry, shadowAliases } = AddonRegistry.init(projectRootPath);
const ploneDir = path.join(projectRootPath, '.plone');
if (!fs.existsSync(ploneDir)) {
fs.mkdirSync(ploneDir, { recursive: true });
}
const addonsLoaderPath = createAddonsLoader(
registry.getAddonDependencies(),
registry.getAddons(),
{ tempInProject: true },
);
await evaluateAddons(addonsLoaderPath);
createAddonsServerLoader(
registry.getAddonDependencies(),
registry.getAddons(),
);
createViteLoader(getAddonViteExtenders(registry));
createAddonsStyleLoader(registry);
createAddonsLocalesLoader(registry);
return { registry, shadowAliases, addonsLoaderPath };
}
initPloneRegistryLoaders();