@uniweb/build 0.16.3 → 0.16.5

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 (2) hide show
  1. package/package.json +6 -6
  2. package/src/schema.js +58 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/build",
3
- "version": "0.16.3",
3
+ "version": "0.16.5",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -59,15 +59,15 @@
59
59
  "js-yaml": "^4.1.0",
60
60
  "sharp": "^0.35.3",
61
61
  "yaml": "^2.5.0",
62
- "@uniweb/content-writer": "0.3.2",
62
+ "@uniweb/content-writer": "0.3.3",
63
63
  "@uniweb/theming": "0.1.15",
64
- "@uniweb/projections": "0.2.2"
64
+ "@uniweb/projections": "0.2.3"
65
65
  },
66
66
  "optionalDependencies": {
67
+ "@uniweb/content-reader": "1.2.2",
67
68
  "@uniweb/runtime": "0.9.0",
68
- "@uniweb/semantic-parser": "1.2.0",
69
- "@uniweb/content-reader": "1.2.1",
70
- "@uniweb/schemas": "0.2.4"
69
+ "@uniweb/schemas": "0.2.4",
70
+ "@uniweb/semantic-parser": "1.2.0"
71
71
  },
72
72
  "peerDependencies": {
73
73
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
package/src/schema.js CHANGED
@@ -120,6 +120,63 @@ export async function loadPackageJson(srcDir) {
120
120
  * - props: Foundation-wide props
121
121
  * - Future: providers, middleware, etc.
122
122
  */
123
+ /**
124
+ * Capability keys that only work as keys of the DEFAULT export.
125
+ *
126
+ * The list is `cli/partials/agents.md`'s ("A single `export default { … }` whose
127
+ * top-level keys are the capabilities the foundation provides"). `vars` is
128
+ * deliberately absent: it is the one capability that also works named, because
129
+ * `generate-entry.js` reads it explicitly.
130
+ */
131
+ const DEFAULT_ONLY_CAPABILITIES = [
132
+ 'name',
133
+ 'description',
134
+ 'defaultLayout',
135
+ 'defaultSection',
136
+ 'viewTransitions',
137
+ 'props',
138
+ 'defaultInsets',
139
+ 'xref',
140
+ 'outputs',
141
+ 'handlers',
142
+ 'extension',
143
+ ]
144
+
145
+ /**
146
+ * Warn when a capability was written as a named export.
147
+ *
148
+ * `generate-entry.js` builds `capabilities` as `{ ..._foundationModule.default,
149
+ * vars: … }` — it spreads only the DEFAULT export. A named `export const xref =
150
+ * …` is therefore dropped with no error, no warning, and a build that succeeds.
151
+ * Whatever the capability did simply does not happen, which reads as "the
152
+ * feature is not implemented" rather than "it is declared in the wrong place".
153
+ *
154
+ * Real incident (2026-07-31): cross-references were wired onto uniweb.io as
155
+ * named `xref` and `defaultInsets` exports. The build passed, the site ran, and
156
+ * every `[#id]` rendered as its own literal text — indistinguishable from a
157
+ * foundation that had never opted in. Found only by reading generate-entry.js.
158
+ *
159
+ * A warning rather than an error: a foundation may legitimately export a name
160
+ * that collides for its own use, and failing someone's build over a naming
161
+ * coincidence is worse than telling them what we ignored.
162
+ */
163
+ function warnMisplacedCapabilities(module, filePath) {
164
+ const onDefault = module.default && typeof module.default === 'object' ? module.default : {}
165
+ const misplaced = DEFAULT_ONLY_CAPABILITIES.filter(
166
+ key => module[key] !== undefined && onDefault[key] === undefined,
167
+ )
168
+ if (misplaced.length === 0) return
169
+
170
+ const list = misplaced.map(k => `\`${k}\``).join(', ')
171
+ console.warn(
172
+ `Warning: ${filePath} exports ${list} as named export${misplaced.length > 1 ? 's' : ''}, ` +
173
+ `which the build ignores.\n` +
174
+ ` Capabilities are read from the default export only — move ${misplaced.length > 1 ? 'them' : 'it'} into ` +
175
+ `\`export default { … }\`.\n` +
176
+ ` (\`vars\` is the exception and may stay a named export.)`,
177
+ )
178
+ }
179
+
123
180
  export async function loadFoundationConfig(srcDir) {
124
181
  let filePath = null
125
182
  for (const name of FOUNDATION_FILE_NAMES) {
@@ -133,6 +190,7 @@ export async function loadFoundationConfig(srcDir) {
133
190
 
134
191
  try {
135
192
  const module = await import(pathToFileURL(filePath).href)
193
+ warnMisplacedCapabilities(module, filePath)
136
194
  // Support both default export and named exports
137
195
  return {
138
196
  ...module.default,