@crombolo/api-management 0.0.0-stage → 0.10.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/LICENSE +21 -0
- package/NOTICE +69 -0
- package/package.json +32 -4
- package/src/authorization.ts +453 -0
- package/src/handlers/content-type.ts +784 -0
- package/src/handlers/data-type.ts +267 -0
- package/src/handlers/dictionary.ts +245 -0
- package/src/handlers/document-blueprint.ts +193 -0
- package/src/handlers/document.ts +961 -0
- package/src/handlers/editor-services.ts +59 -0
- package/src/handlers/element.ts +492 -0
- package/src/handlers/file-systems.ts +207 -0
- package/src/handlers/import.ts +46 -0
- package/src/handlers/localization.ts +116 -0
- package/src/handlers/log-viewer.ts +125 -0
- package/src/handlers/manifest.ts +15 -0
- package/src/handlers/media.ts +453 -0
- package/src/handlers/member-group.ts +87 -0
- package/src/handlers/member.ts +189 -0
- package/src/handlers/models-builder.ts +29 -0
- package/src/handlers/package.ts +193 -0
- package/src/handlers/public-access.ts +107 -0
- package/src/handlers/published-cache.ts +27 -0
- package/src/handlers/redirects.ts +78 -0
- package/src/handlers/references.ts +44 -0
- package/src/handlers/server.ts +25 -0
- package/src/handlers/settings-stubs.ts +76 -0
- package/src/handlers/start-node-trees.ts +84 -0
- package/src/handlers/template-query.ts +191 -0
- package/src/handlers/template.ts +150 -0
- package/src/handlers/temporary-file.ts +62 -0
- package/src/handlers/user.ts +604 -0
- package/src/index.ts +17 -0
- package/src/ports-content.ts +564 -0
- package/src/ports-files.ts +51 -0
- package/src/ports-logs.ts +38 -0
- package/src/ports-members.ts +111 -0
- package/src/ports-models-builder.ts +26 -0
- package/src/ports-packages.ts +59 -0
- package/src/ports-users.ts +230 -0
- package/src/ports.ts +225 -0
- package/src/router.ts +216 -0
- package/src/routes.ts +99 -0
- package/src/server-events.ts +71 -0
- package/README.md +0 -3
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ports for content types, data types, templates and documents.
|
|
3
|
+
*
|
|
4
|
+
* Return types come from the generated contract so an implementation that drifts
|
|
5
|
+
* from the wire shape fails to compile.
|
|
6
|
+
*/
|
|
7
|
+
import type {
|
|
8
|
+
ComponentModel,
|
|
9
|
+
ContentTypeAggregate,
|
|
10
|
+
DataTypeModel,
|
|
11
|
+
DocumentAggregate,
|
|
12
|
+
DocumentTreeItem,
|
|
13
|
+
DocumentValidationError,
|
|
14
|
+
DocumentValue,
|
|
15
|
+
DocumentVersionSummary,
|
|
16
|
+
ElementTreeItem,
|
|
17
|
+
Page,
|
|
18
|
+
TreeItem,
|
|
19
|
+
} from '@crombolo/core'
|
|
20
|
+
import type { Principal } from './router.ts'
|
|
21
|
+
|
|
22
|
+
/** A failed port call; `status` overrides the handler's default 400 (409 for a write gate). */
|
|
23
|
+
export type PortFailure = {
|
|
24
|
+
ok: false
|
|
25
|
+
reason: string
|
|
26
|
+
status?: number
|
|
27
|
+
/** Validation failures, when the reason is the request's values. */
|
|
28
|
+
errors?: DocumentValidationError[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SkipTake {
|
|
32
|
+
skip: number
|
|
33
|
+
take: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A settings tree page: folders and items, or folders only. */
|
|
37
|
+
export interface TreePage extends SkipTake {
|
|
38
|
+
foldersOnly?: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface FolderInput {
|
|
42
|
+
key?: string
|
|
43
|
+
name: string
|
|
44
|
+
parentKey: string | null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Content types and media types share one port shape. */
|
|
48
|
+
export type ContentTypeKind = 'document' | 'media' | 'member'
|
|
49
|
+
|
|
50
|
+
/** Umbraco's TreeItemKind: which of folders and items a search returns. */
|
|
51
|
+
export type TreeItemKind = 'All' | 'Item' | 'Folder'
|
|
52
|
+
|
|
53
|
+
/** The Library section: a tree of folders, with no items in it yet. */
|
|
54
|
+
/**
|
|
55
|
+
* The Library section: Umbraco 18's Elements.
|
|
56
|
+
*
|
|
57
|
+
* Publishable, versioned content with no URL and no template — so this is the
|
|
58
|
+
* document port without URLs, templates, schedules or domains, plus the folders
|
|
59
|
+
* elements are gathered in. `folders` and the four tree reads stay as they were,
|
|
60
|
+
* because a folder is a plain node and the generic folder port already carries it.
|
|
61
|
+
*/
|
|
62
|
+
export interface ElementPort {
|
|
63
|
+
folders: FolderPort
|
|
64
|
+
treeRoot(paging: TreePage): Promise<Page<ElementTreeItem>>
|
|
65
|
+
treeChildren(parentKey: string, paging: TreePage): Promise<Page<ElementTreeItem>>
|
|
66
|
+
ancestors(descendantKey: string): Promise<ElementTreeItem[]>
|
|
67
|
+
items(keys: readonly string[]): Promise<ElementTreeItem[]>
|
|
68
|
+
treeSiblings(
|
|
69
|
+
target: string,
|
|
70
|
+
before: number,
|
|
71
|
+
after: number,
|
|
72
|
+
): Promise<{ items: ElementTreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
73
|
+
|
|
74
|
+
byKey(key: string): Promise<DocumentAggregate | undefined>
|
|
75
|
+
/** The published version's values; undefined when nothing is published. */
|
|
76
|
+
byKeyPublished(key: string): Promise<DocumentAggregate | undefined>
|
|
77
|
+
validate(input: SaveDocument, cultures: string[] | null): Promise<DocumentValidationError[]>
|
|
78
|
+
create(
|
|
79
|
+
input: SaveDocument,
|
|
80
|
+
principal: Principal,
|
|
81
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
82
|
+
update(
|
|
83
|
+
key: string,
|
|
84
|
+
input: SaveDocument,
|
|
85
|
+
principal: Principal,
|
|
86
|
+
): Promise<{ ok: true } | PortFailure>
|
|
87
|
+
createAndPublish(
|
|
88
|
+
input: SaveDocument,
|
|
89
|
+
cultures: string[] | null,
|
|
90
|
+
principal: Principal,
|
|
91
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
92
|
+
updateAndPublish(
|
|
93
|
+
key: string,
|
|
94
|
+
input: SaveDocument,
|
|
95
|
+
cultures: string[] | null,
|
|
96
|
+
principal: Principal,
|
|
97
|
+
): Promise<{ ok: true } | PortFailure>
|
|
98
|
+
publish(key: string, cultures: string[] | null): Promise<{ ok: true } | PortFailure>
|
|
99
|
+
unpublish(key: string, cultures: string[] | null): Promise<{ ok: true } | PortFailure>
|
|
100
|
+
copy(
|
|
101
|
+
key: string,
|
|
102
|
+
targetKey: string | null,
|
|
103
|
+
options: { includeDescendants: boolean },
|
|
104
|
+
principal: Principal,
|
|
105
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
106
|
+
move(key: string, targetKey: string | null): Promise<{ ok: true } | PortFailure>
|
|
107
|
+
moveToRecycleBin(key: string): Promise<boolean>
|
|
108
|
+
remove(key: string): Promise<boolean>
|
|
109
|
+
/** `targetKey` undefined restores to where it was trashed from. */
|
|
110
|
+
restore(key: string, targetKey: string | null | undefined): Promise<{ ok: true } | PortFailure>
|
|
111
|
+
emptyRecycleBin(): Promise<void>
|
|
112
|
+
/** null at the root; undefined when the element does not exist. */
|
|
113
|
+
originalParent(key: string): Promise<string | null | undefined>
|
|
114
|
+
recycleBin(parentKey: string | null, paging: SkipTake): Promise<Page<ElementTreeItem>>
|
|
115
|
+
recycleBinSiblings(
|
|
116
|
+
target: string,
|
|
117
|
+
before: number,
|
|
118
|
+
after: number,
|
|
119
|
+
): Promise<{ items: ElementTreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
120
|
+
search(
|
|
121
|
+
query: string,
|
|
122
|
+
options: { trashed?: boolean; parentKey?: string | null } & SkipTake,
|
|
123
|
+
): Promise<Page<ElementTreeItem>>
|
|
124
|
+
versions(key: string): Promise<DocumentVersionSummary[]>
|
|
125
|
+
/** The element as it stood at a version. */
|
|
126
|
+
atVersion(
|
|
127
|
+
versionId: string,
|
|
128
|
+
): Promise<{ versionId: string; document: DocumentAggregate } | undefined>
|
|
129
|
+
rollback(versionId: string): Promise<boolean>
|
|
130
|
+
setPreventCleanup(versionId: string, prevent: boolean): Promise<boolean>
|
|
131
|
+
/** The author the audit log falls back to, as documents and media do. */
|
|
132
|
+
systemUserKey(): Promise<string | null>
|
|
133
|
+
/**
|
|
134
|
+
* Folders move and trash too, which no other area's folders do — so these are
|
|
135
|
+
* here rather than on the shared `FolderPort`.
|
|
136
|
+
*/
|
|
137
|
+
moveFolder(key: string, targetKey: string | null): Promise<{ ok: true } | PortFailure>
|
|
138
|
+
folderToRecycleBin(key: string): Promise<boolean>
|
|
139
|
+
/** The folders alone, for the picker that chooses where a folder goes. */
|
|
140
|
+
folderItems(keys: readonly string[]): Promise<ElementTreeItem[]>
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface FolderPort {
|
|
144
|
+
/** Name search over the tree's folders and items. */
|
|
145
|
+
search(query: string, kind: TreeItemKind, paging: SkipTake): Promise<Page<TreeItem>>
|
|
146
|
+
folder(key: string): Promise<{ key: string; name: string; parentKey: string | null } | undefined>
|
|
147
|
+
createFolder(input: FolderInput): Promise<{ key: string }>
|
|
148
|
+
renameFolder(key: string, name: string): Promise<boolean>
|
|
149
|
+
deleteFolder(key: string): Promise<'deleted' | 'not-empty' | 'not-found'>
|
|
150
|
+
siblings(
|
|
151
|
+
target: string,
|
|
152
|
+
before: number,
|
|
153
|
+
after: number,
|
|
154
|
+
foldersOnly?: boolean,
|
|
155
|
+
): Promise<{ items: TreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface TreePort {
|
|
159
|
+
root(paging: SkipTake): Promise<Page<TreeItem>>
|
|
160
|
+
children(parentKey: string, paging: SkipTake): Promise<Page<TreeItem>>
|
|
161
|
+
ancestors(descendantKey: string): Promise<TreeItem[]>
|
|
162
|
+
items(keys: readonly string[]): Promise<TreeItem[]>
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface ContentTypePort extends TreePort {
|
|
166
|
+
byKey(key: string): Promise<ContentTypeAggregate | undefined>
|
|
167
|
+
create(aggregate: ContentTypeAggregate, principal: Principal): Promise<{ ok: true } | PortFailure>
|
|
168
|
+
update(
|
|
169
|
+
key: string,
|
|
170
|
+
aggregate: ContentTypeAggregate,
|
|
171
|
+
principal: Principal,
|
|
172
|
+
): Promise<{ ok: true } | PortFailure>
|
|
173
|
+
remove(key: string): Promise<boolean>
|
|
174
|
+
/** The type as Umbraco's `.udt` XML, or undefined when it is not there. */
|
|
175
|
+
exportUdt(key: string): Promise<string | undefined>
|
|
176
|
+
/**
|
|
177
|
+
* Creates from a `.udt` document, or updates `targetKey` from one. `mismatch`
|
|
178
|
+
* means the file describes a different kind or a different type.
|
|
179
|
+
*/
|
|
180
|
+
importUdt(
|
|
181
|
+
xml: string,
|
|
182
|
+
targetKey?: string,
|
|
183
|
+
): Promise<
|
|
184
|
+
| { status: 'ok'; key: string }
|
|
185
|
+
| { status: 'not-found' | 'invalid' | 'mismatch'; reason?: string }
|
|
186
|
+
>
|
|
187
|
+
/** The type's values as a JSON Schema, or undefined when it is not there. */
|
|
188
|
+
jsonSchema(key: string): Promise<Record<string, unknown> | undefined>
|
|
189
|
+
allowedAtRoot(paging: SkipTake): Promise<Page<ContentTypeAggregate>>
|
|
190
|
+
allowedInLibrary(paging: SkipTake): Promise<Page<ContentTypeAggregate>>
|
|
191
|
+
allowedChildren(key: string, paging: SkipTake): Promise<Page<ContentTypeAggregate>>
|
|
192
|
+
byKeys(keys: readonly string[]): Promise<ContentTypeAggregate[]>
|
|
193
|
+
search(
|
|
194
|
+
query: string,
|
|
195
|
+
options: { isElement?: boolean } & SkipTake,
|
|
196
|
+
): Promise<Page<ContentTypeAggregate>>
|
|
197
|
+
compositionReferences(key: string): Promise<ContentTypeAggregate[]>
|
|
198
|
+
allowedParents(key: string): Promise<string[]>
|
|
199
|
+
availableCompositions(request: {
|
|
200
|
+
key: string | null
|
|
201
|
+
isElement: boolean
|
|
202
|
+
currentPropertyAliases: string[]
|
|
203
|
+
currentCompositeKeys: string[]
|
|
204
|
+
}): Promise<Array<{ type: ContentTypeAggregate; folderPath: string[]; isCompatible: boolean }>>
|
|
205
|
+
move(key: string, parentKey: string | null): Promise<boolean>
|
|
206
|
+
copy(key: string, parentKey: string | null): Promise<ContentTypeAggregate | undefined>
|
|
207
|
+
/** Creates a view for the type and attaches it, as the "Create template" toggle does. Content types only. */
|
|
208
|
+
createTemplate(
|
|
209
|
+
key: string,
|
|
210
|
+
template: { alias: string; name: string; isDefault: boolean },
|
|
211
|
+
principal: Principal,
|
|
212
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
213
|
+
folders: FolderPort
|
|
214
|
+
/** Tree pages that may include folders. */
|
|
215
|
+
treeRoot(paging: TreePage): Promise<Page<TreeItem>>
|
|
216
|
+
treeChildren(parentKey: string, paging: TreePage): Promise<Page<TreeItem>>
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface DataTypePort extends TreePort {
|
|
220
|
+
/** The value a data type stores, as a JSON Schema; undefined when missing. */
|
|
221
|
+
valueSchema(
|
|
222
|
+
key: string,
|
|
223
|
+
): Promise<{ valueTypeName: string; jsonSchema: Record<string, unknown> } | undefined>
|
|
224
|
+
byKey(key: string): Promise<DataTypeModel | undefined>
|
|
225
|
+
byKeys(keys: readonly string[]): Promise<DataTypeModel[]>
|
|
226
|
+
save(model: DataTypeModel, principal: Principal): Promise<void>
|
|
227
|
+
/** 'in-use' when a property type still uses it. */
|
|
228
|
+
remove(key: string): Promise<boolean | 'in-use'>
|
|
229
|
+
filter(
|
|
230
|
+
criteria: { name?: string; editorAlias?: string; editorUiAlias?: string },
|
|
231
|
+
paging: SkipTake,
|
|
232
|
+
): Promise<Page<DataTypeModel>>
|
|
233
|
+
search(query: string, paging: SkipTake): Promise<Page<DataTypeModel>>
|
|
234
|
+
referencedBy(key: string): Promise<
|
|
235
|
+
Array<{
|
|
236
|
+
propertyKey: string
|
|
237
|
+
alias: string
|
|
238
|
+
name: string
|
|
239
|
+
contentType: { key: string; alias: string; name: string; icon: string }
|
|
240
|
+
}>
|
|
241
|
+
>
|
|
242
|
+
move(key: string, parentKey: string | null): Promise<boolean>
|
|
243
|
+
copy(key: string, parentKey: string | null): Promise<DataTypeModel | undefined>
|
|
244
|
+
folders: FolderPort
|
|
245
|
+
treeRoot(paging: TreePage): Promise<Page<TreeItem>>
|
|
246
|
+
treeChildren(parentKey: string, paging: TreePage): Promise<Page<TreeItem>>
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface TemplatePort extends TreePort {
|
|
250
|
+
byKey(key: string): Promise<ComponentModel | undefined>
|
|
251
|
+
save(model: ComponentModel, principal: Principal): Promise<void>
|
|
252
|
+
remove(key: string): Promise<boolean>
|
|
253
|
+
/** A starter view for a new template, as Umbraco scaffolds one. */
|
|
254
|
+
scaffold(name: string, alias: string): string
|
|
255
|
+
search(query: string, paging: SkipTake): Promise<Page<ComponentModel>>
|
|
256
|
+
siblings(
|
|
257
|
+
target: string,
|
|
258
|
+
before: number,
|
|
259
|
+
after: number,
|
|
260
|
+
): Promise<{ items: TreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface DocumentPort extends TreePort {
|
|
264
|
+
byKey(key: string): Promise<DocumentAggregate | undefined>
|
|
265
|
+
/** The published version's values; undefined when nothing is published. */
|
|
266
|
+
byKeyPublished(key: string): Promise<DocumentAggregate | undefined>
|
|
267
|
+
/** What the editor asks before a save: the rules the server would enforce. */
|
|
268
|
+
validate(input: SaveDocument, cultures: string[] | null): Promise<DocumentValidationError[]>
|
|
269
|
+
createAndPublish(
|
|
270
|
+
input: SaveDocument,
|
|
271
|
+
cultures: string[] | null,
|
|
272
|
+
principal: Principal,
|
|
273
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
274
|
+
updateAndPublish(
|
|
275
|
+
key: string,
|
|
276
|
+
input: SaveDocument,
|
|
277
|
+
cultures: string[] | null,
|
|
278
|
+
principal: Principal,
|
|
279
|
+
): Promise<{ ok: true } | PortFailure>
|
|
280
|
+
/** The content tree's own items, richer than the generic tree item. */
|
|
281
|
+
treeRoot(paging: SkipTake): Promise<Page<DocumentTreeItem>>
|
|
282
|
+
treeChildren(parentKey: string, paging: SkipTake): Promise<Page<DocumentTreeItem>>
|
|
283
|
+
treeAncestors(descendantKey: string): Promise<DocumentTreeItem[]>
|
|
284
|
+
/** Documents by key, in the order asked, skipping unknown keys. */
|
|
285
|
+
documentItems(keys: readonly string[]): Promise<DocumentTreeItem[]>
|
|
286
|
+
treeSiblings(
|
|
287
|
+
target: string,
|
|
288
|
+
before: number,
|
|
289
|
+
after: number,
|
|
290
|
+
): Promise<{ items: DocumentTreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
291
|
+
search(
|
|
292
|
+
query: string,
|
|
293
|
+
options: { trashed?: boolean; parentKey?: string | null } & SkipTake,
|
|
294
|
+
): Promise<Page<DocumentTreeItem>>
|
|
295
|
+
recycleBin(parentKey: string | null, paging: SkipTake): Promise<Page<DocumentTreeItem>>
|
|
296
|
+
recycleBinSiblings(
|
|
297
|
+
target: string,
|
|
298
|
+
before: number,
|
|
299
|
+
after: number,
|
|
300
|
+
): Promise<{ items: DocumentTreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
301
|
+
/** null at the root; undefined when the document does not exist. */
|
|
302
|
+
originalParent(key: string): Promise<string | null | undefined>
|
|
303
|
+
create(
|
|
304
|
+
input: SaveDocument,
|
|
305
|
+
principal: Principal,
|
|
306
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
307
|
+
update(
|
|
308
|
+
key: string,
|
|
309
|
+
input: SaveDocument,
|
|
310
|
+
principal: Principal,
|
|
311
|
+
): Promise<{ ok: true } | PortFailure>
|
|
312
|
+
publish(key: string, cultures: string[] | null): Promise<{ ok: true } | PortFailure>
|
|
313
|
+
unpublish(key: string, cultures: string[] | null): Promise<{ ok: true } | PortFailure>
|
|
314
|
+
moveToRecycleBin(key: string): Promise<boolean>
|
|
315
|
+
remove(key: string): Promise<boolean>
|
|
316
|
+
move(key: string, targetKey: string | null): Promise<{ ok: true } | PortFailure>
|
|
317
|
+
copy(
|
|
318
|
+
key: string,
|
|
319
|
+
targetKey: string | null,
|
|
320
|
+
options: { includeDescendants: boolean },
|
|
321
|
+
principal: Principal,
|
|
322
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
323
|
+
sort(
|
|
324
|
+
parentKey: string | null,
|
|
325
|
+
sorting: ReadonlyArray<{ key: string; sortOrder: number }>,
|
|
326
|
+
): Promise<{ ok: true } | PortFailure>
|
|
327
|
+
sortChildrenBy(
|
|
328
|
+
parentKey: string | null,
|
|
329
|
+
field: 'Name' | 'CreateDate' | 'UpdateDate',
|
|
330
|
+
direction: 'Ascending' | 'Descending',
|
|
331
|
+
): Promise<{ ok: true } | PortFailure>
|
|
332
|
+
/** `targetKey` undefined restores to where it was trashed from. */
|
|
333
|
+
restore(key: string, targetKey: string | null | undefined): Promise<{ ok: true } | PortFailure>
|
|
334
|
+
emptyRecycleBin(): Promise<void>
|
|
335
|
+
publishBranch(
|
|
336
|
+
key: string,
|
|
337
|
+
cultures: string[] | null,
|
|
338
|
+
includeUnpublished: boolean,
|
|
339
|
+
): Promise<
|
|
340
|
+
{ ok: true; published: string[]; failed: Array<{ key: string; reason: string }> } | PortFailure
|
|
341
|
+
>
|
|
342
|
+
/** Replaces the scheduled publish/unpublish of each culture given. */
|
|
343
|
+
schedule(
|
|
344
|
+
key: string,
|
|
345
|
+
entries: ReadonlyArray<{
|
|
346
|
+
culture: string | null
|
|
347
|
+
publishTime: Date | null
|
|
348
|
+
unpublishTime: Date | null
|
|
349
|
+
}>,
|
|
350
|
+
): Promise<boolean>
|
|
351
|
+
domains(key: string): Promise<DocumentDomains | undefined>
|
|
352
|
+
setDomains(
|
|
353
|
+
key: string,
|
|
354
|
+
domains: DocumentDomains,
|
|
355
|
+
): Promise<
|
|
356
|
+
/** `file` names the declaration the site keeps hostnames in, when it has one. */
|
|
357
|
+
| { status: 'ok'; file?: string }
|
|
358
|
+
| { status: 'notFound' }
|
|
359
|
+
| { status: 'invalidLanguage'; isoCode: string }
|
|
360
|
+
| { status: 'invalidName' | 'conflict'; domainName: string }
|
|
361
|
+
>
|
|
362
|
+
/** Every action the user may subscribe to on the document, and whether they have. */
|
|
363
|
+
notifications(
|
|
364
|
+
key: string,
|
|
365
|
+
principal: Principal,
|
|
366
|
+
): Promise<Array<{ actionId: string; alias: string; subscribed: boolean }> | undefined>
|
|
367
|
+
setNotifications(key: string, principal: Principal, actionIds: string[]): Promise<boolean>
|
|
368
|
+
/** The document as it stood at a version. */
|
|
369
|
+
atVersion(
|
|
370
|
+
versionId: string,
|
|
371
|
+
): Promise<{ versionId: string; document: DocumentAggregate } | undefined>
|
|
372
|
+
versions(key: string): Promise<DocumentVersionSummary[]>
|
|
373
|
+
/** Who a version with no recorded author is attributed to: the first administrator. */
|
|
374
|
+
systemUserKey(): Promise<string | null>
|
|
375
|
+
rollback(versionId: string): Promise<boolean>
|
|
376
|
+
setPreventCleanup(versionId: string, prevent: boolean): Promise<boolean>
|
|
377
|
+
/** Published URLs per culture, for the editor's info panel. */
|
|
378
|
+
urls(key: string): Promise<Array<{ culture: string | null; url: string }>>
|
|
379
|
+
collection(parentKey: string | null, paging: SkipTake): Promise<Page<DocumentAggregate>>
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export interface SaveDocument {
|
|
383
|
+
key: string
|
|
384
|
+
contentTypeKey: string
|
|
385
|
+
componentKey: string | null
|
|
386
|
+
parentKey: string | null
|
|
387
|
+
values: DocumentValue[]
|
|
388
|
+
variants: Array<{ culture: string | null; segment: string | null; name: string }>
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export interface DocumentDomains {
|
|
392
|
+
defaultIsoCode: string | null
|
|
393
|
+
domains: Array<{ domainName: string; isoCode: string }>
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Document blueprints: documents that are never published, used to prefill new ones. */
|
|
397
|
+
export interface BlueprintPort {
|
|
398
|
+
byKey(key: string): Promise<DocumentAggregate | undefined>
|
|
399
|
+
create(input: SaveDocument, principal: Principal): Promise<{ ok: true } | PortFailure>
|
|
400
|
+
update(
|
|
401
|
+
key: string,
|
|
402
|
+
input: SaveDocument,
|
|
403
|
+
principal: Principal,
|
|
404
|
+
): Promise<{ ok: true } | PortFailure>
|
|
405
|
+
/** A blueprint from a document's current draft, under `name`. */
|
|
406
|
+
fromDocument(
|
|
407
|
+
documentKey: string,
|
|
408
|
+
init: { key: string; name: string; parentKey: string | null },
|
|
409
|
+
principal: Principal,
|
|
410
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
411
|
+
remove(key: string): Promise<boolean>
|
|
412
|
+
move(key: string, targetKey: string | null): Promise<{ ok: true } | PortFailure>
|
|
413
|
+
versions(key: string): Promise<DocumentVersionSummary[]>
|
|
414
|
+
systemUserKey(): Promise<string | null>
|
|
415
|
+
/** Blueprints of one content type, by name. */
|
|
416
|
+
forContentType(
|
|
417
|
+
contentTypeKey: string,
|
|
418
|
+
paging: SkipTake,
|
|
419
|
+
): Promise<Page<{ key: string; name: string }>>
|
|
420
|
+
treeRoot(paging: TreePage): Promise<Page<TreeItem>>
|
|
421
|
+
treeChildren(parentKey: string, paging: TreePage): Promise<Page<TreeItem>>
|
|
422
|
+
treeAncestors(descendantKey: string): Promise<TreeItem[]>
|
|
423
|
+
treeSiblings(
|
|
424
|
+
target: string,
|
|
425
|
+
before: number,
|
|
426
|
+
after: number,
|
|
427
|
+
foldersOnly?: boolean,
|
|
428
|
+
): Promise<{ items: TreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
429
|
+
items(
|
|
430
|
+
keys: readonly string[],
|
|
431
|
+
): Promise<Array<{ key: string; name: string; contentTypeKey: string; icon: string }>>
|
|
432
|
+
folders: FolderPort
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/** Media: documents that never publish, whose file is served at its `umbracoFile` path. */
|
|
436
|
+
export interface MediaPort {
|
|
437
|
+
byKey(key: string): Promise<DocumentAggregate | undefined>
|
|
438
|
+
validate(input: SaveDocument): Promise<DocumentValidationError[]>
|
|
439
|
+
create(
|
|
440
|
+
input: SaveDocument,
|
|
441
|
+
principal: Principal,
|
|
442
|
+
): Promise<{ ok: true; key: string } | PortFailure>
|
|
443
|
+
update(
|
|
444
|
+
key: string,
|
|
445
|
+
input: SaveDocument,
|
|
446
|
+
principal: Principal,
|
|
447
|
+
): Promise<{ ok: true } | PortFailure>
|
|
448
|
+
/** Deletes a branch for good, and its files. */
|
|
449
|
+
remove(key: string): Promise<boolean>
|
|
450
|
+
moveToRecycleBin(key: string): Promise<boolean>
|
|
451
|
+
move(key: string, targetKey: string | null): Promise<{ ok: true } | PortFailure>
|
|
452
|
+
sort(
|
|
453
|
+
parentKey: string | null,
|
|
454
|
+
sorting: ReadonlyArray<{ key: string; sortOrder: number }>,
|
|
455
|
+
): Promise<{ ok: true } | PortFailure>
|
|
456
|
+
sortChildrenBy(
|
|
457
|
+
parentKey: string | null,
|
|
458
|
+
field: 'Name' | 'CreateDate' | 'UpdateDate',
|
|
459
|
+
direction: 'Ascending' | 'Descending',
|
|
460
|
+
): Promise<{ ok: true } | PortFailure>
|
|
461
|
+
restore(key: string, targetKey: string | null | undefined): Promise<{ ok: true } | PortFailure>
|
|
462
|
+
emptyRecycleBin(): Promise<void>
|
|
463
|
+
originalParent(key: string): Promise<string | null | undefined>
|
|
464
|
+
versions(key: string): Promise<DocumentVersionSummary[]>
|
|
465
|
+
systemUserKey(): Promise<string | null>
|
|
466
|
+
treeRoot(paging: SkipTake): Promise<Page<DocumentTreeItem>>
|
|
467
|
+
treeChildren(parentKey: string, paging: SkipTake): Promise<Page<DocumentTreeItem>>
|
|
468
|
+
treeAncestors(descendantKey: string): Promise<DocumentTreeItem[]>
|
|
469
|
+
treeSiblings(
|
|
470
|
+
target: string,
|
|
471
|
+
before: number,
|
|
472
|
+
after: number,
|
|
473
|
+
): Promise<{ items: DocumentTreeItem[]; totalBefore: number; totalAfter: number } | undefined>
|
|
474
|
+
recycleBin(parentKey: string | null, paging: SkipTake): Promise<Page<DocumentTreeItem>>
|
|
475
|
+
items(keys: readonly string[]): Promise<DocumentTreeItem[]>
|
|
476
|
+
search(
|
|
477
|
+
query: string,
|
|
478
|
+
options: { trashed?: boolean; parentKey?: string | null } & SkipTake,
|
|
479
|
+
): Promise<Page<DocumentTreeItem>>
|
|
480
|
+
/** A folder's children for the media collection view, with their values. */
|
|
481
|
+
collection(
|
|
482
|
+
parentKey: string | null,
|
|
483
|
+
options: {
|
|
484
|
+
filter?: string
|
|
485
|
+
orderBy: string
|
|
486
|
+
orderDirection: 'Ascending' | 'Descending'
|
|
487
|
+
} & SkipTake,
|
|
488
|
+
): Promise<Page<DocumentAggregate & { sortOrder: number; creator: string | null }>>
|
|
489
|
+
/** The URL of each item's file, if it has one. */
|
|
490
|
+
urls(keys: readonly string[]): Promise<Array<{ key: string; url: string | null }>>
|
|
491
|
+
/** Media types an upload of this extension can become, as Umbraco matches them. */
|
|
492
|
+
typesForExtension(
|
|
493
|
+
extension: string,
|
|
494
|
+
): Promise<Array<{ key: string; name: string; icon: string; matched: boolean }>>
|
|
495
|
+
/** Media types that act as folders: no file, and something allowed inside. */
|
|
496
|
+
folderTypes(): Promise<Array<{ key: string; name: string; icon: string }>>
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/** What refers to a document, media item or member — the Info tab's list. */
|
|
500
|
+
export interface ReferencePort {
|
|
501
|
+
referencedBy(key: string, paging: SkipTake): Promise<Page<unknown>>
|
|
502
|
+
referencedDescendants(key: string, paging: SkipTake): Promise<Page<{ id: string }>>
|
|
503
|
+
areReferenced(keys: readonly string[], paging: SkipTake): Promise<Page<{ id: string }>>
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** One redirect as the dashboard and the Info tab read it. */
|
|
507
|
+
export interface RedirectListing {
|
|
508
|
+
key: string
|
|
509
|
+
originalUrl: string
|
|
510
|
+
destinationUrl: string
|
|
511
|
+
culture: string | null
|
|
512
|
+
/** The document it points at, when it points at one. */
|
|
513
|
+
documentKey: string | null
|
|
514
|
+
created: Date
|
|
515
|
+
/** A rule the site's configuration owns cannot be deleted through the API. */
|
|
516
|
+
isConfigured: boolean
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/** The Redirect URL Management dashboard, and the redirects on a page's Info tab. */
|
|
520
|
+
export interface RedirectPort {
|
|
521
|
+
list(filter: string | undefined, paging: SkipTake): Promise<Page<RedirectListing>>
|
|
522
|
+
byDocument(key: string, paging: SkipTake): Promise<Page<RedirectListing>>
|
|
523
|
+
/** `'configured'` refuses a rule the site's config owns. */
|
|
524
|
+
remove(key: string): Promise<'deleted' | 'notFound' | 'configured'>
|
|
525
|
+
/** Whether renaming a page records a redirect; from the site's config. */
|
|
526
|
+
isTracking(): boolean
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/** One filter the template query builder applies, in the contract's vocabulary. */
|
|
530
|
+
export interface TemplateQueryFilter {
|
|
531
|
+
propertyAlias: string
|
|
532
|
+
constraintValue: string
|
|
533
|
+
operator: string
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
export interface TemplateQuerySort {
|
|
537
|
+
propertyAlias: string
|
|
538
|
+
direction: string | null
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/** A query the builder describes, normalised out of the wire model. */
|
|
542
|
+
export interface TemplateQueryRequest {
|
|
543
|
+
/** The document the query starts below, or null for the page being rendered. */
|
|
544
|
+
rootKey: string | null
|
|
545
|
+
documentTypeAlias: string | null
|
|
546
|
+
filters: TemplateQueryFilter[]
|
|
547
|
+
sort: TemplateQuerySort | null
|
|
548
|
+
take: number
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
export interface TemplateQueryItem {
|
|
552
|
+
icon: string
|
|
553
|
+
name: string
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Runs what the query builder describes, so the count and the sample it shows
|
|
558
|
+
* are the answer the generated snippet would give.
|
|
559
|
+
*/
|
|
560
|
+
export interface TemplateQueryPort {
|
|
561
|
+
/** The aliases a query may be narrowed to: the routable content types. */
|
|
562
|
+
documentTypeAliases(): Promise<string[]>
|
|
563
|
+
execute(request: TemplateQueryRequest): Promise<{ items: TemplateQueryItem[]; total: number }>
|
|
564
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-system areas of the Settings section — partial views, stylesheets and
|
|
3
|
+
* scripts — where the files on disk are the entities and their paths
|
|
4
|
+
* (`/folder/site.css`, relative to the area's root) are their ids.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface FileEntry {
|
|
8
|
+
path: string
|
|
9
|
+
name: string
|
|
10
|
+
parentPath: string | null
|
|
11
|
+
isFolder: boolean
|
|
12
|
+
hasChildren: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface FileContent {
|
|
16
|
+
path: string
|
|
17
|
+
name: string
|
|
18
|
+
parentPath: string | null
|
|
19
|
+
content: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Umbraco's file-system operation statuses. */
|
|
23
|
+
export type FileStatus =
|
|
24
|
+
| 'AlreadyExists'
|
|
25
|
+
| 'NotFound'
|
|
26
|
+
| 'ParentNotFound'
|
|
27
|
+
| 'InvalidName'
|
|
28
|
+
| 'InvalidFileExtension'
|
|
29
|
+
| 'NotEmpty'
|
|
30
|
+
|
|
31
|
+
export type FileResult = { ok: true; path: string } | { ok: false; status: FileStatus }
|
|
32
|
+
|
|
33
|
+
export interface FileSystemPort {
|
|
34
|
+
/** Folders then files, each by name; the root when `parentPath` is null. */
|
|
35
|
+
children(parentPath: string | null): Promise<FileEntry[] | undefined>
|
|
36
|
+
entry(path: string): Promise<FileEntry | undefined>
|
|
37
|
+
read(path: string): Promise<FileContent | undefined>
|
|
38
|
+
create(parentPath: string | null, name: string, content: string): Promise<FileResult>
|
|
39
|
+
update(path: string, content: string): Promise<FileResult>
|
|
40
|
+
rename(path: string, name: string): Promise<FileResult>
|
|
41
|
+
delete(path: string): Promise<FileResult>
|
|
42
|
+
createFolder(parentPath: string | null, name: string): Promise<FileResult>
|
|
43
|
+
deleteFolder(path: string): Promise<FileResult>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** A partial view snippet the "create from snippet" dialog offers. */
|
|
47
|
+
export interface Snippet {
|
|
48
|
+
id: string
|
|
49
|
+
name: string
|
|
50
|
+
content: string
|
|
51
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** The Settings section's log viewer: the site's log files, and the searches saved against them. */
|
|
2
|
+
|
|
3
|
+
export type LogLevelName = 'Verbose' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Fatal'
|
|
4
|
+
|
|
5
|
+
export interface LogRange {
|
|
6
|
+
start: Date | null
|
|
7
|
+
end: Date | null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface LogEntry {
|
|
11
|
+
timestamp: string
|
|
12
|
+
level: LogLevelName
|
|
13
|
+
messageTemplate: string
|
|
14
|
+
renderedMessage: string
|
|
15
|
+
exception: string | null
|
|
16
|
+
properties: Array<{ name: string; value: string | null }>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface LogViewerPort {
|
|
20
|
+
/** Whether the files for the range are small enough to read (Umbraco's 100 MB cap). */
|
|
21
|
+
canView(range: LogRange): Promise<boolean>
|
|
22
|
+
levelCounts(
|
|
23
|
+
range: LogRange,
|
|
24
|
+
): Promise<{ information: number; debug: number; warning: number; error: number; fatal: number }>
|
|
25
|
+
/** Each message template with how often it was logged, most frequent first. */
|
|
26
|
+
templates(range: LogRange): Promise<Array<{ messageTemplate: string; count: number }>>
|
|
27
|
+
/** Entries matching the filter expression and levels, ordered by time. */
|
|
28
|
+
logs(
|
|
29
|
+
range: LogRange,
|
|
30
|
+
query: { filter: string | null; levels: LogLevelName[]; direction: 'Ascending' | 'Descending' },
|
|
31
|
+
): Promise<LogEntry[]>
|
|
32
|
+
/** The loggers and the least severe level each writes; `Global` is the one the viewer shows. */
|
|
33
|
+
loggers(): Array<{ name: string; level: LogLevelName }>
|
|
34
|
+
savedSearches(): Promise<Array<{ name: string; query: string }>>
|
|
35
|
+
savedSearch(name: string): Promise<{ name: string; query: string } | undefined>
|
|
36
|
+
saveSearch(name: string, query: string): Promise<'created' | 'duplicate'>
|
|
37
|
+
deleteSearch(name: string): Promise<boolean>
|
|
38
|
+
}
|