@jwilleke/ngdpbase-types 5.40.0 → 5.41.0
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/lib/packages/ngdpbase-types/index.d.ts +1 -1
- package/lib/src/ice/fileHandling.d.ts +6 -1
- package/lib/src/ice/runExport.d.ts +41 -0
- package/lib/src/ice/runImport.d.ts +16 -7
- package/lib/src/ice/shims/csv.d.ts +24 -0
- package/lib/src/ice/shims/export.d.ts +23 -0
- package/lib/src/ice/shims/index.d.ts +3 -1
- package/lib/src/ice/shims/svg.d.ts +27 -0
- package/lib/src/ice/shims/takeout.d.ts +83 -0
- package/lib/src/ice/types.d.ts +251 -5
- package/lib/src/ice/vet.d.ts +19 -0
- package/lib/src/managers/AttachmentManager.d.ts +86 -36
- package/lib/src/managers/AuthManager.d.ts +117 -7
- package/lib/src/managers/AuthManager.js +341 -37
- package/lib/src/managers/ExportManager.d.ts +16 -0
- package/lib/src/managers/ExportManager.js +25 -0
- package/lib/src/managers/FileManager.d.ts +182 -0
- package/lib/src/managers/ImportManager.d.ts +264 -16
- package/lib/src/managers/MediaManager.d.ts +2 -0
- package/lib/src/managers/SharedFolderManager.d.ts +320 -0
- package/lib/src/providers/BaseMediaProvider.d.ts +4 -0
- package/lib/src/providers/FileSystemMediaProvider.d.ts +6 -0
- package/lib/src/security/PolicyDecisionPoint.d.ts +3 -2
- package/lib/src/security/permissions.generated.d.ts +3 -3
- package/lib/src/types/File.d.ts +90 -0
- package/lib/src/types/express.d.ts +3 -1
- package/lib/src/types/linkedom.d.ts +2 -0
- package/lib/src/utils/auditEventNames.generated.d.ts +2 -0
- package/lib/src/utils/auditEventNames.generated.js +2 -0
- package/lib/src/utils/auditEvents.d.ts +3 -0
- package/lib/src/utils/auditEvents.js +3 -0
- package/lib/src/utils/fileMigrationPlan.d.ts +81 -0
- package/lib/src/utils/privateStoreAccess.d.ts +21 -0
- package/lib/src/utils/privateStoreAccess.js +11 -0
- package/lib/src/utils/privateStoreImport.d.ts +0 -10
- package/lib/src/utils/privateStorePath.d.ts +12 -0
- package/lib/src/utils/privateStorePath.js +18 -0
- package/lib/src/utils/recoveryWordsFile.d.ts +54 -0
- package/lib/src/utils/sessionEnd.d.ts +1 -0
- package/lib/src/utils/sessionEnd.js +4 -0
- package/lib/src/utils/sessionIdle.d.ts +4 -0
- package/lib/src/utils/sessionIdle.js +6 -0
- package/package.json +1 -1
|
@@ -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,
|
|
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.
|
|
45
|
-
*
|
|
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,
|
|
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(
|
|
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(
|
|
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;
|
package/lib/src/ice/types.d.ts
CHANGED
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
* noise filter, fingerprints, skipping unchanged files, per-file status,
|
|
15
15
|
* keeping the original, and running the work as a background job.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* - An __export source__ is the owner's door for reading the thing being
|
|
18
|
+
* exported (#2120): a page, later a search result or an add-on's list. It
|
|
19
|
+
* checks the owner's existing read permission (D5) and yields items that
|
|
20
|
+
* `out` shims chain into one file to download.
|
|
20
21
|
*/
|
|
21
22
|
import type { ActorContext } from '../context/ActorContext.js';
|
|
22
23
|
import type { GuardedFetchOptions, GuardedResponse } from '../http/guardedFetch.js';
|
|
@@ -61,6 +62,28 @@ export interface IceItem {
|
|
|
61
62
|
* (a feed entry): an item whose key the engine has seen before is skipped.
|
|
62
63
|
*/
|
|
63
64
|
itemKey?: string;
|
|
65
|
+
/**
|
|
66
|
+
* The archive the file was unpacked from (#2118), when it was: what lies
|
|
67
|
+
* beside it, for a shim whose format spans the files of an archive (a
|
|
68
|
+
* takeout's pages link to its files by the ids its file index names).
|
|
69
|
+
* The engine still hands each file to the shims on its own.
|
|
70
|
+
*/
|
|
71
|
+
archive?: IceArchiveView;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The archive a file was unpacked from (#2118): this file's own path in it,
|
|
75
|
+
* and every member, read only. Paths are the archive's own, `/`-separated.
|
|
76
|
+
* Never part of an item's key: what an item is, is its content.
|
|
77
|
+
*/
|
|
78
|
+
export interface IceArchiveView {
|
|
79
|
+
/** The archive's name, as the file's `name` begins: `takeout.zip`. */
|
|
80
|
+
name: string;
|
|
81
|
+
/** This file's path within the archive. */
|
|
82
|
+
path: string;
|
|
83
|
+
/** Every member's path, in the archive's order. */
|
|
84
|
+
paths: readonly string[];
|
|
85
|
+
/** A member's bytes, or undefined when there is no such member. */
|
|
86
|
+
read(memberPath: string): Buffer | undefined;
|
|
64
87
|
}
|
|
65
88
|
/**
|
|
66
89
|
* The `data` of a `record` item (#2109): one row of a table or one entry of a
|
|
@@ -99,6 +122,14 @@ export interface ShimTools {
|
|
|
99
122
|
*/
|
|
100
123
|
options: Record<string, unknown>;
|
|
101
124
|
}
|
|
125
|
+
/** What an `out` shim is handed (#2120): a shim's tools, and who the export is for. */
|
|
126
|
+
export interface ExportShimTools extends ShimTools {
|
|
127
|
+
/**
|
|
128
|
+
* The job context of the user who asked for the export, for a core shim
|
|
129
|
+
* that calls a core door with it (the PDF render, P1).
|
|
130
|
+
*/
|
|
131
|
+
ctx: ActorContext;
|
|
132
|
+
}
|
|
102
133
|
/** What a shim's read returns. */
|
|
103
134
|
export interface ShimReadResult {
|
|
104
135
|
items: IceItem[];
|
|
@@ -107,6 +138,13 @@ export interface ShimReadResult {
|
|
|
107
138
|
* records plus a partial note): the file's status is then `partial`, with this.
|
|
108
139
|
*/
|
|
109
140
|
partial?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Set, with no items, when the file is part of its format's layout and
|
|
143
|
+
* holds nothing to import on its own (#2118): a takeout's file index, read
|
|
144
|
+
* through the archive by the files it names. The file's status is then
|
|
145
|
+
* `noise`, with this, and the ledger records nothing for it.
|
|
146
|
+
*/
|
|
147
|
+
skip?: string;
|
|
110
148
|
}
|
|
111
149
|
/**
|
|
112
150
|
* A shim as its author writes it (D7). `name` is unique within its owner; the
|
|
@@ -132,8 +170,47 @@ export interface IceShim {
|
|
|
132
170
|
duplicates?: 'file' | 'item';
|
|
133
171
|
/** Inbound: read one input. Required for `in` and `both`. */
|
|
134
172
|
read?(input: IceItem, tools: ShimTools): Promise<ShimReadResult>;
|
|
135
|
-
/**
|
|
136
|
-
|
|
173
|
+
/**
|
|
174
|
+
* Outbound (export, #2120): turn the items into this shim's `produces`.
|
|
175
|
+
* Required for `out` and `both`. An outbound shim matches its input by
|
|
176
|
+
* `accepts.kinds` alone; a shim that produces `file` makes the download,
|
|
177
|
+
* and is what the Export action offers.
|
|
178
|
+
*/
|
|
179
|
+
write?(items: IceItem[], tools: ExportShimTools): Promise<IceItem[]>;
|
|
180
|
+
/**
|
|
181
|
+
* An outbound shim whose engine is missing says so (#2120): PDF with no
|
|
182
|
+
* provider chosen. The Export action does not offer it. Default: available.
|
|
183
|
+
*/
|
|
184
|
+
isAvailable?(): boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Vetting (#2149): clean this format's own kind of risky content out of a
|
|
187
|
+
* file that is about to be kept as a file (scripts and handlers in an SVG,
|
|
188
|
+
* HTML and formulas in CSV cells). Returns the cleaned bytes, and one note
|
|
189
|
+
* per kind of thing removed, saying what and how many, never the content.
|
|
190
|
+
* An inbound shim has `read()`, `clean()` or both; one with only `clean()`
|
|
191
|
+
* is never picked for a run.
|
|
192
|
+
*/
|
|
193
|
+
clean?(input: IceItem): Promise<IceCleanResult>;
|
|
194
|
+
}
|
|
195
|
+
/** What a shim's `clean` returns (#2149). `removed` is empty when the file needed nothing. */
|
|
196
|
+
export interface IceCleanResult {
|
|
197
|
+
bytes: Buffer;
|
|
198
|
+
removed: IceWarning[];
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* A file after the engine's vetting (#2149): its type read from its bytes,
|
|
202
|
+
* and, when its format's shim found something to clean, the cleaned bytes
|
|
203
|
+
* and what was removed. The caller keeps `bytes`, never the bytes it sent.
|
|
204
|
+
*/
|
|
205
|
+
export interface IceVetResult {
|
|
206
|
+
name: string;
|
|
207
|
+
bytes: Buffer;
|
|
208
|
+
/** From the bytes when they show it (#1624), else the declared or extension type. */
|
|
209
|
+
mediaType: string;
|
|
210
|
+
/** What cleaning removed, one note per kind; empty when nothing was. */
|
|
211
|
+
removed: IceWarning[];
|
|
212
|
+
/** The shim that cleaned it, when one did. */
|
|
213
|
+
cleanedBy?: string;
|
|
137
214
|
}
|
|
138
215
|
/** A shim the engine holds: its full id, and who registered it. */
|
|
139
216
|
export interface RegisteredShim extends IceShim {
|
|
@@ -214,6 +291,18 @@ export interface ReceiveInfo {
|
|
|
214
291
|
* taken there: never a silent replace.
|
|
215
292
|
*/
|
|
216
293
|
givenName?: string;
|
|
294
|
+
/**
|
|
295
|
+
* The place within the receiver the run goes to (#2118), for a receiver
|
|
296
|
+
* with `targets`: one its `targets` gave the user the run is for, checked
|
|
297
|
+
* by the engine before the run. The receiver's door still checks it.
|
|
298
|
+
*/
|
|
299
|
+
target?: string;
|
|
300
|
+
/**
|
|
301
|
+
* Set when the file was taken before and is read again only because the
|
|
302
|
+
* receiver `rechecks` this item (#2171): the receiver's own check decides
|
|
303
|
+
* whether it still holds it, and one it holds is `duplicate`.
|
|
304
|
+
*/
|
|
305
|
+
rechecked?: boolean;
|
|
217
306
|
}
|
|
218
307
|
/** What a receiver's `fileDone` is told (#2109). */
|
|
219
308
|
export interface FileDoneInfo extends ReceiveInfo {
|
|
@@ -236,6 +325,11 @@ export interface ReceiveOutcome {
|
|
|
236
325
|
*/
|
|
237
326
|
heldAs?: string;
|
|
238
327
|
}
|
|
328
|
+
/** A place within a receiver (#2118): a user's private store. */
|
|
329
|
+
export interface IceTarget {
|
|
330
|
+
id: string;
|
|
331
|
+
label?: string;
|
|
332
|
+
}
|
|
239
333
|
/**
|
|
240
334
|
* A receiver as its owner writes it (D4). Its doors are the receiver's own
|
|
241
335
|
* existing ones; each checks its own permission with the context given (D5).
|
|
@@ -294,6 +388,49 @@ export interface IceReceiver {
|
|
|
294
388
|
* before the run is queued; the run reuses what was kept and needs no key.
|
|
295
389
|
*/
|
|
296
390
|
keepsEncrypted?: boolean;
|
|
391
|
+
/**
|
|
392
|
+
* `receive` itself may write into an encrypted store (a takeout into a
|
|
393
|
+
* sealed private store, #2118), which only a request holding the user's
|
|
394
|
+
* unlocked key can write. The engine then runs an upload into it during
|
|
395
|
+
* the upload request, with the request's own context, instead of as a
|
|
396
|
+
* background job: no key is ever carried into a job (#2034's decision).
|
|
397
|
+
* An import into it is confidential (#2110). Core's only: an add-on
|
|
398
|
+
* receiver that declares it is refused at registration, so an add-on is
|
|
399
|
+
* confidential only through `keepsEncrypted`.
|
|
400
|
+
*/
|
|
401
|
+
writesEncrypted?: boolean;
|
|
402
|
+
/**
|
|
403
|
+
* A zip inside an uploaded zip is handed on as a file, not unpacked
|
|
404
|
+
* (#2118): for a receiver whose format holds zips as content (a takeout's
|
|
405
|
+
* files). Without it, the engine unpacks nested zips too.
|
|
406
|
+
*/
|
|
407
|
+
innerZipsAsFiles?: boolean;
|
|
408
|
+
/**
|
|
409
|
+
* The items this receiver checks for itself whether it still holds
|
|
410
|
+
* (#2118, operator 2026-10-30): a takeout's page, by its uuid, and a
|
|
411
|
+
* takeout's file, by its bytes (#2171), so one deleted since an earlier
|
|
412
|
+
* import comes back when the same takeout is imported again. A file whose
|
|
413
|
+
* fingerprint the scope already took is then read again, and only these
|
|
414
|
+
* of its items go to `receive`, with `info.rechecked`; the rest are
|
|
415
|
+
* duplicates. When nothing new is stored it stays `unchanged`, unrecorded,
|
|
416
|
+
* as the fingerprint skip leaves it. Without this, the fingerprint decides.
|
|
417
|
+
*/
|
|
418
|
+
rechecks?(item: IceItem): boolean;
|
|
419
|
+
/**
|
|
420
|
+
* The places within this receiver this context may import into (#2118):
|
|
421
|
+
* a user's own private stores. The receiver's own rule (D5). A receiver
|
|
422
|
+
* with targets takes a run only with one of them (`IceRunRequest.target`),
|
|
423
|
+
* which the engine checks against this before the run, binds into the
|
|
424
|
+
* ledger scope, and hands on in every item's `ReceiveInfo.target`.
|
|
425
|
+
*/
|
|
426
|
+
targets?(ctx: ActorContext): Promise<IceTarget[]>;
|
|
427
|
+
/**
|
|
428
|
+
* Called once when a run into this receiver has read every file (#2118),
|
|
429
|
+
* with its report: a receiver that records the run as one act (a
|
|
430
|
+
* takeout's `store-import` audit event). Not called for a refused run. A
|
|
431
|
+
* throw is the run's failure.
|
|
432
|
+
*/
|
|
433
|
+
runDone?(ctx: ActorContext, report: IceRunReport): Promise<void>;
|
|
297
434
|
/** The original-file choices this receiver offers (D11). Without it: all three. */
|
|
298
435
|
originals?: IceOriginalChoices;
|
|
299
436
|
/**
|
|
@@ -321,6 +458,8 @@ export interface IceUpload {
|
|
|
321
458
|
* drops it on a zip). Checked by the engine against the receiver's `names`.
|
|
322
459
|
*/
|
|
323
460
|
givenName?: string;
|
|
461
|
+
/** The archive the engine unpacked this file from (#2118); set by the engine, never by a caller. */
|
|
462
|
+
archive?: IceArchiveView;
|
|
324
463
|
}
|
|
325
464
|
/**
|
|
326
465
|
* A URL the engine fetches as the run's one file (D1, D10, #2109): through
|
|
@@ -378,6 +517,12 @@ export interface IceRunRequest {
|
|
|
378
517
|
* client sent.
|
|
379
518
|
*/
|
|
380
519
|
options?: Record<string, unknown>;
|
|
520
|
+
/**
|
|
521
|
+
* The place within the receiver (#2118), for a receiver with `targets`:
|
|
522
|
+
* one of those it gives the user the run is for. Required for such a
|
|
523
|
+
* receiver and refused for any other.
|
|
524
|
+
*/
|
|
525
|
+
target?: string;
|
|
381
526
|
}
|
|
382
527
|
/** Per-file status (first slice). */
|
|
383
528
|
export type IceFileStatus = 'imported' | 'partial' | 'unchanged' | 'duplicate' | 'noise' | 'unreadable' | 'refused' | 'failed';
|
|
@@ -410,6 +555,8 @@ export interface IceFileReport {
|
|
|
410
555
|
export interface IceRunReport {
|
|
411
556
|
runId: string;
|
|
412
557
|
receiver: string;
|
|
558
|
+
/** The place within the receiver (#2118), when it has places. */
|
|
559
|
+
target?: string;
|
|
413
560
|
scope: string;
|
|
414
561
|
/** Who it ran as. */
|
|
415
562
|
username: string;
|
|
@@ -461,6 +608,9 @@ export interface RecentImport {
|
|
|
461
608
|
/** The receiver it went into. */
|
|
462
609
|
receiver: string;
|
|
463
610
|
receiverLabel?: string;
|
|
611
|
+
/** The place within it (#2118), when the receiver has places. */
|
|
612
|
+
target?: string;
|
|
613
|
+
targetLabel?: string;
|
|
464
614
|
/** How many references the receiver gave (pages, records). */
|
|
465
615
|
refs: number;
|
|
466
616
|
/** Where the user can open the first of them (`linkFor`), when they may. */
|
|
@@ -482,3 +632,99 @@ export interface IceLedger {
|
|
|
482
632
|
recordItems(scope: string, itemKeys: string[]): Promise<void>;
|
|
483
633
|
files(scope: string): Promise<LedgerFileEntry[]>;
|
|
484
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* The kind of the one item an export ends with: a file to download, with
|
|
637
|
+
* `bytes`, `mediaType` and the `name` it is saved under.
|
|
638
|
+
*/
|
|
639
|
+
export declare const EXPORT_FILE_KIND = "file";
|
|
640
|
+
/** What an export source is told about the read it is asked for. */
|
|
641
|
+
export interface ExportReadInfo {
|
|
642
|
+
/** The shim that will make the file (`core.pdf`). */
|
|
643
|
+
format: string;
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* The owner's door for reading the thing being exported (#2120, D5): a page
|
|
647
|
+
* through PageManager, later a search result or an add-on's list. Export
|
|
648
|
+
* starts from the thing (operator, 2026-10-28): the source says what kind of
|
|
649
|
+
* items it yields, and only the `out` shims that can make a file from that
|
|
650
|
+
* kind are offered.
|
|
651
|
+
*/
|
|
652
|
+
export interface IceExportSource {
|
|
653
|
+
name: string;
|
|
654
|
+
label?: string;
|
|
655
|
+
/** The kind of the items it yields, e.g. `ncm` for a page. */
|
|
656
|
+
yields: IceKind;
|
|
657
|
+
/**
|
|
658
|
+
* Would this context be allowed to export `ref`? Asked only to decide
|
|
659
|
+
* whether to offer the Export action: an affordance, which records nothing.
|
|
660
|
+
* The owner's existing read rule (D5).
|
|
661
|
+
*/
|
|
662
|
+
mayExport(ref: string, ctx: ActorContext): Promise<boolean>;
|
|
663
|
+
/**
|
|
664
|
+
* Read `ref` for export as `ctx`: the door. It checks the owner's existing
|
|
665
|
+
* permission, records what its owner records, and answers null when the
|
|
666
|
+
* thing is not there or `ctx` may not export it, without telling the two apart.
|
|
667
|
+
*/
|
|
668
|
+
read(ref: string, ctx: ActorContext, info: ExportReadInfo): Promise<IceItem[] | null>;
|
|
669
|
+
/**
|
|
670
|
+
* Record how an export of `ref` ended, as its owner records exports: once
|
|
671
|
+
* the run has ended, with the file made or not. Also called, as a failure,
|
|
672
|
+
* when what was read is not exported (too large, the site too busy).
|
|
673
|
+
* Optional; a record that fails is logged, never thrown.
|
|
674
|
+
*/
|
|
675
|
+
recordExport?(ref: string, ctx: ActorContext, outcome: ExportOutcome): Promise<void>;
|
|
676
|
+
}
|
|
677
|
+
/** How an export ended, for its source's record (#2120). */
|
|
678
|
+
export interface ExportOutcome {
|
|
679
|
+
/** The shim that made, or was to make, the file. */
|
|
680
|
+
format: string;
|
|
681
|
+
runId: string;
|
|
682
|
+
/** The names of the items the source read. */
|
|
683
|
+
items: string[];
|
|
684
|
+
result: 'success' | 'failure';
|
|
685
|
+
/** Why it failed, as the user is told. */
|
|
686
|
+
reason?: string;
|
|
687
|
+
}
|
|
688
|
+
export interface RegisteredExportSource extends IceExportSource {
|
|
689
|
+
id: string;
|
|
690
|
+
owner: string;
|
|
691
|
+
}
|
|
692
|
+
/** A format the Export action offers: the shim that makes the file, and the shims before it. */
|
|
693
|
+
export interface IceExportFormat {
|
|
694
|
+
/** The shim that makes the file, `core.pdf`. */
|
|
695
|
+
id: string;
|
|
696
|
+
label: string;
|
|
697
|
+
/** Every shim the export runs through, in order, ending with `id`. */
|
|
698
|
+
chain: string[];
|
|
699
|
+
}
|
|
700
|
+
/** One export, as a caller asks for it. */
|
|
701
|
+
export interface IceExportRequest {
|
|
702
|
+
/** The export source's id, `core.pages`. */
|
|
703
|
+
source: string;
|
|
704
|
+
/** What to export, in the source's own terms: a page's name. */
|
|
705
|
+
ref: string;
|
|
706
|
+
/** The format: an id `exportFormatsFor` offered. */
|
|
707
|
+
format: string;
|
|
708
|
+
}
|
|
709
|
+
/** The file an export made, as its status shows it. */
|
|
710
|
+
export interface IceExportFile {
|
|
711
|
+
name: string;
|
|
712
|
+
mediaType: string;
|
|
713
|
+
size: number;
|
|
714
|
+
}
|
|
715
|
+
export interface IceExportReport {
|
|
716
|
+
runId: string;
|
|
717
|
+
source: string;
|
|
718
|
+
ref: string;
|
|
719
|
+
format: string;
|
|
720
|
+
chain: string[];
|
|
721
|
+
/** Who it ran as: the only user who sees it or downloads its file. */
|
|
722
|
+
username: string;
|
|
723
|
+
state: 'queued' | 'running' | 'done' | 'failed';
|
|
724
|
+
startedAt?: string;
|
|
725
|
+
finishedAt?: string;
|
|
726
|
+
error?: string;
|
|
727
|
+
file?: IceExportFile;
|
|
728
|
+
/** When the file is let go (`ngdpbase.export.engine.keep-minutes`). */
|
|
729
|
+
expiresAt?: string;
|
|
730
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IceUpload, IceVetResult, RegisteredShim } from './types.js';
|
|
2
|
+
/** A file whose format's shim failed while cleaning it: it is not kept, since it could not be checked. */
|
|
3
|
+
export declare class IceVetRefused extends Error {
|
|
4
|
+
readonly file: string;
|
|
5
|
+
readonly reason: string;
|
|
6
|
+
constructor(file: string, reason: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The shim that cleans this file: one whose media types include the type the
|
|
10
|
+
* bytes show; or, when the bytes show no type of their own (CSV, plain text),
|
|
11
|
+
* one whose extensions include the file's. Its "can I read this?" must agree.
|
|
12
|
+
*/
|
|
13
|
+
export declare function cleanerFor(shims: readonly RegisteredShim[], name: string, mediaType: string, bytesShowType: boolean): RegisteredShim | null;
|
|
14
|
+
/**
|
|
15
|
+
* Vet one file (#2149). `shims` are the enabled ones. Throws
|
|
16
|
+
* {@link IceVetRefused} when the cleaning shim fails: a file that could not
|
|
17
|
+
* be checked is not kept.
|
|
18
|
+
*/
|
|
19
|
+
export declare function vetFile(shims: readonly RegisteredShim[], upload: IceUpload): Promise<IceVetResult>;
|