@data-fair/dev-server 2.6.1 → 2.6.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-fair/dev-server",
3
- "version": "2.6.1",
3
+ "version": "2.6.3",
4
4
  "description": "A development server for optimal development experience of data-fair applications.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/app.js CHANGED
@@ -425,7 +425,12 @@ app.use('/app', createProxyMiddleware({
425
425
  catch (err) {
426
426
  console.warn('[dev-server] failed to enrich configuration datasets', err);
427
427
  }
428
- const filledBody = output.replace(/%APPLICATION%/g, JSON.stringify({
428
+ // Same substitution as data-fair's proxy (api/src/applications/proxy.ts), on purpose:
429
+ // anchored on the assignment the contract defines rather than on the bare placeholder,
430
+ // so an application naming %APPLICATION% elsewhere (a comment documenting the contract)
431
+ // does not consume it — and with < / > escaped so no string of the application can
432
+ // close the script or a comment. An application that loads here must load there.
433
+ const applicationJson = JSON.stringify({
429
434
  id: 'dev-application',
430
435
  slug: 'dev-application',
431
436
  title: 'Dev application',
@@ -437,7 +442,8 @@ app.use('/app', createProxyMiddleware({
437
442
  apiUrl: `http://localhost:${config.port}/data-fair/api/v1`,
438
443
  wsUrl: `ws://localhost:${config.port}/data-fair`,
439
444
  owner: config.dataFair && config.dataFair.owner
440
- }));
445
+ }).replace(/</g, '\\u003C').replace(/>/g, '\\u003E');
446
+ const filledBody = output.replace(/window\.APPLICATION\s*=\s*%APPLICATION%/g, () => `window.APPLICATION=${applicationJson}`);
441
447
  const document = parse5.parse(filledBody);
442
448
  const html = document.childNodes.filter(isElementNode).find(c => c.tagName === 'html');
443
449
  if (!html)
@@ -446,6 +452,17 @@ app.use('/app', createProxyMiddleware({
446
452
  const bodyNode = html.childNodes.filter(isElementNode).find(c => c.tagName === 'body');
447
453
  if (!headNode || !bodyNode)
448
454
  throw new Error('HTML structure is broken, expect html, head and body elements');
455
+ // data-fair owns the language and the title of the served document (proxy.ts): it
456
+ // replaces whatever the application declares, because a <title> declared by an
457
+ // application names its model in the catalog, not the visualization being served, and
458
+ // a document with no language — or the wrong one — fails WCAG 3.1.1 / 2.4.2. Doing it
459
+ // here too means a developer sees the document production will actually serve.
460
+ html.attrs = (html.attrs ?? []).filter(attr => attr.name !== 'lang');
461
+ html.attrs.push({ name: 'lang', value: config.lang?.default ?? 'fr' });
462
+ headNode.childNodes = headNode.childNodes.filter(c => !isElementNode(c) || c.tagName !== 'title');
463
+ const titleNode = createElement('title');
464
+ appendChild(titleNode, createTextNode('Dev application'));
465
+ headNode.childNodes.push(titleNode);
449
466
  const meta = {};
450
467
  for (const node of headNode.childNodes.filter(isElementNode)) {
451
468
  if (node.tagName === 'meta') {
package/src/enrich.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const INJECTED_DATASET_PROPS: readonly ["id", "href", "page", "title", "slug", "finalizedAt", "schema", "isRest", "userPermissions"];
1
+ export declare const INJECTED_DATASET_PROPS: readonly ["id", "href", "page", "title", "slug", "finalizedAt", "schema", "isRest", "userPermissions", "bbox", "timePeriod", "attachmentsAsImage", "count"];
2
2
  export declare const enrichDataset: (dataset: any, fetchJson: (path: string) => Promise<any>) => Promise<any>;
3
3
  export interface PrepareConfigDeps {
4
4
  fetchJson: (path: string) => Promise<any>;
package/src/enrich.js CHANGED
@@ -13,12 +13,18 @@
13
13
  const datasetsCache = new Map();
14
14
  const DATASETS_CACHE_TTL = 30_000;
15
15
  // The set of properties data-fair injects in a configuration dataset entry. Sticking to it
16
- // matters: forwarding the whole remote dataset would let an application rely, in dev, on a
17
- // property that production never sends. data-fair refreshes the keys stored in the entry plus
18
- // the `select` of the app's config schema dataset selector — this list covers that contract,
19
- // including `isRest`, carried by the select of editing apps and used as the gate deciding
20
- // whether rest line editing (POST/PATCH/DELETE /lines) is offered at all.
21
- export const INJECTED_DATASET_PROPS = ['id', 'href', 'page', 'title', 'slug', 'finalizedAt', 'schema', 'isRest', 'userPermissions'];
16
+ // matters in both directions: forwarding the whole remote dataset would let an application rely,
17
+ // in dev, on a property production never sends — and omitting one production does send makes an
18
+ // application work in production and not here, which is worse still.
19
+ //
20
+ // data-fair derives the set per request (refreshConfigDatasetsRefs, api/src/applications/utils.ts):
21
+ // the keys already stored in the entry, plus `finalizedAt` and `slug`, plus the `select` of the
22
+ // dataset selector declared in the application's own config schema. We cannot derive it without
23
+ // parsing that schema, so this list mirrors it and has to track it: it is the union of the
24
+ // selects used by the published applications. `isRest` gates whether rest line editing
25
+ // (POST/PATCH/DELETE /lines) is offered at all; `bbox` and `timePeriod` drive the initial map
26
+ // bounds and period pickers; `attachmentsAsImage` switches list apps to thumbnail mode.
27
+ export const INJECTED_DATASET_PROPS = ['id', 'href', 'page', 'title', 'slug', 'finalizedAt', 'schema', 'isRest', 'userPermissions', 'bbox', 'timePeriod', 'attachmentsAsImage', 'count'];
22
28
  export const enrichDataset = async (dataset, fetchJson) => {
23
29
  if (!dataset?.id)
24
30
  return dataset;