@jwilleke/ngdpbase-types 5.26.0 → 5.28.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.
Files changed (52) hide show
  1. package/lib/packages/ngdpbase-types/index.d.ts +8 -2
  2. package/lib/packages/ngdpbase-types/testing.d.ts +7 -3
  3. package/lib/packages/ngdpbase-types/testing.js +7 -3
  4. package/lib/src/context/ActorContext.d.ts +15 -2
  5. package/lib/src/context/ActorContext.js +20 -0
  6. package/lib/src/converters/DocxConverter.d.ts +30 -0
  7. package/lib/src/converters/MarkdownConverter.d.ts +31 -0
  8. package/lib/src/export/ChromeServicePdfProvider.d.ts +52 -0
  9. package/lib/src/export/ChromeServicePdfProvider.js +153 -0
  10. package/lib/src/export/LocalChromePdfProvider.d.ts +25 -0
  11. package/lib/src/export/LocalChromePdfProvider.js +33 -0
  12. package/lib/src/export/PdfProvider.d.ts +51 -0
  13. package/lib/src/export/PdfProvider.js +37 -0
  14. package/lib/src/export/pdfEngine.d.ts +113 -0
  15. package/lib/src/export/pdfEngine.js +195 -0
  16. package/lib/src/ice/converterShim.d.ts +5 -0
  17. package/lib/src/ice/fileHandling.d.ts +30 -0
  18. package/lib/src/ice/ledger.d.ts +37 -0
  19. package/lib/src/ice/runImport.d.ts +51 -0
  20. package/lib/src/ice/types.d.ts +284 -0
  21. package/lib/src/mail/MailProvider.d.ts +15 -0
  22. package/lib/src/mail/NodemailerMailProvider.d.ts +1 -1
  23. package/lib/src/managers/AddonsManager.d.ts +25 -5
  24. package/lib/src/managers/AssetManager.d.ts +7 -3
  25. package/lib/src/managers/EmailManager.d.ts +32 -5
  26. package/lib/src/managers/ExportManager.d.ts +62 -0
  27. package/lib/src/managers/ExportManager.js +152 -2
  28. package/lib/src/managers/ImportManager.d.ts +611 -0
  29. package/lib/src/managers/OrganizationManager.d.ts +5 -3
  30. package/lib/src/managers/PageManager.d.ts +77 -1
  31. package/lib/src/managers/PersonManager.d.ts +36 -11
  32. package/lib/src/managers/RoleManager.d.ts +76 -17
  33. package/lib/src/managers/UserManager.d.ts +55 -2
  34. package/lib/src/security/PolicyDecisionPoint.d.ts +18 -9
  35. package/lib/src/security/PolicyInformationPoint.d.ts +48 -10
  36. package/lib/src/types/Config.d.ts +2 -0
  37. package/lib/src/types/User.d.ts +1 -1
  38. package/lib/src/utils/addonHost.d.ts +23 -2
  39. package/lib/src/utils/addonHost.js +25 -2
  40. package/lib/src/utils/auditEventNames.generated.d.ts +10 -10
  41. package/lib/src/utils/auditEventNames.generated.js +10 -10
  42. package/lib/src/utils/contactAccess.d.ts +30 -0
  43. package/lib/src/utils/frontmatterAccess.d.ts +54 -11
  44. package/lib/src/utils/importRunSummary.d.ts +64 -0
  45. package/lib/src/utils/keyedSerial.d.ts +31 -0
  46. package/lib/src/utils/ncmNotify.d.ts +30 -0
  47. package/lib/src/utils/privateStoreAccess.js +1 -3
  48. package/lib/src/utils/privateStoreImport.d.ts +58 -0
  49. package/lib/src/utils/roleChangeError.d.ts +25 -0
  50. package/lib/src/utils/subjectMayDo.d.ts +2 -2
  51. package/lib/src/utils/zipArchive.d.ts +71 -0
  52. package/package.json +1 -1
@@ -25,7 +25,6 @@
25
25
  * slice 4).
26
26
  */
27
27
  import { isJobContext } from '../context/ActorContext.js';
28
- import { toPermissionSubject } from '../context/JobContext.js';
29
28
  import { shareNamesVault } from '../types/Share.js';
30
29
  import { mixesProxyWithDelegation, proxyCarries } from './proxyClaim.js';
31
30
  export function mayActInPrivateContainer(ctx, owner, opts = {}) {
@@ -60,6 +59,5 @@ export function mayActInPrivateContainer(ctx, owner, opts = {}) {
60
59
  export async function permitsInVault(pdp, ctx, action, where) {
61
60
  if (!pdp || !mayActInPrivateContainer(ctx, where.owner, { vault: where.vault }))
62
61
  return false;
63
- const subject = isJobContext(ctx) ? toPermissionSubject(ctx) : ctx;
64
- return (await pdp.decide(subject, { action, resource: { type: 'page', id: where.resource }, attributes: { vault: where.vault } })).permit;
62
+ return (await pdp.decide(ctx, { action, resource: { type: 'page', id: where.resource }, attributes: { vault: where.vault } })).permit;
65
63
  }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Reading a takeout handed back for import (#1472) — the mirror of
3
+ * `privateStoreExport.ts`.
4
+ *
5
+ * Pure: entries in, a description of what they hold out. No I/O, no access
6
+ * decision, no write. The door that acts on it is
7
+ * `ImportManager.importOwnStoreTakeout`.
8
+ *
9
+ * What a takeout is, as #1387 writes it: one `{store}/` folder holding each
10
+ * page as `{title}.md` with full frontmatter, files under `attachments/`, and
11
+ * `files-index.json` mapping each file's id to its path in the archive. The
12
+ * reader is lenient about the one thing people change — the folder. Someone
13
+ * who extracts a takeout and zips it again may add a level, or zip the
14
+ * contents with no folder at all, so the takeout's root is found rather than
15
+ * assumed.
16
+ */
17
+ import type { ZipEntry } from './zipArchive.js';
18
+ /** One page of a takeout. */
19
+ export type TakeoutPage = {
20
+ /** Where it was in the archive — how the report names a page that failed. */
21
+ archivePath: string;
22
+ /** From the frontmatter, else the file's name. */
23
+ title: string;
24
+ /** From the frontmatter. Absent for a page written by hand. */
25
+ uuid?: string;
26
+ /** The frontmatter, as written. */
27
+ metadata: Record<string, unknown>;
28
+ body: string;
29
+ };
30
+ /** One file of a takeout. */
31
+ export type TakeoutFile = {
32
+ archivePath: string;
33
+ /** Its id where it came from, when the file index names it. */
34
+ oldId?: string;
35
+ /** The name it was uploaded with. */
36
+ name: string;
37
+ encodingFormat?: string;
38
+ description?: string;
39
+ bytes: Buffer;
40
+ };
41
+ export type ParsedTakeout = {
42
+ pages: TakeoutPage[];
43
+ files: TakeoutFile[];
44
+ /** Archive members that are neither a page nor a file, left alone. */
45
+ ignored: string[];
46
+ };
47
+ /** What a takeout's entries hold. */
48
+ export declare function readTakeout(entries: readonly ZipEntry[]): ParsedTakeout;
49
+ /** `body` with every `/attachments/{old}` link pointed at its new id. */
50
+ export declare function rewriteAttachmentLinks(body: string, ids: ReadonlyMap<string, string>): string;
51
+ /** Whether `body` links to the file `id`. */
52
+ export declare function linksToAttachment(body: string, id: string): boolean;
53
+ /**
54
+ * The first free title of `title`, `title (imported)`, `title (imported 2)` …
55
+ * (operator, 2026-09-25): a DIFFERENT page already holding the title keeps it,
56
+ * and the import lands beside it.
57
+ */
58
+ export declare function freeImportTitle(title: string, isTaken: (candidate: string) => Promise<boolean>): Promise<string>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A role change that did not happen (#2015).
3
+ *
4
+ * Operator, 2026-10-23: adding or removing a role completes or it does not
5
+ * happen, everywhere, and one that cannot be made is always an error. So a
6
+ * request that asks for several role changes either gets all of them or none:
7
+ * RoleManager undoes the ones that landed before the failure, then throws
8
+ * this, and the request that asked fails with it.
9
+ *
10
+ * The message is shown to whoever asked (an administrator's form). It names
11
+ * the account, the change that failed and, when it is something an
12
+ * administrator can fix, the reason (no Person record, no anchor
13
+ * Organization). Storage detail (paths, errno) stays in `cause`, for the log.
14
+ */
15
+ export declare class RoleChangeError extends Error {
16
+ /** The change that could not be made, as `add <role>` / `remove <role>`. */
17
+ readonly failed: readonly string[];
18
+ /** Changes that landed, could not be undone, and so are still in effect. Empty when nothing was left changed. */
19
+ readonly notUndone: readonly string[];
20
+ constructor(subject: string, failed: readonly string[], options?: {
21
+ reason?: string;
22
+ cause?: unknown;
23
+ notUndone?: readonly string[];
24
+ });
25
+ }
@@ -12,10 +12,10 @@
12
12
  * had somewhere to go that is not a second evaluator: a role name skips
13
13
  * PolicyEvaluator, deny policies and the token ceiling; this does not.
14
14
  */
15
- import type { PermissionSubject } from '../managers/UserManager.js';
15
+ import type { ActorContext } from '../context/ActorContext.js';
16
16
  import type { CorePermission } from '../security/permissions.generated.js';
17
17
  type EngineLike = {
18
18
  getManager: (name: string) => unknown;
19
19
  } | null | undefined;
20
- export declare function subjectMayDo(engine: EngineLike, subject: PermissionSubject | null | undefined, action: CorePermission): Promise<boolean>;
20
+ export declare function subjectMayDo(engine: EngineLike, subject: ActorContext | null | undefined, action: CorePermission): Promise<boolean>;
21
21
  export {};
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Writing a zip archive from bytes already in hand (#1387).
3
+ *
4
+ * A takeout lands on the owner's laptop or phone, and that decides the format:
5
+ * iOS, iPadOS, Android, Windows and macOS all open a `.zip` by tapping it,
6
+ * while `.tar.gz` needs a third-party app on exactly the devices people carry.
7
+ *
8
+ * This is the only archive the system writes, and `readZip` below is the only
9
+ * one it reads: a takeout handed back for import (#1472). The instance backup does not use
10
+ * one: it carries private files as base64 inside the backup document (#1387),
11
+ * so there is nothing to unpack on restore.
12
+ *
13
+ * Bytes in, one Buffer out: a takeout is decrypted, and nothing decrypted may
14
+ * be staged on the server's disk, so there is no file for a packer to read.
15
+ *
16
+ * Written here rather than taken from a library because the zip container is
17
+ * small and completely specified, while every candidate library wants to read
18
+ * from or write to the filesystem. The tests extract each archive with an
19
+ * independent implementation and compare the bytes, so this is checked against
20
+ * a real reader rather than against its own assumptions.
21
+ *
22
+ * Deliberately NOT implemented: zip64. An archive over 4 GiB, a member over
23
+ * 4 GiB, or more than 65,535 members is refused with a clear error rather than
24
+ * written as something an extractor would mis-read. A store that large wants
25
+ * streaming and zip64 together, which is its own piece of work.
26
+ */
27
+ /** One file to put in the archive. */
28
+ export type ZipEntry = {
29
+ /** Path inside the archive, `/`-separated, no leading slash. */
30
+ path: string;
31
+ bytes: Buffer;
32
+ /** Defaults to now. Zip stores 2-second resolution, and nothing before 1980. */
33
+ mtime?: Date;
34
+ };
35
+ export declare function crc32(buf: Buffer): number;
36
+ /**
37
+ * A zip archive of the given entries, as one Buffer.
38
+ *
39
+ * Entries are deflated when that makes them smaller — markdown compresses well,
40
+ * and a phone on mobile data is the expected destination — and stored as-is
41
+ * when it does not, which is the usual outcome for photos and other media.
42
+ */
43
+ export declare function packZip(entries: readonly ZipEntry[]): Promise<Buffer>;
44
+ /** Limits on what `readZip` will unpack, so an upload cannot exhaust memory. */
45
+ export type ZipReadLimits = {
46
+ /** Most members accepted. */
47
+ maxEntries: number;
48
+ /** Most bytes accepted once everything is inflated. */
49
+ maxTotalBytes: number;
50
+ };
51
+ /**
52
+ * The files in a zip archive, as bytes in memory (#1472).
53
+ *
54
+ * Read from the central directory, which is the archive's own table of
55
+ * contents, so a member written with a data descriptor — what a streaming
56
+ * writer, or an OS re-zipping a folder, produces — is read the same as any
57
+ * other. Directory entries are dropped, and so is what macOS adds when it
58
+ * zips a folder (`__MACOSX/`, `.DS_Store`): they are not anyone's data.
59
+ *
60
+ * Refused, with an error naming why, rather than read as something else:
61
+ *
62
+ * - a path that would climb out of wherever it is extracted — absolute, or
63
+ * holding a `..` segment, with `\` read as the separator it is on Windows;
64
+ * - encryption, zip64, split archives, and any method but stored and deflate;
65
+ * - a member whose inflated bytes do not match the size or CRC the archive
66
+ * declares for it;
67
+ * - more members, or more inflated bytes, than `limits` allow. Inflating is
68
+ * capped per member at what is left of the budget, so a small archive
69
+ * that expands enormously stops at the budget, not at the machine's memory.
70
+ */
71
+ export declare function readZip(archive: Buffer, limits: ZipReadLimits): ZipEntry[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jwilleke/ngdpbase-types",
3
- "version": "5.26.0",
3
+ "version": "5.28.0",
4
4
  "description": "TypeScript types for ngdpbase add-ons, and a test kit of core's own values. A dev dependency, versioned with ngdpbase.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Jim Willeke",