@vistagenic/vista 0.3.6 → 0.3.8

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.
Files changed (68) hide show
  1. package/bin/flashpack-agent-playground.mjs +134 -0
  2. package/bin/flashpack-boot.mjs +504 -0
  3. package/bin/flashpack-ssr-loader.mjs +42 -0
  4. package/bin/flashpack-ssr.mjs +81 -0
  5. package/bin/flashpack-vendor.mjs +97 -0
  6. package/bin/vista.js +56 -42
  7. package/dist/ai/providers/base.js +7 -1
  8. package/dist/bin/build-rsc.js +16 -0
  9. package/dist/bin/build.js +17 -11
  10. package/dist/bin/deploy.js +7 -0
  11. package/dist/bin/dev-client-runtime.d.ts +6 -0
  12. package/dist/bin/dev-client-runtime.js +99 -0
  13. package/dist/bin/dev-error-overlay-snippet.js +79 -21
  14. package/dist/bin/dev-error-overlay-snippet.ts +840 -0
  15. package/dist/bin/devtools-indicator-snippet.js +29 -13
  16. package/dist/bin/file-scanner.js +7 -24
  17. package/dist/bin/generate.js +94 -2
  18. package/dist/bin/webpack.config.js +3 -1
  19. package/dist/build/rsc/compiler.d.ts +14 -0
  20. package/dist/build/rsc/compiler.js +66 -6
  21. package/dist/build/rsc/server-manifest.js +5 -4
  22. package/dist/config.d.ts +5 -0
  23. package/dist/config.js +15 -1
  24. package/dist/deploy/adapters/render.js +2 -2
  25. package/dist/deploy/index.d.ts +1 -0
  26. package/dist/deploy/index.js +3 -0
  27. package/dist/deploy/runtime-pack.js +22 -1
  28. package/dist/deploy/utils.js +16 -6
  29. package/dist/flashpack/command.d.ts +1 -0
  30. package/dist/flashpack/command.js +42 -76
  31. package/dist/flashpack/runtime.d.ts +12 -0
  32. package/dist/flashpack/runtime.js +124 -22
  33. package/dist/metadata/generate.d.ts +1 -0
  34. package/dist/metadata/generate.js +117 -21
  35. package/dist/metadata/index.d.ts +5 -0
  36. package/dist/metadata/index.js +15 -1
  37. package/dist/metadata/json-ld.d.ts +15 -0
  38. package/dist/metadata/json-ld.js +19 -0
  39. package/dist/metadata/merge.d.ts +17 -0
  40. package/dist/metadata/merge.js +161 -0
  41. package/dist/metadata/routes.d.ts +66 -0
  42. package/dist/metadata/routes.js +143 -0
  43. package/dist/metadata/types.d.ts +1 -1
  44. package/dist/metadata/types.js +3 -1
  45. package/dist/og/image-response.d.ts +38 -0
  46. package/dist/og/image-response.js +88 -0
  47. package/dist/og/index.d.ts +2 -0
  48. package/dist/og/index.js +5 -0
  49. package/dist/rust/index.d.ts +13 -0
  50. package/dist/rust/index.js +132 -0
  51. package/dist/server/engine.js +13 -3
  52. package/dist/server/logger.js +2 -1
  53. package/dist/server/project-alias-resolver.d.ts +7 -0
  54. package/dist/server/project-alias-resolver.js +70 -0
  55. package/dist/server/rsc-engine.js +93 -16
  56. package/dist/server/static-generator.js +4 -3
  57. package/dist/server/typed-api-runtime.js +92 -0
  58. package/docs/ai.md +69 -0
  59. package/docs/app.md +30 -0
  60. package/docs/cli.md +29 -0
  61. package/docs/index.md +18 -0
  62. package/docs/rag.md +54 -0
  63. package/native/win32-x64/flashpack-cli.exe +0 -0
  64. package/package.json +196 -178
  65. package/skills/README.md +9 -0
  66. package/skills/vista-agent/SKILL.md +28 -0
  67. package/skills/vista-dev-loop/SKILL.md +25 -0
  68. package/skills/vista-rag/SKILL.md +26 -0
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MetadataRenderer = MetadataRenderer;
4
4
  exports.generateMetadataHtml = generateMetadataHtml;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const merge_1 = require("./merge");
6
7
  // ============================================================================
7
8
  // Helper Functions
8
9
  // ============================================================================
@@ -19,9 +20,10 @@ function resolveTitle(title, template) {
19
20
  if (title.absolute) {
20
21
  return title.absolute;
21
22
  }
22
- const baseTitle = title.default;
23
- if (title.template) {
24
- return title.template.replace('%s', baseTitle);
23
+ const baseTitle = title.default ?? '';
24
+ const activeTemplate = title.template || template;
25
+ if (activeTemplate && baseTitle) {
26
+ return activeTemplate.replace('%s', baseTitle);
25
27
  }
26
28
  return baseTitle;
27
29
  }
@@ -98,12 +100,7 @@ function generateAuthorMeta(authors) {
98
100
  });
99
101
  return elements;
100
102
  }
101
- function generateRobotsMeta(robots) {
102
- if (!robots)
103
- return [];
104
- if (typeof robots === 'string') {
105
- return [(0, jsx_runtime_1.jsx)("meta", { name: "robots", content: robots }, "robots")];
106
- }
103
+ function robotsDirectives(robots) {
107
104
  const directives = [];
108
105
  if (robots.index !== undefined)
109
106
  directives.push(robots.index ? 'index' : 'noindex');
@@ -117,21 +114,37 @@ function generateRobotsMeta(robots) {
117
114
  directives.push('noimageindex');
118
115
  if (robots.nocache)
119
116
  directives.push('nocache');
117
+ if (robots.notranslate)
118
+ directives.push('notranslate');
120
119
  if (robots['max-snippet'] !== undefined)
121
120
  directives.push(`max-snippet:${robots['max-snippet']}`);
122
121
  if (robots['max-image-preview'])
123
122
  directives.push(`max-image-preview:${robots['max-image-preview']}`);
124
123
  if (robots['max-video-preview'] !== undefined)
125
124
  directives.push(`max-video-preview:${robots['max-video-preview']}`);
125
+ return directives;
126
+ }
127
+ function generateRobotsMeta(robots) {
128
+ if (!robots)
129
+ return [];
130
+ if (typeof robots === 'string') {
131
+ return [(0, jsx_runtime_1.jsx)("meta", { name: "robots", content: robots }, "robots")];
132
+ }
126
133
  const elements = [];
134
+ const directives = robotsDirectives(robots);
127
135
  if (directives.length > 0) {
128
136
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "robots", content: directives.join(', ') }, "robots"));
129
137
  }
130
- // GoogleBot specific
131
138
  if (robots.googleBot) {
132
139
  if (typeof robots.googleBot === 'string') {
133
140
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "googlebot", content: robots.googleBot }, "googlebot"));
134
141
  }
142
+ else {
143
+ const googleDirectives = robotsDirectives(robots.googleBot);
144
+ if (googleDirectives.length > 0) {
145
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: "googlebot", content: googleDirectives.join(', ') }, "googlebot"));
146
+ }
147
+ }
135
148
  }
136
149
  return elements;
137
150
  }
@@ -184,44 +197,108 @@ function generateOpenGraphMeta(og, base) {
184
197
  if (image.alt) {
185
198
  elements.push((0, jsx_runtime_1.jsx)("meta", { property: "og:image:alt", content: image.alt }, `og:image:alt:${index}`));
186
199
  }
200
+ if (image.type) {
201
+ elements.push((0, jsx_runtime_1.jsx)("meta", { property: "og:image:type", content: image.type }, `og:image:type:${index}`));
202
+ }
187
203
  }
188
204
  });
189
205
  }
206
+ if ('article' in og && og.article) {
207
+ const article = og.article;
208
+ if (article.publishedTime) {
209
+ elements.push((0, jsx_runtime_1.jsx)("meta", { property: "article:published_time", content: article.publishedTime }, "og:article:published_time"));
210
+ }
211
+ if (article.modifiedTime) {
212
+ elements.push((0, jsx_runtime_1.jsx)("meta", { property: "article:modified_time", content: article.modifiedTime }, "og:article:modified_time"));
213
+ }
214
+ if (article.section) {
215
+ elements.push((0, jsx_runtime_1.jsx)("meta", { property: "article:section", content: article.section }, "og:article:section"));
216
+ }
217
+ if (article.tags) {
218
+ const tags = Array.isArray(article.tags) ? article.tags : [article.tags];
219
+ tags.forEach((tag, index) => {
220
+ elements.push((0, jsx_runtime_1.jsx)("meta", { property: "article:tag", content: tag }, `og:article:tag:${index}`));
221
+ });
222
+ }
223
+ }
190
224
  return elements;
191
225
  }
192
- function generateTwitterMeta(twitter) {
226
+ function generateTwitterMeta(twitter, base) {
193
227
  if (!twitter)
194
228
  return [];
195
229
  const elements = [];
196
- // Card type
197
230
  if (twitter.card) {
198
231
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:card", content: twitter.card }, "twitter:card"));
199
232
  }
200
- // Site
201
233
  if (twitter.site) {
202
234
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:site", content: twitter.site }, "twitter:site"));
203
235
  }
204
- // Creator
205
236
  if (twitter.creator) {
206
237
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:creator", content: twitter.creator }, "twitter:creator"));
207
238
  }
208
- // Title
209
239
  if (twitter.title) {
210
240
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:title", content: twitter.title }, "twitter:title"));
211
241
  }
212
- // Description
213
242
  if (twitter.description) {
214
243
  elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:description", content: twitter.description }, "twitter:description"));
215
244
  }
216
- // Images
217
245
  if (twitter.images) {
218
246
  const images = Array.isArray(twitter.images) ? twitter.images : [twitter.images];
219
247
  images.forEach((image, index) => {
220
- elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:image", content: image.toString() }, `twitter:image:${index}`));
248
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: "twitter:image", content: resolveUrl(image, base) || image.toString() }, `twitter:image:${index}`));
221
249
  });
222
250
  }
223
251
  return elements;
224
252
  }
253
+ function generateOtherMeta(other) {
254
+ if (!other)
255
+ return [];
256
+ const elements = [];
257
+ Object.entries(other).forEach(([name, value]) => {
258
+ const values = Array.isArray(value) ? value : [value];
259
+ values.forEach((entry, index) => {
260
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: name, content: String(entry) }, `other-${name}-${index}`));
261
+ });
262
+ });
263
+ return elements;
264
+ }
265
+ function generateAppleWebAppMeta(appleWebApp) {
266
+ if (appleWebApp === null || appleWebApp === undefined)
267
+ return [];
268
+ const elements = [];
269
+ if (appleWebApp === true) {
270
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: "apple-mobile-web-app-capable", content: "yes" }, "apple-mobile-web-app-capable"));
271
+ return elements;
272
+ }
273
+ if (appleWebApp === false)
274
+ return elements;
275
+ if (appleWebApp.capable !== undefined) {
276
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: "apple-mobile-web-app-capable", content: appleWebApp.capable ? 'yes' : 'no' }, "apple-mobile-web-app-capable"));
277
+ }
278
+ if (appleWebApp.title) {
279
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: "apple-mobile-web-app-title", content: appleWebApp.title }, "apple-mobile-web-app-title"));
280
+ }
281
+ if (appleWebApp.statusBarStyle) {
282
+ elements.push((0, jsx_runtime_1.jsx)("meta", { name: "apple-mobile-web-app-status-bar-style", content: appleWebApp.statusBarStyle }, "apple-mobile-web-app-status-bar-style"));
283
+ }
284
+ return elements;
285
+ }
286
+ function generateFormatDetectionMeta(formatDetection) {
287
+ if (!formatDetection)
288
+ return [];
289
+ const parts = [];
290
+ ['telephone', 'date', 'address', 'email', 'url'].forEach((key) => {
291
+ if (formatDetection[key] === false)
292
+ parts.push(`${key}=no`);
293
+ if (formatDetection[key] === true)
294
+ parts.push(`${key}=yes`);
295
+ });
296
+ if (parts.length === 0)
297
+ return [];
298
+ return [
299
+ (0, jsx_runtime_1.jsx)("meta", { name: "format-detection", content: parts.join(', ') }, "format-detection"),
300
+ ];
301
+ }
225
302
  function generateIconLinks(icons) {
226
303
  if (!icons)
227
304
  return [];
@@ -305,6 +382,22 @@ function generateAlternateLinks(alternates, base) {
305
382
  });
306
383
  });
307
384
  }
385
+ if (alternates.media) {
386
+ Object.entries(alternates.media).forEach(([media, url]) => {
387
+ const urls = Array.isArray(url) ? url : [url];
388
+ urls.forEach((u, index) => {
389
+ elements.push((0, jsx_runtime_1.jsx)("link", { rel: "alternate", media: media, href: resolveUrl(u, base) || '' }, `alternate-media-${media}-${index}`));
390
+ });
391
+ });
392
+ }
393
+ if (alternates.types) {
394
+ Object.entries(alternates.types).forEach(([type, url]) => {
395
+ const urls = Array.isArray(url) ? url : [url];
396
+ urls.forEach((u, index) => {
397
+ elements.push((0, jsx_runtime_1.jsx)("link", { rel: "alternate", type: type, href: resolveUrl(u, base) || '' }, `alternate-type-${type}-${index}`));
398
+ });
399
+ });
400
+ }
308
401
  return elements;
309
402
  }
310
403
  /**
@@ -313,16 +406,19 @@ function generateAlternateLinks(alternates, base) {
313
406
  */
314
407
  function MetadataRenderer({ metadata, parentTemplate, }) {
315
408
  const base = metadata.metadataBase;
316
- const title = resolveTitle(metadata.title, parentTemplate);
317
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && (0, jsx_runtime_1.jsx)("title", { children: title }), generateBasicMeta(metadata), generateAuthorMeta(metadata.authors), generateRobotsMeta(metadata.robots), generateOpenGraphMeta(metadata.openGraph, base), generateTwitterMeta(metadata.twitter), generateIconLinks(metadata.icons), generateVerificationMeta(metadata.verification), generateAlternateLinks(metadata.alternates, base), metadata.manifest && ((0, jsx_runtime_1.jsx)("link", { rel: "manifest", href: resolveUrl(metadata.manifest, base) || '' }))] }));
409
+ const inheritedTemplate = parentTemplate ?? (0, merge_1.resolveParentTitleTemplate)(metadata);
410
+ const title = resolveTitle(metadata.title, inheritedTemplate);
411
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && (0, jsx_runtime_1.jsx)("title", { children: title }), generateBasicMeta(metadata), generateAuthorMeta(metadata.authors), generateRobotsMeta(metadata.robots), generateOpenGraphMeta(metadata.openGraph, base), generateTwitterMeta(metadata.twitter, base), generateIconLinks(metadata.icons), generateVerificationMeta(metadata.verification), generateAlternateLinks(metadata.alternates, base), generateAppleWebAppMeta(metadata.appleWebApp), generateFormatDetectionMeta(metadata.formatDetection), generateOtherMeta(metadata.other), metadata.manifest && ((0, jsx_runtime_1.jsx)("link", { rel: "manifest", href: resolveUrl(metadata.manifest, base) || '' })), metadata.classification && ((0, jsx_runtime_1.jsx)("meta", { name: "classification", content: metadata.classification }))] }));
318
412
  }
319
413
  /**
320
414
  * Converts metadata to HTML string for SSR injection.
415
+ * Applies title template from merged metadata when parentTemplate is omitted.
321
416
  */
322
417
  function generateMetadataHtml(metadata, parentTemplate) {
323
418
  if (!metadata || typeof metadata !== 'object')
324
419
  return '';
325
420
  const { renderToStaticMarkup } = require('react-dom/server');
326
- return renderToStaticMarkup((0, jsx_runtime_1.jsx)(MetadataRenderer, { metadata: metadata, parentTemplate: parentTemplate }));
421
+ const template = parentTemplate ?? (0, merge_1.resolveParentTitleTemplate)(metadata);
422
+ return renderToStaticMarkup((0, jsx_runtime_1.jsx)(MetadataRenderer, { metadata: metadata, parentTemplate: template }));
327
423
  }
328
424
  exports.default = MetadataRenderer;
@@ -5,3 +5,8 @@
5
5
  */
6
6
  export * from './types';
7
7
  export { MetadataRenderer, generateMetadataHtml } from './generate';
8
+ export { deepMergeMetadata, mergeMetadataChain, resolveParentTitleTemplate } from './merge';
9
+ export { robots, sitemap, manifest, serializeRobots, serializeSitemap, metadataRouteToResponse, MetadataRoute, } from './routes';
10
+ export type { RobotsFile, RobotsRule, SitemapFile, SitemapEntry, ManifestFile, ManifestIcon, } from './routes';
11
+ export { jsonLd, JsonLd } from './json-ld';
12
+ export type { JsonLdProps } from './json-ld';
@@ -19,8 +19,22 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.generateMetadataHtml = exports.MetadataRenderer = void 0;
22
+ exports.JsonLd = exports.jsonLd = exports.metadataRouteToResponse = exports.serializeSitemap = exports.serializeRobots = exports.manifest = exports.sitemap = exports.robots = exports.resolveParentTitleTemplate = exports.mergeMetadataChain = exports.deepMergeMetadata = exports.generateMetadataHtml = exports.MetadataRenderer = void 0;
23
23
  __exportStar(require("./types"), exports);
24
24
  var generate_1 = require("./generate");
25
25
  Object.defineProperty(exports, "MetadataRenderer", { enumerable: true, get: function () { return generate_1.MetadataRenderer; } });
26
26
  Object.defineProperty(exports, "generateMetadataHtml", { enumerable: true, get: function () { return generate_1.generateMetadataHtml; } });
27
+ var merge_1 = require("./merge");
28
+ Object.defineProperty(exports, "deepMergeMetadata", { enumerable: true, get: function () { return merge_1.deepMergeMetadata; } });
29
+ Object.defineProperty(exports, "mergeMetadataChain", { enumerable: true, get: function () { return merge_1.mergeMetadataChain; } });
30
+ Object.defineProperty(exports, "resolveParentTitleTemplate", { enumerable: true, get: function () { return merge_1.resolveParentTitleTemplate; } });
31
+ var routes_1 = require("./routes");
32
+ Object.defineProperty(exports, "robots", { enumerable: true, get: function () { return routes_1.robots; } });
33
+ Object.defineProperty(exports, "sitemap", { enumerable: true, get: function () { return routes_1.sitemap; } });
34
+ Object.defineProperty(exports, "manifest", { enumerable: true, get: function () { return routes_1.manifest; } });
35
+ Object.defineProperty(exports, "serializeRobots", { enumerable: true, get: function () { return routes_1.serializeRobots; } });
36
+ Object.defineProperty(exports, "serializeSitemap", { enumerable: true, get: function () { return routes_1.serializeSitemap; } });
37
+ Object.defineProperty(exports, "metadataRouteToResponse", { enumerable: true, get: function () { return routes_1.metadataRouteToResponse; } });
38
+ var json_ld_1 = require("./json-ld");
39
+ Object.defineProperty(exports, "jsonLd", { enumerable: true, get: function () { return json_ld_1.jsonLd; } });
40
+ Object.defineProperty(exports, "JsonLd", { enumerable: true, get: function () { return json_ld_1.JsonLd; } });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * SSR-safe JSON-LD helpers for structured data.
3
+ */
4
+ import * as React from 'react';
5
+ /** Serialize structured data for embedding in a script tag. */
6
+ export declare function jsonLd(data: unknown): string;
7
+ export interface JsonLdProps {
8
+ data: unknown;
9
+ id?: string;
10
+ }
11
+ /**
12
+ * Renders `<script type="application/ld+json">` with XSS-safe serialization.
13
+ * Prefer this over hand-rolling dangerouslySetInnerHTML.
14
+ */
15
+ export declare function JsonLd({ data, id }: JsonLdProps): React.ReactElement;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.jsonLd = jsonLd;
4
+ exports.JsonLd = JsonLd;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ function serializeJsonLd(data) {
7
+ return JSON.stringify(data).replace(/</g, '\\u003c');
8
+ }
9
+ /** Serialize structured data for embedding in a script tag. */
10
+ function jsonLd(data) {
11
+ return serializeJsonLd(data);
12
+ }
13
+ /**
14
+ * Renders `<script type="application/ld+json">` with XSS-safe serialization.
15
+ * Prefer this over hand-rolling dangerouslySetInnerHTML.
16
+ */
17
+ function JsonLd({ data, id }) {
18
+ return ((0, jsx_runtime_1.jsx)("script", { id: id, type: "application/ld+json", dangerouslySetInnerHTML: { __html: serializeJsonLd(data) } }));
19
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Next.js-compatible deep merge for Metadata objects.
3
+ * Nested openGraph / twitter / robots / alternates / icons merge instead of replace.
4
+ * Title templates inherit from parent layouts.
5
+ */
6
+ import type { Metadata } from './types';
7
+ /**
8
+ * Deep-merge parent layout metadata with child page/layout metadata.
9
+ * Child wins on scalar fields; nested objects merge.
10
+ */
11
+ export declare function deepMergeMetadata(parent: Metadata | null | undefined, child: Metadata | null | undefined): Metadata;
12
+ /** Fold a chain of metadata objects (root → … → page). */
13
+ export declare function mergeMetadataChain(chain: Array<Metadata | null | undefined>): Metadata;
14
+ /**
15
+ * Resolve the active title template string from merged metadata (for generateMetadataHtml).
16
+ */
17
+ export declare function resolveParentTitleTemplate(metadata: Metadata | null | undefined): string | undefined;
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ /**
3
+ * Next.js-compatible deep merge for Metadata objects.
4
+ * Nested openGraph / twitter / robots / alternates / icons merge instead of replace.
5
+ * Title templates inherit from parent layouts.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.deepMergeMetadata = deepMergeMetadata;
9
+ exports.mergeMetadataChain = mergeMetadataChain;
10
+ exports.resolveParentTitleTemplate = resolveParentTitleTemplate;
11
+ const types_1 = require("./types");
12
+ function isPlainObject(value) {
13
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof URL);
14
+ }
15
+ function mergeTitle(parent, child) {
16
+ if (child === null)
17
+ return null;
18
+ if (child === undefined)
19
+ return parent;
20
+ const parentTemplate = (0, types_1.isTemplateString)(parent) && parent.template
21
+ ? parent.template
22
+ : typeof parent === 'object' && parent && 'template' in parent
23
+ ? parent.template
24
+ : undefined;
25
+ if (typeof child === 'string') {
26
+ if (parentTemplate) {
27
+ return { default: child, template: parentTemplate };
28
+ }
29
+ return child;
30
+ }
31
+ if ((0, types_1.isTemplateString)(child)) {
32
+ if (child.absolute) {
33
+ return {
34
+ absolute: child.absolute,
35
+ default: child.default ?? child.absolute,
36
+ template: child.template ?? parentTemplate,
37
+ };
38
+ }
39
+ return {
40
+ default: child.default ?? '',
41
+ absolute: child.absolute,
42
+ template: child.template ?? parentTemplate,
43
+ };
44
+ }
45
+ return child;
46
+ }
47
+ function mergeRobots(parent, child) {
48
+ if (child === null)
49
+ return null;
50
+ if (child === undefined)
51
+ return parent;
52
+ if (typeof child === 'string' || typeof parent === 'string')
53
+ return child;
54
+ if (!parent || typeof parent !== 'object')
55
+ return child;
56
+ const merged = { ...parent, ...child };
57
+ if (isPlainObject(parent.googleBot) && isPlainObject(child.googleBot)) {
58
+ merged.googleBot = { ...parent.googleBot, ...child.googleBot };
59
+ }
60
+ return merged;
61
+ }
62
+ function mergeOpenGraph(parent, child) {
63
+ if (child === null)
64
+ return null;
65
+ if (child === undefined)
66
+ return parent;
67
+ if (!parent)
68
+ return child;
69
+ return { ...parent, ...child };
70
+ }
71
+ function mergeTwitter(parent, child) {
72
+ if (child === null)
73
+ return null;
74
+ if (child === undefined)
75
+ return parent;
76
+ if (!parent)
77
+ return child;
78
+ return { ...parent, ...child };
79
+ }
80
+ function mergeIcons(parent, child) {
81
+ if (child === null)
82
+ return null;
83
+ if (child === undefined)
84
+ return parent;
85
+ if (!parent || typeof parent !== 'object' || Array.isArray(parent) || parent instanceof URL) {
86
+ return child;
87
+ }
88
+ if (!child || typeof child !== 'object' || Array.isArray(child) || child instanceof URL) {
89
+ return child;
90
+ }
91
+ if ('url' in child)
92
+ return child;
93
+ return { ...parent, ...child };
94
+ }
95
+ function mergeAlternates(parent, child) {
96
+ if (child === null)
97
+ return null;
98
+ if (child === undefined)
99
+ return parent;
100
+ if (!parent)
101
+ return child;
102
+ return {
103
+ ...parent,
104
+ ...child,
105
+ languages: { ...(parent.languages || {}), ...(child.languages || {}) },
106
+ media: { ...(parent.media || {}), ...(child.media || {}) },
107
+ types: { ...(parent.types || {}), ...(child.types || {}) },
108
+ };
109
+ }
110
+ /**
111
+ * Deep-merge parent layout metadata with child page/layout metadata.
112
+ * Child wins on scalar fields; nested objects merge.
113
+ */
114
+ function deepMergeMetadata(parent, child) {
115
+ const base = parent && typeof parent === 'object' ? { ...parent } : {};
116
+ if (!child || typeof child !== 'object')
117
+ return base;
118
+ const next = { ...base, ...child };
119
+ next.title = mergeTitle(base.title, child.title);
120
+ next.robots = mergeRobots(base.robots, child.robots);
121
+ next.openGraph = mergeOpenGraph(base.openGraph, child.openGraph);
122
+ next.twitter = mergeTwitter(base.twitter, child.twitter);
123
+ next.icons = mergeIcons(base.icons, child.icons);
124
+ next.alternates = mergeAlternates(base.alternates, child.alternates);
125
+ if (isPlainObject(base.other) || isPlainObject(child.other)) {
126
+ next.other = { ...(base.other || {}), ...(child.other || {}) };
127
+ }
128
+ if (isPlainObject(base.verification) || isPlainObject(child.verification)) {
129
+ next.verification = { ...(base.verification || {}), ...(child.verification || {}) };
130
+ }
131
+ if (isPlainObject(base.formatDetection) || isPlainObject(child.formatDetection)) {
132
+ next.formatDetection = { ...(base.formatDetection || {}), ...(child.formatDetection || {}) };
133
+ }
134
+ if ((isPlainObject(base.appleWebApp) || typeof base.appleWebApp === 'boolean') &&
135
+ (isPlainObject(child.appleWebApp) || typeof child.appleWebApp === 'boolean')) {
136
+ if (typeof child.appleWebApp === 'boolean' || typeof base.appleWebApp === 'boolean') {
137
+ next.appleWebApp = child.appleWebApp !== undefined ? child.appleWebApp : base.appleWebApp;
138
+ }
139
+ else {
140
+ next.appleWebApp = { ...base.appleWebApp, ...child.appleWebApp };
141
+ }
142
+ }
143
+ if (base.metadataBase && child.metadataBase === undefined) {
144
+ next.metadataBase = base.metadataBase;
145
+ }
146
+ return next;
147
+ }
148
+ /** Fold a chain of metadata objects (root → … → page). */
149
+ function mergeMetadataChain(chain) {
150
+ return chain.reduce((acc, item) => deepMergeMetadata(acc, item), {});
151
+ }
152
+ /**
153
+ * Resolve the active title template string from merged metadata (for generateMetadataHtml).
154
+ */
155
+ function resolveParentTitleTemplate(metadata) {
156
+ if (!metadata?.title)
157
+ return undefined;
158
+ if ((0, types_1.isTemplateString)(metadata.title))
159
+ return metadata.title.template;
160
+ return undefined;
161
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Next-compatible MetadataRoute helpers for robots.txt, sitemap.xml, and web manifests.
3
+ */
4
+ export type RobotsRule = {
5
+ userAgent?: string | string[];
6
+ allow?: string | string[];
7
+ disallow?: string | string[];
8
+ crawlDelay?: number;
9
+ other?: Record<string, string | number | Array<string | number>>;
10
+ };
11
+ export type RobotsFile = {
12
+ rules: RobotsRule | RobotsRule[];
13
+ sitemap?: string | string[];
14
+ host?: string;
15
+ };
16
+ export type SitemapEntry = {
17
+ url: string;
18
+ lastModified?: string | Date;
19
+ changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
20
+ priority?: number;
21
+ alternates?: {
22
+ languages?: Record<string, string>;
23
+ };
24
+ images?: string[];
25
+ videos?: Array<{
26
+ title: string;
27
+ thumbnail_loc: string;
28
+ description: string;
29
+ }>;
30
+ };
31
+ export type SitemapFile = SitemapEntry[];
32
+ export type ManifestIcon = {
33
+ src: string;
34
+ sizes?: string;
35
+ type?: string;
36
+ purpose?: string;
37
+ };
38
+ export type ManifestFile = {
39
+ name?: string;
40
+ short_name?: string;
41
+ description?: string;
42
+ start_url?: string;
43
+ display?: 'fullscreen' | 'standalone' | 'minimal-ui' | 'browser';
44
+ background_color?: string;
45
+ theme_color?: string;
46
+ icons?: ManifestIcon[];
47
+ [key: string]: unknown;
48
+ };
49
+ /** Namespace mirroring Next.js `MetadataRoute`. */
50
+ export declare namespace MetadataRoute {
51
+ type Robots = RobotsFile;
52
+ type Sitemap = SitemapFile;
53
+ type Manifest = ManifestFile;
54
+ }
55
+ /** Serialize a Robots object to robots.txt body text. */
56
+ export declare function serializeRobots(data: RobotsFile): string;
57
+ /** Serialize sitemap entries to XML. */
58
+ export declare function serializeSitemap(entries: SitemapFile): string;
59
+ /** Build a robots.txt Response. */
60
+ export declare function robots(data: RobotsFile): Response;
61
+ /** Build a sitemap.xml Response. */
62
+ export declare function sitemap(entries: SitemapFile): Response;
63
+ /** Build a webmanifest JSON Response. */
64
+ export declare function manifest(data: ManifestFile): Response;
65
+ /** Convert a MetadataRoute default-export payload into a Response. */
66
+ export declare function metadataRouteToResponse(stem: 'robots' | 'sitemap' | 'manifest', payload: unknown): Response | null;