@kernhq/module-quire 0.13.1 → 0.15.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/dist/contract/models.d.ts +394 -0
- package/dist/contract/models.d.ts.map +1 -1
- package/dist/contract/models.js +284 -0
- package/dist/contract/models.js.map +1 -1
- package/dist/contract/permissions.d.ts +14 -0
- package/dist/contract/permissions.d.ts.map +1 -1
- package/dist/contract/permissions.js +114 -0
- package/dist/contract/permissions.js.map +1 -1
- package/dist/contract/properties.d.ts +7 -7
- package/dist/contract/router.d.ts +1124 -96
- package/dist/contract/router.d.ts.map +1 -1
- package/dist/contract/router.js +343 -1
- package/dist/contract/router.js.map +1 -1
- package/dist/server/_impl.d.ts +983 -1168
- package/dist/server/_impl.d.ts.map +1 -1
- package/dist/server/_impl.js +308 -0
- package/dist/server/_impl.js.map +1 -1
- package/dist/server/export/html.d.ts +67 -0
- package/dist/server/export/html.d.ts.map +1 -0
- package/dist/server/export/html.js +206 -0
- package/dist/server/export/html.js.map +1 -0
- package/dist/server/export/markdown.d.ts +51 -0
- package/dist/server/export/markdown.d.ts.map +1 -0
- package/dist/server/export/markdown.js +351 -0
- package/dist/server/export/markdown.js.map +1 -0
- package/dist/server/export/pdf.d.ts +20 -0
- package/dist/server/export/pdf.d.ts.map +1 -0
- package/dist/server/export/pdf.js +91 -0
- package/dist/server/export/pdf.js.map +1 -0
- package/dist/server/export/zip.d.ts +31 -0
- package/dist/server/export/zip.d.ts.map +1 -0
- package/dist/server/export/zip.js +158 -0
- package/dist/server/export/zip.js.map +1 -0
- package/dist/server/import/csv.d.ts +77 -0
- package/dist/server/import/csv.d.ts.map +1 -0
- package/dist/server/import/csv.js +263 -0
- package/dist/server/import/csv.js.map +1 -0
- package/dist/server/import/html.d.ts +52 -0
- package/dist/server/import/html.d.ts.map +1 -0
- package/dist/server/import/html.js +472 -0
- package/dist/server/import/html.js.map +1 -0
- package/dist/server/import/markdown.d.ts +63 -0
- package/dist/server/import/markdown.d.ts.map +1 -0
- package/dist/server/import/markdown.js +692 -0
- package/dist/server/import/markdown.js.map +1 -0
- package/dist/server/import/plan.d.ts +70 -0
- package/dist/server/import/plan.d.ts.map +1 -0
- package/dist/server/import/plan.js +761 -0
- package/dist/server/import/plan.js.map +1 -0
- package/dist/server/import/ydoc.d.ts +35 -0
- package/dist/server/import/ydoc.d.ts.map +1 -0
- package/dist/server/import/ydoc.js +91 -0
- package/dist/server/import/ydoc.js.map +1 -0
- package/dist/server/import/zip.d.ts +63 -0
- package/dist/server/import/zip.d.ts.map +1 -0
- package/dist/server/import/zip.js +308 -0
- package/dist/server/import/zip.js.map +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/render.d.ts +158 -0
- package/dist/server/render.d.ts.map +1 -1
- package/dist/server/render.js +240 -0
- package/dist/server/render.js.map +1 -1
- package/dist/server/schema.d.ts +704 -1
- package/dist/server/schema.d.ts.map +1 -1
- package/dist/server/schema.js +254 -1
- package/dist/server/schema.js.map +1 -1
- package/dist/server/services/databases.d.ts +10 -10
- package/dist/server/services/export.d.ts +176 -0
- package/dist/server/services/export.d.ts.map +1 -0
- package/dist/server/services/export.js +822 -0
- package/dist/server/services/export.js.map +1 -0
- package/dist/server/services/import.d.ts +109 -0
- package/dist/server/services/import.d.ts.map +1 -0
- package/dist/server/services/import.js +570 -0
- package/dist/server/services/import.js.map +1 -0
- package/dist/server/services/index.d.ts +32 -1
- package/dist/server/services/index.d.ts.map +1 -1
- package/dist/server/services/index.js +87 -4
- package/dist/server/services/index.js.map +1 -1
- package/dist/server/services/macros.d.ts +83 -0
- package/dist/server/services/macros.d.ts.map +1 -0
- package/dist/server/services/macros.js +488 -0
- package/dist/server/services/macros.js.map +1 -0
- package/dist/server/services/publications.d.ts +2 -1
- package/dist/server/services/publications.d.ts.map +1 -1
- package/dist/server/services/publications.js +43 -4
- package/dist/server/services/publications.js.map +1 -1
- package/dist/server/services/templates.d.ts +135 -0
- package/dist/server/services/templates.d.ts.map +1 -0
- package/dist/server/services/templates.js +897 -0
- package/dist/server/services/templates.js.map +1 -0
- package/dist/server/services/versions.d.ts +13 -1
- package/dist/server/services/versions.d.ts.map +1 -1
- package/dist/server/services/versions.js +3 -1
- package/dist/server/services/versions.js.map +1 -1
- package/migrations/0010_transfers.sql +154 -0
- package/migrations/0011_templates.sql +157 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +5 -5
- package/src/client/components/ExportDialog.svelte +685 -0
- package/src/client/components/ImportDialog.svelte +702 -0
- package/src/client/components/ImportReport.svelte +310 -0
- package/src/client/components/NewSpaceDialog.svelte +77 -8
- package/src/client/components/PageEditor.svelte +80 -0
- package/src/client/components/PagePicker.svelte +264 -0
- package/src/client/components/SaveAsTemplateDialog.svelte +502 -0
- package/src/client/components/SidebarSpaces.svelte +112 -1
- package/src/client/components/TemplatePicker.svelte +437 -0
- package/src/client/i18n.ts +941 -0
- package/src/client/index.ts +51 -0
- package/src/client/mock.ts +592 -0
- package/src/client/module.ts +36 -0
- package/src/client/pages/PageView.svelte +86 -0
- package/src/client/pages/SpacePage.svelte +20 -4
- package/src/client/pages/TransfersPage.svelte +570 -0
- package/src/client/permissions.ts +11 -0
- package/src/client/query.ts +40 -0
- package/src/client/transfers.ts +142 -0
- package/src/contract/models.ts +343 -0
- package/src/contract/permissions.ts +117 -0
- package/src/contract/router.ts +375 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import type { Kernel } from '@kernhq/kernel';
|
|
1
|
+
import type { JobDef, Kernel } from '@kernhq/kernel';
|
|
2
2
|
import { quireAccess } from './access.js';
|
|
3
3
|
import { quireComments } from './comments.js';
|
|
4
4
|
import { quireDatabases } from './databases.js';
|
|
5
|
+
import { quireExport } from './export.js';
|
|
6
|
+
import { quireImport } from './import.js';
|
|
7
|
+
import { quireMacros } from './macros.js';
|
|
5
8
|
import { quireOrganisation } from './organisation.js';
|
|
6
9
|
import { quirePages } from './pages.js';
|
|
7
10
|
import { quirePublications } from './publications.js';
|
|
8
11
|
import { quireSpaces } from './spaces.js';
|
|
12
|
+
import { quireTemplates } from './templates.js';
|
|
9
13
|
import { quireVersions } from './versions.js';
|
|
10
14
|
export interface QuireServices {
|
|
11
15
|
access: ReturnType<typeof quireAccess>;
|
|
@@ -16,17 +20,44 @@ export interface QuireServices {
|
|
|
16
20
|
databases: ReturnType<typeof quireDatabases>;
|
|
17
21
|
organisation: ReturnType<typeof quireOrganisation>;
|
|
18
22
|
publications: ReturnType<typeof quirePublications>;
|
|
23
|
+
exports: ReturnType<typeof quireExport>;
|
|
24
|
+
imports: ReturnType<typeof quireImport>;
|
|
25
|
+
templates: ReturnType<typeof quireTemplates>;
|
|
26
|
+
macros: ReturnType<typeof quireMacros>;
|
|
19
27
|
}
|
|
20
28
|
/** One set of services per kernel: they are stateless, and rebuilding them per request is waste. */
|
|
21
29
|
export declare function quireServices(kernel: Kernel): QuireServices;
|
|
30
|
+
/**
|
|
31
|
+
* The background work this module hands to a worker process, gathered here rather than in
|
|
32
|
+
* `index.ts`.
|
|
33
|
+
*
|
|
34
|
+
* One line in the module definition, so adding a job is an edit to this file and not to the file
|
|
35
|
+
* every other part of the module is also editing. The names reach pg-boss as `quire.<name>` — the
|
|
36
|
+
* kernel prefixes them — and only a process started with a worker role runs them; an API process
|
|
37
|
+
* registers nothing and merely sends.
|
|
38
|
+
*
|
|
39
|
+
* `retryLimit` is deliberately small. An export that fails for a reason of its own — Gotenberg is
|
|
40
|
+
* not running, a page will not render — records that reason on its row and returns *successfully*,
|
|
41
|
+
* because it has finished: it failed, and it said so, and repeating it would only write the same
|
|
42
|
+
* sentence three more times. A throw out of the handler means something underneath went wrong
|
|
43
|
+
* (the database, the broker), which is the case a retry is for.
|
|
44
|
+
*/
|
|
45
|
+
export declare const quireJobs: JobDef<{
|
|
46
|
+
workspaceId: string;
|
|
47
|
+
jobId: string;
|
|
48
|
+
}>[];
|
|
22
49
|
export * from './access.js';
|
|
23
50
|
export * from './comments.js';
|
|
24
51
|
export * from './databases.js';
|
|
52
|
+
export * from './export.js';
|
|
53
|
+
export * from './import.js';
|
|
54
|
+
export * from './macros.js';
|
|
25
55
|
export * from './organisation.js';
|
|
26
56
|
export * from './pages.js';
|
|
27
57
|
export * from './publications.js';
|
|
28
58
|
/** The public surface resolves a workspace slug before anything touches the schema. */
|
|
29
59
|
export { resolveWorkspaceSegment } from './publications.js';
|
|
30
60
|
export * from './spaces.js';
|
|
61
|
+
export * from './templates.js';
|
|
31
62
|
export * from './versions.js';
|
|
32
63
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;IACtC,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;IACtC,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;IACpC,QAAQ,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;IAC1C,QAAQ,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;IAC1C,SAAS,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;IAC5C,YAAY,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;IAClD,YAAY,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;IAClD,OAAO,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;IACvC,OAAO,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;IACvC,SAAS,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;IAC5C,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CACvC;AAID,oGAAoG;AACpG,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CA0C3D;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAiCrE,CAAA;AAED,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,YAAY,CAAA;AAC1B,cAAc,mBAAmB,CAAA;AACjC,uFAAuF;AACvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
1
2
|
import { quireAccess } from './access.js';
|
|
2
3
|
import { quireComments } from './comments.js';
|
|
3
4
|
import { quireDatabases } from './databases.js';
|
|
5
|
+
import { quireExport } from './export.js';
|
|
6
|
+
import { quireImport } from './import.js';
|
|
7
|
+
import { quireMacros } from './macros.js';
|
|
4
8
|
import { quireOrganisation } from './organisation.js';
|
|
5
9
|
import { quirePages } from './pages.js';
|
|
6
10
|
import { quirePublications } from './publications.js';
|
|
7
11
|
import { quireSpaces } from './spaces.js';
|
|
12
|
+
import { quireTemplates } from './templates.js';
|
|
8
13
|
import { quireVersions } from './versions.js';
|
|
9
14
|
const cache = new WeakMap();
|
|
10
15
|
/** One set of services per kernel: they are stateless, and rebuilding them per request is waste. */
|
|
@@ -14,27 +19,105 @@ export function quireServices(kernel) {
|
|
|
14
19
|
return existing;
|
|
15
20
|
const access = quireAccess(kernel);
|
|
16
21
|
const versions = quireVersions(kernel, access);
|
|
22
|
+
// An import writes pages *and* databases, so it is the one service built on another one: it needs
|
|
23
|
+
// `databases` to mint the properties whose keys its rows are keyed by. See `import.ts`'s `write`.
|
|
24
|
+
const databases = quireDatabases(kernel, access);
|
|
25
|
+
/*
|
|
26
|
+
* Templates make pages and spaces, so they are built on the two services that already know how —
|
|
27
|
+
* a second implementation of "create a page" would be a second fractional-index algorithm, and two
|
|
28
|
+
* orderings of one tree is a sidebar that disagrees with itself.
|
|
29
|
+
*/
|
|
30
|
+
const spaces = quireSpaces(access);
|
|
31
|
+
const pages = quirePages(access);
|
|
32
|
+
/*
|
|
33
|
+
* Built before `publications`, which needs it: a published page's HTML is rendered on the public
|
|
34
|
+
* path, and a macro inside it has to resolve there too — against the publication rather than
|
|
35
|
+
* against a reader, because on that path there is no reader at all.
|
|
36
|
+
*/
|
|
37
|
+
const macros = quireMacros(kernel, access);
|
|
17
38
|
const services = {
|
|
18
39
|
access,
|
|
19
|
-
spaces
|
|
20
|
-
pages
|
|
40
|
+
spaces,
|
|
41
|
+
pages,
|
|
21
42
|
versions,
|
|
22
43
|
comments: quireComments(access),
|
|
23
|
-
databases
|
|
44
|
+
databases,
|
|
24
45
|
organisation: quireOrganisation(access),
|
|
25
|
-
publications: quirePublications(kernel, access, versions),
|
|
46
|
+
publications: quirePublications(kernel, access, versions, macros),
|
|
47
|
+
exports: quireExport(kernel, access),
|
|
48
|
+
imports: quireImport(kernel, access, databases),
|
|
49
|
+
templates: quireTemplates(kernel, access, pages, spaces),
|
|
50
|
+
/*
|
|
51
|
+
* Macros resolve *reads* against whoever is reading, so this service has `access` and nothing
|
|
52
|
+
* that writes. It is deliberately not built on `pages`: a macro must never reach a procedure
|
|
53
|
+
* that answers for the caller rather than for the reader.
|
|
54
|
+
*/
|
|
55
|
+
macros,
|
|
26
56
|
};
|
|
27
57
|
cache.set(kernel, services);
|
|
28
58
|
return services;
|
|
29
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* The background work this module hands to a worker process, gathered here rather than in
|
|
62
|
+
* `index.ts`.
|
|
63
|
+
*
|
|
64
|
+
* One line in the module definition, so adding a job is an edit to this file and not to the file
|
|
65
|
+
* every other part of the module is also editing. The names reach pg-boss as `quire.<name>` — the
|
|
66
|
+
* kernel prefixes them — and only a process started with a worker role runs them; an API process
|
|
67
|
+
* registers nothing and merely sends.
|
|
68
|
+
*
|
|
69
|
+
* `retryLimit` is deliberately small. An export that fails for a reason of its own — Gotenberg is
|
|
70
|
+
* not running, a page will not render — records that reason on its row and returns *successfully*,
|
|
71
|
+
* because it has finished: it failed, and it said so, and repeating it would only write the same
|
|
72
|
+
* sentence three more times. A throw out of the handler means something underneath went wrong
|
|
73
|
+
* (the database, the broker), which is the case a retry is for.
|
|
74
|
+
*/
|
|
75
|
+
export const quireJobs = [
|
|
76
|
+
{
|
|
77
|
+
name: 'export',
|
|
78
|
+
schema: z.object({ workspaceId: z.uuid(), jobId: z.uuid() }),
|
|
79
|
+
handler: async (input, { kernel }) => {
|
|
80
|
+
await quireServices(kernel).exports.run(input.workspaceId, input.jobId);
|
|
81
|
+
},
|
|
82
|
+
options: { retryLimit: 2, retryDelay: 30, expireInSeconds: 900 },
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* An import, with **no retries at all** — the one place in this module where that is the safe
|
|
86
|
+
* setting rather than the timid one.
|
|
87
|
+
*
|
|
88
|
+
* `run` is idempotent against its own row (`done` and `failed` are terminal, and it claims the row
|
|
89
|
+
* before it does anything), so a retry after a *completed* run is a no-op. What a retry cannot be
|
|
90
|
+
* safe against is the case pg-boss actually retries: a handler that threw. An import commits its
|
|
91
|
+
* pages and its finished row in one transaction, so a throw means nothing was written — but a
|
|
92
|
+
* *lost connection after the commit* looks exactly the same from here, and running it again would
|
|
93
|
+
* write every page in the archive a second time. Two hundred duplicate pages in somebody's space
|
|
94
|
+
* is a worse outcome than a job that says it failed and can be started again by a person who can
|
|
95
|
+
* see what is in the space.
|
|
96
|
+
*
|
|
97
|
+
* The window is longer than an export's for the obvious reason: reading a few hundred megabytes of
|
|
98
|
+
* zip and writing four thousand rows is not a fifteen-minute job on a busy instance.
|
|
99
|
+
*/
|
|
100
|
+
{
|
|
101
|
+
name: 'import',
|
|
102
|
+
schema: z.object({ workspaceId: z.uuid(), jobId: z.uuid() }),
|
|
103
|
+
handler: async (input, { kernel }) => {
|
|
104
|
+
await quireServices(kernel).imports.run(input.workspaceId, input.jobId);
|
|
105
|
+
},
|
|
106
|
+
options: { retryLimit: 0, expireInSeconds: 3600 },
|
|
107
|
+
},
|
|
108
|
+
];
|
|
30
109
|
export * from './access.js';
|
|
31
110
|
export * from './comments.js';
|
|
32
111
|
export * from './databases.js';
|
|
112
|
+
export * from './export.js';
|
|
113
|
+
export * from './import.js';
|
|
114
|
+
export * from './macros.js';
|
|
33
115
|
export * from './organisation.js';
|
|
34
116
|
export * from './pages.js';
|
|
35
117
|
export * from './publications.js';
|
|
36
118
|
/** The public surface resolves a workspace slug before anything touches the schema. */
|
|
37
119
|
export { resolveWorkspaceSegment } from './publications.js';
|
|
38
120
|
export * from './spaces.js';
|
|
121
|
+
export * from './templates.js';
|
|
39
122
|
export * from './versions.js';
|
|
40
123
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/services/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/services/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a macro is allowed to say, to the person actually reading.
|
|
3
|
+
*
|
|
4
|
+
* Five of the eight macros draw pages that are not in the document — `pageChildren`,
|
|
5
|
+
* `excerptInclude`, `includePage`, `recentlyUpdated` and `contributors`. Everything about them that
|
|
6
|
+
* matters is in this file, because this is the only place that decides *which* pages, and the
|
|
7
|
+
* decision is the feature's whole risk: a children macro that forgets its filter still compiles,
|
|
8
|
+
* still renders, and looks right to the author, because the author can read everything on it.
|
|
9
|
+
*
|
|
10
|
+
* The rule, in three parts, and `macros.int.test.ts` holds all three:
|
|
11
|
+
*
|
|
12
|
+
* 1. **The renderer never reads a database.** `renderPageDoc` draws a reading macro only from a
|
|
13
|
+
* `MacroResolver` it was handed. With none — which is what every caller written before this
|
|
14
|
+
* feature passes, the exporters and the publish-time render included — a reading macro draws
|
|
15
|
+
* its frame and nothing else. Fail-closed is the default rather than a branch to remember.
|
|
16
|
+
* 2. **A signed-in reader sees exactly what they could open.** Every page named here is asked
|
|
17
|
+
* about with `quire.page.view` at *page* scope, so a DENY bound to one page removes it.
|
|
18
|
+
* 3. **A published site has no reader, so the publication is the audience.** The set of publicly
|
|
19
|
+
* reachable pages — which `publications.walk` already computes, root first and pruned — is the
|
|
20
|
+
* whole of what exists. Anything outside it is not drawn as a title with a dead link; it is
|
|
21
|
+
* not drawn.
|
|
22
|
+
*
|
|
23
|
+
* Two structural choices follow from that and are worth stating rather than leaving to be inferred.
|
|
24
|
+
*
|
|
25
|
+
* **Resolution is a pass, not a per-node lookup.** `macrosIn` collects the reading macros in a
|
|
26
|
+
* document and de-duplicates them by their attributes, this file answers them against one audience,
|
|
27
|
+
* and `renderPageDoc` reads the answers out of a map. The alternative — resolving inside the
|
|
28
|
+
* renderer — is a database round trip per macro in render order, on a request that is otherwise two
|
|
29
|
+
* queries, and it would make the renderer async for every caller that has no macros at all.
|
|
30
|
+
*
|
|
31
|
+
* **A prune is not a filter.** Where a page is not visible, its descendants go with it. Removing a
|
|
32
|
+
* page from a children list and then listing its children anyway would name every page under it to
|
|
33
|
+
* whoever guessed there was something there, which is exactly the shape `publications.ts`'s walk
|
|
34
|
+
* exists to avoid — and the reason that walk prunes is the reason this one does.
|
|
35
|
+
*/
|
|
36
|
+
import type { Principal } from '@kernhq/contracts';
|
|
37
|
+
import type { Kernel, Tx } from '@kernhq/kernel';
|
|
38
|
+
import { type PageDoc } from '@kernhq/ui/editor/page-doc';
|
|
39
|
+
import { type MacroResolver } from '../render.js';
|
|
40
|
+
import type { QuireAccess } from './access.js';
|
|
41
|
+
/**
|
|
42
|
+
* Who is being drawn for.
|
|
43
|
+
*
|
|
44
|
+
* A discriminated union with exactly two members, and there is deliberately no third: a caller
|
|
45
|
+
* cannot express "resolve this for nobody in particular", because that is the shape that leaks. A
|
|
46
|
+
* caller with no audience passes no resolver at all, and the renderer draws empty frames.
|
|
47
|
+
*/
|
|
48
|
+
export type MacroAudience = {
|
|
49
|
+
kind: 'reader';
|
|
50
|
+
principal: Principal;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The publicly reachable pages, as `publications.walk` computed them for *this* publication.
|
|
54
|
+
* A set rather than a publication id, so this file cannot disagree with the walk about what
|
|
55
|
+
* "public" means — there is only one definition of it and it is not here.
|
|
56
|
+
*/
|
|
57
|
+
| {
|
|
58
|
+
kind: 'publication';
|
|
59
|
+
pageIds: ReadonlySet<string>;
|
|
60
|
+
};
|
|
61
|
+
export interface MacroContext {
|
|
62
|
+
/** The page the document belongs to. `null` for a render with no page — a preview, an import. */
|
|
63
|
+
pageId: string | null;
|
|
64
|
+
/** Where to send a reader for a page id, if this render has addresses at all. */
|
|
65
|
+
pageHref?: (pageId: string) => string | null;
|
|
66
|
+
/** For the dates a list macro draws. `principal.locale` for a reader; the site's for a publication. */
|
|
67
|
+
locale?: string | null;
|
|
68
|
+
}
|
|
69
|
+
export declare function quireMacros(kernel: Kernel, access: QuireAccess): {
|
|
70
|
+
/**
|
|
71
|
+
* Answer every reading macro in a document, for one audience, in one pass.
|
|
72
|
+
*
|
|
73
|
+
* Returns the synchronous lookup `renderPageDoc` takes. A macro this could not answer — a page
|
|
74
|
+
* that was deleted, a page the audience may not see, a lookup that failed — is simply absent
|
|
75
|
+
* from the map, and an absent answer is the empty frame. There is no path through this function
|
|
76
|
+
* that returns a page the audience failed the gate on, and no way to express one: `visible` is
|
|
77
|
+
* the only thing that builds a `MacroPageRef`'s input, and every caller of `refOf` has just
|
|
78
|
+
* awaited it.
|
|
79
|
+
*/
|
|
80
|
+
resolve(tx: Tx, workspaceId: string, doc: PageDoc | null | undefined, audience: MacroAudience, ctx: MacroContext): Promise<MacroResolver>;
|
|
81
|
+
};
|
|
82
|
+
export type QuireMacros = ReturnType<typeof quireMacros>;
|
|
83
|
+
//# sourceMappingURL=macros.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"macros.d.ts","sourceRoot":"","sources":["../../../src/server/services/macros.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAGL,KAAK,OAAO,EAEb,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAGL,KAAK,aAAa,EAKnB,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE;AAC1C;;;;GAIG;GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAEzD,MAAM,WAAW,YAAY;IAC3B,iGAAiG;IACjG,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IAC5C,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AA6GD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAgV3D;;;;;;;;;OASG;gBAEG,EAAE,eACO,MAAM,OACd,OAAO,GAAG,IAAI,GAAG,SAAS,YACrB,aAAa,OAClB,YAAY,GAChB,OAAO,CAAC,aAAa,CAAC;EA0H5B;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA"}
|