nextjs-cms 0.5.56 → 0.5.58
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/api/index.d.ts +82 -45
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/lib/serverActions.d.ts +68 -5
- package/dist/api/lib/serverActions.d.ts.map +1 -1
- package/dist/api/lib/serverActions.js +33 -8
- package/dist/api/root.d.ts +953 -44
- package/dist/api/root.d.ts.map +1 -1
- package/dist/api/root.js +2 -1
- package/dist/api/routers/accountSettings.d.ts +1 -3
- package/dist/api/routers/accountSettings.d.ts.map +1 -1
- package/dist/api/routers/admins.d.ts +1 -3
- package/dist/api/routers/admins.d.ts.map +1 -1
- package/dist/api/routers/admins.js +1 -1
- package/dist/api/routers/auth.d.ts +1 -3
- package/dist/api/routers/auth.d.ts.map +1 -1
- package/dist/api/routers/categorySection.d.ts +1 -3
- package/dist/api/routers/categorySection.d.ts.map +1 -1
- package/dist/api/routers/cmsSettings.d.ts +1 -3
- package/dist/api/routers/cmsSettings.d.ts.map +1 -1
- package/dist/api/routers/cpanel.d.ts +1 -3
- package/dist/api/routers/cpanel.d.ts.map +1 -1
- package/dist/api/routers/files.d.ts +1 -3
- package/dist/api/routers/files.d.ts.map +1 -1
- package/dist/api/routers/gallery.d.ts +1 -3
- package/dist/api/routers/gallery.d.ts.map +1 -1
- package/dist/api/routers/gallery.js +7 -6
- package/dist/api/routers/googleAnalytics.d.ts +1 -3
- package/dist/api/routers/googleAnalytics.d.ts.map +1 -1
- package/dist/api/routers/hasItemsSection.d.ts +49 -5
- package/dist/api/routers/hasItemsSection.d.ts.map +1 -1
- package/dist/api/routers/navigation.d.ts +1 -3
- package/dist/api/routers/navigation.d.ts.map +1 -1
- package/dist/api/routers/simpleSection.d.ts +21 -4
- package/dist/api/routers/simpleSection.d.ts.map +1 -1
- package/dist/api/trpc/query-client.d.ts +3 -0
- package/dist/api/trpc/query-client.d.ts.map +1 -0
- package/dist/api/trpc/query-client.js +23 -0
- package/dist/api/trpc/server.d.ts +8 -0
- package/dist/api/trpc/server.d.ts.map +1 -0
- package/dist/api/trpc/server.js +23 -0
- package/dist/api/trpc.d.ts +6 -17
- package/dist/api/trpc.d.ts.map +1 -1
- package/dist/api/trpc.js +6 -9
- package/dist/auth/react.js +1 -1
- package/dist/core/config/config-loader.d.ts +1 -1
- package/dist/core/config/config-loader.d.ts.map +1 -1
- package/dist/core/config/config-loader.js +9 -6
- package/dist/core/config/index.d.ts +1 -0
- package/dist/core/config/index.d.ts.map +1 -1
- package/dist/core/config/index.js +1 -0
- package/dist/core/config/loader-with-esbuild.d.ts +7 -0
- package/dist/core/config/loader-with-esbuild.d.ts.map +1 -0
- package/dist/core/config/loader-with-esbuild.js +98 -0
- package/dist/core/config/loader-with-jiti.d.ts +13 -0
- package/dist/core/config/loader-with-jiti.d.ts.map +1 -0
- package/dist/core/config/loader-with-jiti.js +162 -0
- package/dist/core/config/loader.d.ts +1 -1
- package/dist/core/config/loader.d.ts.map +1 -1
- package/dist/core/config/loader.js +1 -75
- package/dist/core/factories/SectionFactory.d.ts +1 -109
- package/dist/core/factories/SectionFactory.d.ts.map +1 -1
- package/dist/core/factories/SectionFactory.js +1 -452
- package/dist/core/factories/section-factory-with-esbuild.d.ts +110 -0
- package/dist/core/factories/section-factory-with-esbuild.d.ts.map +1 -0
- package/dist/core/factories/section-factory-with-esbuild.js +509 -0
- package/dist/core/factories/section-factory-with-jiti.d.ts +113 -0
- package/dist/core/factories/section-factory-with-jiti.d.ts.map +1 -0
- package/dist/core/factories/section-factory-with-jiti.js +556 -0
- package/dist/core/fields/document.d.ts +0 -1
- package/dist/core/fields/document.d.ts.map +1 -1
- package/dist/core/fields/document.js +5 -4
- package/dist/core/fields/photo.d.ts +10 -7
- package/dist/core/fields/photo.d.ts.map +1 -1
- package/dist/core/fields/photo.js +44 -17
- package/dist/core/fields/richText.d.ts +0 -1
- package/dist/core/fields/richText.d.ts.map +1 -1
- package/dist/core/fields/richText.js +5 -4
- package/dist/core/fields/video.d.ts +0 -1
- package/dist/core/fields/video.d.ts.map +1 -1
- package/dist/core/fields/video.js +5 -4
- package/dist/core/sections/section.d.ts +17 -15
- package/dist/core/sections/section.d.ts.map +1 -1
- package/dist/core/sections/section.js +28 -5
- package/dist/core/submit/submit.d.ts.map +1 -1
- package/dist/core/submit/submit.js +13 -12
- package/dist/translations/dictionaries/ar.json +1 -0
- package/dist/translations/dictionaries/en.json +1 -0
- package/dist/translations/index.d.ts.map +1 -1
- package/dist/translations/index.js +1 -3
- package/package.json +18 -9
|
@@ -4,7 +4,7 @@ if (typeof window !== 'undefined') {
|
|
|
4
4
|
// import 'server-only'
|
|
5
5
|
// import chalk from 'chalk'
|
|
6
6
|
import * as z from 'zod';
|
|
7
|
-
import { loadConfigModule } from './loader.js';
|
|
7
|
+
import { loadConfigModule, getConfigImportVersion } from './loader.js';
|
|
8
8
|
// 1. Define config schema
|
|
9
9
|
const cmsConfigSchema = z.object({
|
|
10
10
|
/**
|
|
@@ -237,6 +237,7 @@ const defaultConfig = {
|
|
|
237
237
|
return `${chalk.bgRed.bold(' Error ')} ${error} ${greyMsg ? chalk.grey(greyMsg) : ''}`.trim()
|
|
238
238
|
}*/
|
|
239
239
|
let cachedConfig;
|
|
240
|
+
let cachedConfigVersion = -1;
|
|
240
241
|
/**
|
|
241
242
|
* Loads and parses the user configuration module.
|
|
242
243
|
* This is called lazily when getCMSConfig() is first invoked.
|
|
@@ -244,9 +245,9 @@ let cachedConfig;
|
|
|
244
245
|
* @returns The parsed user configuration object, or undefined if no config file exists
|
|
245
246
|
* @throws Error if the config file exists but cannot be loaded or parsed
|
|
246
247
|
*/
|
|
247
|
-
function loadUserConfig() {
|
|
248
|
+
async function loadUserConfig() {
|
|
248
249
|
try {
|
|
249
|
-
const mod = loadConfigModule();
|
|
250
|
+
const mod = (await loadConfigModule());
|
|
250
251
|
const config = mod ? (mod.config ?? mod) : undefined;
|
|
251
252
|
if (!config) {
|
|
252
253
|
return undefined;
|
|
@@ -270,13 +271,15 @@ function loadUserConfig() {
|
|
|
270
271
|
* @returns A readonly computed CMS configuration with all required fields
|
|
271
272
|
* @throws Error if the config file exists but is invalid
|
|
272
273
|
*/
|
|
273
|
-
export function getCMSConfig() {
|
|
274
|
-
|
|
274
|
+
export async function getCMSConfig() {
|
|
275
|
+
const currentVersion = getConfigImportVersion();
|
|
276
|
+
if (cachedConfig === undefined || cachedConfigVersion !== currentVersion) {
|
|
275
277
|
// Load user config lazily (only when this function is first called)
|
|
276
|
-
const userConfig = loadUserConfig();
|
|
278
|
+
const userConfig = await loadUserConfig();
|
|
277
279
|
// Merge user config with defaults
|
|
278
280
|
const mergedConfig = mergeConfig(defaultConfig, userConfig ?? {});
|
|
279
281
|
cachedConfig = mergedConfig;
|
|
282
|
+
cachedConfigVersion = currentVersion;
|
|
280
283
|
}
|
|
281
284
|
return cachedConfig;
|
|
282
285
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACpD,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turbopack-safe loader:
|
|
3
|
+
* - In Next 16 Turbopack SSR, dynamic require(found) fails ("expression is too dynamic")
|
|
4
|
+
* - Use runtime import(file://...) and tell turbopack to ignore analyzing it.
|
|
5
|
+
*/
|
|
6
|
+
export declare const loadConfigModule: () => Promise<unknown>;
|
|
7
|
+
//# sourceMappingURL=loader-with-esbuild.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader-with-esbuild.d.ts","sourceRoot":"","sources":["../../../src/core/config/loader-with-esbuild.ts"],"names":[],"mappings":"AAgFA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,OAAO,CA2BxD,CAAA"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// loader.ts (or config-loader.ts)
|
|
2
|
+
// Turbopack-safe config loader for Next.js 16+
|
|
3
|
+
// - Avoids dynamic require(found) which Turbopack rejects ("expression is too dynamic")
|
|
4
|
+
// - Uses runtime import(file://...) with `turbopackIgnore`
|
|
5
|
+
// - Still supports TS configs via esbuild-register
|
|
6
|
+
// - Keeps your Node CJS resolve patch for tests (js specifier -> ts fallback)
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { resolve, join } from 'path';
|
|
9
|
+
import { createRequire } from 'module';
|
|
10
|
+
import { pathToFileURL } from 'url';
|
|
11
|
+
// Create a require function that works in ES modules
|
|
12
|
+
const safeRequire = createRequire(import.meta.url);
|
|
13
|
+
/**
|
|
14
|
+
* See SectionFactory.ts: during dev/tests we may runtime-load TS that contains NodeNext-style `./x.js` specifiers
|
|
15
|
+
* pointing at `./x.ts` in the source tree. Patch CJS resolution to fall back to `.ts` for relative imports.
|
|
16
|
+
*/
|
|
17
|
+
const withPatchedCjsResolveJsToTs = (fn) => {
|
|
18
|
+
const NodeModule = safeRequire('module');
|
|
19
|
+
const originalResolve = NodeModule._resolveFilename;
|
|
20
|
+
NodeModule._resolveFilename = function (request, parent, isMain, options) {
|
|
21
|
+
try {
|
|
22
|
+
return originalResolve.call(this, request, parent, isMain, options);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (typeof request === 'string' && /^(\.{1,2}\/.*)\.js$/.test(request)) {
|
|
26
|
+
const tsRequest = request.replace(/\.js$/, '.ts');
|
|
27
|
+
try {
|
|
28
|
+
return originalResolve.call(this, tsRequest, parent, isMain, options);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// fall through to rethrow original error
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
return fn();
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
NodeModule._resolveFilename = originalResolve;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const registerEsbuildForTs = () => {
|
|
45
|
+
try {
|
|
46
|
+
const { register } = safeRequire('esbuild-register/dist/node');
|
|
47
|
+
return register({ format: 'cjs', loader: 'ts' }).unregister;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
throw new Error(`Unable to load TypeScript config. Install 'esbuild-register', or provide cms.config.js/json.`);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const findConfigFile = () => {
|
|
54
|
+
const cwd = process.cwd();
|
|
55
|
+
const candidates = [
|
|
56
|
+
'cms.config.js',
|
|
57
|
+
'cms.config.cjs',
|
|
58
|
+
'cms.config.mjs',
|
|
59
|
+
'cms.config.json',
|
|
60
|
+
'cms.config.ts',
|
|
61
|
+
'cms.config.cts',
|
|
62
|
+
'cms.config.mts',
|
|
63
|
+
].map((f) => resolve(join(cwd, f)));
|
|
64
|
+
const found = candidates.find((p) => existsSync(p));
|
|
65
|
+
if (!found) {
|
|
66
|
+
throw new Error(`Config file not found. Searched: ${candidates.join(', ')}`);
|
|
67
|
+
}
|
|
68
|
+
const isTs = found.endsWith('.ts') || found.endsWith('.cts') || found.endsWith('.mts');
|
|
69
|
+
return { found, isTs };
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Turbopack-safe loader:
|
|
73
|
+
* - In Next 16 Turbopack SSR, dynamic require(found) fails ("expression is too dynamic")
|
|
74
|
+
* - Use runtime import(file://...) and tell turbopack to ignore analyzing it.
|
|
75
|
+
*/
|
|
76
|
+
export const loadConfigModule = async () => {
|
|
77
|
+
const { found, isTs } = findConfigFile();
|
|
78
|
+
let unregister;
|
|
79
|
+
try {
|
|
80
|
+
if (isTs) {
|
|
81
|
+
unregister = registerEsbuildForTs();
|
|
82
|
+
}
|
|
83
|
+
// For tests (NODE_ENV=test), keep your CJS resolver patch behavior
|
|
84
|
+
const importConfig = async () => {
|
|
85
|
+
const url = pathToFileURL(found).href;
|
|
86
|
+
// IMPORTANT: prevent Turbopack from trying to statically analyze the specifier
|
|
87
|
+
const mod = await import(/* turbopackIgnore: true */ url);
|
|
88
|
+
return mod;
|
|
89
|
+
};
|
|
90
|
+
const mod = process.env.NODE_ENV === 'test' && isTs
|
|
91
|
+
? await withPatchedCjsResolveJsToTs(() => importConfig())
|
|
92
|
+
: await importConfig();
|
|
93
|
+
return mod?.default ?? mod;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
unregister?.();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const getConfigImportVersion: () => number;
|
|
2
|
+
/**
|
|
3
|
+
* Turbopack-safe loader:
|
|
4
|
+
* - In Next 16 Turbopack SSR, dynamic require(found) fails ("expression is too dynamic")
|
|
5
|
+
* - Native ESM importing `.ts` triggers MODULE_TYPELESS_PACKAGE_JSON warning
|
|
6
|
+
*
|
|
7
|
+
* SOLUTION:
|
|
8
|
+
* - Use `jiti` for TypeScript configs (no Node ESM, no warnings)
|
|
9
|
+
* - Use `require()` for CJS / JSON
|
|
10
|
+
* - Use native `import()` only for `.mjs`
|
|
11
|
+
*/
|
|
12
|
+
export declare const loadConfigModule: () => Promise<unknown>;
|
|
13
|
+
//# sourceMappingURL=loader-with-jiti.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader-with-jiti.d.ts","sourceRoot":"","sources":["../../../src/core/config/loader-with-jiti.ts"],"names":[],"mappings":"AAyCA,eAAO,MAAM,sBAAsB,cAAmC,CAAA;AA6GtE;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,OAAO,CA4BxD,CAAA"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// loader.ts (or config-loader.ts)
|
|
2
|
+
// Turbopack-safe config loader for Next.js 16+
|
|
3
|
+
//
|
|
4
|
+
// - Avoids dynamic require(found) which Turbopack rejects ("expression is too dynamic")
|
|
5
|
+
// - Avoids native ESM importing `.ts` config (prevents MODULE_TYPELESS_PACKAGE_JSON warning)
|
|
6
|
+
// - Uses jiti for TypeScript configs (sync, no Node ESM guessing)
|
|
7
|
+
// - Still supports JS / CJS / MJS / JSON configs
|
|
8
|
+
// - Keeps your Node CJS resolve patch for tests (js specifier -> ts fallback)
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { resolve, join } from 'path';
|
|
11
|
+
import chokidar from 'chokidar';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
let jitiInstance = null;
|
|
15
|
+
const hotMarkerFile = resolve(process.cwd(), 'components/form/helpers/_section-hot-reload.js');
|
|
16
|
+
const configWatcherState = (() => {
|
|
17
|
+
const key = Symbol.for('nextjs-cms.configWatcher');
|
|
18
|
+
const globalAny = globalThis;
|
|
19
|
+
if (!globalAny[key]) {
|
|
20
|
+
globalAny[key] = {
|
|
21
|
+
watcher: null,
|
|
22
|
+
version: 0,
|
|
23
|
+
lastEventAt: new Map(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return globalAny[key];
|
|
27
|
+
})();
|
|
28
|
+
export const getConfigImportVersion = () => configWatcherState.version;
|
|
29
|
+
const clearJitiCache = (absPath) => {
|
|
30
|
+
if (!jitiInstance)
|
|
31
|
+
return;
|
|
32
|
+
try {
|
|
33
|
+
let resolvedPath;
|
|
34
|
+
try {
|
|
35
|
+
resolvedPath = jitiInstance.resolve(absPath);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
resolvedPath = absPath;
|
|
39
|
+
}
|
|
40
|
+
if (resolvedPath && jitiInstance.cache?.[resolvedPath]) {
|
|
41
|
+
delete jitiInstance.cache[resolvedPath];
|
|
42
|
+
}
|
|
43
|
+
const tsPath = absPath.endsWith('.ts') ? absPath : `${absPath}.ts`;
|
|
44
|
+
if (tsPath !== resolvedPath && jitiInstance.cache?.[tsPath]) {
|
|
45
|
+
delete jitiInstance.cache[tsPath];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
const absPathNormalized = absPath.replace(/\\/g, '/');
|
|
50
|
+
for (const key in jitiInstance.cache) {
|
|
51
|
+
if (key.replace(/\\/g, '/').includes(absPathNormalized)) {
|
|
52
|
+
delete jitiInstance.cache[key];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const bumpHotMarker = async () => {
|
|
58
|
+
if (process.env.NODE_ENV === 'production')
|
|
59
|
+
return;
|
|
60
|
+
const content = `/**\n` +
|
|
61
|
+
` * AUTO-GENERATED. DO NOT EDIT.\n` +
|
|
62
|
+
` * This file is used to track the last time the sections/config schema was updated.\n` +
|
|
63
|
+
` * It is used to trigger a hot reload of the section/config in development mode.\n` +
|
|
64
|
+
` */\n` +
|
|
65
|
+
`\n` +
|
|
66
|
+
`export const revalidate = 0\n` +
|
|
67
|
+
`\n` +
|
|
68
|
+
`// @refresh reset\n` +
|
|
69
|
+
`\n` +
|
|
70
|
+
`export const configLastUpdated = ${Date.now()}\n`;
|
|
71
|
+
try {
|
|
72
|
+
fs.writeFileSync(hotMarkerFile, content, 'utf8');
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
console.error('Failed to bump _section-hot-reload.js:', err);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const startConfigWatcher = () => {
|
|
79
|
+
if (process.env.NODE_ENV === 'production' || configWatcherState.watcher)
|
|
80
|
+
return;
|
|
81
|
+
const cwd = process.cwd();
|
|
82
|
+
const invalidateForRelPath = async (relPath) => {
|
|
83
|
+
const normalized = relPath.replace(/\\/g, '/');
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
const last = configWatcherState.lastEventAt.get(normalized);
|
|
86
|
+
if (last && now - last < 150)
|
|
87
|
+
return;
|
|
88
|
+
configWatcherState.lastEventAt.set(normalized, now);
|
|
89
|
+
console.log(chalk.green('Detected config file change, reloading config...'));
|
|
90
|
+
const absPath = resolve(cwd, relPath);
|
|
91
|
+
clearJitiCache(absPath);
|
|
92
|
+
configWatcherState.version++;
|
|
93
|
+
await bumpHotMarker();
|
|
94
|
+
};
|
|
95
|
+
configWatcherState.watcher = chokidar
|
|
96
|
+
.watch('cms.config.*', {
|
|
97
|
+
cwd,
|
|
98
|
+
ignoreInitial: true,
|
|
99
|
+
atomic: true,
|
|
100
|
+
awaitWriteFinish: {
|
|
101
|
+
stabilityThreshold: 100,
|
|
102
|
+
pollInterval: 20,
|
|
103
|
+
},
|
|
104
|
+
})
|
|
105
|
+
.setMaxListeners(3)
|
|
106
|
+
.on('add', async (path) => await invalidateForRelPath(path))
|
|
107
|
+
.on('change', async (path) => await invalidateForRelPath(path))
|
|
108
|
+
.on('unlink', async (path) => await invalidateForRelPath(path));
|
|
109
|
+
};
|
|
110
|
+
const findConfigFile = () => {
|
|
111
|
+
const cwd = process.cwd();
|
|
112
|
+
const candidates = [
|
|
113
|
+
'cms.config.js',
|
|
114
|
+
'cms.config.cjs',
|
|
115
|
+
'cms.config.mjs',
|
|
116
|
+
'cms.config.json',
|
|
117
|
+
'cms.config.ts',
|
|
118
|
+
'cms.config.cts',
|
|
119
|
+
'cms.config.mts',
|
|
120
|
+
].map((f) => resolve(join(cwd, f)));
|
|
121
|
+
const found = candidates.find((p) => existsSync(p));
|
|
122
|
+
if (!found) {
|
|
123
|
+
throw new Error(`Config file not found. Searched: ${candidates.join(', ')}`);
|
|
124
|
+
}
|
|
125
|
+
const ext = found.slice(found.lastIndexOf('.')).toLowerCase();
|
|
126
|
+
return { found, ext };
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Turbopack-safe loader:
|
|
130
|
+
* - In Next 16 Turbopack SSR, dynamic require(found) fails ("expression is too dynamic")
|
|
131
|
+
* - Native ESM importing `.ts` triggers MODULE_TYPELESS_PACKAGE_JSON warning
|
|
132
|
+
*
|
|
133
|
+
* SOLUTION:
|
|
134
|
+
* - Use `jiti` for TypeScript configs (no Node ESM, no warnings)
|
|
135
|
+
* - Use `require()` for CJS / JSON
|
|
136
|
+
* - Use native `import()` only for `.mjs`
|
|
137
|
+
*/
|
|
138
|
+
export const loadConfigModule = async () => {
|
|
139
|
+
startConfigWatcher();
|
|
140
|
+
const { found, ext } = findConfigFile();
|
|
141
|
+
if (!jitiInstance) {
|
|
142
|
+
const { createJiti } = await import('jiti');
|
|
143
|
+
jitiInstance = createJiti(import.meta.url, {
|
|
144
|
+
// Keep your previous behavior:
|
|
145
|
+
// - return default export compatibly
|
|
146
|
+
interopDefault: true,
|
|
147
|
+
// Caching (new API uses fsCache/moduleCache)
|
|
148
|
+
// Keep them enabled for better performance.
|
|
149
|
+
fsCache: true,
|
|
150
|
+
moduleCache: true,
|
|
151
|
+
rebuildFsCache: true,
|
|
152
|
+
// Optional: nicer debugging in stack traces (off by default in jiti)
|
|
153
|
+
// sourceMaps: true,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* We're using the deprecated synchronous API because
|
|
158
|
+
* it works with Turbopack, the new jiti.import() does not.
|
|
159
|
+
*/
|
|
160
|
+
const mod = jitiInstance(found);
|
|
161
|
+
return mod?.default ?? mod;
|
|
162
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './loader-with-jiti.js';
|
|
2
2
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/config/loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/config/loader.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA"}
|
|
@@ -1,75 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { resolve, join } from 'path';
|
|
3
|
-
import { createRequire } from 'module';
|
|
4
|
-
// Create a require function that works in ES modules
|
|
5
|
-
const safeRequire = createRequire(import.meta.url);
|
|
6
|
-
/**
|
|
7
|
-
* See SectionFactory.ts: during dev/tests we may runtime-load TS that contains NodeNext-style `./x.js` specifiers
|
|
8
|
-
* pointing at `./x.ts` in the source tree. Patch CJS resolution to fall back to `.ts` for relative imports.
|
|
9
|
-
*/
|
|
10
|
-
const withPatchedCjsResolveJsToTs = (fn) => {
|
|
11
|
-
const NodeModule = safeRequire('module');
|
|
12
|
-
const originalResolve = NodeModule._resolveFilename;
|
|
13
|
-
NodeModule._resolveFilename = function (request, parent, isMain, options) {
|
|
14
|
-
try {
|
|
15
|
-
return originalResolve.call(this, request, parent, isMain, options);
|
|
16
|
-
}
|
|
17
|
-
catch (err) {
|
|
18
|
-
if (typeof request === 'string' && /^(\.{1,2}\/.*)\.js$/.test(request)) {
|
|
19
|
-
const tsRequest = request.replace(/\.js$/, '.ts');
|
|
20
|
-
try {
|
|
21
|
-
return originalResolve.call(this, tsRequest, parent, isMain, options);
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
// fall through to rethrow original error
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
throw err;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
try {
|
|
31
|
-
return fn();
|
|
32
|
-
}
|
|
33
|
-
finally {
|
|
34
|
-
NodeModule._resolveFilename = originalResolve;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
export const loadConfigModule = () => {
|
|
38
|
-
const cwd = process.cwd();
|
|
39
|
-
const candidates = [
|
|
40
|
-
'cms.config.js',
|
|
41
|
-
'cms.config.cjs',
|
|
42
|
-
'cms.config.mjs',
|
|
43
|
-
'cms.config.json',
|
|
44
|
-
'cms.config.ts',
|
|
45
|
-
'cms.config.cts',
|
|
46
|
-
'cms.config.mts',
|
|
47
|
-
].map((f) => resolve(join(cwd, f)));
|
|
48
|
-
const found = candidates.find((p) => existsSync(p));
|
|
49
|
-
if (!found) {
|
|
50
|
-
throw new Error(`Config file not found. Searched: ${candidates.join(', ')}`);
|
|
51
|
-
}
|
|
52
|
-
const isTs = found.endsWith('.ts') || found.endsWith('.cts') || found.endsWith('.mts');
|
|
53
|
-
let unregister;
|
|
54
|
-
try {
|
|
55
|
-
if (isTs) {
|
|
56
|
-
try {
|
|
57
|
-
const { register } = safeRequire('esbuild-register/dist/node');
|
|
58
|
-
unregister = register({ format: 'cjs', loader: 'ts' }).unregister;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
throw new Error(`Unable to load TypeScript config '${found}'. Install 'esbuild-register', or provide cms.config.js/json.`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const mod = process.env.NODE_ENV === 'test'
|
|
65
|
-
? isTs
|
|
66
|
-
? withPatchedCjsResolveJsToTs(() => safeRequire(found))
|
|
67
|
-
: safeRequire(found)
|
|
68
|
-
: safeRequire(found);
|
|
69
|
-
unregister?.();
|
|
70
|
-
return mod.default ?? mod;
|
|
71
|
-
}
|
|
72
|
-
finally {
|
|
73
|
-
unregister?.();
|
|
74
|
-
}
|
|
75
|
-
};
|
|
1
|
+
export * from './loader-with-jiti.js';
|
|
@@ -1,110 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { CategorySectionConfig, HasItemsSectionConfig, SimpleSectionConfig } from '../sections/index.js';
|
|
3
|
-
import type { SectionTypes } from '../types/index.js';
|
|
4
|
-
type AnySectionConfig = HasItemsSectionConfig | SimpleSectionConfig | CategorySectionConfig;
|
|
5
|
-
export declare class SectionFactory {
|
|
6
|
-
/**
|
|
7
|
-
* These are the fixed sections that can not be present in the sections folder.
|
|
8
|
-
*/
|
|
9
|
-
static readonly fixedSections: string[];
|
|
10
|
-
private static readonly isDev;
|
|
11
|
-
private static readonly isProd;
|
|
12
|
-
private static sectionProcessingErrors;
|
|
13
|
-
private static sectionFetchingErrors;
|
|
14
|
-
private static errorCount;
|
|
15
|
-
/**
|
|
16
|
-
* Global in-process cache for all section configs.
|
|
17
|
-
* Populated once per Node process via loadAllSections(),
|
|
18
|
-
* reused by all get*() calls until the process is restarted,
|
|
19
|
-
* so all subsequent calls reuse this array.
|
|
20
|
-
*/
|
|
21
|
-
private static allSectionsPromise;
|
|
22
|
-
private static allSectionsLoaded;
|
|
23
|
-
private static watcherStarted;
|
|
24
|
-
static bumpHotMarker(): void;
|
|
25
|
-
/**
|
|
26
|
-
* Get all sections
|
|
27
|
-
* @param type - The type of sections to get
|
|
28
|
-
* @returns The sections
|
|
29
|
-
*/
|
|
30
|
-
static getSections(type?: SectionTypes | SectionTypes[]): Promise<AnySectionConfig[]>;
|
|
31
|
-
/**
|
|
32
|
-
* Get all accessible sections for an admin
|
|
33
|
-
* @param type - The type of section to get
|
|
34
|
-
* @param admin - The admin to get the sections for
|
|
35
|
-
* @returns The sections for the admin
|
|
36
|
-
*/
|
|
37
|
-
static getSectionsForAdmin({ type, admin, }: {
|
|
38
|
-
type?: SectionTypes | SectionTypes[];
|
|
39
|
-
admin: {
|
|
40
|
-
id: string;
|
|
41
|
-
requiredRole?: 'C' | 'U' | 'D';
|
|
42
|
-
};
|
|
43
|
-
}): Promise<{
|
|
44
|
-
simple: SimpleSectionConfig[];
|
|
45
|
-
has_items: HasItemsSectionConfig[];
|
|
46
|
-
category: CategorySectionConfig[];
|
|
47
|
-
fixed: string[];
|
|
48
|
-
}>;
|
|
49
|
-
/**
|
|
50
|
-
* Get a section
|
|
51
|
-
* @param name - The name of the section to get
|
|
52
|
-
* @param type - The type of section to get
|
|
53
|
-
* @returns The section
|
|
54
|
-
*/
|
|
55
|
-
static getSection({ name, type, }: {
|
|
56
|
-
name: string;
|
|
57
|
-
type?: SectionTypes | SectionTypes[];
|
|
58
|
-
}): Promise<AnySectionConfig | null>;
|
|
59
|
-
/**
|
|
60
|
-
* Get an accessible section for an admin
|
|
61
|
-
* @param name - The name of the section to get
|
|
62
|
-
* @param type - The type of section to get
|
|
63
|
-
* @param admin - The admin to get the section for
|
|
64
|
-
* @returns The section for the admin
|
|
65
|
-
*/
|
|
66
|
-
static getSectionForAdmin({ name, type, admin, }: {
|
|
67
|
-
name: string;
|
|
68
|
-
type?: SectionTypes | SectionTypes[];
|
|
69
|
-
admin: {
|
|
70
|
-
id: string;
|
|
71
|
-
requiredRole?: 'C' | 'U' | 'D';
|
|
72
|
-
};
|
|
73
|
-
}): Promise<AnySectionConfig | null>;
|
|
74
|
-
/**
|
|
75
|
-
* Create a Section instance from a section config
|
|
76
|
-
* The config must have a build() method (created via helper functions like simpleSection(), hasItemsSection(), etc.)
|
|
77
|
-
*
|
|
78
|
-
* Note: This factory only accepts configs. If you already have a Section instance,
|
|
79
|
-
* use it directly - don't pass it to this factory.
|
|
80
|
-
*
|
|
81
|
-
* @param config - A section config object with a build() method
|
|
82
|
-
* @returns A Section instance
|
|
83
|
-
* @throws Error if config doesn't have a build() method
|
|
84
|
-
*/
|
|
85
|
-
static create(config: {
|
|
86
|
-
build: () => HasItemsSection | SimpleSection | CategorySection;
|
|
87
|
-
[key: string]: any;
|
|
88
|
-
}): HasItemsSection | SimpleSection | CategorySection;
|
|
89
|
-
/**
|
|
90
|
-
* Return a clone of the section(s) info to get a fresh copy of the section(s).
|
|
91
|
-
* Not cloning will cause the original section(s) (in *.section.ts file) to be modified!
|
|
92
|
-
* Each *.section.ts file must have exactly one default export (arrays are not allowed).
|
|
93
|
-
|
|
94
|
-
* @param name - The name of the section to get
|
|
95
|
-
* @param type - The type of section to get
|
|
96
|
-
* @param admin - The admin to get the section for
|
|
97
|
-
* @returns The section(s)
|
|
98
|
-
*/
|
|
99
|
-
private static get;
|
|
100
|
-
/**
|
|
101
|
-
* Load all *.section.ts files once, require their default exports,
|
|
102
|
-
* and cache the resulting configs for the lifetime of the process
|
|
103
|
-
* (until invalidated in dev by file changes).
|
|
104
|
-
*/
|
|
105
|
-
private static loadAllSections;
|
|
106
|
-
private static startWatcher;
|
|
107
|
-
private static init;
|
|
108
|
-
}
|
|
109
|
-
export {};
|
|
1
|
+
export * from './section-factory-with-jiti.js';
|
|
110
2
|
//# sourceMappingURL=SectionFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFactory.d.ts","sourceRoot":"","sources":["../../../src/core/factories/SectionFactory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SectionFactory.d.ts","sourceRoot":"","sources":["../../../src/core/factories/SectionFactory.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA"}
|