@occultist/occultist 0.0.8 → 0.0.10
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/actions/context.d.ts +10 -1
- package/dist/actions/context.js +29 -0
- package/dist/mod.d.ts +1 -0
- package/dist/mod.js +1 -0
- package/dist/registry.d.ts +20 -0
- package/dist/registry.js +48 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.js +2 -0
- package/lib/actions/context.ts +34 -1
- package/lib/mod.ts +1 -0
- package/lib/registry.ts +59 -0
- package/lib/types.ts +41 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CacheOperation, HandlerDefinition } from "../mod.ts";
|
|
1
|
+
import type { CacheOperation, HandlerDefinition, StaticAsset } from "../mod.ts";
|
|
2
2
|
import type { Registry } from "../registry.ts";
|
|
3
3
|
import type { ActionPayload, ActionSpec, ContextState, ParsedIRIValues } from "./spec.ts";
|
|
4
4
|
import type { AuthState, ImplementedAction } from "./types.ts";
|
|
@@ -84,5 +84,14 @@ export declare class Context<State extends ContextState = ContextState, Auth ext
|
|
|
84
84
|
set status(status: number);
|
|
85
85
|
get body(): undefined | ResponseBody;
|
|
86
86
|
set body(body: ResponseBody);
|
|
87
|
+
/**
|
|
88
|
+
* Returns the public facing URL of a static asset using its
|
|
89
|
+
* static file alias.
|
|
90
|
+
*
|
|
91
|
+
* @param assetAlias The alias of the static asset.
|
|
92
|
+
* @param cspDirective A directive to add the asset to when generating CSP headers.
|
|
93
|
+
* @returns The public facing URL of the static asset.
|
|
94
|
+
*/
|
|
95
|
+
useAsset(assetAlias: string, cspDirective?: string): StaticAsset | undefined;
|
|
87
96
|
get [Symbol.toStringTag](): string;
|
|
88
97
|
}
|
package/dist/actions/context.js
CHANGED
|
@@ -3,6 +3,8 @@ class EditableContext {
|
|
|
3
3
|
etag;
|
|
4
4
|
status;
|
|
5
5
|
body;
|
|
6
|
+
staticAssets = new Map();
|
|
7
|
+
cspDirectives;
|
|
6
8
|
}
|
|
7
9
|
;
|
|
8
10
|
/**
|
|
@@ -121,6 +123,33 @@ export class Context {
|
|
|
121
123
|
set body(body) {
|
|
122
124
|
this.#editable.body = body;
|
|
123
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Returns the public facing URL of a static asset using its
|
|
128
|
+
* static file alias.
|
|
129
|
+
*
|
|
130
|
+
* @param assetAlias The alias of the static asset.
|
|
131
|
+
* @param cspDirective A directive to add the asset to when generating CSP headers.
|
|
132
|
+
* @returns The public facing URL of the static asset.
|
|
133
|
+
*/
|
|
134
|
+
useAsset(assetAlias, cspDirective) {
|
|
135
|
+
const staticAlias = assetAlias.split('/')[0];
|
|
136
|
+
const extension = this.registry.getStaticExtension(staticAlias);
|
|
137
|
+
if (extension == null)
|
|
138
|
+
return;
|
|
139
|
+
const asset = extension.getAsset(assetAlias);
|
|
140
|
+
if (asset == null)
|
|
141
|
+
return;
|
|
142
|
+
this.#editable.staticAssets.set(asset.alias, asset);
|
|
143
|
+
if (typeof cspDirective === 'string' && cspDirective != null) {
|
|
144
|
+
if (!this.#editable.cspDirectives.has(cspDirective)) {
|
|
145
|
+
this.#editable.cspDirectives.set(cspDirective, [asset.alias]);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
this.#editable.cspDirectives.get(cspDirective).push(asset.alias);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return asset;
|
|
152
|
+
}
|
|
124
153
|
get [Symbol.toStringTag]() {
|
|
125
154
|
return `action=${this.action.name} method=${this.method} contentType=${this.contentType}`;
|
|
126
155
|
}
|
package/dist/mod.d.ts
CHANGED
package/dist/mod.js
CHANGED
package/dist/registry.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { IncomingMessage, type ServerResponse } from "node:http";
|
|
|
7
7
|
import type { Merge } from "./actions/spec.ts";
|
|
8
8
|
import type { ContextState, Middleware } from "./actions/spec.ts";
|
|
9
9
|
import { type CacheOperationResult } from "./mod.ts";
|
|
10
|
+
import type { Extension, StaticExtension } from "./types.ts";
|
|
10
11
|
export interface Callable<State extends ContextState = ContextState> {
|
|
11
12
|
method(method: string, name: string, path: string): ActionAuth<State>;
|
|
12
13
|
}
|
|
@@ -248,6 +249,25 @@ export declare class Registry<State extends ContextState = ContextState> impleme
|
|
|
248
249
|
* @returns A NodeJS server response instance.
|
|
249
250
|
*/
|
|
250
251
|
handleRequest(req: IncomingMessage, res: ServerResponse): Promise<ServerResponse>;
|
|
252
|
+
/**
|
|
253
|
+
* Retrieves a static extension by one of the static aliases it uses.
|
|
254
|
+
*
|
|
255
|
+
* @param staticAlias A static alias used to create paths to files served
|
|
256
|
+
* by the static extension.
|
|
257
|
+
*/
|
|
258
|
+
getStaticExtension(staticAlias: string): StaticExtension | undefined;
|
|
259
|
+
/**
|
|
260
|
+
* Registers an Occultist extension. This is usually done
|
|
261
|
+
* by extensions when they are created.
|
|
262
|
+
*
|
|
263
|
+
* @param The Occultist extension to register.
|
|
264
|
+
*/
|
|
265
|
+
registerExtension(extension: Extension): void;
|
|
266
|
+
/**
|
|
267
|
+
* Must be called after all Occultist extensions have been registered.
|
|
268
|
+
* When some of the extensions have async setup tasks.
|
|
269
|
+
*/
|
|
270
|
+
setupExtensions(): Promise<void>;
|
|
251
271
|
addEventListener(type: RegistryEvents, callback: EventListener): void;
|
|
252
272
|
removeEventListener(type: RegistryEvents, callback: EventListener): void;
|
|
253
273
|
}
|
package/dist/registry.js
CHANGED
|
@@ -122,6 +122,8 @@ export class Registry {
|
|
|
122
122
|
#middleware = [];
|
|
123
123
|
#actions = null;
|
|
124
124
|
#handlers = null;
|
|
125
|
+
#extensions = [];
|
|
126
|
+
#staticExtensions = new Map();
|
|
125
127
|
constructor(args) {
|
|
126
128
|
const url = new URL(args.rootIRI);
|
|
127
129
|
this.#rootIRI = args.rootIRI;
|
|
@@ -499,6 +501,52 @@ export class Registry {
|
|
|
499
501
|
return res;
|
|
500
502
|
}
|
|
501
503
|
}
|
|
504
|
+
/**
|
|
505
|
+
* Retrieves a static extension by one of the static aliases it uses.
|
|
506
|
+
*
|
|
507
|
+
* @param staticAlias A static alias used to create paths to files served
|
|
508
|
+
* by the static extension.
|
|
509
|
+
*/
|
|
510
|
+
getStaticExtension(staticAlias) {
|
|
511
|
+
return this.#staticExtensions.get(staticAlias);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Registers an Occultist extension. This is usually done
|
|
515
|
+
* by extensions when they are created.
|
|
516
|
+
*
|
|
517
|
+
* @param The Occultist extension to register.
|
|
518
|
+
*/
|
|
519
|
+
registerExtension(extension) {
|
|
520
|
+
let staticAlias;
|
|
521
|
+
if (typeof extension.getAsset === 'function' &&
|
|
522
|
+
Array.isArray(extension.staticAliases)) {
|
|
523
|
+
for (let i = 0; i < extension.staticAliases.length; i++) {
|
|
524
|
+
staticAlias = extension.staticAliases[i];
|
|
525
|
+
if (this.#staticExtensions.has(staticAlias)) {
|
|
526
|
+
throw new Error(`Static alias '${staticAlias}' already used by other extension`);
|
|
527
|
+
}
|
|
528
|
+
this.#staticExtensions.set(staticAlias, extension);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
this.#extensions.push(extension);
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Must be called after all Occultist extensions have been registered.
|
|
535
|
+
* When some of the extensions have async setup tasks.
|
|
536
|
+
*/
|
|
537
|
+
async setupExtensions() {
|
|
538
|
+
const setupStreams = [];
|
|
539
|
+
for (let i = 0; i < this.#extensions.length; i++) {
|
|
540
|
+
if (typeof this.#extensions[i].setup === 'function') {
|
|
541
|
+
setupStreams.push(this.#extensions[i].setup());
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
for (let i = 0; i < setupStreams.length; i++) {
|
|
545
|
+
for await (const message of setupStreams[i]) {
|
|
546
|
+
console.log(message);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
502
550
|
addEventListener(type, callback) {
|
|
503
551
|
this.#eventTarget.addEventListener(type, callback);
|
|
504
552
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
export interface StaticAsset {
|
|
2
|
+
alias: string;
|
|
3
|
+
contentType: string;
|
|
4
|
+
url: string;
|
|
5
|
+
integrity?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface StaticContext {
|
|
8
|
+
link(alias: string, as: string): string;
|
|
9
|
+
}
|
|
10
|
+
export interface Extension {
|
|
11
|
+
name: string;
|
|
12
|
+
setup?(): ReadableStream;
|
|
13
|
+
getAsset?(): StaticAsset | undefined;
|
|
14
|
+
staticAliases?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface StaticExtension {
|
|
17
|
+
/**
|
|
18
|
+
* The name of the static extension.
|
|
19
|
+
*/
|
|
20
|
+
name: string;
|
|
21
|
+
/**
|
|
22
|
+
* Root level aliases the extension uses to identify
|
|
23
|
+
* assets it manages.
|
|
24
|
+
*/
|
|
25
|
+
staticAliases: string[];
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves a static assets from the extension.
|
|
28
|
+
*
|
|
29
|
+
* @param assetAlias The alias for the asset.
|
|
30
|
+
*/
|
|
31
|
+
getAsset(assetAlias: string): StaticAsset | undefined;
|
|
32
|
+
}
|
|
1
33
|
export type ProblemDetailsParam = {
|
|
2
34
|
name: string;
|
|
3
35
|
reason: string;
|
package/dist/types.js
CHANGED
package/lib/actions/context.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {CacheOperation, HandlerDefinition} from "../mod.ts";
|
|
1
|
+
import type {CacheOperation, HandlerDefinition, StaticAsset} from "../mod.ts";
|
|
2
2
|
import type {Registry} from "../registry.ts";
|
|
3
3
|
import type {ActionPayload, ActionSpec, ContextState, ParsedIRIValues} from "./spec.ts";
|
|
4
4
|
import type {AuthState, ImplementedAction} from "./types.ts";
|
|
@@ -10,6 +10,8 @@ class EditableContext {
|
|
|
10
10
|
etag?: string;
|
|
11
11
|
status?: number;
|
|
12
12
|
body?: ResponseBody;
|
|
13
|
+
staticAssets: Map<string, StaticAsset> = new Map();
|
|
14
|
+
cspDirectives: Map<string, string[]>;
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
export type CacheContextArgs<
|
|
@@ -187,6 +189,37 @@ export class Context<
|
|
|
187
189
|
this.#editable.body = body;
|
|
188
190
|
}
|
|
189
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Returns the public facing URL of a static asset using its
|
|
194
|
+
* static file alias.
|
|
195
|
+
*
|
|
196
|
+
* @param assetAlias The alias of the static asset.
|
|
197
|
+
* @param cspDirective A directive to add the asset to when generating CSP headers.
|
|
198
|
+
* @returns The public facing URL of the static asset.
|
|
199
|
+
*/
|
|
200
|
+
useAsset(assetAlias: string, cspDirective?: string): StaticAsset | undefined {
|
|
201
|
+
const staticAlias = assetAlias.split('/')[0];
|
|
202
|
+
const extension = this.registry.getStaticExtension(staticAlias);
|
|
203
|
+
|
|
204
|
+
if (extension == null) return;
|
|
205
|
+
|
|
206
|
+
const asset = extension.getAsset(assetAlias);
|
|
207
|
+
|
|
208
|
+
if (asset == null) return;
|
|
209
|
+
|
|
210
|
+
this.#editable.staticAssets.set(asset.alias, asset);
|
|
211
|
+
|
|
212
|
+
if (typeof cspDirective === 'string' && cspDirective != null) {
|
|
213
|
+
if (!this.#editable.cspDirectives.has(cspDirective)) {
|
|
214
|
+
this.#editable.cspDirectives.set(cspDirective, [asset.alias]);
|
|
215
|
+
} else {
|
|
216
|
+
this.#editable.cspDirectives.get(cspDirective).push(asset.alias);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return asset;
|
|
221
|
+
}
|
|
222
|
+
|
|
190
223
|
get [Symbol.toStringTag]() {
|
|
191
224
|
return `action=${this.action.name} method=${this.method} contentType=${this.contentType}`;
|
|
192
225
|
}
|
package/lib/mod.ts
CHANGED
package/lib/registry.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { ContextState, Middleware } from "./actions/spec.ts";
|
|
|
11
11
|
import {ProblemDetailsError} from "./errors.ts"
|
|
12
12
|
import {WrappedRequest} from "./request.ts";
|
|
13
13
|
import {type CacheOperationResult} from "./mod.ts";
|
|
14
|
+
import type {Extension, StaticExtension} from "./types.ts";
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
export interface Callable<
|
|
@@ -187,6 +188,8 @@ export class Registry<
|
|
|
187
188
|
#middleware: Middleware[] = [];
|
|
188
189
|
#actions: ImplementedAction[] | null = null;
|
|
189
190
|
#handlers: HandlerDefinition[] | null = null;
|
|
191
|
+
#extensions: Extension[] = [];
|
|
192
|
+
#staticExtensions: Map<string, StaticExtension> = new Map();
|
|
190
193
|
|
|
191
194
|
constructor(args: RegistryArgs) {
|
|
192
195
|
const url = new URL(args.rootIRI);
|
|
@@ -731,6 +734,62 @@ export class Registry<
|
|
|
731
734
|
}
|
|
732
735
|
}
|
|
733
736
|
|
|
737
|
+
/**
|
|
738
|
+
* Retrieves a static extension by one of the static aliases it uses.
|
|
739
|
+
*
|
|
740
|
+
* @param staticAlias A static alias used to create paths to files served
|
|
741
|
+
* by the static extension.
|
|
742
|
+
*/
|
|
743
|
+
getStaticExtension(staticAlias: string): StaticExtension | undefined {
|
|
744
|
+
return this.#staticExtensions.get(staticAlias);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Registers an Occultist extension. This is usually done
|
|
749
|
+
* by extensions when they are created.
|
|
750
|
+
*
|
|
751
|
+
* @param The Occultist extension to register.
|
|
752
|
+
*/
|
|
753
|
+
registerExtension(extension: Extension): void {
|
|
754
|
+
let staticAlias: string;
|
|
755
|
+
if (
|
|
756
|
+
typeof extension.getAsset === 'function' &&
|
|
757
|
+
Array.isArray(extension.staticAliases)
|
|
758
|
+
) {
|
|
759
|
+
for (let i = 0; i < extension.staticAliases.length; i++) {
|
|
760
|
+
staticAlias = extension.staticAliases[i];
|
|
761
|
+
|
|
762
|
+
if (this.#staticExtensions.has(staticAlias)) {
|
|
763
|
+
throw new Error(`Static alias '${staticAlias}' already used by other extension`);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
this.#staticExtensions.set(staticAlias, extension as StaticExtension);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
this.#extensions.push(extension);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Must be called after all Occultist extensions have been registered.
|
|
775
|
+
* When some of the extensions have async setup tasks.
|
|
776
|
+
*/
|
|
777
|
+
async setupExtensions(): Promise<void> {
|
|
778
|
+
const setupStreams: ReadableStream[] = [];
|
|
779
|
+
|
|
780
|
+
for (let i = 0; i < this.#extensions.length; i++) {
|
|
781
|
+
if (typeof this.#extensions[i].setup === 'function') {
|
|
782
|
+
setupStreams.push(this.#extensions[i].setup());
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
for (let i = 0; i < setupStreams.length; i++) {
|
|
787
|
+
for await (const message of setupStreams[i]) {
|
|
788
|
+
console.log(message);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
734
793
|
addEventListener(type: RegistryEvents, callback: EventListener) {
|
|
735
794
|
this.#eventTarget.addEventListener(type, callback);
|
|
736
795
|
};
|
package/lib/types.ts
CHANGED
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
export interface StaticAsset {
|
|
3
|
+
alias: string;
|
|
4
|
+
contentType: string;
|
|
5
|
+
url: string;
|
|
6
|
+
integrity?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export interface StaticContext {
|
|
10
|
+
link(alias: string, as: string): string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Extension {
|
|
14
|
+
name: string;
|
|
15
|
+
setup?(): ReadableStream;
|
|
16
|
+
getAsset?(): StaticAsset | undefined;
|
|
17
|
+
staticAliases?: string[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export interface StaticExtension {
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The name of the static extension.
|
|
24
|
+
*/
|
|
25
|
+
name: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Root level aliases the extension uses to identify
|
|
29
|
+
* assets it manages.
|
|
30
|
+
*/
|
|
31
|
+
staticAliases: string[];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves a static assets from the extension.
|
|
35
|
+
*
|
|
36
|
+
* @param assetAlias The alias for the asset.
|
|
37
|
+
*/
|
|
38
|
+
getAsset(assetAlias: string): StaticAsset | undefined;
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
1
42
|
export type ProblemDetailsParam = {
|
|
2
43
|
name: string;
|
|
3
44
|
reason: string;
|