ochre-sdk 1.3.12 → 1.3.14

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 (102) hide show
  1. package/README.md +1 -4
  2. package/dist/categories.d.mts +1 -3
  3. package/dist/categories.mjs +1 -2
  4. package/dist/constants.d.mts +1 -3
  5. package/dist/constants.mjs +14 -4
  6. package/dist/errors.d.mts +0 -2
  7. package/dist/errors.mjs +1 -2
  8. package/dist/fetchers/container-items.d.mts +1 -3
  9. package/dist/fetchers/container-items.mjs +1 -2
  10. package/dist/fetchers/gallery.d.mts +1 -3
  11. package/dist/fetchers/gallery.mjs +1 -2
  12. package/dist/fetchers/item-children.d.mts +0 -2
  13. package/dist/fetchers/item-children.mjs +1 -2
  14. package/dist/fetchers/item-links.d.mts +1 -3
  15. package/dist/fetchers/item-links.mjs +1 -2
  16. package/dist/fetchers/item-locations.d.mts +39 -0
  17. package/dist/fetchers/item-locations.mjs +98 -0
  18. package/dist/fetchers/item-ocr-data.d.mts +1 -3
  19. package/dist/fetchers/item-ocr-data.mjs +1 -2
  20. package/dist/fetchers/item.d.mts +0 -2
  21. package/dist/fetchers/item.mjs +1 -2
  22. package/dist/fetchers/map-layers.d.mts +28 -0
  23. package/dist/fetchers/map-layers.mjs +160 -0
  24. package/dist/fetchers/request.d.mts +1 -3
  25. package/dist/fetchers/request.mjs +1 -2
  26. package/dist/fetchers/set/items.d.mts +0 -2
  27. package/dist/fetchers/set/items.mjs +1 -2
  28. package/dist/fetchers/set/property-values.d.mts +1 -3
  29. package/dist/fetchers/set/property-values.mjs +1 -2
  30. package/dist/fetchers/tree/items.d.mts +0 -2
  31. package/dist/fetchers/tree/items.mjs +1 -2
  32. package/dist/fetchers/website-metadata.d.mts +1 -3
  33. package/dist/fetchers/website-metadata.mjs +1 -2
  34. package/dist/fetchers/website.d.mts +1 -3
  35. package/dist/fetchers/website.mjs +11 -3
  36. package/dist/getters.d.mts +0 -2
  37. package/dist/getters.mjs +1 -2
  38. package/dist/helpers.d.mts +0 -2
  39. package/dist/helpers.mjs +1 -2
  40. package/dist/index.d.mts +4 -3
  41. package/dist/index.mjs +3 -2
  42. package/dist/languages.d.mts +1 -3
  43. package/dist/languages.mjs +1 -2
  44. package/dist/ocr.d.mts +1 -3
  45. package/dist/ocr.mjs +1 -2
  46. package/dist/parsers/helpers.d.mts +1 -3
  47. package/dist/parsers/helpers.mjs +1 -2
  48. package/dist/parsers/index.d.mts +3 -4
  49. package/dist/parsers/index.mjs +28 -10
  50. package/dist/parsers/languages.d.mts +1 -3
  51. package/dist/parsers/languages.mjs +1 -2
  52. package/dist/parsers/mdx.d.mts +1 -3
  53. package/dist/parsers/mdx.mjs +1 -2
  54. package/dist/parsers/multilingual.d.mts +0 -2
  55. package/dist/parsers/multilingual.mjs +1 -2
  56. package/dist/parsers/property-token.d.mts +0 -2
  57. package/dist/parsers/property-token.mjs +1 -2
  58. package/dist/parsers/string.d.mts +1 -3
  59. package/dist/parsers/string.mjs +1 -2
  60. package/dist/parsers/website/bounds.d.mts +1 -3
  61. package/dist/parsers/website/bounds.mjs +1 -2
  62. package/dist/parsers/website/components.d.mts +0 -2
  63. package/dist/parsers/website/components.mjs +5 -5
  64. package/dist/parsers/website/index.d.mts +1 -3
  65. package/dist/parsers/website/index.mjs +6 -4
  66. package/dist/parsers/website/links.d.mts +1 -3
  67. package/dist/parsers/website/links.mjs +1 -2
  68. package/dist/parsers/website/messages.d.mts +1 -3
  69. package/dist/parsers/website/messages.mjs +1 -2
  70. package/dist/parsers/website/options.d.mts +1 -3
  71. package/dist/parsers/website/options.mjs +1 -2
  72. package/dist/parsers/website/properties.d.mts +1 -3
  73. package/dist/parsers/website/properties.mjs +1 -2
  74. package/dist/parsers/website/reader.d.mts +0 -2
  75. package/dist/parsers/website/reader.mjs +1 -2
  76. package/dist/parsers/website/slug.d.mts +1 -3
  77. package/dist/parsers/website/slug.mjs +1 -2
  78. package/dist/parsers/website/styles.d.mts +2 -4
  79. package/dist/parsers/website/styles.mjs +2 -2
  80. package/dist/parsers/website/walk.d.mts +1 -3
  81. package/dist/parsers/website/walk.mjs +1 -2
  82. package/dist/query.d.mts +0 -2
  83. package/dist/query.mjs +1 -2
  84. package/dist/reflection.d.mts +1 -3
  85. package/dist/reflection.mjs +1 -2
  86. package/dist/schemas.d.mts +14 -7
  87. package/dist/schemas.mjs +9 -8
  88. package/dist/types/index.d.mts +41 -3
  89. package/dist/types/utilities.d.mts +1 -3
  90. package/dist/types/website.d.mts +5 -6
  91. package/dist/xml/dates.d.mts +1 -3
  92. package/dist/xml/dates.mjs +1 -2
  93. package/dist/xml/metadata.d.mts +1 -3
  94. package/dist/xml/metadata.mjs +1 -2
  95. package/dist/xml/schemas.d.mts +351 -13
  96. package/dist/xml/schemas.mjs +53 -19
  97. package/dist/xml/types.d.mts +47 -6
  98. package/dist/xquery.d.mts +1 -3
  99. package/dist/xquery.mjs +1 -2
  100. package/package.json +9 -8
  101. package/dist/fetchers/set/item-locations.d.mts +0 -35
  102. package/dist/fetchers/set/item-locations.mjs +0 -83
package/README.md CHANGED
@@ -66,10 +66,7 @@ present and `error` is `null`; on failure, the parsed value is `null` and
66
66
  style, collection, and item-page configuration.
67
67
  - `fetchSetItems(params, containedItemCategories, options)` fetches paginated
68
68
  Set search results with typed query and sort support.
69
- - `fetchSetItemLocations(params, options)` fetches the identification,
70
- coordinates and chosen property values of every Set item matching a query,
71
- without paging, for drawing all results on a map while a list pages through
72
- them.
69
+ - `fetchItemLocations(params, options)` fetches the identification, coordinates, and chosen property values of every Set or Tree item matching a query without paging. You can pass `setScopeUuids`, `treeScopeUuids`, or both. Each item lists the scope Sets and Trees it belongs to; this allows a map to draw one layer per Set or Tree while a list pages through the same query.
73
70
  - `fetchTreeItems(params, containedItemCategories, options)` is the same for a
74
71
  Tree, and is how to read a Tree too large to fetch whole. Items nested under
75
72
  headings come back flat, in document order.
@@ -1,5 +1,4 @@
1
1
  import { ContextItemCategory, HeadingItemCategory, ItemCategory, ItemCategoryWithEmbeddedItems, ItemContainerCategory, ItemLinkCategory, TreeItemCategory } from "./types/index.mjs";
2
- //#region src/categories.d.ts
3
2
  /**
4
3
  * Every category an item hierarchy entry can carry, including the
5
4
  * pseudo-category OCHRE uses to group entries
@@ -245,5 +244,4 @@ export declare function isHeadingItemCategory(category: TreeItemCategory): categ
245
244
  * @returns The canonical category, or null when the name is not one
246
245
  * @internal
247
246
  */
248
- export declare function normalizeItemCategory(category: string | undefined): ItemCategory | null;
249
- //#endregion
247
+ export declare function normalizeItemCategory(category: string | undefined): ItemCategory | null;
@@ -1,4 +1,4 @@
1
- //#region src/categories.ts
1
+ // src/categories.ts
2
2
  /**
3
3
  * The one table describing the OCHRE item categories
4
4
  * @internal
@@ -255,5 +255,4 @@ function normalizeItemCategory(category) {
255
255
  const normalizedCategory = ITEM_CATEGORY_BY_ALIAS.get(category);
256
256
  return normalizedCategory != null && ITEM_CATEGORY_FACTS[normalizedCategory].isSetItem ? normalizedCategory : null;
257
257
  }
258
- //#endregion
259
258
  export { CONTEXT_CATEGORY_ALIASES, HEADING_ITEM_CATEGORIES, ITEM_CATEGORIES_WITH_EMBEDDED_ITEMS, ITEM_CATEGORY_ALIASES, ITEM_CATEGORY_BY_ALIAS, ITEM_CATEGORY_FACTS, ITEM_CONTAINER_CATEGORIES, OCHRE_COLLECTION_CATEGORIES, SET_ITEM_CATEGORIES, TREE_ITEM_CATEGORIES, isHeadingItemCategory, isItemCategoryWithEmbeddedItems, isItemContainerCategory, normalizeItemCategory };
@@ -1,5 +1,4 @@
1
1
  import { X2jOptions } from "fast-xml-parser";
2
- //#region src/constants.d.ts
3
2
  export declare const XML_ARRAY_TAGS: ReadonlyArray<string>;
4
3
  export declare const XML_PARSER_OPTIONS: X2jOptions;
5
4
  export declare const DEFAULT_LANGUAGES: readonly ["eng"];
@@ -25,5 +24,4 @@ export declare const TEXT_ANNOTATION_ITEM_PAGE_VARIANT_UUID = "bf4476ab-6bc8-40d
25
24
  export declare const TEXT_ANNOTATION_ENTRY_PAGE_VARIANT_UUID = "9d52db95-a9cf-45f7-a0bf-fc9ba9f0aae0";
26
25
  export declare const TEXT_ANNOTATION_TEXT_STYLING_UUID = "3e6f86ab-df81-45ae-8257-e2867357df56";
27
26
  export declare const TEXT_ANNOTATION_TEXT_STYLING_VARIANT_UUID = "e1647bef-d801-4100-bdde-d081c422f763";
28
- export declare const TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID = "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e";
29
- //#endregion
27
+ export declare const TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID = "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e";
@@ -1,4 +1,5 @@
1
- //#region src/constants.ts
1
+ import { COMMON_HTML, CURRENCY, ENTITY_ACTION, EntityDecoder } from "@nodable/entities";
2
+ // src/constants.ts
2
3
  const XML_ARRAY_TAGS = [
3
4
  "string",
4
5
  "content",
@@ -40,7 +41,10 @@ const XML_ARRAY_TAGS = [
40
41
  "scope",
41
42
  "level",
42
43
  "style",
44
+ "styleLabel",
43
45
  "itemLocation",
46
+ "mapSource",
47
+ "mapLayer",
44
48
  "flattenContexts",
45
49
  "suppressContexts",
46
50
  "filterContexts",
@@ -48,7 +52,8 @@ const XML_ARRAY_TAGS = [
48
52
  "detailContexts",
49
53
  "downloadContexts",
50
54
  "labelContexts",
51
- "prominentContexts"
55
+ "prominentContexts",
56
+ "option"
52
57
  ];
53
58
  const XML_PARSER_OPTIONS = {
54
59
  alwaysCreateTextNode: true,
@@ -62,7 +67,13 @@ const XML_PARSER_OPTIONS = {
62
67
  attributeNamePrefix: "",
63
68
  textNodeName: "payload",
64
69
  stopNodes: ["*.referenceFormatDiv", "*.citationFormatSpan"],
65
- htmlEntities: true,
70
+ entityDecoder: new EntityDecoder({
71
+ namedEntities: {
72
+ ...COMMON_HTML,
73
+ ...CURRENCY
74
+ },
75
+ onInputEntity: () => ENTITY_ACTION.BLOCK
76
+ }),
66
77
  isArray(tagName, _, __, isAttribute) {
67
78
  if (isAttribute) return false;
68
79
  return XML_ARRAY_TAGS.includes(tagName);
@@ -99,5 +110,4 @@ const TEXT_ANNOTATION_ENTRY_PAGE_VARIANT_UUID = "9d52db95-a9cf-45f7-a0bf-fc9ba9f
99
110
  const TEXT_ANNOTATION_TEXT_STYLING_UUID = "3e6f86ab-df81-45ae-8257-e2867357df56";
100
111
  const TEXT_ANNOTATION_TEXT_STYLING_VARIANT_UUID = "e1647bef-d801-4100-bdde-d081c422f763";
101
112
  const TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID = "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e";
102
- //#endregion
103
113
  export { BELONGS_TO_COLLECTION_UUID, DEFAULT_LANGUAGES, DEFAULT_PAGE_SIZE, OCHRE_ENDPOINT, PERMANENT_IDENTIFICATION_URL_PREFIX, PRESENTATION_ITEM_UUID, TEXT_ANNOTATION_ENTRY_PAGE_VARIANT_UUID, TEXT_ANNOTATION_HOVER_CARD_UUID, TEXT_ANNOTATION_ITEM_PAGE_VARIANT_UUID, TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID, TEXT_ANNOTATION_TEXT_STYLING_UUID, TEXT_ANNOTATION_TEXT_STYLING_VARIANT_UUID, TEXT_ANNOTATION_UUID, XML_ARRAY_TAGS, XML_PARSER_OPTIONS, getOchreItemUrl };
package/dist/errors.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import * as v from "valibot";
2
- //#region src/errors.d.ts
3
2
  type SchemaValidationIssue = v.BaseIssue<unknown>;
4
3
  /**
5
4
  * Render an error as a short message and a fully detailed report
@@ -20,5 +19,4 @@ export declare function getErrorOutput(error: unknown, fallbackMessage: string):
20
19
  * @internal
21
20
  */
22
21
  export declare function createSchemaValidationError(message: string, issues: ReadonlyArray<SchemaValidationIssue>): Error;
23
- //#endregion
24
22
  export {};
package/dist/errors.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isObject, readEntries } from "./reflection.mjs";
2
2
  import * as v from "valibot";
3
- //#region src/errors.ts
3
+ // src/errors.ts
4
4
  /**
5
5
  * The shape a valibot issue has to have for this module to render it
6
6
  *
@@ -160,5 +160,4 @@ function createSchemaValidationError(message, issues) {
160
160
  * @returns True if the string is a valid pseudo-UUID, false otherwise
161
161
  * @internal
162
162
  */
163
- //#endregion
164
163
  export { createSchemaValidationError, getErrorOutput };
@@ -1,7 +1,6 @@
1
1
  import { ItemCategory, Query, SetItem, SetItemsSort } from "../types/index.mjs";
2
2
  import { XMLSetItems } from "../xml/types.mjs";
3
3
  import { FetchRuntimeOptions } from "../parsers/helpers.mjs";
4
- //#region src/fetchers/container-items.d.ts
5
4
  /**
6
5
  * Whether a container payload carries any item of a category
7
6
  * @param items - The parsed `<items>` payload
@@ -48,5 +47,4 @@ export declare function fetchContainerItems(parameters: {
48
47
  page: number;
49
48
  pageSize: number;
50
49
  items: Array<SetItem<ItemCategory, ReadonlyArray<string>>>;
51
- }>;
52
- //#endregion
50
+ }>;
@@ -4,7 +4,7 @@ import { parseSetItems } from "../parsers/index.mjs";
4
4
  import { XMLSetItemsData } from "../xml/schemas.mjs";
5
5
  import { getContentLanguage, stringLiteral } from "../xquery.mjs";
6
6
  import { compileContainerItemsQuery } from "../query.mjs";
7
- //#region src/fetchers/container-items.ts
7
+ // src/fetchers/container-items.ts
8
8
  function hasArray(items) {
9
9
  return items != null && items.length > 0;
10
10
  }
@@ -180,5 +180,4 @@ async function fetchContainerItems(parameters) {
180
180
  items: itemsByUuid.values().toArray()
181
181
  };
182
182
  }
183
- //#endregion
184
183
  export { fetchContainerItems, hasItemsCategory };
@@ -1,6 +1,5 @@
1
1
  import { Gallery } from "../types/index.mjs";
2
2
  import { FetchBaseOptions, FetchLanguages } from "../parsers/helpers.mjs";
3
- //#region src/fetchers/gallery.d.ts
4
3
  /**
5
4
  * Fetches and parses a gallery from the OCHRE API
6
5
  *
@@ -27,5 +26,4 @@ export declare function fetchGallery<const TLanguages extends ReadonlyArray<stri
27
26
  gallery: null;
28
27
  error: string;
29
28
  detailedError: string;
30
- }>;
31
- //#endregion
29
+ }>;
@@ -6,7 +6,7 @@ import { parseGallery } from "../parsers/index.mjs";
6
6
  import { XMLGalleryData } from "../xml/schemas.mjs";
7
7
  import { OCHRE_RESPONSE_PADDING, compileOchreQuery, getContentLanguage, stringLiteral } from "../xquery.mjs";
8
8
  import * as v from "valibot";
9
- //#region src/fetchers/gallery.ts
9
+ // src/fetchers/gallery.ts
10
10
  function buildXQuery(parameters) {
11
11
  const { uuid, filter, page, perPage, contentLanguage } = parameters;
12
12
  const start = (page - 1) * perPage + 1;
@@ -61,5 +61,4 @@ async function fetchGallery(parameters, options) {
61
61
  };
62
62
  }
63
63
  }
64
- //#endregion
65
64
  export { fetchGallery };
@@ -1,6 +1,5 @@
1
1
  import { ContainedItemCategoryFromOption, ContainedItemCategoryOption, Item, ItemCategory, ItemCategoryFromOption, ItemCategoryOption, ItemContainerCategory, SetItemCategory, TreeItemCategory } from "../types/index.mjs";
2
2
  import { FetchBaseOptions, FetchLanguages } from "../parsers/helpers.mjs";
3
- //#region src/fetchers/item-children.d.ts
4
3
  type FetchItemChildrenResult<TItems> = Promise<{
5
4
  items: TItems;
6
5
  error: null;
@@ -32,5 +31,4 @@ export declare function fetchItemChildren<const TCategory extends ItemCategoryOp
32
31
  category: TCategory;
33
32
  containedItemCategory?: TContainedItemCategory;
34
33
  }): FetchItemChildrenResult<Array<Item<TChildCategory, ContainedItemCategoryFromOption<TChildCategory, TContainedItemCategory>, FetchLanguages<TLanguages>, ItemChildrenPayloadKind<ItemCategoryFromOption<TCategory>>>>>;
35
- //#endregion
36
34
  export {};
@@ -7,7 +7,7 @@ import { parseLinkedItems } from "../parsers/index.mjs";
7
7
  import { XMLItemLinksData } from "../xml/schemas.mjs";
8
8
  import { OCHRE_RESPONSE_PADDING, compileOchreQuery, getContentLanguage, stringLiteral } from "../xquery.mjs";
9
9
  import * as v from "valibot";
10
- //#region src/fetchers/item-children.ts
10
+ // src/fetchers/item-children.ts
11
11
  function buildXQuery(uuid, category, contentLanguage) {
12
12
  const categories = category == null ? OCHRE_COLLECTION_CATEGORIES : typeof category === "string" ? [category] : category;
13
13
  const collectionQueries = Array.from(categories, (possibleCategory) => `cts:search(fn:collection("ochre/${possibleCategory}")/ochre, $uuid-query)`);
@@ -81,5 +81,4 @@ async function fetchItemChildren(uuid, options) {
81
81
  };
82
82
  }
83
83
  }
84
- //#endregion
85
84
  export { fetchItemChildren };
@@ -1,6 +1,5 @@
1
1
  import { ContainedItemCategoryFromOption, ContainedItemCategoryOption, Item, ItemCategory, ItemContainerCategory } from "../types/index.mjs";
2
2
  import { FetchBaseOptions, FetchLanguages } from "../parsers/helpers.mjs";
3
- //#region src/fetchers/item-links.d.ts
4
3
  /**
5
4
  * Fetches linked OCHRE items by source-item UUID.
6
5
  *
@@ -21,5 +20,4 @@ export declare function fetchItemLinks<const TContainedItemCategory extends Cont
21
20
  items: null;
22
21
  error: string;
23
22
  detailedError: string;
24
- }>;
25
- //#endregion
23
+ }>;
@@ -7,7 +7,7 @@ import { parseLinkedItems } from "../parsers/index.mjs";
7
7
  import { XMLItemLinksData } from "../xml/schemas.mjs";
8
8
  import { OCHRE_RESPONSE_PADDING, compileOchreQuery, getContentLanguage, stringLiteral } from "../xquery.mjs";
9
9
  import * as v from "valibot";
10
- //#region src/fetchers/item-links.ts
10
+ // src/fetchers/item-links.ts
11
11
  /**
12
12
  * Build an XQuery string to fetch linked items from the OCHRE API.
13
13
  *
@@ -70,5 +70,4 @@ async function fetchItemLinks(uuid, options) {
70
70
  };
71
71
  }
72
72
  }
73
- //#endregion
74
73
  export { fetchItemLinks };
@@ -0,0 +1,39 @@
1
+ import { ItemLocation, Query } from "../types/index.mjs";
2
+ import { FetchBaseOptions, FetchLanguages } from "../parsers/helpers.mjs";
3
+ /**
4
+ * Fetches the location of every Set or Tree item that matches a query, without paging
5
+ *
6
+ * Each item carries only its identification, the scope Sets and Trees it
7
+ * belongs to, its publication date, its coordinates, optionally its map
8
+ * polygons, and the values of the requested property variables (inherited
9
+ * values included), which is what a map needs to draw, color and group every
10
+ * match into layers while a list pages through the same query with
11
+ * {@link fetchSetItems} or {@link fetchTreeItems}.
12
+ *
13
+ * @param parameters - The parameters for the fetch
14
+ * @param parameters.setScopeUuids - The Set scope UUIDs to search within
15
+ * @param parameters.treeScopeUuids - The Tree scope UUIDs to search within
16
+ * @param parameters.queries - Recursive query tree used to filter matching items
17
+ * @param parameters.propertyVariableUuids - The property variables whose values each item should carry
18
+ * @param parameters.isMapDataIncluded - Whether each item should carry its map polygons
19
+ * @param options - Options for the fetch
20
+ * @param options.fetch - The fetch function to use
21
+ * @returns The item locations, or an error if the fetch/parse fails
22
+ */
23
+ export declare function fetchItemLocations<const TLanguages extends ReadonlyArray<string> | undefined = undefined>(parameters: {
24
+ setScopeUuids?: Array<string>;
25
+ treeScopeUuids?: Array<string>;
26
+ queries?: Query | null;
27
+ propertyVariableUuids?: Array<string>;
28
+ isMapDataIncluded?: boolean;
29
+ }, options?: FetchBaseOptions<TLanguages>): Promise<{
30
+ totalCount: number;
31
+ items: Array<ItemLocation<FetchLanguages<TLanguages>>>;
32
+ error: null;
33
+ detailedError: null;
34
+ } | {
35
+ totalCount: null;
36
+ items: null;
37
+ error: string;
38
+ detailedError: string;
39
+ }>;
@@ -0,0 +1,98 @@
1
+ import { normalizeItemCategory } from "../categories.mjs";
2
+ import { getErrorOutput } from "../errors.mjs";
3
+ import { requestOchre } from "./request.mjs";
4
+ import { itemLocationsParametersSchema } from "../schemas.mjs";
5
+ import { parseRequiredContentLike } from "../parsers/helpers.mjs";
6
+ import { parseRequestedLanguages, resolveContentLanguages } from "../parsers/languages.mjs";
7
+ import { parseCoordinates, parseIdentification, parseSpatialUnitMapData } from "../parsers/index.mjs";
8
+ import { XMLItemLocationsData } from "../xml/schemas.mjs";
9
+ import { getContentLanguage, stringLiteral } from "../xquery.mjs";
10
+ import { compileContainerItemsQuery } from "../query.mjs";
11
+ import * as v from "valibot";
12
+ // src/fetchers/item-locations.ts
13
+ async function fetchItemLocations(parameters, options) {
14
+ try {
15
+ const { setScopeUuids, treeScopeUuids, belongsToCollectionScopeUuids, queries, propertyVariableUuids, isMapDataIncluded } = v.parse(itemLocationsParametersSchema, parameters);
16
+ const scopes = [{
17
+ container: "set",
18
+ scopeUuids: setScopeUuids
19
+ }, {
20
+ container: "tree",
21
+ scopeUuids: treeScopeUuids
22
+ }].filter(({ scopeUuids }) => scopeUuids.length > 0);
23
+ const outputs = await Promise.all(scopes.map(async ({ container, scopeUuids }) => requestOchre({
24
+ xquery: compileContainerItemsQuery({
25
+ container,
26
+ scopeUuids,
27
+ belongsToCollectionScopeUuids,
28
+ queries,
29
+ contentLanguage: getContentLanguage(options),
30
+ body: ({ items }) => ` let $propertyVariableUuids := (${Array.from(propertyVariableUuids, (uuid) => stringLiteral(uuid)).join(", ")})
31
+
32
+ return <items totalCount="{count(${items})}">{
33
+ for $item in ${items}
34
+ return <itemLocation uuid="{$item/@uuid}" category="{local-name($item)}" scopeUuid="{$item/ancestor::${container}[1]/@uuid}">{
35
+ ${container === "tree" ? "($item/@publicationDateTime, $item/ancestor::tree[1]/@publicationDateTime)[1]" : "$item/@publicationDateTime"},
36
+ $item/identification,
37
+ $item/coordinates,${isMapDataIncluded ? "\n $item/mapData," : ""}
38
+ for $value in $item//properties//property[label/@uuid = $propertyVariableUuids]/value[@uuid]
39
+ return <value variable="{$value/../label/@uuid}" uuid="{$value/@uuid}">{$value/content}</value>
40
+ }</itemLocation>
41
+ }</items>`
42
+ }),
43
+ schema: XMLItemLocationsData,
44
+ label: `OCHRE ${container === "set" ? "Set" : "Tree"} item locations`,
45
+ options
46
+ })));
47
+ const languages = resolveContentLanguages(outputs.map((output) => output.result.ochre.items), parseRequestedLanguages(options?.languages));
48
+ let totalCount = 0;
49
+ for (const output of outputs) totalCount += output.result.ochre.items.totalCount;
50
+ const itemsByUuid = /* @__PURE__ */ new Map();
51
+ const itemLocations = outputs.flatMap((output) => output.result.ochre.items.itemLocation ?? []);
52
+ for (const itemLocation of itemLocations) {
53
+ const category = normalizeItemCategory(itemLocation.category);
54
+ const existing = itemsByUuid.get(itemLocation.uuid);
55
+ if (existing != null) {
56
+ if (!existing.scopeUuids.includes(itemLocation.scopeUuid)) existing.scopeUuids.push(itemLocation.scopeUuid);
57
+ continue;
58
+ }
59
+ if (category == null) continue;
60
+ const propertyValues = [];
61
+ const seenPropertyValues = /* @__PURE__ */ new Set();
62
+ const values = itemLocation.value ?? [];
63
+ for (const value of values) {
64
+ const key = `${value.variable}:${value.uuid}`;
65
+ if (seenPropertyValues.has(key)) continue;
66
+ seenPropertyValues.add(key);
67
+ propertyValues.push({
68
+ variableUuid: value.variable,
69
+ valueUuid: value.uuid,
70
+ label: parseRequiredContentLike(value, { languages })
71
+ });
72
+ }
73
+ itemsByUuid.set(itemLocation.uuid, {
74
+ uuid: itemLocation.uuid,
75
+ category,
76
+ scopeUuids: [itemLocation.scopeUuid],
77
+ publicationDateTime: itemLocation.publicationDateTime ?? null,
78
+ identification: parseIdentification(itemLocation.identification, { languages }),
79
+ coordinates: parseCoordinates(itemLocation.coordinates, { languages }),
80
+ mapData: parseSpatialUnitMapData(itemLocation.mapData),
81
+ propertyValues
82
+ });
83
+ }
84
+ return {
85
+ totalCount,
86
+ items: itemsByUuid.values().toArray(),
87
+ error: null,
88
+ detailedError: null
89
+ };
90
+ } catch (error) {
91
+ return {
92
+ totalCount: null,
93
+ items: null,
94
+ ...getErrorOutput(error, "Failed to fetch item locations")
95
+ };
96
+ }
97
+ }
98
+ export { fetchItemLocations };
@@ -1,6 +1,5 @@
1
1
  import { OcrString } from "../types/index.mjs";
2
2
  import { OchreRequestOptions } from "./request.mjs";
3
- //#region src/fetchers/item-ocr-data.d.ts
4
3
  /**
5
4
  * Fetches and parses the OCR strings of an OCHRE item that match a search value
6
5
  *
@@ -35,5 +34,4 @@ export declare function fetchItemOcrData(uuid: string, value: string, options?:
35
34
  ocrStrings: null;
36
35
  error: string;
37
36
  detailedError: string;
38
- }>;
39
- //#endregion
37
+ }>;
@@ -4,7 +4,7 @@ import { itemOcrDataParametersSchema } from "../schemas.mjs";
4
4
  import { OCHRE_RESPONSE_PADDING, stringLiteral } from "../xquery.mjs";
5
5
  import { buildOcrWordPath } from "../ocr.mjs";
6
6
  import * as v from "valibot";
7
- //#region src/fetchers/item-ocr-data.ts
7
+ // src/fetchers/item-ocr-data.ts
8
8
  const OCR_STRING_VERTEX_REGEX = /\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)/g;
9
9
  /**
10
10
  * Schema for a single matched OCR string in the OCHRE API response
@@ -164,5 +164,4 @@ async function fetchItemOcrData(uuid, value, options) {
164
164
  };
165
165
  }
166
166
  }
167
- //#endregion
168
167
  export { fetchItemOcrData };
@@ -1,6 +1,5 @@
1
1
  import { ContainedItemCategoryFromOption, ContainedItemCategoryOption, Item, ItemCategory, ItemCategoryFromOption, ItemCategoryOption, ItemCategoryWithEmbeddedItems, ItemContainerCategory, ItemWithoutEmbeddedItems } from "../types/index.mjs";
2
2
  import { FetchBaseOptions, FetchLanguages } from "../parsers/helpers.mjs";
3
- //#region src/fetchers/item.d.ts
4
3
  type FetchItemResult<TItem> = Promise<{
5
4
  item: TItem;
6
5
  error: null;
@@ -44,5 +43,4 @@ export declare function fetchItem<const TCategory extends ItemCategoryOption, co
44
43
  containedItemCategory?: TContainedItemCategory;
45
44
  shouldOmitEmbeddedItems: true;
46
45
  }): FetchItemResult<ItemWithoutEmbeddedItems<Extract<ItemCategoryFromOption<TCategory>, ItemCategoryWithEmbeddedItems>, ContainedItemCategoryFromOption<Extract<ItemCategoryFromOption<TCategory>, ItemCategoryWithEmbeddedItems>, TContainedItemCategory>, FetchLanguages<TLanguages>> | Item<Exclude<ItemCategoryFromOption<TCategory>, ItemCategoryWithEmbeddedItems>, never, FetchLanguages<TLanguages>>>;
47
- //#endregion
48
46
  export {};
@@ -8,7 +8,7 @@ import { XMLData } from "../xml/schemas.mjs";
8
8
  import { OCHRE_RESPONSE_PADDING, compileOchreQuery, getContentLanguage, stringLiteral } from "../xquery.mjs";
9
9
  import { parseWebpageView } from "../parsers/website/index.mjs";
10
10
  import * as v from "valibot";
11
- //#region src/fetchers/item.ts
11
+ // src/fetchers/item.ts
12
12
  function isItemWithEmbeddedItems(item) {
13
13
  return isItemCategoryWithEmbeddedItems(item.category);
14
14
  }
@@ -100,5 +100,4 @@ async function fetchItem(uuid, options) {
100
100
  };
101
101
  }
102
102
  }
103
- //#endregion
104
103
  export { fetchItem };
@@ -0,0 +1,28 @@
1
+ import { MapLayer } from "../types/index.mjs";
2
+ import { FetchBaseOptions, FetchLanguages } from "../parsers/helpers.mjs";
3
+ /**
4
+ * Fetches the layers a map draws from the Sets and Trees it links to
5
+ *
6
+ * A linked Set holding only Sets, Trees and Resources is a layer list: each
7
+ * linked Set or Tree becomes an OCHRE layer and each webpage Resource whose
8
+ * href points at a geospatial web service becomes a service layer. Any other
9
+ * linked Set or Tree is drawn as one OCHRE layer itself. The variant is
10
+ * `"arcgis"` when any service layer is present, else `"maplibre-gl"`.
11
+ *
12
+ * @param uuids - The UUIDs of the Sets and Trees the map links to, in order
13
+ * @param options - Options for the fetch
14
+ * @param options.languages - Language codes to parse
15
+ * @param options.fetch - The fetch function to use
16
+ * @returns The map variant and layers, or an error if the fetch/parse fails
17
+ */
18
+ export declare function fetchMapLayers<const TLanguages extends ReadonlyArray<string> | undefined = undefined>(uuids: Array<string>, options?: FetchBaseOptions<TLanguages>): Promise<{
19
+ variant: "maplibre-gl" | "arcgis";
20
+ layers: Array<MapLayer<FetchLanguages<TLanguages>>>;
21
+ error: null;
22
+ detailedError: null;
23
+ } | {
24
+ variant: null;
25
+ layers: null;
26
+ error: string;
27
+ detailedError: string;
28
+ }>;
@@ -0,0 +1,160 @@
1
+ import { getErrorOutput } from "../errors.mjs";
2
+ import { requestOchre } from "./request.mjs";
3
+ import { uuidSchema } from "../schemas.mjs";
4
+ import { parseRequestedLanguages, resolveContentLanguages } from "../parsers/languages.mjs";
5
+ import { parseIdentification } from "../parsers/index.mjs";
6
+ import { XMLMapSourcesData } from "../xml/schemas.mjs";
7
+ import { OCHRE_RESPONSE_PADDING, compileOchreQuery, getContentLanguage, stringLiteral } from "../xquery.mjs";
8
+ import * as v from "valibot";
9
+ // src/fetchers/map-layers.ts
10
+ const REGEX_TILE_TEMPLATE_LEVEL = /\{(?:level|z)\}/i;
11
+ const REGEX_TILE_TEMPLATE_ROW = /\{(?:row|y)\}/i;
12
+ const REGEX_TILE_TEMPLATE_COLUMN = /\{(?:col|x)\}/i;
13
+ const REGEX_UNSUPPORTED_HOST = /(?:^|\.)google\.[a-z.]+$/i;
14
+ const REGEX_PORTAL_ITEM_PATH = /\/home\/(?:item|webmap\/viewer)\.html$/i;
15
+ const REGEX_PORTAL_ITEM_ID = /^[\da-f]{32}$/i;
16
+ const REGEX_WMTS_CAPABILITIES = /\/WMTSCapabilities\.xml$/i;
17
+ const REGEX_WMS_PATH = /\/wms(?:\/|$)/i;
18
+ const REGEX_FEATURE_SERVER = /\/FeatureServer(?:\/\d+)?\/?$/i;
19
+ const REGEX_MAP_SERVER = /\/MapServer(?:\/\d+)?\/?$/i;
20
+ const REGEX_IMAGE_SERVER = /\/ImageServer\/?$/i;
21
+ const REGEX_TRAILING_SLASH = /\/$/;
22
+ const REGEX_ARCGIS_SOAP_SERVICES = /\/arcgis\/services\//i;
23
+ /**
24
+ * Classify the href of a webpage Resource as a geospatial web service
25
+ * @param href - The Resource href
26
+ * @returns The service layer, or null when the href names no supported service
27
+ */
28
+ function parseServiceLayer(href) {
29
+ const trimmedHref = href.trim();
30
+ const url = URL.parse(trimmedHref);
31
+ if (url == null || REGEX_UNSUPPORTED_HOST.test(url.hostname)) return null;
32
+ if (REGEX_TILE_TEMPLATE_LEVEL.test(trimmedHref) && REGEX_TILE_TEMPLATE_ROW.test(trimmedHref) && REGEX_TILE_TEMPLATE_COLUMN.test(trimmedHref)) return {
33
+ type: "web-tile",
34
+ url: trimmedHref
35
+ };
36
+ let service = null;
37
+ for (const [key, value] of url.searchParams) if (key.toLowerCase() === "service") service = value.toLowerCase();
38
+ const itemId = url.searchParams.get("webmap") ?? (REGEX_PORTAL_ITEM_PATH.test(url.pathname) ? url.searchParams.get("id") : null);
39
+ if (itemId != null && REGEX_PORTAL_ITEM_ID.test(itemId)) return {
40
+ type: "arcgis-item",
41
+ itemId,
42
+ portalUrl: url.origin
43
+ };
44
+ const baseUrl = `${url.origin}${url.pathname.replace(REGEX_TRAILING_SLASH, "")}`;
45
+ const restUrl = baseUrl.replace(REGEX_ARCGIS_SOAP_SERVICES, "/arcgis/rest/services/");
46
+ if (service === "wmts") return {
47
+ type: "wmts",
48
+ url: baseUrl
49
+ };
50
+ if (REGEX_WMTS_CAPABILITIES.test(url.pathname)) return {
51
+ type: "wmts",
52
+ url: trimmedHref
53
+ };
54
+ if (service === "wms" || REGEX_WMS_PATH.test(url.pathname)) return {
55
+ type: "wms",
56
+ url: baseUrl
57
+ };
58
+ if (REGEX_FEATURE_SERVER.test(url.pathname)) return {
59
+ type: "arcgis-feature",
60
+ url: restUrl
61
+ };
62
+ if (REGEX_MAP_SERVER.test(url.pathname)) return {
63
+ type: "arcgis-map",
64
+ url: restUrl
65
+ };
66
+ if (REGEX_IMAGE_SERVER.test(url.pathname)) return {
67
+ type: "arcgis-image",
68
+ url: restUrl
69
+ };
70
+ return null;
71
+ }
72
+ /**
73
+ * Build the layer a Set, Tree or Resource of a map's layer list stands for
74
+ * @param member - The linked Set, Tree or Resource
75
+ * @param languages - The languages to parse
76
+ * @returns The layer, or null when a Resource names no supported service
77
+ */
78
+ function parseMapLayer(member, languages) {
79
+ const { label } = parseIdentification(member.identification, { languages });
80
+ if (member.category === "set" || member.category === "tree") return {
81
+ type: member.category === "set" ? "ochre-set" : "ochre-tree",
82
+ uuid: member.uuid,
83
+ label,
84
+ wkid: member.WKID ?? null
85
+ };
86
+ const service = "href" in member && member.href != null ? parseServiceLayer(member.href) : null;
87
+ return service == null ? null : {
88
+ ...service,
89
+ uuid: member.uuid,
90
+ label
91
+ };
92
+ }
93
+ async function fetchMapLayers(uuids, options) {
94
+ try {
95
+ const parsedUuids = v.parse(v.pipe(v.array(uuidSchema), v.minLength(1, "At least one map link UUID is required")), uuids);
96
+ const output = await requestOchre({
97
+ xquery: compileOchreQuery({
98
+ contentLanguage: getContentLanguage(options),
99
+ body: () => `<ochre>${OCHRE_RESPONSE_PADDING}<mapSources>{
100
+ for $uuid in (${parsedUuids.map((uuid) => stringLiteral(uuid)).join(", ")})
101
+ let $set := fn:collection("ochre/set")/ochre[@uuid = $uuid]/set
102
+ let $source := if (exists($set)) then $set else fn:collection("ochre/tree")/ochre[@uuid = $uuid]/tree
103
+ let $members := $set/items/*
104
+ let $layers := $members[self::set or self::tree or self::resource]
105
+ where exists($source)
106
+ return <mapSource uuid="{$uuid}" category="{local-name($source[1])}">{
107
+ $source[1]/@WKID,
108
+ $source[1]/identification,
109
+ if (exists($members) and count($layers) = count($members))
110
+ then
111
+ for $layer in $layers
112
+ let $layerUuid := $layer/@uuid/string()
113
+ return <mapLayer uuid="{$layerUuid}" category="{local-name($layer)}">{
114
+ $layer/@type,
115
+ $layer/@href,
116
+ if (local-name($layer) = "set")
117
+ then fn:collection("ochre/set")/ochre[@uuid = $layerUuid]/set[1]/@WKID
118
+ else (),
119
+ $layer/identification
120
+ }</mapLayer>
121
+ else ()
122
+ }</mapSource>
123
+ }</mapSources></ochre>`
124
+ }),
125
+ schema: XMLMapSourcesData,
126
+ label: "OCHRE map layers",
127
+ options
128
+ });
129
+ const languages = resolveContentLanguages(output.result.ochre.mapSources, parseRequestedLanguages(options?.languages));
130
+ const layers = [];
131
+ const layerUuids = /* @__PURE__ */ new Set();
132
+ const sources = output.result.ochre.mapSources.mapSource ?? [];
133
+ for (const source of sources) {
134
+ const sourceLayers = [];
135
+ const members = source.mapLayer ?? [source];
136
+ for (const member of members) {
137
+ const layer = parseMapLayer(member, languages);
138
+ if (layer != null) sourceLayers.push(layer);
139
+ }
140
+ const mapServerUrls = sourceLayers.flatMap((layer) => layer.type === "arcgis-map" ? [`${layer.url}/`] : []);
141
+ for (const layer of sourceLayers) if (!(layer.type === "wmts" && mapServerUrls.some((url) => layer.url.startsWith(url))) && !layerUuids.has(layer.uuid)) {
142
+ layerUuids.add(layer.uuid);
143
+ layers.push(layer);
144
+ }
145
+ }
146
+ return {
147
+ variant: layers.some((layer) => layer.type !== "ochre-set" && layer.type !== "ochre-tree") ? "arcgis" : "maplibre-gl",
148
+ layers,
149
+ error: null,
150
+ detailedError: null
151
+ };
152
+ } catch (error) {
153
+ return {
154
+ variant: null,
155
+ layers: null,
156
+ ...getErrorOutput(error, "Failed to fetch map layers")
157
+ };
158
+ }
159
+ }
160
+ export { fetchMapLayers };
@@ -1,6 +1,5 @@
1
1
  import { FetchFunction } from "../parsers/helpers.mjs";
2
2
  import * as v from "valibot";
3
- //#region src/fetchers/request.d.ts
4
3
  export type OchreRequestOptions = {
5
4
  fetch?: FetchFunction;
6
5
  signal?: AbortSignal;
@@ -66,5 +65,4 @@ export declare function isOchreJsonAccepted(parameters: {
66
65
  body: unknown;
67
66
  label: string;
68
67
  options?: OchreRequestOptions;
69
- }): Promise<boolean>;
70
- //#endregion
68
+ }): Promise<boolean>;