@daihum/record-formats 0.1.0 → 0.1.1

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.
@@ -0,0 +1,592 @@
1
+ import { i as hasFormatErrors, n as formatFail, r as formatOk, t as createFormatIssue } from "./result-Cl7IY6PN.js";
2
+ import { a as getXmlText, c as parseXml, n as buildXml, r as findXmlValue, s as normalizeXmlName, t as asXmlArray } from "./xml-DXtayJiw.js";
3
+
4
+ //#region src/ead3/ead3.ts
5
+ const EAD3_FORMAT_ID = "ead3";
6
+ const EAD3_NAMESPACE = "http://ead3.archivists.org/schema/";
7
+ const EAD3_FORMAT_GENERATION = "EAD3";
8
+ const EAD3_SCHEMA_VERSION = "1.1.1";
9
+ const EAD3_SCHEMA_REVISION = "1.1.1";
10
+ const EAD3_TAG_LIBRARY_VERSION = "1.1.2";
11
+ const EAD3_VALIDATION_LEVEL = "projection";
12
+ const EAD3_OFFICIAL_SCHEMA_VALIDATION = false;
13
+ const EAD3_ADAPTER_PROFILE = {
14
+ profileId: "daihum.record-formats.ead3.projection.v0",
15
+ profileVersion: "0.1.0",
16
+ formatId: EAD3_FORMAT_ID,
17
+ formatGeneration: EAD3_FORMAT_GENERATION,
18
+ namespace: EAD3_NAMESPACE,
19
+ schemaVersion: EAD3_SCHEMA_VERSION,
20
+ schemaRevision: EAD3_SCHEMA_REVISION,
21
+ tagLibraryVersion: EAD3_TAG_LIBRARY_VERSION,
22
+ validationLevel: EAD3_VALIDATION_LEVEL,
23
+ officialSchemaValidation: EAD3_OFFICIAL_SCHEMA_VALIDATION,
24
+ conformanceNotes: [
25
+ "This adapter is a DAIHUM finding-aid projection for common EAD3 elements.",
26
+ "Validation checks required projection fields and structured parser/serializer invariants.",
27
+ "It does not run official EAD3 RNG, XSD, DTD, or Schematron schema validation.",
28
+ "Unknown XML subtrees can be preserved through extension fields when preserveUnknown is enabled.",
29
+ "DAIHUM href/source policy metadata is carried as projection attributes and is not official EAD3 schema validation."
30
+ ],
31
+ sourceReferences: [{
32
+ label: "Library of Congress EAD3 schema page",
33
+ url: "https://www.loc.gov/ead/ead3schema.html"
34
+ }, {
35
+ label: "Library of Congress EAD3 tag library",
36
+ url: "https://www.loc.gov/ead/EAD3taglib/"
37
+ }]
38
+ };
39
+ const EAD3_ARRAY_TAGS = [
40
+ "unitdate",
41
+ "dao",
42
+ "c",
43
+ "odd"
44
+ ];
45
+ const ACCESS_POINT_XML_TAGS = {
46
+ person: "persname",
47
+ family: "famname",
48
+ organization: "corpname",
49
+ place: "geogname",
50
+ subject: "subject",
51
+ documentaryForm: "genreform",
52
+ occupation: "occupation",
53
+ function: "function"
54
+ };
55
+ function isRecord(value) {
56
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
57
+ }
58
+ function readString(value) {
59
+ if (typeof value !== "string") return void 0;
60
+ const trimmed = value.trim();
61
+ return trimmed.length > 0 ? trimmed : void 0;
62
+ }
63
+ function readElementText(parent, localName) {
64
+ return getXmlText(findXmlValue(parent, localName));
65
+ }
66
+ function readParagraphElementText(parent, localName) {
67
+ return readElementText(readRecord(parent, localName), "p");
68
+ }
69
+ function readRecord(parent, localName) {
70
+ const value = findXmlValue(parent, localName);
71
+ return isRecord(value) ? value : {};
72
+ }
73
+ function createEad3Issue(params) {
74
+ return createFormatIssue({
75
+ severity: params.severity ?? "error",
76
+ code: params.code,
77
+ path: params.path,
78
+ message: params.message,
79
+ format: EAD3_FORMAT_ID
80
+ });
81
+ }
82
+ function withEad3Profile(result) {
83
+ return {
84
+ ...result,
85
+ adapterProfile: EAD3_ADAPTER_PROFILE
86
+ };
87
+ }
88
+ function ead3Ok(value, issues = []) {
89
+ return withEad3Profile(formatOk(value, issues));
90
+ }
91
+ function ead3Fail(issues, value) {
92
+ return withEad3Profile(formatFail(issues, value));
93
+ }
94
+ function collectUnknownXml(record, knownLocalNames) {
95
+ const known = new Set(knownLocalNames);
96
+ const unknown = Object.fromEntries(Object.entries(record).filter(([key]) => !known.has(normalizeXmlName(key))));
97
+ return Object.keys(unknown).length > 0 ? unknown : void 0;
98
+ }
99
+ function mergeKnown(extension, known) {
100
+ return {
101
+ ...extension ?? {},
102
+ ...known
103
+ };
104
+ }
105
+ function hasExtensionKeys(extension) {
106
+ return extension !== void 0 && Object.keys(extension).length > 0;
107
+ }
108
+ function hasComponentExtensions(extensions) {
109
+ return hasExtensionKeys(extensions.xml) || hasExtensionKeys(extensions.did);
110
+ }
111
+ function hasFindingAidExtensions(extensions) {
112
+ return hasExtensionKeys(extensions.ead) || hasExtensionKeys(extensions.control);
113
+ }
114
+ function dateToXml(date) {
115
+ return mergeKnown(date.extensions, {
116
+ "#text": date.expression,
117
+ ...date.normalized ? { "@_normal": date.normalized } : {},
118
+ ...date.type ? { "@_type": date.type } : {}
119
+ });
120
+ }
121
+ function textBlockToXml(value) {
122
+ return { p: value };
123
+ }
124
+ function accessPointToXml(value) {
125
+ return mergeKnown(value.extensions, {
126
+ "#text": value.label,
127
+ ...value.identifier ? { "@_identifier": value.identifier } : {},
128
+ ...value.source ? { "@_source": value.source } : {}
129
+ });
130
+ }
131
+ function controlAccessToXml(values, extensions) {
132
+ const grouped = {};
133
+ for (const value of values) {
134
+ const tag = ACCESS_POINT_XML_TAGS[value.type];
135
+ (grouped[tag] ??= []).push(accessPointToXml(value));
136
+ }
137
+ return mergeKnown(extensions, grouped);
138
+ }
139
+ function nestedExtension(extension, localName) {
140
+ const value = findXmlValue(extension, localName);
141
+ return isRecord(value) ? value : void 0;
142
+ }
143
+ function isHrefPolicyKind(value) {
144
+ return value === "preserve" || value === "relative" || value === "redact" || value === "externalize";
145
+ }
146
+ function readJsonRecord(value) {
147
+ const text = readString(value);
148
+ if (!text) return void 0;
149
+ try {
150
+ const parsed = JSON.parse(text);
151
+ return isRecord(parsed) ? parsed : void 0;
152
+ } catch {
153
+ return;
154
+ }
155
+ }
156
+ function jsonRecordAttribute(value) {
157
+ if (!value || Object.keys(value).length === 0) return void 0;
158
+ try {
159
+ return JSON.stringify(value);
160
+ } catch {
161
+ return;
162
+ }
163
+ }
164
+ function digitalObjectToXml(ref) {
165
+ const locatorJson = jsonRecordAttribute(ref.sourceRef?.locator);
166
+ const metadataJson = jsonRecordAttribute(ref.sourceRef?.metadata);
167
+ return mergeKnown(ref.extensions, {
168
+ "@_href": ref.href,
169
+ ...ref.label ? { "@_label": ref.label } : {},
170
+ ...ref.role ? { "@_role": ref.role } : {},
171
+ ...ref.targetKind ? { "@_targetkind": ref.targetKind } : {},
172
+ ...ref.hrefPolicy?.kind ? { "@_data-daihum-href-policy": ref.hrefPolicy.kind } : {},
173
+ ...ref.hrefPolicy?.publicHref ? { "@_data-daihum-public-href": ref.hrefPolicy.publicHref } : {},
174
+ ...ref.hrefPolicy?.baseHref ? { "@_data-daihum-base-href": ref.hrefPolicy.baseHref } : {},
175
+ ...ref.hrefPolicy?.redactedHref ? { "@_data-daihum-redacted-href": ref.hrefPolicy.redactedHref } : {},
176
+ ...ref.hrefPolicy?.note ? { "@_data-daihum-policy-note": ref.hrefPolicy.note } : {},
177
+ ...ref.sourceRef?.kind ? { "@_data-daihum-source-kind": ref.sourceRef.kind } : {},
178
+ ...ref.sourceRef?.id ? { "@_data-daihum-source-id": ref.sourceRef.id } : {},
179
+ ...ref.sourceRef?.label ? { "@_data-daihum-source-label": ref.sourceRef.label } : {},
180
+ ...locatorJson ? { "@_data-daihum-source-locator": locatorJson } : {},
181
+ ...metadataJson ? { "@_data-daihum-source-metadata": metadataJson } : {}
182
+ });
183
+ }
184
+ function componentToXml(component) {
185
+ const repositoryExtension = nestedExtension(component.extensions?.did, "repository");
186
+ const repositoryNameExtension = nestedExtension(repositoryExtension, "corpname");
187
+ const controlAccessExtension = nestedExtension(component.extensions?.xml, "controlaccess");
188
+ const did = mergeKnown(component.extensions?.did, {
189
+ ...component.referenceCode ? { unitid: component.referenceCode } : {},
190
+ unittitle: component.title,
191
+ ...component.repository ? { repository: mergeKnown(repositoryExtension, { corpname: mergeKnown(repositoryNameExtension, { "#text": component.repository }) }) } : {},
192
+ ...component.dates?.length ? { unitdate: component.dates.map(dateToXml) } : {},
193
+ ...component.extent ? { physdesc: { extent: component.extent } } : {},
194
+ ...component.creator ? { origination: { name: component.creator } } : {},
195
+ ...component.language ? { langmaterial: { language: component.language } } : {},
196
+ ...component.digitalObjects?.length ? { dao: component.digitalObjects.map(digitalObjectToXml) } : {}
197
+ });
198
+ return mergeKnown(component.extensions?.xml, {
199
+ ...component.id ? { "@_id": component.id } : {},
200
+ "@_level": component.level,
201
+ ...component.otherLevel ? { "@_otherlevel": component.otherLevel } : {},
202
+ did,
203
+ ...component.abstract ? { abstract: textBlockToXml(component.abstract) } : {},
204
+ ...component.scopeContent ? { scopecontent: { p: component.scopeContent } } : {},
205
+ ...component.arrangement ? { arrangement: { p: component.arrangement } } : {},
206
+ ...component.accessRestriction ? { accessrestrict: { p: component.accessRestriction } } : {},
207
+ ...component.useRestriction ? { userestrict: { p: component.useRestriction } } : {},
208
+ ...component.biographicalHistory ? { bioghist: textBlockToXml(component.biographicalHistory) } : {},
209
+ ...component.custodialHistory ? { custodhist: { p: component.custodialHistory } } : {},
210
+ ...component.acquisitionInformation ? { acqinfo: textBlockToXml(component.acquisitionInformation) } : {},
211
+ ...component.appraisal ? { appraisal: textBlockToXml(component.appraisal) } : {},
212
+ ...component.processingInformation ? { processinfo: textBlockToXml(component.processingInformation) } : {},
213
+ ...component.relatedMaterial ? { relatedmaterial: textBlockToXml(component.relatedMaterial) } : {},
214
+ ...component.separatedMaterial ? { separatedmaterial: textBlockToXml(component.separatedMaterial) } : {},
215
+ ...component.preferredCitation ? { prefercite: textBlockToXml(component.preferredCitation) } : {},
216
+ ...component.notes?.length ? { odd: component.notes.map((note) => ({ p: note })) } : {},
217
+ ...component.accessPoints?.length || controlAccessExtension ? { controlaccess: controlAccessToXml(component.accessPoints ?? [], controlAccessExtension) } : {},
218
+ ...component.components?.length ? { dsc: { c: component.components.map(componentToXml) } } : {}
219
+ });
220
+ }
221
+ function findingAidToXmlObject(findingAid) {
222
+ const languageDeclarationExtension = nestedExtension(findingAid.extensions?.control, "languagedeclaration");
223
+ const languageExtension = nestedExtension(languageDeclarationExtension, "language");
224
+ const control = mergeKnown(findingAid.extensions?.control, {
225
+ recordid: findingAid.recordId,
226
+ maintenancestatus: findingAid.maintenanceStatus ?? "new",
227
+ publicationstatus: "inprocess",
228
+ ...findingAid.agencyName ? { maintenanceagency: { agencyname: findingAid.agencyName } } : {},
229
+ ...findingAid.language ? { languagedeclaration: mergeKnown(languageDeclarationExtension, { language: mergeKnown(languageExtension, { "#text": findingAid.language }) }) } : {},
230
+ filedesc: { titlestmt: { titleproper: findingAid.title } }
231
+ });
232
+ return { ead: mergeKnown(findingAid.extensions?.ead, {
233
+ "@_xmlns": EAD3_NAMESPACE,
234
+ control,
235
+ archdesc: componentToXml(findingAid.description)
236
+ }) };
237
+ }
238
+ function readDate(value) {
239
+ const expression = getXmlText(value);
240
+ if (!expression) return void 0;
241
+ const record = isRecord(value) ? value : {};
242
+ const normalized = readString(findXmlValue(record, "normal"));
243
+ const type = readString(findXmlValue(record, "type"));
244
+ const extensions = collectUnknownXml(record, [
245
+ "#text",
246
+ "normal",
247
+ "type"
248
+ ]);
249
+ return {
250
+ expression,
251
+ ...normalized ? { normalized } : {},
252
+ ...type ? { type } : {},
253
+ ...extensions ? { extensions } : {}
254
+ };
255
+ }
256
+ function readDigitalObject(value) {
257
+ if (!isRecord(value)) return void 0;
258
+ const href = readString(findXmlValue(value, "href"));
259
+ if (!href) return void 0;
260
+ const label = readString(findXmlValue(value, "label"));
261
+ const role = readString(findXmlValue(value, "role"));
262
+ const targetKind = readString(findXmlValue(value, "targetkind"));
263
+ const hrefPolicyKind = readString(findXmlValue(value, "data-daihum-href-policy"));
264
+ const publicHref = readString(findXmlValue(value, "data-daihum-public-href"));
265
+ const baseHref = readString(findXmlValue(value, "data-daihum-base-href"));
266
+ const redactedHref = readString(findXmlValue(value, "data-daihum-redacted-href"));
267
+ const policyNote = readString(findXmlValue(value, "data-daihum-policy-note"));
268
+ const sourceKind = readString(findXmlValue(value, "data-daihum-source-kind"));
269
+ const sourceId = readString(findXmlValue(value, "data-daihum-source-id"));
270
+ const sourceLabel = readString(findXmlValue(value, "data-daihum-source-label"));
271
+ const sourceLocator = readJsonRecord(findXmlValue(value, "data-daihum-source-locator"));
272
+ const sourceMetadata = readJsonRecord(findXmlValue(value, "data-daihum-source-metadata"));
273
+ const extensions = collectUnknownXml(value, [
274
+ "href",
275
+ "label",
276
+ "role",
277
+ "targetkind",
278
+ "data-daihum-href-policy",
279
+ "data-daihum-public-href",
280
+ "data-daihum-base-href",
281
+ "data-daihum-redacted-href",
282
+ "data-daihum-policy-note",
283
+ "data-daihum-source-kind",
284
+ "data-daihum-source-id",
285
+ "data-daihum-source-label",
286
+ "data-daihum-source-locator",
287
+ "data-daihum-source-metadata"
288
+ ]);
289
+ return {
290
+ href,
291
+ ...label ? { label } : {},
292
+ ...role ? { role } : {},
293
+ ...targetKind ? { targetKind } : {},
294
+ ...isHrefPolicyKind(hrefPolicyKind) ? { hrefPolicy: {
295
+ kind: hrefPolicyKind,
296
+ ...publicHref ? { publicHref } : {},
297
+ ...baseHref ? { baseHref } : {},
298
+ ...redactedHref ? { redactedHref } : {},
299
+ ...policyNote ? { note: policyNote } : {}
300
+ } } : {},
301
+ ...sourceKind && sourceId ? { sourceRef: {
302
+ kind: sourceKind,
303
+ id: sourceId,
304
+ ...sourceLabel ? { label: sourceLabel } : {},
305
+ ...sourceLocator ? { locator: sourceLocator } : {},
306
+ ...sourceMetadata ? { metadata: sourceMetadata } : {}
307
+ } } : {},
308
+ ...extensions ? { extensions } : {}
309
+ };
310
+ }
311
+ function readAccessPoint(value, type) {
312
+ const label = getXmlText(value);
313
+ if (!label) return void 0;
314
+ const record = isRecord(value) ? value : {};
315
+ const identifier = readString(findXmlValue(record, "identifier"));
316
+ const source = readString(findXmlValue(record, "source"));
317
+ const extensions = collectUnknownXml(record, [
318
+ "#text",
319
+ "identifier",
320
+ "source"
321
+ ]);
322
+ return {
323
+ type,
324
+ label,
325
+ ...identifier ? { identifier } : {},
326
+ ...source ? { source } : {},
327
+ ...extensions ? { extensions } : {}
328
+ };
329
+ }
330
+ function readAccessPoints(controlAccess) {
331
+ return Object.entries(ACCESS_POINT_XML_TAGS).flatMap(([type, tag]) => asXmlArray(findXmlValue(controlAccess, tag)).map((value) => readAccessPoint(value, type)).filter((value) => Boolean(value)));
332
+ }
333
+ function readMaintenanceStatus(value) {
334
+ const status = getXmlText(value);
335
+ if (status === "new" || status === "revised" || status === "deleted" || status === "derived" || status === "unknown") return status;
336
+ }
337
+ function readLevel(value) {
338
+ const level = readString(value);
339
+ if (level === "collection" || level === "series" || level === "subseries" || level === "file" || level === "item" || level === "otherlevel") return { level };
340
+ return {
341
+ level: "otherlevel",
342
+ ...level ? { otherLevel: level } : {}
343
+ };
344
+ }
345
+ function readComponent(value, path, issues, options) {
346
+ if (!isRecord(value)) return void 0;
347
+ const did = readRecord(value, "did");
348
+ const title = readElementText(did, "unittitle") ?? "";
349
+ if (!title) issues.push(createEad3Issue({
350
+ code: "ead3.component.title.required",
351
+ path: `${path}.title`,
352
+ message: "EAD3 component title is required."
353
+ }));
354
+ const childrenContainer = readRecord(value, "dsc");
355
+ const dates = asXmlArray(findXmlValue(did, "unitdate")).map(readDate).filter((date) => Boolean(date));
356
+ const digitalObjects = asXmlArray(findXmlValue(did, "dao")).map(readDigitalObject).filter((ref) => Boolean(ref));
357
+ const components = asXmlArray(findXmlValue(childrenContainer, "c")).map((child, index) => readComponent(child, `${path}.components.${index}`, issues, options)).filter((component) => Boolean(component));
358
+ const level = readLevel(findXmlValue(value, "level"));
359
+ const explicitOtherLevel = readString(findXmlValue(value, "otherlevel"));
360
+ const id = readString(findXmlValue(value, "id"));
361
+ const referenceCode = readElementText(did, "unitid");
362
+ const repository = readElementText(readRecord(did, "repository"), "corpname");
363
+ const extent = readElementText(readRecord(did, "physdesc"), "extent");
364
+ const creator = readElementText(readRecord(did, "origination"), "name");
365
+ const abstract = readParagraphElementText(value, "abstract");
366
+ const scopeContent = readParagraphElementText(value, "scopecontent");
367
+ const arrangement = readParagraphElementText(value, "arrangement");
368
+ const accessRestriction = readParagraphElementText(value, "accessrestrict");
369
+ const useRestriction = readParagraphElementText(value, "userestrict");
370
+ const language = readElementText(readRecord(did, "langmaterial"), "language");
371
+ const biographicalHistory = readParagraphElementText(value, "bioghist");
372
+ const custodialHistory = readParagraphElementText(value, "custodhist");
373
+ const acquisitionInformation = readParagraphElementText(value, "acqinfo");
374
+ const appraisal = readParagraphElementText(value, "appraisal");
375
+ const processingInformation = readParagraphElementText(value, "processinfo");
376
+ const relatedMaterial = readParagraphElementText(value, "relatedmaterial");
377
+ const separatedMaterial = readParagraphElementText(value, "separatedmaterial");
378
+ const preferredCitation = readParagraphElementText(value, "prefercite");
379
+ const notes = asXmlArray(findXmlValue(value, "odd")).map((note) => readElementText(note, "p")).filter((note) => Boolean(note));
380
+ const accessPoints = readAccessPoints(readRecord(value, "controlaccess"));
381
+ const componentUnknown = collectUnknownXml(value, [
382
+ "id",
383
+ "level",
384
+ "otherlevel",
385
+ "did",
386
+ "abstract",
387
+ "scopecontent",
388
+ "arrangement",
389
+ "accessrestrict",
390
+ "userestrict",
391
+ "bioghist",
392
+ "custodhist",
393
+ "acqinfo",
394
+ "appraisal",
395
+ "processinfo",
396
+ "relatedmaterial",
397
+ "separatedmaterial",
398
+ "prefercite",
399
+ "odd",
400
+ "dsc"
401
+ ]);
402
+ const didUnknown = collectUnknownXml(did, [
403
+ "unitid",
404
+ "unittitle",
405
+ "unitdate",
406
+ "physdesc",
407
+ "origination",
408
+ "langmaterial",
409
+ "dao"
410
+ ]);
411
+ const componentExtensions = options.preserveUnknown === false ? {} : {
412
+ ...componentUnknown ? { xml: componentUnknown } : {},
413
+ ...didUnknown ? { did: didUnknown } : {}
414
+ };
415
+ return {
416
+ ...id ? { id } : {},
417
+ level: level.level,
418
+ ...explicitOtherLevel ?? level.otherLevel ? { otherLevel: explicitOtherLevel ?? level.otherLevel } : {},
419
+ title,
420
+ ...referenceCode ? { referenceCode } : {},
421
+ ...repository ? { repository } : {},
422
+ ...dates.length > 0 ? { dates } : {},
423
+ ...extent ? { extent } : {},
424
+ ...creator ? { creator } : {},
425
+ ...abstract ? { abstract } : {},
426
+ ...scopeContent ? { scopeContent } : {},
427
+ ...arrangement ? { arrangement } : {},
428
+ ...accessRestriction ? { accessRestriction } : {},
429
+ ...useRestriction ? { useRestriction } : {},
430
+ ...language ? { language } : {},
431
+ ...biographicalHistory ? { biographicalHistory } : {},
432
+ ...custodialHistory ? { custodialHistory } : {},
433
+ ...acquisitionInformation ? { acquisitionInformation } : {},
434
+ ...appraisal ? { appraisal } : {},
435
+ ...processingInformation ? { processingInformation } : {},
436
+ ...relatedMaterial ? { relatedMaterial } : {},
437
+ ...separatedMaterial ? { separatedMaterial } : {},
438
+ ...preferredCitation ? { preferredCitation } : {},
439
+ ...notes.length > 0 ? { notes } : {},
440
+ ...accessPoints.length > 0 ? { accessPoints } : {},
441
+ ...digitalObjects.length > 0 ? { digitalObjects } : {},
442
+ ...components.length > 0 ? { components } : {},
443
+ ...hasComponentExtensions(componentExtensions) ? { extensions: componentExtensions } : {}
444
+ };
445
+ }
446
+ function getEadRoot(document) {
447
+ if (normalizeXmlName(document.rootName) === "ead") return document.root;
448
+ const maybeEad = findXmlValue(document.raw, "ead");
449
+ return isRecord(maybeEad) ? maybeEad : void 0;
450
+ }
451
+ function ead3FromXmlDocument(document, options = {}) {
452
+ const issues = [];
453
+ const ead = getEadRoot(document);
454
+ if (!ead) return ead3Fail([createEad3Issue({
455
+ code: "ead3.root.required",
456
+ path: "ead",
457
+ message: "EAD3 document must contain an ead root element."
458
+ })]);
459
+ const control = readRecord(ead, "control");
460
+ const titlestmt = readRecord(readRecord(control, "filedesc"), "titlestmt");
461
+ const description = readComponent(findXmlValue(ead, "archdesc"), "description", issues, options);
462
+ if (!description) return ead3Fail([createEad3Issue({
463
+ code: "ead3.archdesc.required",
464
+ path: "ead.archdesc",
465
+ message: "EAD3 document must contain an archdesc element."
466
+ })]);
467
+ const recordId = readElementText(control, "recordid") ?? "";
468
+ if (!recordId) issues.push(createEad3Issue({
469
+ code: "ead3.recordId.required",
470
+ path: "recordId",
471
+ message: "EAD3 record id is required."
472
+ }));
473
+ const title = readElementText(titlestmt, "titleproper") ?? description.title;
474
+ if (!title) issues.push(createEad3Issue({
475
+ code: "ead3.title.required",
476
+ path: "title",
477
+ message: "EAD3 title is required."
478
+ }));
479
+ const agencyName = readElementText(readRecord(control, "maintenanceagency"), "agencyname");
480
+ const language = readElementText(readRecord(control, "languagedeclaration"), "language");
481
+ const maintenanceStatus = readMaintenanceStatus(findXmlValue(control, "maintenancestatus"));
482
+ const eadUnknown = options.preserveUnknown === false ? void 0 : collectUnknownXml(ead, [
483
+ "xmlns",
484
+ "control",
485
+ "archdesc"
486
+ ]);
487
+ const controlUnknown = options.preserveUnknown === false ? void 0 : collectUnknownXml(control, [
488
+ "recordid",
489
+ "maintenancestatus",
490
+ "publicationstatus",
491
+ "maintenanceagency",
492
+ "filedesc"
493
+ ]);
494
+ const extensions = {
495
+ ...eadUnknown ? { ead: eadUnknown } : {},
496
+ ...controlUnknown ? { control: controlUnknown } : {}
497
+ };
498
+ const findingAid = {
499
+ recordId,
500
+ title,
501
+ ...maintenanceStatus ? { maintenanceStatus } : {},
502
+ ...agencyName ? { agencyName } : {},
503
+ ...language ? { language } : {},
504
+ description,
505
+ ...hasFindingAidExtensions(extensions) ? { extensions } : {}
506
+ };
507
+ return hasFormatErrors(issues) ? ead3Fail(issues, findingAid) : ead3Ok(findingAid, issues);
508
+ }
509
+ function parseEad3Xml(input, options = {}) {
510
+ const parsed = parseXml(input, { arrayTags: EAD3_ARRAY_TAGS });
511
+ if (!parsed.ok) return ead3Fail(parsed.issues);
512
+ return ead3FromXmlDocument(parsed.value, options);
513
+ }
514
+ function ead3ToXmlDocument(findingAid, options = {}) {
515
+ const issues = validateEad3(findingAid, options);
516
+ if (hasFormatErrors(issues)) return ead3Fail(issues);
517
+ const raw = findingAidToXmlObject(findingAid);
518
+ const ead = raw.ead;
519
+ if (!isRecord(ead)) return ead3Fail([createEad3Issue({
520
+ code: "ead3.serialize.failed",
521
+ path: "ead",
522
+ message: "EAD3 serializer did not produce an ead root element."
523
+ })]);
524
+ return ead3Ok({
525
+ rootName: "ead",
526
+ root: ead,
527
+ raw
528
+ });
529
+ }
530
+ function serializeEad3Xml(findingAid, options = {}) {
531
+ const document = ead3ToXmlDocument(findingAid);
532
+ if (!document.ok) return ead3Fail(document.issues);
533
+ return withEad3Profile(buildXml(document.value, {
534
+ format: options.format ?? true,
535
+ suppressEmptyNode: true
536
+ }));
537
+ }
538
+ function validateComponent(component, path) {
539
+ const issues = [];
540
+ if (!readString(component.title)) issues.push(createEad3Issue({
541
+ code: "ead3.component.title.required",
542
+ path: `${path}.title`,
543
+ message: "EAD3 component title is required."
544
+ }));
545
+ component.digitalObjects?.forEach((ref, index) => {
546
+ if (!readString(ref.href)) issues.push(createEad3Issue({
547
+ code: "ead3.digitalObject.href.required",
548
+ path: `${path}.digitalObjects.${index}.href`,
549
+ message: "EAD3 digital object href is required."
550
+ }));
551
+ });
552
+ component.accessPoints?.forEach((accessPoint, index) => {
553
+ if (!readString(accessPoint.label)) issues.push(createEad3Issue({
554
+ code: "ead3.accessPoint.label.required",
555
+ path: `${path}.accessPoints.${index}.label`,
556
+ message: "EAD3 access point label is required."
557
+ }));
558
+ });
559
+ component.components?.forEach((child, index) => {
560
+ issues.push(...validateComponent(child, `${path}.components.${index}`));
561
+ });
562
+ return issues;
563
+ }
564
+ function validateEad3(findingAid, options = {}) {
565
+ const issues = [];
566
+ if ((options.requireRecordId ?? true) && !readString(findingAid.recordId)) issues.push(createEad3Issue({
567
+ code: "ead3.recordId.required",
568
+ path: "recordId",
569
+ message: "EAD3 record id is required."
570
+ }));
571
+ if (!readString(findingAid.title)) issues.push(createEad3Issue({
572
+ code: "ead3.title.required",
573
+ path: "title",
574
+ message: "EAD3 title is required."
575
+ }));
576
+ issues.push(...validateComponent(findingAid.description, "description"));
577
+ return issues;
578
+ }
579
+ const ead3Adapter = {
580
+ format: EAD3_FORMAT_ID,
581
+ profile: EAD3_ADAPTER_PROFILE,
582
+ parse: parseEad3Xml,
583
+ serialize: serializeEad3Xml,
584
+ validate: validateEad3,
585
+ detect(input) {
586
+ return /<([A-Za-z0-9_-]+:)?ead[\s>]/.test(input);
587
+ }
588
+ };
589
+
590
+ //#endregion
591
+ export { EAD3_OFFICIAL_SCHEMA_VALIDATION as a, EAD3_TAG_LIBRARY_VERSION as c, ead3FromXmlDocument as d, ead3ToXmlDocument as f, validateEad3 as h, EAD3_NAMESPACE as i, EAD3_VALIDATION_LEVEL as l, serializeEad3Xml as m, EAD3_FORMAT_GENERATION as n, EAD3_SCHEMA_REVISION as o, parseEad3Xml as p, EAD3_FORMAT_ID as r, EAD3_SCHEMA_VERSION as s, EAD3_ADAPTER_PROFILE as t, ead3Adapter as u };
592
+ //# sourceMappingURL=ead3-DM2in-ck.js.map