@jwilleke/ngdpbase-types 5.40.0 → 5.41.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.
Files changed (47) hide show
  1. package/lib/packages/media-date/index.d.ts +34 -0
  2. package/lib/packages/ngdpbase-types/index.d.ts +1 -1
  3. package/lib/src/ice/fileHandling.d.ts +6 -1
  4. package/lib/src/ice/runExport.d.ts +41 -0
  5. package/lib/src/ice/runImport.d.ts +16 -7
  6. package/lib/src/ice/shims/csv.d.ts +24 -0
  7. package/lib/src/ice/shims/export.d.ts +23 -0
  8. package/lib/src/ice/shims/index.d.ts +3 -1
  9. package/lib/src/ice/shims/svg.d.ts +27 -0
  10. package/lib/src/ice/shims/takeout.d.ts +83 -0
  11. package/lib/src/ice/types.d.ts +251 -5
  12. package/lib/src/ice/vet.d.ts +19 -0
  13. package/lib/src/managers/AttachmentManager.d.ts +86 -36
  14. package/lib/src/managers/AuthManager.d.ts +117 -7
  15. package/lib/src/managers/AuthManager.js +341 -37
  16. package/lib/src/managers/ConfigurationManager.d.ts +6 -0
  17. package/lib/src/managers/ExportManager.d.ts +16 -0
  18. package/lib/src/managers/ExportManager.js +25 -0
  19. package/lib/src/managers/FileManager.d.ts +182 -0
  20. package/lib/src/managers/ImportManager.d.ts +264 -16
  21. package/lib/src/managers/MediaManager.d.ts +11 -0
  22. package/lib/src/managers/SharedFolderManager.d.ts +320 -0
  23. package/lib/src/providers/BaseMediaProvider.d.ts +4 -0
  24. package/lib/src/providers/FileSystemMediaProvider.d.ts +25 -0
  25. package/lib/src/security/PolicyDecisionPoint.d.ts +3 -2
  26. package/lib/src/security/permissions.generated.d.ts +3 -3
  27. package/lib/src/types/File.d.ts +90 -0
  28. package/lib/src/types/express.d.ts +3 -1
  29. package/lib/src/types/linkedom.d.ts +2 -0
  30. package/lib/src/utils/auditEventNames.generated.d.ts +2 -0
  31. package/lib/src/utils/auditEventNames.generated.js +2 -0
  32. package/lib/src/utils/auditEvents.d.ts +3 -0
  33. package/lib/src/utils/auditEvents.js +3 -0
  34. package/lib/src/utils/fileMigrationPlan.d.ts +81 -0
  35. package/lib/src/utils/mediaFolderOverlap.d.ts +50 -0
  36. package/lib/src/utils/privateStoreAccess.d.ts +21 -0
  37. package/lib/src/utils/privateStoreAccess.js +11 -0
  38. package/lib/src/utils/privateStoreImport.d.ts +0 -10
  39. package/lib/src/utils/privateStorePath.d.ts +12 -0
  40. package/lib/src/utils/privateStorePath.js +18 -0
  41. package/lib/src/utils/recoveryWordsFile.d.ts +54 -0
  42. package/lib/src/utils/sessionEnd.d.ts +1 -0
  43. package/lib/src/utils/sessionEnd.js +4 -0
  44. package/lib/src/utils/sessionIdle.d.ts +4 -0
  45. package/lib/src/utils/sessionIdle.js +6 -0
  46. package/package.json +1 -1
  47. package/lib/src/providers/mediaFilenameDate.d.ts +0 -22
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Filename → capture-date parser, the one implementation of it.
3
+ *
4
+ * ngdpbase uses it when a media file carries no usable EXIF/QuickTime date, and
5
+ * mjs-media-handling uses a built copy of it to place and stamp files. Both must read a name the same way, which is why it is one package.
6
+ *
7
+ * It is a pure function of the name: no filesystem, no network, no server.
8
+ *
9
+ * Missing parts are filled with fixed, documented values — see FAKE_MONTH below
10
+ * and README.md. Callers that must know what was real read `parseFilenameDate`,
11
+ * whose `month`/`day`/`time` are null where the name did not carry them.
12
+ */
13
+ /** Written when the name gives a year but no month. */
14
+ export declare const FAKE_MONTH = 6;
15
+ /** Written when the name gives no day of the month. */
16
+ export declare const FAKE_DAY = 15;
17
+ /** Written when the name gives no time of day. */
18
+ export declare const FAKE_TIME = "11:59:00";
19
+ /** What a filename said, with null for each part it did not say. */
20
+ export interface FilenameDate {
21
+ year: number;
22
+ month: number | null;
23
+ day: number | null;
24
+ /** `HH:MM:SS`, only when the name carried a valid time. */
25
+ time: string | null;
26
+ /** Which rule matched, e.g. `filename:YYYY-MM-DD`. */
27
+ source: string;
28
+ }
29
+ /** What the name itself says, nothing filled in. Null when it says nothing. */
30
+ export declare function parseFilenameDate(filename: string): FilenameDate | null;
31
+ /** `YYYY-MM-DD HH:MM:SS`, with FAKE_MONTH, FAKE_DAY and FAKE_TIME where missing. */
32
+ export declare function fillFilenameDate(date: FilenameDate): string;
33
+ /** The capture date a filename gives, filled in; null when it gives none. */
34
+ export declare function parseDateFromFilename(filename: string): string | null;
@@ -40,7 +40,7 @@ export type { PageAction } from '../../src/utils/pageUrl.js';
40
40
  export type { default as ConsentManager, ConsentScopeStatus } from '../../src/managers/ConsentManager.js';
41
41
  export type { AddonConsentRegistration, ConsentDocument, ConsentRecord, ConsentRequiredError, ConsentScope, ConsentSeen, ConsentStatus } from '../../src/types/Consent.js';
42
42
  export type { default as ImportManager } from '../../src/managers/ImportManager.js';
43
- export type { IceShim, IceReceiver, IceItem, IceKind, IceWarning, ShimDirection, ShimAccepts, ShimTools, ShimReadResult, ReceiveInfo, ReceiveOutcome, IceCitation, KeptOriginal, OriginalChoice, IceOriginalChoices, OriginalKeep, IceUpload, IceSource, IceUrlSource, IceRunRequest, IceRecordData, FileDoneInfo, IceRunReport, IceFileReport, IceFileStatus, RecentImport } from '../../src/ice/types.js';
43
+ export type { IceShim, IceReceiver, IceItem, IceKind, IceWarning, ShimDirection, ShimAccepts, ShimTools, ShimReadResult, ReceiveInfo, ReceiveOutcome, IceCitation, KeptOriginal, OriginalChoice, IceOriginalChoices, OriginalKeep, IceUpload, IceSource, IceUrlSource, IceRunRequest, IceRecordData, FileDoneInfo, IceTarget, IceArchiveView, IceRunReport, IceFileReport, IceFileStatus, RecentImport } from '../../src/ice/types.js';
44
44
  export type { default as UserManager, UserUpdateInput, UserUpdateFn } from '../../src/managers/UserManager.js';
45
45
  export type { User, UserPreferences } from '../../src/types/User.js';
46
46
  export type { default as AuthManager, InviteOutcome, InvitationView } from '../../src/managers/AuthManager.js';
@@ -41,8 +41,13 @@ export declare function isZip(upload: IceUpload): boolean;
41
41
  * with the type its request gave it. Limits are per archive (`ZipReadLimits`), so a small
42
42
  * archive that expands enormously stops at the budget. An archive that cannot
43
43
  * be read is returned in `unreadable`, with why; the rest go on.
44
+ *
45
+ * With `innerZipsAsFiles` (#2118), only the uploads themselves are unpacked:
46
+ * a zip inside one is passed on as a file, like any other member.
44
47
  */
45
- export declare function expandUploads(uploads: readonly IceUpload[], limits: ZipReadLimits, maxDepth: number, depth?: number): {
48
+ export declare function expandUploads(uploads: readonly IceUpload[], limits: ZipReadLimits, maxDepth: number, options?: {
49
+ innerZipsAsFiles?: boolean;
50
+ }, depth?: number): {
46
51
  files: IceUpload[];
47
52
  unreadable: Array<{
48
53
  name: string;
@@ -0,0 +1,41 @@
1
+ import type { ExportShimTools, IceItem, IceKind, RegisteredShim } from './types.js';
2
+ /** Core's page export source: pages, read through PageManager's door. */
3
+ export declare const PAGES_EXPORT_SOURCE = "core.pages";
4
+ /** Configuration an export reads (each a key under `ngdpbase.export.engine.`). */
5
+ export interface IceExportSettings {
6
+ /** The most bytes an export's source, or any step of its chain, may hold. */
7
+ maxBytes: number;
8
+ /** The most shims one export runs through (`ngdpbase.import.engine.max-chain-depth`, shared with import). */
9
+ maxChainDepth: number;
10
+ }
11
+ /** An export that cannot be made, with the reason a user is shown. */
12
+ export declare class IceExportFailed extends Error {
13
+ constructor(message: string);
14
+ }
15
+ /**
16
+ * The formats that can be made from items of this kind: for each `out`
17
+ * shim that makes a file, the shortest chain of `out` shims that reaches it
18
+ * from `kind`, at most `maxChainDepth` long. Shims are tried in registration
19
+ * order, so between two chains of one length the first registered wins.
20
+ *
21
+ * @returns The file-making shim's id → the chain, ending with it
22
+ */
23
+ export declare function exportChains(shims: readonly RegisteredShim[], kind: IceKind, maxChainDepth: number): Map<string, RegisteredShim[]>;
24
+ /** The bytes items hold, their text counted as UTF-8. */
25
+ export declare function exportSize(items: readonly IceItem[]): number;
26
+ /**
27
+ * Refuse items larger than the export limit.
28
+ *
29
+ * @throws IceExportFailed when they are
30
+ */
31
+ export declare function checkExportSize(items: readonly IceItem[], maxBytes: number): void;
32
+ /**
33
+ * Run the source's items through the chain, each shim's output the next
34
+ * one's input, and return the one file the last shim made. What came before
35
+ * travels with each item while a shim keeps the count: earlier metadata
36
+ * under later, as an import's chain does.
37
+ *
38
+ * @throws IceExportFailed when a step holds more than `maxBytes`, a shim
39
+ * makes something other than what it declares, or the end is not one file
40
+ */
41
+ export declare function runExportChain(items: IceItem[], chain: readonly RegisteredShim[], tools: (shim: RegisteredShim) => ExportShimTools, settings: IceExportSettings): Promise<IceItem>;
@@ -41,10 +41,11 @@ export declare const SCOPE_FORM = "ice2";
41
41
  * The scope a run's fingerprints, per-file status and item keys live in
42
42
  * (#2013): bound to the receiver and to the user the run is for, by their
43
43
  * identity `@id` (else their username, #2041). The engine works it out from
44
- * the caller's context; a request cannot name another user's. A caller's own
45
- * `sub` (phr's source id) narrows it within that user's scope, never outside.
44
+ * the caller's context; a request cannot name another user's. What follows
45
+ * narrows it within that user's scope, never outside: the place within the
46
+ * receiver (#2118), then a caller's own sub-scope (phr's source id).
46
47
  */
47
- export declare function boundScope(receiverId: string, owner: string, sub?: string): string;
48
+ export declare function boundScope(receiverId: string, owner: string, ...subs: Array<string | undefined>): string;
48
49
  /** Does this shim list the receiver, by id or as any receiver (`'*'`, #2109)? */
49
50
  export declare function handsTo(shim: Pick<RegisteredShim, 'receivers'>, receiverId: string): boolean;
50
51
  export interface ChainLeaf {
@@ -64,9 +65,10 @@ export interface ChainSpec {
64
65
  /**
65
66
  * Run a shim, then the shims after it (D9), until each item is done. What
66
67
  * came before travels with each item: earlier metadata under later, earlier
67
- * warnings first. Partial notes are collected into `partial`.
68
+ * warnings first. Partial notes are collected into `partial`; a shim's note
69
+ * that the file holds nothing to import on its own (#2118) into `skipped`.
68
70
  */
69
- export declare function convertChain(shim: RegisteredShim, input: IceItem, chain: string[], spec: ChainSpec, partial: string[]): Promise<ChainLeaf[]>;
71
+ export declare function convertChain(shim: RegisteredShim, input: IceItem, chain: string[], spec: ChainSpec, partial: string[], skipped?: string[]): Promise<ChainLeaf[]>;
70
72
  /**
71
73
  * The name the user gave this file (#2130), as the engine applies it: none
72
74
  * when the receiver names things itself (it declares no `names`) or the user
@@ -85,6 +87,13 @@ export declare function resolveGivenName(upload: IceUpload, receiver: Registered
85
87
  export declare function receiverLink(receiver: RegisteredReceiver, ref: string | undefined, ctx: ActorContext): Promise<string | undefined>;
86
88
  /** What a file's status says when a name the user gave was not applied: the file is already here under another (#2130). */
87
89
  export declare function alreadyHereAs(name: string): string;
90
+ /**
91
+ * Is an import into this receiver confidential (#2110)? Only when its
92
+ * destination is encrypted: a receiver that keeps into a sealed store
93
+ * (`keepsEncrypted`), or whose own door writes into one (`writesEncrypted`,
94
+ * #2118). No receiver can declare itself so otherwise.
95
+ */
96
+ export declare function isConfidentialReceiver(receiver: Pick<RegisteredReceiver, 'keepsEncrypted' | 'writesEncrypted'> | undefined): boolean;
88
97
  /** Does this run keep its originals during the upload (#2034)? */
89
98
  export declare function keepsAtUpload(receiver: RegisteredReceiver | undefined, original: OriginalChoice): boolean;
90
99
  /** What keeping at upload did: how many it kept, or the first file it could not keep. */
@@ -110,10 +119,10 @@ export interface UploadKeepResult {
110
119
  * then queues nothing. Originals kept before it stay kept, and recorded, so
111
120
  * the next try reuses them.
112
121
  */
113
- export declare function keepOriginalsAtUpload(deps: IceRunDeps, request: IceRunRequest, ctx: ActorContext, scope: string): Promise<UploadKeepResult>;
122
+ export declare function keepOriginalsAtUpload(siteDeps: IceRunDeps, request: IceRunRequest, ctx: ActorContext, scope: string): Promise<UploadKeepResult>;
114
123
  /**
115
124
  * Run one import. Fills and returns `report`, which the caller may be
116
125
  * showing while it runs. Never throws for one file's failure; that file's
117
126
  * status says why.
118
127
  */
119
- export declare function runImport(deps: IceRunDeps, request: IceRunRequest, ctx: ActorContext, report: IceRunReport): Promise<IceRunReport>;
128
+ export declare function runImport(siteDeps: IceRunDeps, request: IceRunRequest, ctx: ActorContext, report: IceRunReport): Promise<IceRunReport>;
@@ -54,6 +54,30 @@ export declare function parseCsv(text: string, delimiter?: string, skipLines?: n
54
54
  * invisible one.
55
55
  */
56
56
  export declare function preambleSuspicion(columns: readonly string[]): string | null;
57
+ /**
58
+ * Clean CSV text before it is kept as a file (#2149): HTML is taken out of
59
+ * every cell, and a cell a spreadsheet would run as a formula gets a leading
60
+ * `'`, so it shows as text (the usual CSV-injection defence). Only the cells
61
+ * that change are rewritten, quoted; every other byte is kept as it was.
62
+ * Returns how many cells of each kind were cleaned.
63
+ */
64
+ export declare function cleanCsvText(text: string, delimiter?: string): {
65
+ text: string;
66
+ html: number;
67
+ formulas: number;
68
+ };
69
+ /**
70
+ * How a CSV is read and written back for cleaning (#2149), so its bytes stay
71
+ * its own: UTF-16 with a byte-order mark as UTF-16; valid UTF-8 as UTF-8;
72
+ * anything else (Latin-1, Windows-1252 and the like) one byte to one
73
+ * character and back, which round-trips every byte exactly. The characters
74
+ * cleaning looks for (`, " < > = + - @`, tab, line ends) are ASCII, the same
75
+ * byte in each of these.
76
+ */
77
+ export declare function csvEncoding(bytes: Buffer): {
78
+ text: string;
79
+ encode: (text: string) => Buffer;
80
+ };
57
81
  /** One row as a record: its own id, or one synthesized from its content. */
58
82
  export declare function csvRecord(raw: RawRecord, opts: RecordShimOptions): IceRecordData | null;
59
83
  export declare const csvShim: IceShim;
@@ -0,0 +1,23 @@
1
+ import type { ActorContext } from '../../context/ActorContext.js';
2
+ import { type IceItem, type IceShim } from '../types.js';
3
+ /** The core doors the export shims call. */
4
+ export interface ExportShimDoors {
5
+ /** A complete HTML document for one NCM item (ExportManager's page document). */
6
+ renderDocument(item: IceItem): Promise<string>;
7
+ /** HTML → PDF (ExportManager.htmlToPdf), as the run's user. */
8
+ htmlToPdf(ctx: ActorContext, html: string): Promise<Buffer>;
9
+ /** Is a PDF provider chosen? */
10
+ pdfAvailable(): boolean;
11
+ }
12
+ /** A file name from a title: the title, with what no file system takes replaced. */
13
+ export declare function exportFileName(item: IceItem, extension: string): string;
14
+ /**
15
+ * The HTML with nothing in it that a renderer would fetch (#2120): only
16
+ * `data:` URLs are left, in attributes and in CSS. The local renderer
17
+ * already blocks the network; a remote one (`chrome-service`, Gotenberg)
18
+ * fetches what the HTML names, from where it runs, so this is done before
19
+ * the HTML leaves the process. Links (`<a href>`) stay: printing never
20
+ * follows them.
21
+ */
22
+ export declare function withoutRemoteUrls(html: string): string;
23
+ export declare function exportShims(doors: ExportShimDoors): IceShim[];
@@ -12,5 +12,7 @@
12
12
  * receiver that takes records (`receivers: ['*']`).
13
13
  */
14
14
  import type { IceShim } from '../types.js';
15
- /** Every record shim, in registration order. */
15
+ /** Every record shim, in registration order. `core.csv` also cleans a CSV kept as a file (#2149). */
16
16
  export declare const RECORD_SHIMS: readonly IceShim[];
17
+ /** Shims that only vet a file kept as a file (#2149): they clean and are never picked for a run. */
18
+ export declare const VETTING_SHIMS: readonly IceShim[];
@@ -0,0 +1,27 @@
1
+ /**
2
+ * svg shim (#2149): cleans an SVG before it is kept as a file. An SVG is a
3
+ * document, not a picture: it can carry scripts, HTML inside
4
+ * `<foreignObject>`, `on…` event handlers, script links and animations that
5
+ * set a link. The file is parsed and rebuilt from an allow-list of SVG
6
+ * elements and attributes, never patched with patterns: what the parser did
7
+ * not take as an allowed element or attribute is not written back. The note
8
+ * says what kind of thing was removed and how many, never the content.
9
+ *
10
+ * The parser is the one the site already uses for author HTML
11
+ * (`src/rendering/htmlPolicy.ts`): sanitize-html on htmlparser2, here in XML
12
+ * mode so names keep their case. This file only configures it for SVG.
13
+ *
14
+ * Defence in depth, not the boundary: an uploaded file is always served
15
+ * sandboxed (`untrustedFileHeaders`, #1624), so nothing in it runs as the
16
+ * site. Cleaning keeps a file that is downloaded, embedded elsewhere or
17
+ * opened outside the site from carrying it.
18
+ *
19
+ * A vetting shim only (`clean`, no `read`): never picked for an import run.
20
+ */
21
+ import type { IceShim, IceWarning } from '../types.js';
22
+ /** The cleaned text and what was removed: the pure step behind the shim. */
23
+ export declare function cleanSvgText(text: string): {
24
+ text: string;
25
+ removed: IceWarning[];
26
+ };
27
+ export declare const svgShim: IceShim;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * `core.takeout` (#2118, ICE #1979): a download of a private store (#1387)
3
+ * handed back, into its owner's private store (`core.private-store`). It
4
+ * replaces the takeout import's own path (#1472).
5
+ *
6
+ * The engine unpacks the zip and hands each member here on its own, with the
7
+ * archive beside it (`IceItem.archive`); this shim reads the takeout's
8
+ * layout through that. What a takeout is, as #1387 writes it: one `{store}/`
9
+ * folder holding each page as `{title}.md` with full frontmatter, files under
10
+ * `attachments/`, and `files-index.json` mapping each file's id to its path
11
+ * in the archive. The reader is lenient about the one thing people change,
12
+ * the folder: someone who extracts a takeout and zips it again may add a
13
+ * level, or zip the contents with no folder at all, so the takeout's root is
14
+ * found rather than assumed.
15
+ *
16
+ * - A page (`.md` directly in the root) is one `takeout` item: its body as
17
+ * text, and in `data` its title, uuid and frontmatter, and the files of
18
+ * the takeout its body links to (`/attachments/{old id}`), so the
19
+ * receiver can store those first and point the links at their new ids.
20
+ * - A file (directly in `attachments/`) is one `takeout` item: its bytes,
21
+ * and in `data` its old id, name, media type and description from the index.
22
+ * - The file index is read through the archive by the members it names; on
23
+ * its own it holds nothing to import (`skip`). So does anything else in
24
+ * the archive: versions, the trash, footnotes and comments are not brought
25
+ * back, as before.
26
+ *
27
+ * Pure: no I/O, no access decision, no write. The receiver's door does those.
28
+ */
29
+ import type { IceShim } from '../types.js';
30
+ /** The kind this shim produces: one page or one file of a takeout. */
31
+ export declare const TAKEOUT_KIND = "takeout";
32
+ /** The receiver a takeout goes into: its owner's private store. */
33
+ export declare const PRIVATE_STORE_RECEIVER = "core.private-store";
34
+ /** A file of the takeout that a page links to, found through the archive. */
35
+ export interface TakeoutLinkedFile {
36
+ /** Its id where it came from: what the page's links name. */
37
+ oldId: string;
38
+ /** Its path in the archive. */
39
+ path: string;
40
+ name: string;
41
+ encodingFormat?: string;
42
+ description?: string;
43
+ }
44
+ /** A page of a takeout: the `data` of its item; the body is the item's `text`. */
45
+ export interface TakeoutPageData {
46
+ entry: 'page';
47
+ /** From the frontmatter, else the file's name. */
48
+ title: string;
49
+ /** From the frontmatter. Absent for a page written by hand. */
50
+ uuid?: string;
51
+ /** The frontmatter, as written. */
52
+ metadata: Record<string, unknown>;
53
+ /** The takeout's files its body links to. */
54
+ files: TakeoutLinkedFile[];
55
+ }
56
+ /** A file of a takeout: the `data` of its item; the bytes are the item's `bytes`. */
57
+ export interface TakeoutFileData {
58
+ entry: 'file';
59
+ /** Its id where it came from, when the file index names it. */
60
+ oldId?: string;
61
+ /** The name it was uploaded with. */
62
+ name: string;
63
+ encodingFormat?: string;
64
+ description?: string;
65
+ }
66
+ export type TakeoutData = TakeoutPageData | TakeoutFileData;
67
+ /**
68
+ * The folder the takeout lives in: the one holding the file index, else the
69
+ * shallowest one holding a page. `''` is the archive's own root.
70
+ */
71
+ export declare function takeoutRoot(paths: readonly string[]): string;
72
+ /** `body` with every `/attachments/{old}` link pointed at its new id. */
73
+ export declare function rewriteAttachmentLinks(body: string, ids: ReadonlyMap<string, string>): string;
74
+ /** Whether `body` links to the file `id`. */
75
+ export declare function linksToAttachment(body: string, id: string): boolean;
76
+ /**
77
+ * The first free title of `title`, `title (imported)`, `title (imported 2)` …
78
+ * (operator, 2026-09-25): a DIFFERENT page already holding the title keeps
79
+ * it, and the import lands beside it.
80
+ */
81
+ export declare function freeImportTitle(title: string, isTaken: (candidate: string) => Promise<boolean>): Promise<string>;
82
+ /** The takeout shim: every member of a zip, read as a takeout's layout says. */
83
+ export declare const takeoutShim: IceShim;