@djangocfg/nextjs 2.1.541 → 2.1.543
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/README.md +3 -2
- package/dist/config/index.d.mts +32 -16
- package/dist/config/index.mjs +58 -45
- package/dist/config/index.mjs.map +1 -1
- package/dist/health/index.d.mts +1 -1
- package/dist/health/index.mjs +5 -2
- package/dist/health/index.mjs.map +1 -1
- package/dist/i18n/routing.d.mts +20 -20
- package/dist/i18n/server.d.mts +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +63 -47
- package/dist/index.mjs.map +1 -1
- package/dist/pwa/index.mjs +6 -5
- package/dist/pwa/index.mjs.map +1 -1
- package/dist/pwa/manifest.d.mts +1 -1
- package/dist/pwa/manifest.mjs +6 -5
- package/dist/pwa/manifest.mjs.map +1 -1
- package/dist/pwa/worker/index.mjs.map +1 -1
- package/dist/sitemap/index.d.mts +1 -1
- package/dist/{types-l9x1Rkmf.d.mts → types-CMxSgWnS.d.mts} +2 -0
- package/package.json +9 -9
- package/src/config/constants.ts +21 -4
- package/src/config/createNextConfig.ts +51 -28
- package/src/config/csp.ts +8 -5
- package/src/config/packages/installer.ts +11 -7
- package/src/config/packages/updater.ts +6 -6
- package/src/config/plugins/compression.ts +1 -1
- package/src/config/utils/deepMerge.ts +25 -21
- package/src/config/utils/version.ts +3 -3
- package/src/health/route.ts +5 -2
- package/src/pwa/manifest.ts +11 -8
- package/src/pwa/worker/index.ts +9 -7
- package/src/types.ts +2 -0
|
@@ -4,29 +4,33 @@
|
|
|
4
4
|
* Recursively merges objects, replacing arrays instead of merging them.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
8
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `T extends object` rather than `Record<string, unknown>`: call sites pass
|
|
13
|
+
* Next.js config interfaces, which have declared keys and no index signature —
|
|
14
|
+
* they are not assignable to `Record<string, unknown>`.
|
|
15
|
+
*/
|
|
16
|
+
export function deepMerge<T extends object>(target: T, source: Partial<T>): T {
|
|
17
|
+
const output: T = { ...target };
|
|
18
|
+
|
|
19
|
+
for (const key of Object.keys(source) as Array<keyof T & string>) {
|
|
20
|
+
const sourceValue: unknown = source[key];
|
|
21
|
+
if (sourceValue === undefined) continue;
|
|
22
|
+
|
|
23
|
+
const targetValue: unknown = output[key];
|
|
9
24
|
|
|
10
|
-
|
|
11
|
-
|
|
25
|
+
// Objects: deep merge. Arrays and primitives: replace.
|
|
26
|
+
// The recursion is instantiated at Record<string, unknown> — all the guards
|
|
27
|
+
// prove — and the result cast back to the key's declared type.
|
|
28
|
+
const merged =
|
|
29
|
+
isPlainObject(sourceValue) && isPlainObject(targetValue)
|
|
30
|
+
? deepMerge(targetValue, sourceValue)
|
|
31
|
+
: sourceValue;
|
|
12
32
|
|
|
13
|
-
|
|
14
|
-
if (Array.isArray(source[key])) {
|
|
15
|
-
output[key] = source[key] as any;
|
|
16
|
-
}
|
|
17
|
-
// Objects: deep merge
|
|
18
|
-
else if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
19
|
-
const targetValue = output[key];
|
|
20
|
-
if (targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {
|
|
21
|
-
output[key] = deepMerge(targetValue, source[key] as any);
|
|
22
|
-
} else {
|
|
23
|
-
output[key] = source[key] as any;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
// Primitives: replace
|
|
27
|
-
else {
|
|
28
|
-
output[key] = source[key] as any;
|
|
29
|
-
}
|
|
33
|
+
output[key] = merged as T[typeof key];
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
return output;
|
|
@@ -16,13 +16,13 @@ type VersionCacheShape = {
|
|
|
16
16
|
lastCheck?: number;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
interface CacheLike<T extends Record<string,
|
|
19
|
+
interface CacheLike<T extends Record<string, unknown>> {
|
|
20
20
|
get<K extends keyof T>(key: K): T[K] | undefined;
|
|
21
21
|
set<K extends keyof T>(key: K, value: T[K]): void;
|
|
22
22
|
clear(): void;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function createMemoryCache<T extends Record<string,
|
|
25
|
+
function createMemoryCache<T extends Record<string, unknown>>(): CacheLike<T> {
|
|
26
26
|
const store = new Map<string, unknown>();
|
|
27
27
|
return {
|
|
28
28
|
get<K extends keyof T>(key: K): T[K] | undefined {
|
|
@@ -88,7 +88,7 @@ export async function fetchLatestVersion(): Promise<string | null> {
|
|
|
88
88
|
const req = https.get(
|
|
89
89
|
`https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
|
|
90
90
|
{ timeout: 5000 },
|
|
91
|
-
(res
|
|
91
|
+
(res) => {
|
|
92
92
|
let data = '';
|
|
93
93
|
res.on('data', (chunk: string) => { data += chunk; });
|
|
94
94
|
res.on('end', () => {
|
package/src/health/route.ts
CHANGED
|
@@ -42,7 +42,7 @@ export function createHealthHandler(config: HealthConfig = {}) {
|
|
|
42
42
|
if (!result) {
|
|
43
43
|
status = 'error';
|
|
44
44
|
}
|
|
45
|
-
} catch
|
|
45
|
+
} catch {
|
|
46
46
|
checkResults[check.name] = false;
|
|
47
47
|
status = 'error';
|
|
48
48
|
}
|
|
@@ -54,7 +54,10 @@ export function createHealthHandler(config: HealthConfig = {}) {
|
|
|
54
54
|
timestamp: new Date().toISOString(),
|
|
55
55
|
uptime: process.uptime(),
|
|
56
56
|
...(version && { version }),
|
|
57
|
-
...(
|
|
57
|
+
...(checks.length > 0 && {
|
|
58
|
+
checks: checkResults,
|
|
59
|
+
durationMs: Date.now() - startTime,
|
|
60
|
+
}),
|
|
58
61
|
...customData,
|
|
59
62
|
};
|
|
60
63
|
|
package/src/pwa/manifest.ts
CHANGED
|
@@ -174,7 +174,8 @@ export interface SmartScreenshotInput {
|
|
|
174
174
|
export function createScreenshot(input: SmartScreenshotInput | string): ScreenshotConfig {
|
|
175
175
|
// Allow string shorthand
|
|
176
176
|
const config = typeof input === 'string' ? { src: input } : input;
|
|
177
|
-
|
|
177
|
+
const { src, label, form_factor } = config;
|
|
178
|
+
let { width, height } = config;
|
|
178
179
|
|
|
179
180
|
// Auto-detect image type from extension
|
|
180
181
|
const ext = src.split('.').pop()?.toLowerCase();
|
|
@@ -189,10 +190,12 @@ export function createScreenshot(input: SmartScreenshotInput | string): Screensh
|
|
|
189
190
|
|
|
190
191
|
// Try to parse dimensions from filename (e.g., "1920x1080.png" or "screenshot-390x844.png")
|
|
191
192
|
const filename = src.toLowerCase();
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
// Destructured: `\d{3,4}` cannot match empty, so both groups exist whenever
|
|
194
|
+
// the match does — but only binding them says so without an assertion.
|
|
195
|
+
const [, matchedWidth, matchedHeight] = filename.match(/(\d{3,4})x(\d{3,4})/) ?? [];
|
|
196
|
+
if (matchedWidth && matchedHeight && !width && !height) {
|
|
197
|
+
width = parseInt(matchedWidth, 10);
|
|
198
|
+
height = parseInt(matchedHeight, 10);
|
|
196
199
|
}
|
|
197
200
|
|
|
198
201
|
// Auto-detect form_factor from filename if not provided
|
|
@@ -333,12 +336,12 @@ export function createManifest(config: {
|
|
|
333
336
|
|
|
334
337
|
// Add screenshots if provided (for Richer PWA Install UI)
|
|
335
338
|
if (config.screenshots && config.screenshots.length > 0) {
|
|
336
|
-
|
|
339
|
+
manifest.screenshots = config.screenshots;
|
|
337
340
|
}
|
|
338
341
|
|
|
339
342
|
// Add protocol handlers if provided
|
|
340
343
|
if (config.protocol_handlers && config.protocol_handlers.length > 0) {
|
|
341
|
-
|
|
344
|
+
manifest.protocol_handlers = config.protocol_handlers;
|
|
342
345
|
}
|
|
343
346
|
|
|
344
347
|
return manifest;
|
|
@@ -350,6 +353,6 @@ export function createManifest(config: {
|
|
|
350
353
|
*
|
|
351
354
|
* @deprecated Use createManifest() instead
|
|
352
355
|
*/
|
|
353
|
-
export function generateManifest(config: ManifestConfig):
|
|
356
|
+
export function generateManifest(config: ManifestConfig): MetadataRoute.Manifest {
|
|
354
357
|
return createManifest(config)();
|
|
355
358
|
}
|
package/src/pwa/worker/index.ts
CHANGED
|
@@ -43,21 +43,23 @@ export function createServiceWorker(options: ServiceWorkerOptions = {}): void {
|
|
|
43
43
|
cacheName = 'app-cache-v1',
|
|
44
44
|
} = options;
|
|
45
45
|
|
|
46
|
-
//
|
|
47
|
-
|
|
46
|
+
// `self` resolves to the DOM lib's `Window` when this file is compiled as part
|
|
47
|
+
// of an app; inside a service worker it is really a ServiceWorkerGlobalScope.
|
|
48
|
+
// Casting once here types every event handler below via the standard overloads.
|
|
49
|
+
const sw = self as unknown as ServiceWorkerGlobalScope;
|
|
48
50
|
|
|
49
|
-
sw.addEventListener('install', (event
|
|
51
|
+
sw.addEventListener('install', (event) => {
|
|
50
52
|
event.waitUntil(
|
|
51
|
-
caches.open(cacheName).then((cache
|
|
53
|
+
caches.open(cacheName).then((cache) => cache.addAll([offlineFallback]))
|
|
52
54
|
);
|
|
53
55
|
if (skipWaiting) sw.skipWaiting();
|
|
54
56
|
});
|
|
55
57
|
|
|
56
|
-
sw.addEventListener('activate', (event
|
|
58
|
+
sw.addEventListener('activate', (event) => {
|
|
57
59
|
event.waitUntil(
|
|
58
60
|
caches
|
|
59
61
|
.keys()
|
|
60
|
-
.then((keys
|
|
62
|
+
.then((keys) =>
|
|
61
63
|
Promise.all(keys.filter((k) => k !== cacheName).map((k) => caches.delete(k)))
|
|
62
64
|
)
|
|
63
65
|
.then(() => {
|
|
@@ -66,7 +68,7 @@ export function createServiceWorker(options: ServiceWorkerOptions = {}): void {
|
|
|
66
68
|
);
|
|
67
69
|
});
|
|
68
70
|
|
|
69
|
-
sw.addEventListener('fetch', (event
|
|
71
|
+
sw.addEventListener('fetch', (event) => {
|
|
70
72
|
const { request } = event;
|
|
71
73
|
if (request.mode !== 'navigate') return;
|
|
72
74
|
event.respondWith(
|