nextjs-cms 0.5.61 → 0.5.63

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.
@@ -1 +1 @@
1
- {"version":3,"file":"loader-with-esbuild.d.ts","sourceRoot":"","sources":["../../../src/core/config/loader-with-esbuild.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,sBAAsB,cAAmC,CAAA;AA0KtE;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,OAAO,CAiBxD,CAAA"}
1
+ {"version":3,"file":"loader-with-esbuild.d.ts","sourceRoot":"","sources":["../../../src/core/config/loader-with-esbuild.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,sBAAsB,cAAmC,CAAA;AA0KtE;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,OAAO,CASxD,CAAA"}
@@ -180,16 +180,9 @@ const findConfigFile = () => {
180
180
  export const loadConfigModule = async () => {
181
181
  startConfigWatcher();
182
182
  const { found, isTs } = findConfigFile();
183
- if (!isTs) {
184
- // For non-TS configs, load directly
185
- const url = pathToFileURL(found).href;
186
- // IMPORTANT: prevent Turbopack from trying to statically analyze the specifier
187
- const mod = await import(/* turbopackIgnore: true */ url);
188
- return mod?.default ?? mod;
189
- }
190
183
  // For TS configs, bundle them first (like sections do)
191
184
  const bundled = await ensureBundledConfig(found);
192
185
  const url = `${pathToFileURL(bundled).href}?v=${configWatcherState.version}`;
193
- const mod = await import(/* turbopackIgnore: true */ url);
186
+ const mod = await import(/* turbopackIgnore: true */ /* webpackIgnore: true */ url);
194
187
  return mod?.default ?? mod;
195
188
  };
@@ -1,6 +1,7 @@
1
1
  import { HasItemsSection, SimpleSection, CategorySection } from '../sections/index.js';
2
2
  import type { CategorySectionConfig, HasItemsSectionConfig, SimpleSectionConfig } from '../sections/index.js';
3
3
  import type { SectionTypes } from '../types/index.js';
4
+ export declare const getSectionImportVersion: () => number;
4
5
  type AnySectionConfig = HasItemsSectionConfig | SimpleSectionConfig | CategorySectionConfig;
5
6
  export declare class SectionFactory {
6
7
  /**
@@ -20,9 +21,7 @@ export declare class SectionFactory {
20
21
  */
21
22
  private static allSectionsPromise;
22
23
  private static allSectionsLoaded;
23
- private static watcherStarted;
24
24
  private static configVersion;
25
- private static sectionWatcher;
26
25
  private static ensureConfigFresh;
27
26
  static bumpHotMarker(): void;
28
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"section-factory-with-esbuild.d.ts","sourceRoot":"","sources":["../../../src/core/factories/section-factory-with-esbuild.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"section-factory-with-esbuild.d.ts","sourceRoot":"","sources":["../../../src/core/factories/section-factory-with-esbuild.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC7G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA2CrD,eAAO,MAAM,uBAAuB,cAAoC,CAAA;AAsHxE,KAAK,gBAAgB,GAAG,qBAAqB,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAY3F,qBAAa,cAAc;IACvB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,aAAa,WAAiD;IAE9E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAwC;IACrE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAc;IAE5C,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA+B;IACrE,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAA+B;IACnE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAI;IAE7B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA2C;IAC5E,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAQ;IACxC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAK;mBAEZ,iBAAiB;IAsBtC,MAAM,CAAC,aAAa,IAAI,IAAI;IAwB5B;;;;OAIG;WACU,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI3F;;;;;OAKG;WACU,mBAAmB,CAAC,EAC7B,IAAI,EACJ,KAAK,GACR,EAAE;QACC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;QACpC,KAAK,EAAE;YACH,EAAE,EAAE,MAAM,CAAA;YACV,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;SACjC,CAAA;KACJ,GAAG,OAAO,CAAC;QACR,MAAM,EAAE,mBAAmB,EAAE,CAAA;QAC7B,SAAS,EAAE,qBAAqB,EAAE,CAAA;QAClC,QAAQ,EAAE,qBAAqB,EAAE,CAAA;QACjC,KAAK,EAAE,MAAM,EAAE,CAAA;KAClB,CAAC;IA+BF;;;;;OAKG;WACU,UAAU,CAAC,EACpB,IAAI,EACJ,IAAI,GACP,EAAE;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;KACvC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKpC;;;;;;OAMG;WACU,kBAAkB,CAAC,EAC5B,IAAI,EACJ,IAAI,EACJ,KAAK,GACR,EAAE;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;QACpC,KAAK,EAAE;YACH,EAAE,EAAE,MAAM,CAAA;YACV,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;SACjC,CAAA;KACJ,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKpC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;QAClB,KAAK,EAAE,MAAM,eAAe,GAAG,aAAa,GAAG,eAAe,CAAA;QAC9D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACrB,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe;IAYrD;;;;;;;;;OASG;mBACkB,GAAG;IA6FxB;;;;OAIG;mBACkB,eAAe;IAmKpC,OAAO,CAAC,MAAM,CAAC,YAAY;IAqD3B,OAAO,CAAC,MAAM,CAAC,IAAI;CAatB"}
@@ -21,6 +21,19 @@ const getCmsConfigCached = async (currentVersion = getConfigImportVersion()) =>
21
21
  return cachedCmsConfig;
22
22
  };
23
23
  const hotMarkerFile = resolve(process.cwd(), 'components/form/helpers/_section-hot-reload.js');
24
+ const sectionWatcherState = (() => {
25
+ const key = Symbol.for('nextjs-cms.sectionWatcher');
26
+ const globalAny = globalThis;
27
+ if (!globalAny[key]) {
28
+ globalAny[key] = {
29
+ watcher: null,
30
+ version: 0,
31
+ lastEventAt: new Map(),
32
+ };
33
+ }
34
+ return globalAny[key];
35
+ })();
36
+ export const getSectionImportVersion = () => sectionWatcherState.version;
24
37
  // Create a require function that works in ES modules
25
38
  const safeRequire = createRequire(import.meta.url);
26
39
  /**
@@ -66,11 +79,6 @@ const loadEsbuildRegister = () => {
66
79
  const id = 'esbuild-register/dist/node'; // avoid inline literal in require call
67
80
  return safeRequire(id);
68
81
  };
69
- /**
70
- * Runtime module import version token.
71
- * Node caches ESM modules by URL. Adding `?v=` busts the cache when files change.
72
- */
73
- let sectionImportVersion = 0;
74
82
  const getEsbuild = () => safeRequire('esbuild');
75
83
  const cacheRoot = resolve(process.cwd(), '.nextjs-cms', 'sections');
76
84
  if (!existsSync(cacheRoot))
@@ -118,8 +126,8 @@ const loadSectionModuleRuntime = async (absPath) => {
118
126
  }
119
127
  // Dev/runtime: bundle then import the bundled output (Turbopack-safe)
120
128
  const bundled = await ensureBundledSection(absPath);
121
- const url = `${pathToFileURL(bundled).href}?v=${sectionImportVersion}`;
122
- const mod = await import(/* turbopackIgnore: true */ url);
129
+ const url = `${pathToFileURL(bundled).href}?v=${sectionWatcherState.version}`;
130
+ const mod = await import(/* turbopackIgnore: true */ /* webpackIgnore: true */ url);
123
131
  return mod?.default;
124
132
  };
125
133
  /**
@@ -150,9 +158,7 @@ export class SectionFactory {
150
158
  */
151
159
  static allSectionsPromise = null;
152
160
  static allSectionsLoaded = false;
153
- static watcherStarted = false;
154
161
  static configVersion = -1;
155
- static sectionWatcher = null;
156
162
  static async ensureConfigFresh() {
157
163
  const currentVersion = getConfigImportVersion();
158
164
  const cmsConfig = await getCmsConfigCached(currentVersion);
@@ -163,13 +169,10 @@ export class SectionFactory {
163
169
  this.errorCount = 0;
164
170
  this.allSectionsPromise = null;
165
171
  this.allSectionsLoaded = false;
166
- // Reset section import version to force re-bundling
167
- sectionImportVersion = 0;
168
172
  // Close and reset the watcher if it exists
169
- if (this.sectionWatcher) {
170
- await this.sectionWatcher.close();
171
- this.sectionWatcher = null;
172
- this.watcherStarted = false;
173
+ if (sectionWatcherState.watcher) {
174
+ await sectionWatcherState.watcher.close();
175
+ sectionWatcherState.watcher = null;
173
176
  }
174
177
  }
175
178
  return cmsConfig;
@@ -490,23 +493,17 @@ If you added an extension manually, remove it.`);
490
493
  }
491
494
  // ---------- DEV WATCHER & CACHE INVALIDATION ----------
492
495
  static startWatcher(cmsConfig) {
493
- if (!this.isDev || this.watcherStarted)
496
+ if (!this.isDev || sectionWatcherState.watcher)
494
497
  return;
495
- this.watcherStarted = true;
496
- const watcher = chokidar.watch('**/*.section.ts', {
497
- cwd: cmsConfig.sections.path,
498
- ignoreInitial: true,
499
- });
500
- this.sectionWatcher = watcher;
501
- log('Starting section watcher in dev mode...');
502
- /**
503
- * Invalidate section cache + bust runtime import cache.
504
- * For Turbopack runtime import we increment sectionImportVersion which changes the URL (`?v=`).
505
- * We still bump the hot marker to trigger Fast Refresh + react-query invalidation.
506
- */
507
498
  const invalidateForRelPath = (relPath) => {
508
- // Bust ESM import cache (Node caches by URL)
509
- sectionImportVersion++;
499
+ const normalized = relPath.replace(/\\/g, '/');
500
+ const now = Date.now();
501
+ const last = sectionWatcherState.lastEventAt.get(normalized);
502
+ if (last && now - last < 150)
503
+ return;
504
+ sectionWatcherState.lastEventAt.set(normalized, now);
505
+ // Increment global version to force re-bundling
506
+ sectionWatcherState.version++;
510
507
  // Reset our in-process caches
511
508
  this.sectionProcessingErrors = {};
512
509
  this.sectionFetchingErrors = {};
@@ -516,7 +513,17 @@ If you added an extension manually, remove it.`);
516
513
  log('Invalidated section cache due to change in', relPath);
517
514
  this.bumpHotMarker();
518
515
  };
519
- watcher
516
+ sectionWatcherState.watcher = chokidar
517
+ .watch('**/*.section.ts', {
518
+ cwd: cmsConfig.sections.path,
519
+ ignoreInitial: true,
520
+ atomic: true,
521
+ awaitWriteFinish: {
522
+ stabilityThreshold: 100,
523
+ pollInterval: 20,
524
+ },
525
+ })
526
+ .setMaxListeners(3)
520
527
  .on('add', (path) => {
521
528
  log('Section file added:', path);
522
529
  invalidateForRelPath(path);
@@ -529,6 +536,7 @@ If you added an extension manually, remove it.`);
529
536
  log('Section file removed:', path);
530
537
  invalidateForRelPath(path);
531
538
  });
539
+ log('Starting section watcher in dev mode...');
532
540
  }
533
541
  static init() {
534
542
  if (this.isProd) {
@@ -1,6 +1,7 @@
1
1
  import { HasItemsSection, SimpleSection, CategorySection } from '../sections/index.js';
2
2
  import type { CategorySectionConfig, HasItemsSectionConfig, SimpleSectionConfig } from '../sections/index.js';
3
3
  import type { SectionTypes } from '../types/index.js';
4
+ export declare const getSectionImportVersion: () => number;
4
5
  type AnySectionConfig = HasItemsSectionConfig | SimpleSectionConfig | CategorySectionConfig;
5
6
  export declare class SectionFactory {
6
7
  /**
@@ -20,9 +21,7 @@ export declare class SectionFactory {
20
21
  */
21
22
  private static allSectionsPromise;
22
23
  private static allSectionsLoaded;
23
- private static watcherStarted;
24
24
  private static configVersion;
25
- private static sectionWatcher;
26
25
  private static ensureConfigFresh;
27
26
  static bumpHotMarker(): void;
28
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"section-factory-with-jiti.d.ts","sourceRoot":"","sources":["../../../src/core/factories/section-factory-with-jiti.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC7G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA+IrD,KAAK,gBAAgB,GAAG,qBAAqB,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAE3F,qBAAa,cAAc;IACvB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,aAAa,WAAiD;IAE9E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAwC;IACrE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAc;IAE5C,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA+B;IACrE,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAA+B;IACnE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAI;IAE7B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA2C;IAC5E,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAQ;IACxC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAQ;IACrC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAK;IACjC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAkC;mBAE1C,iBAAiB;IAsBtC,MAAM,CAAC,aAAa,IAAI,IAAI;IAwB5B;;;;OAIG;WACU,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI3F;;;;;OAKG;WACU,mBAAmB,CAAC,EAC7B,IAAI,EACJ,KAAK,GACR,EAAE;QACC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;QACpC,KAAK,EAAE;YACH,EAAE,EAAE,MAAM,CAAA;YACV,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;SACjC,CAAA;KACJ,GAAG,OAAO,CAAC;QACR,MAAM,EAAE,mBAAmB,EAAE,CAAA;QAC7B,SAAS,EAAE,qBAAqB,EAAE,CAAA;QAClC,QAAQ,EAAE,qBAAqB,EAAE,CAAA;QACjC,KAAK,EAAE,MAAM,EAAE,CAAA;KAClB,CAAC;IA+BF;;;;;OAKG;WACU,UAAU,CAAC,EACpB,IAAI,EACJ,IAAI,GACP,EAAE;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;KACvC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKpC;;;;;;OAMG;WACU,kBAAkB,CAAC,EAC5B,IAAI,EACJ,IAAI,EACJ,KAAK,GACR,EAAE;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;QACpC,KAAK,EAAE;YACH,EAAE,EAAE,MAAM,CAAA;YACV,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;SACjC,CAAA;KACJ,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKpC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;QAClB,KAAK,EAAE,MAAM,eAAe,GAAG,aAAa,GAAG,eAAe,CAAA;QAC9D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACrB,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe;IAYrD;;;;;;;;;OASG;mBACkB,GAAG;IA6FxB;;;;OAIG;mBACkB,eAAe;IAmKpC,OAAO,CAAC,MAAM,CAAC,YAAY;IAmE3B,OAAO,CAAC,MAAM,CAAC,IAAI;CAatB"}
1
+ {"version":3,"file":"section-factory-with-jiti.d.ts","sourceRoot":"","sources":["../../../src/core/factories/section-factory-with-jiti.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC7G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA+BrD,eAAO,MAAM,uBAAuB,cAAoC,CAAA;AAyIxE,KAAK,gBAAgB,GAAG,qBAAqB,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAE3F,qBAAa,cAAc;IACvB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,aAAa,WAAiD;IAE9E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAwC;IACrE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAc;IAE5C,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA+B;IACrE,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAA+B;IACnE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAI;IAE7B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA2C;IAC5E,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAQ;IACxC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAK;mBAEZ,iBAAiB;IAqBtC,MAAM,CAAC,aAAa,IAAI,IAAI;IAwB5B;;;;OAIG;WACU,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI3F;;;;;OAKG;WACU,mBAAmB,CAAC,EAC7B,IAAI,EACJ,KAAK,GACR,EAAE;QACC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;QACpC,KAAK,EAAE;YACH,EAAE,EAAE,MAAM,CAAA;YACV,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;SACjC,CAAA;KACJ,GAAG,OAAO,CAAC;QACR,MAAM,EAAE,mBAAmB,EAAE,CAAA;QAC7B,SAAS,EAAE,qBAAqB,EAAE,CAAA;QAClC,QAAQ,EAAE,qBAAqB,EAAE,CAAA;QACjC,KAAK,EAAE,MAAM,EAAE,CAAA;KAClB,CAAC;IA+BF;;;;;OAKG;WACU,UAAU,CAAC,EACpB,IAAI,EACJ,IAAI,GACP,EAAE;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;KACvC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKpC;;;;;;OAMG;WACU,kBAAkB,CAAC,EAC5B,IAAI,EACJ,IAAI,EACJ,KAAK,GACR,EAAE;QACC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;QACpC,KAAK,EAAE;YACH,EAAE,EAAE,MAAM,CAAA;YACV,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;SACjC,CAAA;KACJ,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKpC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;QAClB,KAAK,EAAE,MAAM,eAAe,GAAG,aAAa,GAAG,eAAe,CAAA;QAC9D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACrB,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe;IAYrD;;;;;;;;;OASG;mBACkB,GAAG;IA6FxB;;;;OAIG;mBACkB,eAAe;IAmKpC,OAAO,CAAC,MAAM,CAAC,YAAY;IAwE3B,OAAO,CAAC,MAAM,CAAC,IAAI;CAatB"}
@@ -10,6 +10,19 @@ import { db } from '../../db/client.js';
10
10
  import { AdminPrivilegesTable } from '../../db/schema.js';
11
11
  import { getCMSConfig, getConfigImportVersion } from '../config/index.js';
12
12
  const hotMarkerFile = resolve(process.cwd(), 'components/form/helpers/_section-hot-reload.js');
13
+ const sectionWatcherState = (() => {
14
+ const key = Symbol.for('nextjs-cms.sectionWatcher');
15
+ const globalAny = globalThis;
16
+ if (!globalAny[key]) {
17
+ globalAny[key] = {
18
+ watcher: null,
19
+ version: 0,
20
+ lastEventAt: new Map(),
21
+ };
22
+ }
23
+ return globalAny[key];
24
+ })();
25
+ export const getSectionImportVersion = () => sectionWatcherState.version;
13
26
  // Create a require function that works in ES modules
14
27
  const safeRequire = createRequire(import.meta.url);
15
28
  /**
@@ -146,9 +159,7 @@ export class SectionFactory {
146
159
  */
147
160
  static allSectionsPromise = null;
148
161
  static allSectionsLoaded = false;
149
- static watcherStarted = false;
150
162
  static configVersion = -1;
151
- static sectionWatcher = null;
152
163
  static async ensureConfigFresh() {
153
164
  const currentVersion = getConfigImportVersion();
154
165
  const cmsConfig = await getCmsConfigCached(currentVersion);
@@ -159,10 +170,9 @@ export class SectionFactory {
159
170
  this.errorCount = 0;
160
171
  this.allSectionsPromise = null;
161
172
  this.allSectionsLoaded = false;
162
- if (this.sectionWatcher) {
163
- await this.sectionWatcher.close();
164
- this.sectionWatcher = null;
165
- this.watcherStarted = false;
173
+ if (sectionWatcherState.watcher) {
174
+ await sectionWatcherState.watcher.close();
175
+ sectionWatcherState.watcher = null;
166
176
  }
167
177
  }
168
178
  return cmsConfig;
@@ -483,24 +493,15 @@ If you added an extension manually, remove it.`);
483
493
  }
484
494
  // ---------- DEV WATCHER & CACHE INVALIDATION ----------
485
495
  static startWatcher(cmsConfig) {
486
- if (!this.isDev || this.watcherStarted)
496
+ if (!this.isDev || sectionWatcherState.watcher)
487
497
  return;
488
- this.watcherStarted = true;
489
- const watcher = chokidar.watch('**/*.section.ts', {
490
- cwd: cmsConfig.sections.path,
491
- ignoreInitial: true,
492
- });
493
- this.sectionWatcher = watcher;
494
- log('Starting section watcher in dev mode...');
495
- /**
496
- * Invalidate section cache + bust runtime import cache.
497
- * When a section file changes, we need to:
498
- * 1. Clear jiti's module cache for that file
499
- * 2. Reset our in-process caches
500
- * 3. Reset the promise so sections reload on next access
501
- * 4. Bump the hot marker to trigger Next.js Fast Refresh
502
- */
503
498
  const invalidateForRelPath = (relPath) => {
499
+ const normalized = relPath.replace(/\\/g, '/');
500
+ const now = Date.now();
501
+ const last = sectionWatcherState.lastEventAt.get(normalized);
502
+ if (last && now - last < 150)
503
+ return;
504
+ sectionWatcherState.lastEventAt.set(normalized, now);
504
505
  const absPath = resolve(cmsConfig.sections.path, relPath);
505
506
  // Clear jiti's cache for the changed file
506
507
  clearJitiCache(absPath);
@@ -523,11 +524,23 @@ If you added an extension manually, remove it.`);
523
524
  this.errorCount = 0;
524
525
  this.allSectionsPromise = null;
525
526
  this.allSectionsLoaded = false;
527
+ // Increment version to force re-bundling
528
+ sectionWatcherState.version++;
526
529
  log('Invalidated section cache due to change in', relPath);
527
530
  // Bump the hot marker to trigger Next.js Fast Refresh
528
531
  this.bumpHotMarker();
529
532
  };
530
- watcher
533
+ sectionWatcherState.watcher = chokidar
534
+ .watch('**/*.section.ts', {
535
+ cwd: cmsConfig.sections.path,
536
+ ignoreInitial: true,
537
+ atomic: true,
538
+ awaitWriteFinish: {
539
+ stabilityThreshold: 100,
540
+ pollInterval: 20,
541
+ },
542
+ })
543
+ .setMaxListeners(3)
531
544
  .on('add', (path) => {
532
545
  log('Section file added:', path);
533
546
  invalidateForRelPath(path);
@@ -540,6 +553,7 @@ If you added an extension manually, remove it.`);
540
553
  log('Section file removed:', path);
541
554
  invalidateForRelPath(path);
542
555
  });
556
+ log('Starting section watcher in dev mode...');
543
557
  }
544
558
  static init() {
545
559
  if (this.isProd) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/db/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IAClG,QAAQ,EAAE,MAAM,CAAA;CACnB;AAWD,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,QAAQ,CAc3E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/db/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IAClG,QAAQ,EAAE,MAAM,CAAA;CACnB;AAQD,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,QAAQ,CAyC3E"}
package/dist/db/config.js CHANGED
@@ -1,22 +1,39 @@
1
+ import chalk from 'chalk';
1
2
  const defaultConfig = {
2
3
  host: 'localhost',
3
- user: 'root',
4
- password: 'password',
5
- database: 'nextjs_cms_db',
6
4
  port: 3306,
7
5
  charset: 'utf8mb4',
8
6
  };
9
7
  export function resolveDbConfig(overrides = {}) {
10
- const base = {
11
- host: process.env.DB_HOST ?? defaultConfig.host,
12
- user: process.env.DB_USER ?? defaultConfig.user,
13
- password: process.env.DB_PASSWORD ?? defaultConfig.password,
14
- database: process.env.DB_NAME ?? defaultConfig.database,
15
- port: process.env.DB_PORT ? parseInt(process.env.DB_PORT, 10) : defaultConfig.port,
16
- charset: process.env.DB_CHARSET ?? defaultConfig.charset,
17
- };
18
- return {
19
- ...base,
20
- ...overrides,
21
- };
8
+ try {
9
+ const base = {
10
+ host: process.env.DB_HOST ?? defaultConfig.host,
11
+ user: process.env.DB_USER ?? undefined,
12
+ password: process.env.DB_PASSWORD ?? undefined,
13
+ database: process.env.DB_NAME ?? undefined,
14
+ port: process.env.DB_PORT ? parseInt(process.env.DB_PORT, 10) : defaultConfig.port,
15
+ charset: process.env.DB_CHARSET ?? defaultConfig.charset,
16
+ };
17
+ const config = {
18
+ ...base,
19
+ ...overrides,
20
+ };
21
+ /**
22
+ * Make sure database and user are not undefined
23
+ */
24
+ if (!config.database || !config.user) {
25
+ throw new Error(chalk.red('Database name and user are required'), {
26
+ cause: 'Database configuration is incomplete.',
27
+ });
28
+ }
29
+ return config;
30
+ }
31
+ catch (error) {
32
+ const idDev = process.env.NODE_ENV === 'development';
33
+ console.log('');
34
+ console.error(chalk.redBright('Database name and user are required'));
35
+ console.log(chalk.gray(`Make sure to set the ${chalk.white.italic('DB_NAME')} and ${chalk.white.italic('DB_USER')} in your ${idDev ? 'development' : 'production'} environment variables.`));
36
+ console.log(chalk.gray(`Or, you can run ${chalk.greenBright.italic(`nextjs-cms-kit ${idDev ? '--dev' : ''} db-config`)} command at the root of your nextjs-cms project to set db config interactively.`));
37
+ process.exit(1);
38
+ }
22
39
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextjs-cms",
3
- "version": "0.5.61",
3
+ "version": "0.5.63",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",