@xyd-js/documan 0.1.0-xyd.10 → 0.1.0-xyd.115
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/LICENSE +21 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1137 -169
- package/dist/index.js.map +1 -1
- package/package.json +21 -32
- package/dist/build.d.ts +0 -2
- package/dist/build.js +0 -106
- package/dist/build.js.map +0 -1
- package/dist/dev.d.ts +0 -2
- package/dist/dev.js +0 -96
- package/dist/dev.js.map +0 -1
- package/dist/serve.d.ts +0 -2
- package/dist/serve.js +0 -110
- package/dist/serve.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,238 +1,1206 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
1
|
+
// src/build.ts
|
|
2
|
+
import path2 from "path";
|
|
3
|
+
import fs2 from "fs";
|
|
5
4
|
import { build as viteBuild } from "vite";
|
|
6
5
|
import tsconfigPaths from "vite-tsconfig-paths";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
6
|
+
|
|
7
|
+
// src/utils.ts
|
|
8
|
+
import path from "path";
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
import { execSync } from "child_process";
|
|
12
|
+
import crypto from "crypto";
|
|
13
|
+
import { createServer } from "vite";
|
|
14
|
+
import { reactRouter } from "@react-router/dev/vite";
|
|
15
|
+
import { IconSet } from "@iconify/tools";
|
|
16
|
+
import { readSettings, pluginDocs } from "@xyd-js/plugin-docs";
|
|
17
|
+
import { vitePlugins as xydContentVitePlugins } from "@xyd-js/content/vite";
|
|
18
|
+
|
|
19
|
+
// src/const.ts
|
|
20
|
+
var XYD_FOLDER_PATH = ".xyd";
|
|
21
|
+
var HOST_FOLDER_PATH = `${XYD_FOLDER_PATH}/host`;
|
|
22
|
+
var CACHE_FOLDER_PATH = `${XYD_FOLDER_PATH}/.cache`;
|
|
23
|
+
var BUILD_FOLDER_PATH = `${XYD_FOLDER_PATH}/build`;
|
|
24
|
+
var SUPPORTED_SETTINGS_FILES = [
|
|
25
|
+
"docs.json",
|
|
26
|
+
"docs.ts",
|
|
27
|
+
"docs.tsx"
|
|
28
|
+
];
|
|
29
|
+
var SUPPORTED_CONTENT_FILES = [
|
|
30
|
+
".md",
|
|
31
|
+
".mdx"
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// src/cli.ts
|
|
35
|
+
import readline from "readline";
|
|
36
|
+
import cliSpinners from "cli-spinners";
|
|
37
|
+
var CLI = class {
|
|
38
|
+
spinner;
|
|
39
|
+
spinnerInterval = null;
|
|
40
|
+
currentFrame = 0;
|
|
41
|
+
currentMessage = "";
|
|
42
|
+
isSpinning = false;
|
|
43
|
+
constructor(spinnerType = "dots") {
|
|
44
|
+
this.spinner = cliSpinners[spinnerType];
|
|
45
|
+
}
|
|
46
|
+
startSpinner(message) {
|
|
47
|
+
if (this.isSpinning) {
|
|
48
|
+
this.stopSpinner();
|
|
49
|
+
}
|
|
50
|
+
this.currentMessage = message;
|
|
51
|
+
this.isSpinning = true;
|
|
52
|
+
this.currentFrame = 0;
|
|
53
|
+
this.write(`${this.spinner.frames[0]} ${this.currentMessage}`);
|
|
54
|
+
this.spinnerInterval = setInterval(() => {
|
|
55
|
+
const frame = this.spinner.frames[this.currentFrame];
|
|
56
|
+
this.write(`${frame} ${this.currentMessage}`);
|
|
57
|
+
this.currentFrame = (this.currentFrame + 1) % this.spinner.frames.length;
|
|
58
|
+
}, this.spinner.interval);
|
|
59
|
+
}
|
|
60
|
+
stopSpinner() {
|
|
61
|
+
if (this.spinnerInterval) {
|
|
62
|
+
clearInterval(this.spinnerInterval);
|
|
63
|
+
this.spinnerInterval = null;
|
|
64
|
+
}
|
|
65
|
+
this.isSpinning = false;
|
|
66
|
+
this.clearLine();
|
|
67
|
+
}
|
|
68
|
+
clearLine() {
|
|
69
|
+
readline.clearLine(process.stdout, 0);
|
|
70
|
+
readline.cursorTo(process.stdout, 0);
|
|
71
|
+
}
|
|
72
|
+
write(message) {
|
|
73
|
+
this.clearLine();
|
|
74
|
+
process.stdout.write(message);
|
|
75
|
+
}
|
|
76
|
+
log(message) {
|
|
77
|
+
if (this.isSpinning) {
|
|
78
|
+
this.stopSpinner();
|
|
79
|
+
}
|
|
80
|
+
console.log(message);
|
|
81
|
+
}
|
|
82
|
+
error(message) {
|
|
83
|
+
if (this.isSpinning) {
|
|
84
|
+
this.stopSpinner();
|
|
85
|
+
}
|
|
86
|
+
console.error(message);
|
|
87
|
+
}
|
|
88
|
+
updateMessage(message) {
|
|
89
|
+
this.currentMessage = message;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var cli = new CLI();
|
|
93
|
+
|
|
94
|
+
// src/utils.ts
|
|
10
95
|
var __filename = fileURLToPath(import.meta.url);
|
|
11
96
|
var __dirname = path.dirname(__filename);
|
|
12
|
-
async function
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
15
|
-
|
|
97
|
+
async function appInit(options) {
|
|
98
|
+
const readPreloadSettings = await readSettings();
|
|
99
|
+
if (!readPreloadSettings) {
|
|
100
|
+
return null;
|
|
16
101
|
}
|
|
17
|
-
const
|
|
102
|
+
const preloadSettings = typeof readPreloadSettings === "string" ? JSON.parse(readPreloadSettings) : readPreloadSettings;
|
|
18
103
|
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
104
|
+
if (!preloadSettings.integrations?.search) {
|
|
105
|
+
preloadSettings.integrations = {
|
|
106
|
+
...preloadSettings.integrations || {},
|
|
107
|
+
search: {
|
|
108
|
+
orama: true
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const plugins = integrationsToPlugins(preloadSettings.integrations);
|
|
113
|
+
if (preloadSettings.plugins) {
|
|
114
|
+
preloadSettings.plugins = [...plugins, ...preloadSettings.plugins];
|
|
115
|
+
} else {
|
|
116
|
+
preloadSettings.plugins = plugins;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
let resolvedPlugins = [];
|
|
120
|
+
{
|
|
121
|
+
resolvedPlugins = await loadPlugins(preloadSettings) || [];
|
|
122
|
+
const userUniformVitePlugins = [];
|
|
123
|
+
const componentPlugins = [];
|
|
124
|
+
resolvedPlugins?.forEach((p) => {
|
|
125
|
+
if (p.uniform) {
|
|
126
|
+
userUniformVitePlugins.push(...p.uniform);
|
|
127
|
+
}
|
|
128
|
+
if (p.components) {
|
|
129
|
+
componentPlugins.push(...p.components);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
globalThis.__xydUserUniformVitePlugins = userUniformVitePlugins;
|
|
133
|
+
globalThis.__xydUserComponents = componentPlugins;
|
|
134
|
+
}
|
|
135
|
+
const respPluginDocs = await pluginDocs(options);
|
|
136
|
+
if (!respPluginDocs) {
|
|
137
|
+
throw new Error("PluginDocs not found");
|
|
138
|
+
}
|
|
139
|
+
if (!respPluginDocs.settings) {
|
|
140
|
+
throw new Error("Settings not found in respPluginDocs");
|
|
141
|
+
}
|
|
142
|
+
respPluginDocs.settings.plugins = [
|
|
143
|
+
...respPluginDocs.settings?.plugins || [],
|
|
144
|
+
...preloadSettings.plugins || []
|
|
145
|
+
];
|
|
146
|
+
globalThis.__xydBasePath = respPluginDocs.basePath;
|
|
147
|
+
globalThis.__xydSettings = respPluginDocs.settings;
|
|
148
|
+
globalThis.__xydPagePathMapping = respPluginDocs.pagePathMapping;
|
|
149
|
+
return {
|
|
150
|
+
respPluginDocs,
|
|
151
|
+
resolvedPlugins
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function virtualComponentsPlugin() {
|
|
155
|
+
return {
|
|
156
|
+
name: "xyd-plugin-virtual-components",
|
|
157
|
+
resolveId(id) {
|
|
158
|
+
if (id === "virtual:xyd-user-components") {
|
|
159
|
+
return id + ".jsx";
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
},
|
|
163
|
+
async load(id) {
|
|
164
|
+
if (id === "virtual:xyd-user-components.jsx") {
|
|
165
|
+
const userComponents = globalThis.__xydUserComponents || [];
|
|
166
|
+
if (userComponents.length > 0 && userComponents[0]?.dist) {
|
|
167
|
+
const imports = userComponents.map(
|
|
168
|
+
(component, index) => `import Component${index} from '${component.dist}';`
|
|
169
|
+
).join("\n");
|
|
170
|
+
const componentObjects = userComponents.map(
|
|
171
|
+
(component, index) => `{
|
|
172
|
+
component: Component${index},
|
|
173
|
+
name: '${component.name}',
|
|
174
|
+
dist: '${component.dist}'
|
|
175
|
+
}`
|
|
176
|
+
).join(",\n ");
|
|
177
|
+
return `
|
|
178
|
+
// Pre-bundled at build time - no async loading needed
|
|
179
|
+
${imports}
|
|
180
|
+
|
|
181
|
+
export const components = [
|
|
182
|
+
${componentObjects}
|
|
183
|
+
];
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
return `
|
|
187
|
+
export const components = globalThis.__xydUserComponents || {}
|
|
188
|
+
`;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function virtualProvidersPlugin(settings) {
|
|
195
|
+
return {
|
|
196
|
+
name: "xyd-plugin-virtual-providers",
|
|
197
|
+
enforce: "pre",
|
|
198
|
+
resolveId(id) {
|
|
199
|
+
if (id === "virtual:xyd-analytics-providers") {
|
|
200
|
+
return id;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
async load(id) {
|
|
204
|
+
if (id === "virtual:xyd-analytics-providers") {
|
|
205
|
+
const providers = Object.keys(settings?.integrations?.analytics || {});
|
|
206
|
+
const imports = providers.map(
|
|
207
|
+
(provider) => `import { default as ${provider}Provider } from '@pluganalytics/provider-${provider}'`
|
|
208
|
+
).join("\n");
|
|
209
|
+
const cases = providers.map(
|
|
210
|
+
(provider) => `case '${provider}': return ${provider}Provider`
|
|
211
|
+
).join("\n");
|
|
212
|
+
return `
|
|
213
|
+
${imports}
|
|
214
|
+
|
|
215
|
+
export const loadProvider = async (provider) => {
|
|
216
|
+
switch (provider) {
|
|
217
|
+
${cases}
|
|
218
|
+
default:
|
|
219
|
+
console.error(\`Provider \${provider} not found\`)
|
|
220
|
+
return null
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function commonVitePlugins(respPluginDocs, resolvedPlugins) {
|
|
229
|
+
const userVitePlugins = resolvedPlugins.map((p) => p.vite).flat() || [];
|
|
230
|
+
return [
|
|
231
|
+
...xydContentVitePlugins({
|
|
232
|
+
toc: {
|
|
233
|
+
maxDepth: respPluginDocs.settings.theme?.maxTocDepth || 2
|
|
234
|
+
},
|
|
235
|
+
settings: respPluginDocs.settings
|
|
236
|
+
}),
|
|
237
|
+
...respPluginDocs.vitePlugins,
|
|
238
|
+
reactRouter(),
|
|
239
|
+
virtualComponentsPlugin(),
|
|
240
|
+
virtualProvidersPlugin(respPluginDocs.settings),
|
|
241
|
+
pluginIconSet(respPluginDocs.settings),
|
|
242
|
+
...userVitePlugins
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
function pluginIconSet(settings) {
|
|
246
|
+
const DEFAULT_ICON_SET = "lucide";
|
|
247
|
+
async function fetchIconSet(name, version) {
|
|
248
|
+
if (name.startsWith("http://") || name.startsWith("https://")) {
|
|
249
|
+
try {
|
|
250
|
+
const iconsResp = await fetch(name);
|
|
251
|
+
const iconsData = await iconsResp.json();
|
|
252
|
+
const iconSet = new IconSet(iconsData);
|
|
253
|
+
return { icons: iconsData, iconSet };
|
|
254
|
+
} catch (error) {
|
|
255
|
+
console.warn(`Failed to fetch from URL ${name}:`, error);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const tryReadFile = (filePath) => {
|
|
259
|
+
try {
|
|
260
|
+
if (!fs.existsSync(filePath)) {
|
|
261
|
+
console.warn(`File does not exist: ${filePath}`);
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const fileContent = fs.readFileSync(filePath, "utf-8");
|
|
265
|
+
try {
|
|
266
|
+
const iconsData = JSON.parse(fileContent);
|
|
267
|
+
const iconSet = new IconSet(iconsData);
|
|
268
|
+
return { icons: iconsData, iconSet };
|
|
269
|
+
} catch (parseError) {
|
|
270
|
+
console.warn(`Invalid JSON in file ${filePath}:`, parseError);
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.warn(`Failed to read file ${filePath}:`, error);
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
25
277
|
};
|
|
26
|
-
if (
|
|
27
|
-
|
|
278
|
+
if (path.isAbsolute(name)) {
|
|
279
|
+
const result = tryReadFile(name);
|
|
280
|
+
if (result) return result;
|
|
281
|
+
}
|
|
282
|
+
if (name.startsWith(".")) {
|
|
283
|
+
const fullPath = path.join(process.cwd(), name);
|
|
284
|
+
const result = tryReadFile(fullPath);
|
|
285
|
+
if (result) return result;
|
|
286
|
+
}
|
|
287
|
+
const cdnUrl = version ? `https://cdn.jsdelivr.net/npm/@iconify-json/${name}@${version}/icons.json` : `https://cdn.jsdelivr.net/npm/@iconify-json/${name}/icons.json`;
|
|
288
|
+
try {
|
|
289
|
+
const iconsResp = await fetch(cdnUrl);
|
|
290
|
+
const iconsData = await iconsResp.json();
|
|
291
|
+
const iconSet = new IconSet(iconsData);
|
|
292
|
+
return { icons: iconsData, iconSet };
|
|
293
|
+
} catch (error) {
|
|
294
|
+
throw new Error(`Failed to load icon set from any source (file or CDN): ${name}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async function processIconSet(iconSet, icons, noPrefix) {
|
|
298
|
+
const resp = /* @__PURE__ */ new Map();
|
|
299
|
+
for (const icon of Object.keys(icons.icons)) {
|
|
300
|
+
const svg = iconSet.toSVG(icon);
|
|
301
|
+
if (!svg) continue;
|
|
302
|
+
let prefix = noPrefix ? void 0 : iconSet.prefix;
|
|
303
|
+
const iconName = prefix ? `${prefix}:${icon}` : icon;
|
|
304
|
+
resp.set(iconName, { svg: svg.toString() });
|
|
305
|
+
}
|
|
306
|
+
return resp;
|
|
307
|
+
}
|
|
308
|
+
async function addIconsToMap(resp, name, version, noPrefix) {
|
|
309
|
+
const { icons, iconSet } = await fetchIconSet(name, version);
|
|
310
|
+
const newIcons = await processIconSet(iconSet, icons, noPrefix);
|
|
311
|
+
newIcons.forEach((value, key) => resp.set(key, value));
|
|
312
|
+
}
|
|
313
|
+
async function processIconLibrary(library) {
|
|
314
|
+
const resp = /* @__PURE__ */ new Map();
|
|
315
|
+
if (typeof library === "string") {
|
|
316
|
+
await addIconsToMap(resp, library);
|
|
317
|
+
} else if (Array.isArray(library)) {
|
|
318
|
+
for (const item of library) {
|
|
319
|
+
if (typeof item === "string") {
|
|
320
|
+
await addIconsToMap(resp, item);
|
|
321
|
+
} else {
|
|
322
|
+
const { name, version, default: isDefault, noprefix } = item;
|
|
323
|
+
const noPrefix = isDefault || noprefix === true;
|
|
324
|
+
await addIconsToMap(resp, name, version, noPrefix);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
} else {
|
|
328
|
+
const { name, version, default: isDefault, noprefix } = library;
|
|
329
|
+
const noPrefix = isDefault || noprefix === true;
|
|
330
|
+
await addIconsToMap(resp, name, version, noPrefix);
|
|
331
|
+
}
|
|
332
|
+
return resp;
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
name: "xyd-plugin-icon-set",
|
|
336
|
+
enforce: "pre",
|
|
337
|
+
resolveId(id) {
|
|
338
|
+
if (id === "virtual:xyd-icon-set") {
|
|
339
|
+
return id;
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
async load(id) {
|
|
343
|
+
if (id === "virtual:xyd-icon-set") {
|
|
344
|
+
let resp;
|
|
345
|
+
if (settings.theme?.icons?.library) {
|
|
346
|
+
resp = await processIconLibrary(settings.theme.icons.library);
|
|
347
|
+
} else {
|
|
348
|
+
resp = await processIconLibrary([
|
|
349
|
+
{
|
|
350
|
+
name: DEFAULT_ICON_SET,
|
|
351
|
+
default: true
|
|
352
|
+
}
|
|
353
|
+
]);
|
|
354
|
+
}
|
|
355
|
+
return `
|
|
356
|
+
export const iconSet = ${JSON.stringify(Object.fromEntries(resp))};
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
function getXydFolderPath() {
|
|
363
|
+
return path.join(
|
|
364
|
+
process.cwd(),
|
|
365
|
+
XYD_FOLDER_PATH
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
function getHostPath() {
|
|
369
|
+
if (process.env.XYD_DEV_MODE) {
|
|
370
|
+
if (process.env.XYD_HOST) {
|
|
371
|
+
return path.resolve(process.env.XYD_HOST);
|
|
372
|
+
}
|
|
373
|
+
return path.join(__dirname, "../../../", HOST_FOLDER_PATH);
|
|
374
|
+
}
|
|
375
|
+
return path.join(process.cwd(), HOST_FOLDER_PATH);
|
|
376
|
+
}
|
|
377
|
+
function getAppRoot() {
|
|
378
|
+
return getHostPath();
|
|
379
|
+
}
|
|
380
|
+
function getPublicPath() {
|
|
381
|
+
return path.join(process.cwd(), "public");
|
|
382
|
+
}
|
|
383
|
+
function getBuildPath() {
|
|
384
|
+
return path.join(
|
|
385
|
+
process.cwd(),
|
|
386
|
+
BUILD_FOLDER_PATH
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
function getDocsPluginBasePath() {
|
|
390
|
+
return path.join(getHostPath(), "./plugins/xyd-plugin-docs");
|
|
391
|
+
}
|
|
392
|
+
async function loadPlugins(settings) {
|
|
393
|
+
const resolvedPlugins = [];
|
|
394
|
+
for (const plugin of settings.plugins || []) {
|
|
395
|
+
let pluginName;
|
|
396
|
+
let pluginArgs = [];
|
|
397
|
+
if (typeof plugin === "string") {
|
|
398
|
+
pluginName = plugin;
|
|
399
|
+
pluginArgs = [];
|
|
400
|
+
} else if (Array.isArray(plugin)) {
|
|
401
|
+
pluginName = plugin[0];
|
|
402
|
+
pluginArgs = plugin.slice(1);
|
|
403
|
+
} else {
|
|
404
|
+
console.error(`Currently only string and array plugins are supported, got: ${plugin}`);
|
|
405
|
+
return [];
|
|
406
|
+
}
|
|
407
|
+
let mod;
|
|
408
|
+
try {
|
|
409
|
+
mod = await import(pluginName);
|
|
410
|
+
} catch (e) {
|
|
411
|
+
pluginName = path.join(process.cwd(), pluginName);
|
|
412
|
+
const pluginPreview = await createServer({
|
|
413
|
+
optimizeDeps: {
|
|
414
|
+
include: []
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
mod = await pluginPreview.ssrLoadModule(pluginName);
|
|
418
|
+
}
|
|
419
|
+
if (!mod.default) {
|
|
420
|
+
console.error(`Plugin ${plugin} has no default export`);
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
let pluginInstance = mod.default(...pluginArgs);
|
|
424
|
+
if (typeof pluginInstance === "function") {
|
|
425
|
+
const plug = pluginInstance(settings);
|
|
426
|
+
resolvedPlugins.push(plug);
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
resolvedPlugins.push(pluginInstance);
|
|
430
|
+
}
|
|
431
|
+
return resolvedPlugins;
|
|
432
|
+
}
|
|
433
|
+
function integrationsToPlugins(integrations) {
|
|
434
|
+
const plugins = [];
|
|
435
|
+
let foundSearchIntegation = 0;
|
|
436
|
+
if (integrations?.search?.orama) {
|
|
437
|
+
if (typeof integrations.search.orama === "boolean") {
|
|
438
|
+
plugins.push("@xyd-js/plugin-orama");
|
|
439
|
+
} else {
|
|
440
|
+
plugins.push(["@xyd-js/plugin-orama", integrations.search.orama]);
|
|
441
|
+
}
|
|
442
|
+
foundSearchIntegation++;
|
|
443
|
+
}
|
|
444
|
+
if (integrations?.search?.algolia) {
|
|
445
|
+
plugins.push(["@xyd-js/plugin-algolia", integrations.search.algolia]);
|
|
446
|
+
foundSearchIntegation++;
|
|
447
|
+
}
|
|
448
|
+
if (foundSearchIntegation > 1) {
|
|
449
|
+
throw new Error("Only one search integration is allowed");
|
|
450
|
+
}
|
|
451
|
+
return plugins;
|
|
452
|
+
}
|
|
453
|
+
async function preWorkspaceSetup(options = {}) {
|
|
454
|
+
await ensureFoldersExist();
|
|
455
|
+
if (!options.force) {
|
|
456
|
+
if (await shouldSkipHostSetup()) {
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const hostTemplate = process.env.XYD_DEV_MODE ? path.resolve(__dirname, "../../xyd-host") : path.resolve(__dirname, "../../host");
|
|
461
|
+
const hostPath = getHostPath();
|
|
462
|
+
await copyHostTemplate(hostTemplate, hostPath);
|
|
463
|
+
let pluginDocsPath;
|
|
464
|
+
if (process.env.XYD_DEV_MODE) {
|
|
465
|
+
pluginDocsPath = path.resolve(__dirname, "../../xyd-plugin-docs");
|
|
466
|
+
} else {
|
|
467
|
+
pluginDocsPath = path.resolve(__dirname, "../../plugin-docs");
|
|
468
|
+
}
|
|
469
|
+
const pagesSourcePath = path.join(pluginDocsPath, "src/pages");
|
|
470
|
+
const pagesTargetPath = path.join(hostPath, "plugins/xyd-plugin-docs/src/pages");
|
|
471
|
+
if (fs.existsSync(pagesSourcePath)) {
|
|
472
|
+
await copyHostTemplate(pagesSourcePath, pagesTargetPath);
|
|
473
|
+
} else {
|
|
474
|
+
console.warn(`Pages source path does not exist: ${pagesSourcePath}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function calculateFolderChecksum(folderPath) {
|
|
478
|
+
const hash = crypto.createHash("sha256");
|
|
479
|
+
const ignorePatterns = [...getGitignorePatterns(folderPath), ".xydchecksum", "node_modules", "dist", ".react-router", "package-lock.json", "pnpm-lock.yaml"];
|
|
480
|
+
function processFile(filePath) {
|
|
481
|
+
const relativePath = path.relative(folderPath, filePath);
|
|
482
|
+
const content = fs.readFileSync(filePath);
|
|
483
|
+
hash.update(relativePath);
|
|
484
|
+
hash.update(content);
|
|
485
|
+
}
|
|
486
|
+
function processDirectory(dirPath) {
|
|
487
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
488
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
489
|
+
for (const entry of entries) {
|
|
490
|
+
const sourceEntry = path.join(dirPath, entry.name);
|
|
491
|
+
if (shouldIgnoreEntry(entry.name, ignorePatterns)) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
if (entry.name === ".git") {
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (entry.isDirectory()) {
|
|
498
|
+
processDirectory(sourceEntry);
|
|
499
|
+
} else {
|
|
500
|
+
processFile(sourceEntry);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
processDirectory(folderPath);
|
|
505
|
+
return hash.digest("hex");
|
|
506
|
+
}
|
|
507
|
+
function getGitignorePatterns(folderPath) {
|
|
508
|
+
const gitignorePath = path.join(folderPath, ".gitignore");
|
|
509
|
+
if (fs.existsSync(gitignorePath)) {
|
|
510
|
+
const gitignoreContent = fs.readFileSync(gitignorePath, "utf-8");
|
|
511
|
+
return gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
512
|
+
}
|
|
513
|
+
return [];
|
|
514
|
+
}
|
|
515
|
+
function shouldIgnoreEntry(entryName, ignorePatterns) {
|
|
516
|
+
return ignorePatterns.some((pattern) => {
|
|
517
|
+
const regex = new RegExp(pattern.replace(/\*/g, ".*"));
|
|
518
|
+
return regex.test(entryName);
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
async function copyHostTemplate(sourcePath, targetPath) {
|
|
522
|
+
if (!fs.existsSync(sourcePath)) {
|
|
523
|
+
throw new Error(`Host template source path does not exist: ${sourcePath}`);
|
|
524
|
+
}
|
|
525
|
+
if (fs.existsSync(targetPath)) {
|
|
526
|
+
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
527
|
+
}
|
|
528
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
529
|
+
const ignorePatterns = getGitignorePatterns(sourcePath);
|
|
530
|
+
const entries = fs.readdirSync(sourcePath, { withFileTypes: true });
|
|
531
|
+
for (const entry of entries) {
|
|
532
|
+
const sourceEntry = path.join(sourcePath, entry.name);
|
|
533
|
+
const targetEntry = path.join(targetPath, entry.name);
|
|
534
|
+
if (shouldIgnoreEntry(entry.name, ignorePatterns)) {
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (entry.name === ".git") {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
if (entry.isDirectory()) {
|
|
541
|
+
await copyHostTemplate(sourceEntry, targetEntry);
|
|
542
|
+
} else {
|
|
543
|
+
fs.copyFileSync(sourceEntry, targetEntry);
|
|
544
|
+
if (entry.name === "package.json" && process.env.XYD_DEV_MODE) {
|
|
545
|
+
const packageJsonPath = targetEntry;
|
|
546
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
547
|
+
packageJson.name = "xyd-host-dev";
|
|
548
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
549
|
+
}
|
|
28
550
|
}
|
|
29
|
-
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
async function ensureFoldersExist() {
|
|
554
|
+
const folders = [CACHE_FOLDER_PATH];
|
|
555
|
+
for (const folder of folders) {
|
|
556
|
+
const fullPath = path.resolve(process.cwd(), folder);
|
|
557
|
+
if (!fs.existsSync(fullPath)) {
|
|
558
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async function postWorkspaceSetup(settings) {
|
|
563
|
+
const spinner = new CLI("dots");
|
|
564
|
+
try {
|
|
565
|
+
spinner.startSpinner("Installing xyd framework...");
|
|
566
|
+
const hostPath = getHostPath();
|
|
567
|
+
const packageJsonPath = path.join(hostPath, "package.json");
|
|
568
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
569
|
+
console.warn("No package.json found in host path");
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
573
|
+
if (!packageJson.dependencies) {
|
|
574
|
+
packageJson.dependencies = {};
|
|
575
|
+
}
|
|
576
|
+
for (const plugin of settings.plugins || []) {
|
|
577
|
+
let pluginName;
|
|
578
|
+
if (typeof plugin === "string") {
|
|
579
|
+
pluginName = plugin;
|
|
580
|
+
} else if (Array.isArray(plugin)) {
|
|
581
|
+
pluginName = plugin[0];
|
|
582
|
+
} else {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
if (pluginName.startsWith("@xyd-js/")) {
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
const isValidNpmPackage = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(pluginName);
|
|
589
|
+
if (isValidNpmPackage) {
|
|
590
|
+
const hostPackageJsonPath = path.join(hostPath, "package.json");
|
|
591
|
+
if (fs.existsSync(hostPackageJsonPath)) {
|
|
592
|
+
const hostPackageJson = JSON.parse(fs.readFileSync(hostPackageJsonPath, "utf-8"));
|
|
593
|
+
const deps = hostPackageJson.dependencies || {};
|
|
594
|
+
const matchingDep = Object.entries(deps).find(([depName]) => {
|
|
595
|
+
return depName === pluginName;
|
|
596
|
+
});
|
|
597
|
+
if (matchingDep) {
|
|
598
|
+
packageJson.dependencies[pluginName] = matchingDep[1];
|
|
599
|
+
} else {
|
|
600
|
+
console.warn(`no matching dependency found for: ${pluginName} in: ${hostPackageJsonPath}`);
|
|
601
|
+
}
|
|
602
|
+
} else {
|
|
603
|
+
console.warn(`no host package.json found in: ${hostPath}`);
|
|
604
|
+
}
|
|
605
|
+
} else if (!pluginName.startsWith(".") && !pluginName.startsWith("/")) {
|
|
606
|
+
console.warn(`invalid plugin name: ${pluginName}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
610
|
+
await nodeInstallPackages(hostPath);
|
|
611
|
+
spinner.stopSpinner();
|
|
612
|
+
spinner.log("\u2714 Local xyd framework installed successfully");
|
|
613
|
+
} catch (error) {
|
|
614
|
+
spinner.stopSpinner();
|
|
615
|
+
spinner.error("\u274C Failed to install xyd framework");
|
|
616
|
+
throw error;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
function nodeInstallPackages(hostPath) {
|
|
620
|
+
const cmdInstall = pmInstall();
|
|
621
|
+
const execOptions = {
|
|
622
|
+
cwd: hostPath,
|
|
623
|
+
env: {
|
|
624
|
+
...process.env,
|
|
625
|
+
NODE_ENV: ""
|
|
626
|
+
// since 'production' does not install it well,
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
const customRegistry = process.env.XYD_NPM_REGISTRY || process.env.npm_config_registry;
|
|
630
|
+
if (customRegistry) {
|
|
631
|
+
if (!execOptions.env) {
|
|
632
|
+
execOptions.env = {};
|
|
633
|
+
}
|
|
634
|
+
execOptions.env["npm_config_registry"] = customRegistry;
|
|
635
|
+
}
|
|
636
|
+
if (process.env.XYD_VERBOSE) {
|
|
637
|
+
execOptions.stdio = "inherit";
|
|
638
|
+
}
|
|
639
|
+
execSync(cmdInstall, execOptions);
|
|
640
|
+
}
|
|
641
|
+
function pmInstall() {
|
|
642
|
+
if (process.env.XYD_NODE_PM) {
|
|
643
|
+
switch (process.env.XYD_NODE_PM) {
|
|
644
|
+
case "npm": {
|
|
645
|
+
return npmInstall();
|
|
646
|
+
}
|
|
647
|
+
case "pnpm": {
|
|
648
|
+
return pnpmInstall();
|
|
649
|
+
}
|
|
650
|
+
case "bun": {
|
|
651
|
+
return bunInstall();
|
|
652
|
+
}
|
|
653
|
+
default: {
|
|
654
|
+
console.warn(`Unknown package manager: ${process.env.XYD_NODE_PM}, falling back to npm`);
|
|
655
|
+
return npmInstall();
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
if (hasBun()) {
|
|
660
|
+
return bunInstall();
|
|
661
|
+
}
|
|
662
|
+
const { pnpm } = runningPm();
|
|
663
|
+
console.log("\u2139\uFE0F consider install `bun` for better performance \n");
|
|
664
|
+
if (pnpm) {
|
|
665
|
+
return pnpmInstall();
|
|
666
|
+
}
|
|
667
|
+
return npmInstall();
|
|
668
|
+
}
|
|
669
|
+
function hasBun() {
|
|
670
|
+
try {
|
|
671
|
+
execSync("bun --version", { stdio: "ignore" });
|
|
672
|
+
return true;
|
|
673
|
+
} catch {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
function runningPm() {
|
|
678
|
+
let pnpm = false;
|
|
679
|
+
let bun = false;
|
|
680
|
+
if (process.env.npm_execpath) {
|
|
681
|
+
if (process.env.npm_execpath.includes("pnpm")) {
|
|
682
|
+
pnpm = true;
|
|
683
|
+
} else if (process.env.npm_execpath.includes("bun")) {
|
|
684
|
+
bun = true;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (process.env.NODE_PATH) {
|
|
688
|
+
const nodePath = process.env.NODE_PATH;
|
|
689
|
+
if (nodePath.includes(".pnpm")) {
|
|
690
|
+
pnpm = true;
|
|
691
|
+
} else if (nodePath.includes(".bun")) {
|
|
692
|
+
bun = true;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
if (process.execPath.includes("bun") || path.dirname(process.argv?.[1] || "").includes("bun")) {
|
|
696
|
+
bun = true;
|
|
697
|
+
}
|
|
698
|
+
return {
|
|
699
|
+
pnpm,
|
|
700
|
+
bun
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
function pnpmInstall() {
|
|
704
|
+
return "pnpm install";
|
|
705
|
+
}
|
|
706
|
+
function bunInstall() {
|
|
707
|
+
return "bun install";
|
|
708
|
+
}
|
|
709
|
+
function npmInstall() {
|
|
710
|
+
return "npm install";
|
|
711
|
+
}
|
|
712
|
+
async function shouldSkipHostSetup() {
|
|
713
|
+
const hostPath = getHostPath();
|
|
714
|
+
if (!fs.existsSync(hostPath)) {
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
const currentChecksum = calculateFolderChecksum(hostPath);
|
|
718
|
+
const storedChecksum = getStoredChecksum();
|
|
719
|
+
if (!storedChecksum || storedChecksum !== currentChecksum) {
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
return true;
|
|
723
|
+
}
|
|
724
|
+
function getStoredChecksum() {
|
|
725
|
+
const checksumPath = path.join(getHostPath(), ".xydchecksum");
|
|
726
|
+
if (!fs.existsSync(checksumPath)) {
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
try {
|
|
730
|
+
return fs.readFileSync(checksumPath, "utf-8").trim();
|
|
731
|
+
} catch (error) {
|
|
732
|
+
console.error("Error reading checksum file:", error);
|
|
733
|
+
return null;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
function storeChecksum(checksum) {
|
|
737
|
+
const checksumPath = path.join(getHostPath(), ".xydchecksum");
|
|
738
|
+
try {
|
|
739
|
+
fs.writeFileSync(checksumPath, checksum);
|
|
740
|
+
} catch (error) {
|
|
741
|
+
console.error("Error writing checksum file:", error);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// src/build.ts
|
|
746
|
+
async function build() {
|
|
747
|
+
const skip = await preWorkspaceSetup({
|
|
748
|
+
force: true
|
|
749
|
+
});
|
|
750
|
+
const inited = await appInit();
|
|
751
|
+
if (!inited) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
const { respPluginDocs, resolvedPlugins } = inited;
|
|
755
|
+
const commonRunVitePlugins = commonVitePlugins(respPluginDocs, resolvedPlugins);
|
|
756
|
+
const appRoot = getAppRoot();
|
|
757
|
+
if (!skip) {
|
|
758
|
+
await postWorkspaceSetup(respPluginDocs.settings);
|
|
759
|
+
const newChecksum = calculateFolderChecksum(getHostPath());
|
|
760
|
+
storeChecksum(newChecksum);
|
|
761
|
+
}
|
|
762
|
+
{
|
|
763
|
+
await setupInstallableEnvironmentV2();
|
|
30
764
|
}
|
|
31
765
|
try {
|
|
32
766
|
await viteBuild({
|
|
33
|
-
|
|
34
|
-
|
|
767
|
+
mode: "production",
|
|
768
|
+
root: appRoot,
|
|
35
769
|
plugins: [
|
|
36
|
-
...
|
|
37
|
-
|
|
38
|
-
minDepth: 2
|
|
39
|
-
}
|
|
40
|
-
}),
|
|
41
|
-
reactRouter({
|
|
42
|
-
outDir: buildDir,
|
|
43
|
-
routes: resp.routes
|
|
44
|
-
}),
|
|
45
|
-
tsconfigPaths(),
|
|
46
|
-
...resp.vitePlugins
|
|
770
|
+
...commonRunVitePlugins,
|
|
771
|
+
tsconfigPaths()
|
|
47
772
|
],
|
|
48
773
|
optimizeDeps: {
|
|
49
774
|
include: ["react/jsx-runtime"]
|
|
775
|
+
},
|
|
776
|
+
define: {
|
|
777
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
778
|
+
"process.env": {}
|
|
779
|
+
},
|
|
780
|
+
resolve: {
|
|
781
|
+
alias: {
|
|
782
|
+
process: "process/browser"
|
|
783
|
+
}
|
|
50
784
|
}
|
|
785
|
+
// ssr: {
|
|
786
|
+
// noExternal: ["react", "react-dom", "react-router"]
|
|
787
|
+
// }
|
|
51
788
|
});
|
|
52
789
|
await viteBuild({
|
|
53
|
-
|
|
790
|
+
mode: "production",
|
|
791
|
+
root: appRoot,
|
|
54
792
|
build: {
|
|
55
793
|
ssr: true
|
|
794
|
+
// rollupOptions: {
|
|
795
|
+
// external: ["@xyd-js/framework/hydration", "fs"]
|
|
796
|
+
// }
|
|
56
797
|
},
|
|
57
|
-
// @ts-ignore
|
|
58
798
|
plugins: [
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
}),
|
|
64
|
-
reactRouter({
|
|
65
|
-
outDir: buildDir,
|
|
66
|
-
routes: resp.routes
|
|
67
|
-
}),
|
|
68
|
-
tsconfigPaths(),
|
|
69
|
-
...resp.vitePlugins
|
|
799
|
+
fixManifestPlugin(appRoot),
|
|
800
|
+
...commonRunVitePlugins,
|
|
801
|
+
tsconfigPaths()
|
|
70
802
|
],
|
|
71
803
|
optimizeDeps: {
|
|
72
804
|
include: ["react/jsx-runtime"]
|
|
805
|
+
// include: ["react", "react-dom", "react/jsx-runtime", "react-router"],
|
|
806
|
+
// force: true
|
|
807
|
+
},
|
|
808
|
+
define: {
|
|
809
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
810
|
+
"process.env": {}
|
|
811
|
+
},
|
|
812
|
+
resolve: {
|
|
813
|
+
alias: {
|
|
814
|
+
process: "process/browser"
|
|
815
|
+
// react: path.resolve(workspaceNodeModulesPath, "react"),
|
|
816
|
+
// "react-dom": path.resolve(workspaceNodeModulesPath, "react-dom")
|
|
817
|
+
}
|
|
73
818
|
}
|
|
819
|
+
// ssr: {
|
|
820
|
+
// noExternal: ["react", "react-dom", "react-router"]
|
|
821
|
+
// }
|
|
74
822
|
});
|
|
75
|
-
console.log("Build completed successfully.");
|
|
76
823
|
} catch (error) {
|
|
77
824
|
console.error("Build failed:", error);
|
|
78
825
|
}
|
|
79
826
|
}
|
|
827
|
+
function setupInstallableEnvironmentV2() {
|
|
828
|
+
const symbolicXydNodeModules = path2.join(getXydFolderPath(), "node_modules");
|
|
829
|
+
const hostNodeModules = path2.join(getHostPath(), "node_modules");
|
|
830
|
+
if (fs2.existsSync(symbolicXydNodeModules)) {
|
|
831
|
+
if (fs2.lstatSync(symbolicXydNodeModules).isSymbolicLink()) {
|
|
832
|
+
fs2.unlinkSync(symbolicXydNodeModules);
|
|
833
|
+
} else {
|
|
834
|
+
fs2.rmSync(symbolicXydNodeModules, { recursive: true, force: true });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
fs2.symlinkSync(hostNodeModules, symbolicXydNodeModules, "dir");
|
|
838
|
+
}
|
|
839
|
+
function fixManifestPlugin(appRoot) {
|
|
840
|
+
const manifestPath = path2.join(
|
|
841
|
+
getBuildPath(),
|
|
842
|
+
// getAppRoot(),
|
|
843
|
+
"./server/.vite/manifest.json"
|
|
844
|
+
);
|
|
845
|
+
return {
|
|
846
|
+
name: "xyd-fix-rr-manifest",
|
|
847
|
+
apply: "build",
|
|
848
|
+
// run after manifest is generated
|
|
849
|
+
// 2) after bundle is written, compute prefix and strip it
|
|
850
|
+
writeBundle(_, bundle) {
|
|
851
|
+
const cwdDir = process.cwd();
|
|
852
|
+
let prefix = path2.relative(appRoot, cwdDir).replace(/\\/g, "/");
|
|
853
|
+
if (prefix) prefix += "/";
|
|
854
|
+
const esc = prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
855
|
+
const stripRe = new RegExp(`^${esc}`);
|
|
856
|
+
for (const fileName in bundle) {
|
|
857
|
+
const asset = bundle[fileName];
|
|
858
|
+
if (asset.type !== "asset") continue;
|
|
859
|
+
if (fileName.endsWith("manifest.json")) {
|
|
860
|
+
const manifest = JSON.parse(asset.source.toString());
|
|
861
|
+
const fixed = {};
|
|
862
|
+
for (const key of Object.keys(manifest)) {
|
|
863
|
+
const entry = manifest[key];
|
|
864
|
+
const newKey = key.replace(stripRe, "");
|
|
865
|
+
if (typeof entry.src === "string") {
|
|
866
|
+
entry.src = entry.src.replace(stripRe, "");
|
|
867
|
+
}
|
|
868
|
+
fixed[newKey] = entry;
|
|
869
|
+
}
|
|
870
|
+
asset.source = JSON.stringify(fixed, null, 2);
|
|
871
|
+
fs2.writeFileSync(manifestPath, asset.source, "utf8");
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
}
|
|
80
877
|
|
|
81
|
-
// src/
|
|
82
|
-
import
|
|
83
|
-
import
|
|
84
|
-
import { createServer, searchForWorkspaceRoot } from "vite";
|
|
85
|
-
import {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
878
|
+
// src/dev.ts
|
|
879
|
+
import path3 from "path";
|
|
880
|
+
import fs3 from "fs";
|
|
881
|
+
import { createServer as createServer2, searchForWorkspaceRoot } from "vite";
|
|
882
|
+
import { readSettings as readSettings2 } from "@xyd-js/plugin-docs";
|
|
883
|
+
if (!process.env.ENABLE_TIMERS) {
|
|
884
|
+
["time", "timeLog", "timeEnd"].forEach((method) => {
|
|
885
|
+
console[method] = () => {
|
|
886
|
+
};
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
var RELOADING = false;
|
|
890
|
+
async function dev(options) {
|
|
891
|
+
const spinner = new CLI("dots");
|
|
892
|
+
spinner.startSpinner("Preparing local xyd instance...");
|
|
893
|
+
const skip = await preWorkspaceSetup();
|
|
894
|
+
const inited = await appInit();
|
|
895
|
+
if (!inited) {
|
|
896
|
+
return;
|
|
95
897
|
}
|
|
898
|
+
const { respPluginDocs, resolvedPlugins } = inited;
|
|
96
899
|
const allowCwd = searchForWorkspaceRoot(process.cwd());
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
900
|
+
const appRoot = getAppRoot();
|
|
901
|
+
const commonRunVitePlugins = commonVitePlugins(respPluginDocs, resolvedPlugins);
|
|
902
|
+
spinner.stopSpinner();
|
|
903
|
+
if (!skip) {
|
|
904
|
+
await postWorkspaceSetup(respPluginDocs.settings);
|
|
905
|
+
const newChecksum = calculateFolderChecksum(getHostPath());
|
|
906
|
+
storeChecksum(newChecksum);
|
|
907
|
+
}
|
|
908
|
+
spinner.log("\u2714 Local xyd instance is ready");
|
|
909
|
+
let server = null;
|
|
910
|
+
const port = options?.port ?? parseInt(process.env.XYD_PORT ?? "5175");
|
|
911
|
+
let USE_CONTEXT_ISSUE_PACKAGES = [];
|
|
912
|
+
{
|
|
913
|
+
if (process.env.XYD_DEV_MODE) {
|
|
914
|
+
USE_CONTEXT_ISSUE_PACKAGES = [
|
|
915
|
+
"react-github-btn",
|
|
916
|
+
"radix-ui",
|
|
917
|
+
"@code-hike/lighter",
|
|
918
|
+
"lucide-react",
|
|
919
|
+
"openux-js",
|
|
920
|
+
"pluganalytics"
|
|
921
|
+
];
|
|
922
|
+
} else {
|
|
923
|
+
USE_CONTEXT_ISSUE_PACKAGES = [
|
|
924
|
+
"@xyd-js/theme-cosmo",
|
|
925
|
+
"@xyd-js/theme-opener",
|
|
926
|
+
"@xyd-js/theme-picasso",
|
|
927
|
+
"@xyd-js/theme-poetry"
|
|
928
|
+
];
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
const preview = await createServer2({
|
|
932
|
+
root: appRoot,
|
|
933
|
+
publicDir: "/public",
|
|
104
934
|
server: {
|
|
935
|
+
allowedHosts: [],
|
|
105
936
|
port,
|
|
106
937
|
fs: {
|
|
107
938
|
allow: [
|
|
108
939
|
allowCwd,
|
|
109
|
-
|
|
110
|
-
// path.join(__dirname, "../node_modules") // Ensure node_modules from xyd-documan is included
|
|
940
|
+
appRoot
|
|
111
941
|
]
|
|
112
942
|
}
|
|
113
943
|
},
|
|
944
|
+
define: {
|
|
945
|
+
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
|
|
946
|
+
"process.env": {}
|
|
947
|
+
},
|
|
948
|
+
resolve: {
|
|
949
|
+
alias: {
|
|
950
|
+
process: "process/browser"
|
|
951
|
+
}
|
|
952
|
+
// preserveSymlinks: true
|
|
953
|
+
},
|
|
114
954
|
build: {
|
|
115
955
|
rollupOptions: {
|
|
116
|
-
|
|
117
|
-
external: ["@xyd-js/uniform", "@xyd-js/uniform/content", "@xyd-js/plugin-zero"]
|
|
956
|
+
external: []
|
|
118
957
|
}
|
|
119
958
|
},
|
|
120
959
|
ssr: {
|
|
121
|
-
external: [
|
|
122
|
-
// noExternal: [
|
|
123
|
-
// "@xyd-js/uniform",
|
|
124
|
-
// "@xyd-js/uniform/content",
|
|
125
|
-
// "@xyd-js/plugin-zero"
|
|
126
|
-
// ],
|
|
960
|
+
external: []
|
|
127
961
|
},
|
|
128
962
|
optimizeDeps: {
|
|
129
|
-
include: [
|
|
963
|
+
include: [
|
|
964
|
+
"react/jsx-runtime",
|
|
965
|
+
...USE_CONTEXT_ISSUE_PACKAGES
|
|
966
|
+
]
|
|
967
|
+
// exclude: ["react", "react-dom"]
|
|
130
968
|
},
|
|
131
|
-
// @ts-ignore
|
|
132
969
|
plugins: [
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
970
|
+
...commonRunVitePlugins,
|
|
971
|
+
{
|
|
972
|
+
name: "xyd-configureServer",
|
|
973
|
+
configureServer(s) {
|
|
974
|
+
server = s;
|
|
137
975
|
}
|
|
138
|
-
}
|
|
139
|
-
reactRouter2({
|
|
140
|
-
routes: resp.routes
|
|
141
|
-
}),
|
|
142
|
-
...resp.vitePlugins
|
|
976
|
+
}
|
|
143
977
|
]
|
|
144
978
|
});
|
|
979
|
+
const watcher = fs3.watch(allowCwd, { recursive: true }, async (eventType, filename) => {
|
|
980
|
+
if (RELOADING) {
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
if (!filename) {
|
|
984
|
+
console.log("[xyd:dev-watcher] Received empty filename");
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
if (!server) {
|
|
988
|
+
console.log("[xyd:dev-watcher] Server not ready");
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
const filePath = path3.join(allowCwd, filename);
|
|
992
|
+
if (filePath.includes(CACHE_FOLDER_PATH)) {
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const publicPathReload = filePath.includes(getPublicPath());
|
|
996
|
+
if (publicPathReload) {
|
|
997
|
+
const relativePath = path3.relative(allowCwd, filePath);
|
|
998
|
+
const urlPath = "/" + relativePath.replace(/\\/g, "/");
|
|
999
|
+
preview.ws.send({
|
|
1000
|
+
type: "full-reload",
|
|
1001
|
+
path: urlPath
|
|
1002
|
+
});
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
let apiPaths = {};
|
|
1006
|
+
if (respPluginDocs?.settings?.api) {
|
|
1007
|
+
apiPaths = resolveApiFilePaths(process.cwd(), respPluginDocs.settings.api);
|
|
1008
|
+
}
|
|
1009
|
+
const apiChanged = !!apiPaths[filePath];
|
|
1010
|
+
const isSettingsFile = SUPPORTED_SETTINGS_FILES.some((ext) => filePath.endsWith(ext));
|
|
1011
|
+
const isContentFile = SUPPORTED_CONTENT_FILES.some((ext) => filePath.endsWith(ext));
|
|
1012
|
+
const isWatchFile = isSettingsFile || isContentFile || apiChanged;
|
|
1013
|
+
if (!isWatchFile) {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
if (isContentFile && eventType !== "rename") {
|
|
1017
|
+
console.log("\u{1F504} Content file changed, refresh...", eventType);
|
|
1018
|
+
invalidateSettings(server);
|
|
1019
|
+
await touchLayoutPage();
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
const renameContentFile = isContentFile && eventType === "rename";
|
|
1023
|
+
if (isSettingsFile || renameContentFile) {
|
|
1024
|
+
if (renameContentFile) {
|
|
1025
|
+
console.log("\u{1F504} Content file renamed, refresh...");
|
|
1026
|
+
} else {
|
|
1027
|
+
console.log("\u{1F504} Settings file changed, refresh...");
|
|
1028
|
+
}
|
|
1029
|
+
if (respPluginDocs?.settings.engine?.uniform?.store) {
|
|
1030
|
+
await appInit({
|
|
1031
|
+
disableFSWrite: true
|
|
1032
|
+
});
|
|
1033
|
+
} else {
|
|
1034
|
+
await appInit();
|
|
1035
|
+
}
|
|
1036
|
+
const newSettings = await readSettings2();
|
|
1037
|
+
if (typeof newSettings !== "object") {
|
|
1038
|
+
console.log("[xyd:dev-watcher] Settings is not an object");
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
invalidateSettings(server);
|
|
1042
|
+
await touchReactRouterConfig();
|
|
1043
|
+
await touchLayoutPage();
|
|
1044
|
+
server.ws.send({ type: "full-reload" });
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
watcher.on("error", (error) => {
|
|
1048
|
+
console.error("[xyd:dev] File watcher error:", error);
|
|
1049
|
+
});
|
|
145
1050
|
await preview.listen(port);
|
|
1051
|
+
if (respPluginDocs.settings.navigation) {
|
|
1052
|
+
await optimizeDepsFix(port, respPluginDocs.settings.navigation);
|
|
1053
|
+
}
|
|
146
1054
|
preview.printUrls();
|
|
147
1055
|
preview.bindCLIShortcuts({ print: true });
|
|
1056
|
+
preview.httpServer?.once("close", () => {
|
|
1057
|
+
watcher.close();
|
|
1058
|
+
});
|
|
148
1059
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
1060
|
+
function resolveApiFilePaths(basePath, api) {
|
|
1061
|
+
const result = {};
|
|
1062
|
+
const apis = [api.openapi, api.graphql, api.sources].filter((s) => s !== void 0);
|
|
1063
|
+
apis.forEach((section) => {
|
|
1064
|
+
flattenApiFile(section).forEach((p) => {
|
|
1065
|
+
const apiAbsPath = path3.resolve(basePath, p);
|
|
1066
|
+
result[apiAbsPath] = true;
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
return result;
|
|
1070
|
+
}
|
|
1071
|
+
function flattenApiFile(file) {
|
|
1072
|
+
if (!file) return [];
|
|
1073
|
+
if (typeof file === "string") {
|
|
1074
|
+
return [file];
|
|
1075
|
+
}
|
|
1076
|
+
if (Array.isArray(file)) {
|
|
1077
|
+
return file.flatMap(flattenApiFile);
|
|
1078
|
+
}
|
|
1079
|
+
if (typeof file === "object") {
|
|
1080
|
+
const obj = file;
|
|
1081
|
+
if (typeof obj.source === "string") {
|
|
1082
|
+
return [obj.source];
|
|
1083
|
+
}
|
|
1084
|
+
return Object.values(obj).flatMap(flattenApiFile);
|
|
1085
|
+
}
|
|
1086
|
+
return [];
|
|
1087
|
+
}
|
|
1088
|
+
function getFirstPageFromNavigation(navigation) {
|
|
1089
|
+
if (!navigation?.sidebar?.length) {
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1092
|
+
function extractFirstPage(pages) {
|
|
1093
|
+
for (const page of pages) {
|
|
1094
|
+
if (typeof page === "string") {
|
|
1095
|
+
return normalizePagePath(page);
|
|
1096
|
+
}
|
|
1097
|
+
if (typeof page === "object") {
|
|
1098
|
+
if ("route" in page && page.pages) {
|
|
1099
|
+
const firstPage = extractFirstPage(page.pages);
|
|
1100
|
+
if (firstPage) return firstPage;
|
|
1101
|
+
}
|
|
1102
|
+
if ("pages" in page && page.pages) {
|
|
1103
|
+
const firstPage = extractFirstPage(page.pages);
|
|
1104
|
+
if (firstPage) return firstPage;
|
|
1105
|
+
}
|
|
1106
|
+
if ("page" in page && typeof page.page === "string") {
|
|
1107
|
+
return normalizePagePath(page.page);
|
|
180
1108
|
}
|
|
181
1109
|
}
|
|
182
|
-
return null;
|
|
183
1110
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
1113
|
+
return extractFirstPage(navigation.sidebar);
|
|
1114
|
+
}
|
|
1115
|
+
function normalizePagePath(pagePath) {
|
|
1116
|
+
let normalized = pagePath.replace(/\.(md|mdx)$/, "");
|
|
1117
|
+
if (normalized.endsWith("/index") || normalized === "index") {
|
|
1118
|
+
normalized = normalized.replace(/\/?index$/, "");
|
|
1119
|
+
}
|
|
1120
|
+
if (normalized.startsWith("/")) {
|
|
1121
|
+
normalized = normalized.slice(1);
|
|
1122
|
+
}
|
|
1123
|
+
return normalized;
|
|
1124
|
+
}
|
|
1125
|
+
async function fetchFirstPage(firstPage, port) {
|
|
1126
|
+
const urlsToTry = [
|
|
1127
|
+
`http://localhost:${port}/${firstPage}`,
|
|
1128
|
+
`http://localhost:${port}/${firstPage}/`,
|
|
1129
|
+
`http://localhost:${port}/${firstPage}.html`,
|
|
1130
|
+
`http://localhost:${port}/${firstPage}/index.html`
|
|
1131
|
+
];
|
|
1132
|
+
for (const url of urlsToTry) {
|
|
1133
|
+
try {
|
|
1134
|
+
const response = await fetch(url);
|
|
1135
|
+
if (response.ok) {
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
continue;
|
|
202
1140
|
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
function invalidateSettings(server) {
|
|
1144
|
+
const virtualId = "virtual:xyd-settings";
|
|
1145
|
+
const resolvedId = virtualId + ".jsx";
|
|
1146
|
+
const mod = server.moduleGraph.getModuleById(resolvedId);
|
|
1147
|
+
if (!mod) {
|
|
1148
|
+
console.log("[xyd:dev-watcher] Settings module not found");
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
server.moduleGraph.invalidateModule(mod);
|
|
1152
|
+
server.ws.send({
|
|
1153
|
+
type: "update",
|
|
1154
|
+
updates: [
|
|
1155
|
+
{
|
|
1156
|
+
type: "js-update",
|
|
1157
|
+
path: `/@id/${resolvedId}`,
|
|
1158
|
+
acceptedPath: `/@id/${resolvedId}`,
|
|
1159
|
+
timestamp: Date.now()
|
|
1160
|
+
}
|
|
1161
|
+
]
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
async function touchReactRouterConfig() {
|
|
1165
|
+
const hostPath = getHostPath();
|
|
1166
|
+
const hostReactRouterConfig = path3.join(hostPath, "react-router.config.ts");
|
|
1167
|
+
await fs3.promises.utimes(hostReactRouterConfig, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date());
|
|
1168
|
+
}
|
|
1169
|
+
async function touchLayoutPage() {
|
|
1170
|
+
const docsPluginBasePath = getDocsPluginBasePath();
|
|
1171
|
+
const layoutPath = path3.join(docsPluginBasePath, "./src/pages/layout.tsx");
|
|
1172
|
+
await fs3.promises.utimes(layoutPath, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date());
|
|
1173
|
+
}
|
|
1174
|
+
async function optimizeDepsFix(port, navigation) {
|
|
1175
|
+
const firstPage = getFirstPageFromNavigation(navigation);
|
|
1176
|
+
if (firstPage) {
|
|
1177
|
+
await fetchFirstPage(firstPage, port);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// src/install.ts
|
|
1182
|
+
import fs4 from "fs";
|
|
1183
|
+
import { readSettings as readSettings3 } from "@xyd-js/plugin-docs";
|
|
1184
|
+
async function install() {
|
|
1185
|
+
const settings = await readSettings3();
|
|
1186
|
+
if (!settings) {
|
|
1187
|
+
throw new Error("cannot preload settings");
|
|
1188
|
+
}
|
|
1189
|
+
if (typeof settings === "string") {
|
|
1190
|
+
throw new Error("install does not support string settings");
|
|
1191
|
+
}
|
|
1192
|
+
const hostPath = getHostPath();
|
|
1193
|
+
if (fs4.existsSync(hostPath)) {
|
|
1194
|
+
fs4.rmSync(hostPath, { recursive: true, force: true });
|
|
1195
|
+
}
|
|
1196
|
+
await preWorkspaceSetup({
|
|
1197
|
+
force: true
|
|
231
1198
|
});
|
|
1199
|
+
await postWorkspaceSetup(settings);
|
|
232
1200
|
}
|
|
233
1201
|
export {
|
|
234
1202
|
build,
|
|
235
1203
|
dev,
|
|
236
|
-
|
|
1204
|
+
install
|
|
237
1205
|
};
|
|
238
1206
|
//# sourceMappingURL=index.js.map
|