@occultist/occultist 0.0.1

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 (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -0
  3. package/dist/accept.d.ts +41 -0
  4. package/dist/accept.js +110 -0
  5. package/dist/accept.test.d.ts +1 -0
  6. package/dist/accept.test.js +44 -0
  7. package/dist/action.test.d.ts +1 -0
  8. package/dist/action.test.js +1 -0
  9. package/dist/actions/actionSets.d.ts +23 -0
  10. package/dist/actions/actionSets.js +49 -0
  11. package/dist/actions/actions.d.ts +163 -0
  12. package/dist/actions/actions.js +436 -0
  13. package/dist/actions/context.d.ts +78 -0
  14. package/dist/actions/context.js +112 -0
  15. package/dist/actions/meta.d.ts +49 -0
  16. package/dist/actions/meta.js +177 -0
  17. package/dist/actions/path.d.ts +21 -0
  18. package/dist/actions/path.js +83 -0
  19. package/dist/actions/path.test.d.ts +1 -0
  20. package/dist/actions/path.test.js +9 -0
  21. package/dist/actions/spec.d.ts +214 -0
  22. package/dist/actions/spec.js +1 -0
  23. package/dist/actions/types.d.ts +112 -0
  24. package/dist/actions/types.js +2 -0
  25. package/dist/actions/writer.d.ts +27 -0
  26. package/dist/actions/writer.js +140 -0
  27. package/dist/actions/writer.test.d.ts +1 -0
  28. package/dist/actions/writer.test.js +42 -0
  29. package/dist/auth/types.d.ts +14 -0
  30. package/dist/auth/types.js +1 -0
  31. package/dist/cache/cache.d.ts +30 -0
  32. package/dist/cache/cache.js +220 -0
  33. package/dist/cache/etag.d.ts +17 -0
  34. package/dist/cache/etag.js +83 -0
  35. package/dist/cache/etag.test.d.ts +1 -0
  36. package/dist/cache/etag.test.js +91 -0
  37. package/dist/cache/memory.d.ts +12 -0
  38. package/dist/cache/memory.js +36 -0
  39. package/dist/cache/types.d.ts +175 -0
  40. package/dist/cache/types.js +4 -0
  41. package/dist/errors.d.ts +11 -0
  42. package/dist/errors.js +54 -0
  43. package/dist/jsonld.d.ts +43 -0
  44. package/dist/jsonld.js +1 -0
  45. package/dist/makeTypeDefs.d.ts +27 -0
  46. package/dist/makeTypeDefs.js +70 -0
  47. package/dist/merge.d.ts +61 -0
  48. package/dist/merge.js +1 -0
  49. package/dist/mod.d.ts +14 -0
  50. package/dist/mod.js +14 -0
  51. package/dist/processAction.d.ts +15 -0
  52. package/dist/processAction.js +512 -0
  53. package/dist/registry.d.ts +88 -0
  54. package/dist/registry.js +314 -0
  55. package/dist/registry.test.d.ts +1 -0
  56. package/dist/registry.test.js +133 -0
  57. package/dist/request.d.ts +29 -0
  58. package/dist/request.js +118 -0
  59. package/dist/scopes.d.ts +35 -0
  60. package/dist/scopes.js +121 -0
  61. package/dist/scopes.test.d.ts +1 -0
  62. package/dist/scopes.test.js +55 -0
  63. package/dist/transformers/fileTransformer.d.ts +1 -0
  64. package/dist/transformers/fileTransformer.js +8 -0
  65. package/dist/types.d.ts +12 -0
  66. package/dist/types.js +1 -0
  67. package/dist/utils/alwaysArray.d.ts +1 -0
  68. package/dist/utils/alwaysArray.js +9 -0
  69. package/dist/utils/contextBuilder.d.ts +9 -0
  70. package/dist/utils/contextBuilder.js +82 -0
  71. package/dist/utils/getActionContext.d.ts +7 -0
  72. package/dist/utils/getActionContext.js +48 -0
  73. package/dist/utils/getInternalName.d.ts +6 -0
  74. package/dist/utils/getInternalName.js +7 -0
  75. package/dist/utils/getParamLocation.d.ts +2 -0
  76. package/dist/utils/getParamLocation.js +6 -0
  77. package/dist/utils/getPropertyValueSpecifications.d.ts +2 -0
  78. package/dist/utils/getPropertyValueSpecifications.js +49 -0
  79. package/dist/utils/getRequestBodyValues.d.ts +11 -0
  80. package/dist/utils/getRequestBodyValues.js +122 -0
  81. package/dist/utils/getRequestIRIValues.d.ts +14 -0
  82. package/dist/utils/getRequestIRIValues.js +133 -0
  83. package/dist/utils/isBodyInit.d.ts +1 -0
  84. package/dist/utils/isBodyInit.js +21 -0
  85. package/dist/utils/isNil.d.ts +1 -0
  86. package/dist/utils/isNil.js +4 -0
  87. package/dist/utils/isObject.d.ts +6 -0
  88. package/dist/utils/isObject.js +6 -0
  89. package/dist/utils/isPopulatedObject.d.ts +5 -0
  90. package/dist/utils/isPopulatedObject.js +8 -0
  91. package/dist/utils/isPopulatedString.d.ts +1 -0
  92. package/dist/utils/isPopulatedString.js +4 -0
  93. package/dist/utils/joinPaths.d.ts +1 -0
  94. package/dist/utils/joinPaths.js +31 -0
  95. package/dist/utils/makeAppendProblemDetails.d.ts +14 -0
  96. package/dist/utils/makeAppendProblemDetails.js +26 -0
  97. package/dist/utils/makeURLPattern.d.ts +5 -0
  98. package/dist/utils/makeURLPattern.js +12 -0
  99. package/dist/utils/normalizeURL.d.ts +4 -0
  100. package/dist/utils/normalizeURL.js +11 -0
  101. package/dist/utils/parseSearchParams.d.ts +3 -0
  102. package/dist/utils/parseSearchParams.js +24 -0
  103. package/dist/utils/preferredMediaTypes.d.ts +42 -0
  104. package/dist/utils/preferredMediaTypes.js +149 -0
  105. package/dist/utils/urlToIRI.d.ts +1 -0
  106. package/dist/utils/urlToIRI.js +8 -0
  107. package/dist/utils/validateSpecValue.d.ts +1 -0
  108. package/dist/utils/validateSpecValue.js +1 -0
  109. package/dist/validators.d.ts +16 -0
  110. package/dist/validators.js +134 -0
  111. package/lib/accept.test.ts +55 -0
  112. package/lib/accept.ts +147 -0
  113. package/lib/action.test.ts +2 -0
  114. package/lib/actions/actionSets.ts +88 -0
  115. package/lib/actions/actions.ts +795 -0
  116. package/lib/actions/context.ts +170 -0
  117. package/lib/actions/meta.ts +251 -0
  118. package/lib/actions/path.test.ts +15 -0
  119. package/lib/actions/path.ts +99 -0
  120. package/lib/actions/spec.ts +545 -0
  121. package/lib/actions/types.ts +146 -0
  122. package/lib/actions/writer.test.ts +57 -0
  123. package/lib/actions/writer.ts +176 -0
  124. package/lib/auth/types.ts +22 -0
  125. package/lib/cache/cache.ts +291 -0
  126. package/lib/cache/etag.test.ts +122 -0
  127. package/lib/cache/etag.ts +106 -0
  128. package/lib/cache/memory.ts +52 -0
  129. package/lib/cache/types.ts +240 -0
  130. package/lib/errors.ts +66 -0
  131. package/lib/jsonld.ts +67 -0
  132. package/lib/makeTypeDefs.ts +138 -0
  133. package/lib/merge.ts +86 -0
  134. package/lib/mod.ts +14 -0
  135. package/lib/processAction.ts +690 -0
  136. package/lib/registry.test.ts +174 -0
  137. package/lib/registry.ts +455 -0
  138. package/lib/request.ts +153 -0
  139. package/lib/scopes.test.ts +70 -0
  140. package/lib/scopes.ts +178 -0
  141. package/lib/transformers/fileTransformer.ts +10 -0
  142. package/lib/types.ts +13 -0
  143. package/lib/utils/alwaysArray.ts +10 -0
  144. package/lib/utils/contextBuilder.ts +111 -0
  145. package/lib/utils/getActionContext.ts +76 -0
  146. package/lib/utils/getInternalName.ts +15 -0
  147. package/lib/utils/getParamLocation.ts +14 -0
  148. package/lib/utils/getPropertyValueSpecifications.ts +76 -0
  149. package/lib/utils/getRequestBodyValues.ts +155 -0
  150. package/lib/utils/getRequestIRIValues.ts +201 -0
  151. package/lib/utils/isBodyInit.ts +22 -0
  152. package/lib/utils/isNil.ts +4 -0
  153. package/lib/utils/isObject.ts +8 -0
  154. package/lib/utils/isPopulatedObject.ts +9 -0
  155. package/lib/utils/isPopulatedString.ts +4 -0
  156. package/lib/utils/joinPaths.ts +36 -0
  157. package/lib/utils/makeAppendProblemDetails.ts +57 -0
  158. package/lib/utils/makeURLPattern.ts +18 -0
  159. package/lib/utils/normalizeURL.ts +15 -0
  160. package/lib/utils/parseSearchParams.ts +36 -0
  161. package/lib/utils/preferredMediaTypes.ts +220 -0
  162. package/lib/utils/urlToIRI.ts +11 -0
  163. package/lib/utils/validateSpecValue.ts +0 -0
  164. package/lib/validators.ts +186 -0
  165. package/package.json +41 -0
@@ -0,0 +1,795 @@
1
+ import {CacheInstanceArgs} from '../cache/types.js';
2
+ import type {JSONLDContext, JSONObject, TypeDef} from "../jsonld.js";
3
+ import type {Registry} from '../registry.js';
4
+ import type {Scope} from "../scopes.js";
5
+ import {getActionContext} from "../utils/getActionContext.js";
6
+ import {getPropertyValueSpecifications} from "../utils/getPropertyValueSpecifications.js";
7
+ import {isPopulatedObject} from '../utils/isPopulatedObject.js';
8
+ import {joinPaths} from "../utils/joinPaths.js";
9
+ import {AfterDefinition, BeforeDefinition, type ActionMeta} from "./meta.js";
10
+ import type {ActionSpec, ContextState} from "./spec.js";
11
+ import type {HandlerArgs, HandleRequestArgs, HandlerFn, HandlerMeta, HandlerObj, HandlerValue, HintArgs, ImplementedAction} from './types.js';
12
+ import {ResponseTypes} from './writer.js';
13
+
14
+
15
+ export type DefineArgs<
16
+ Term extends string = string,
17
+ Spec extends ActionSpec = ActionSpec,
18
+ > = {
19
+ typeDef?: TypeDef<Term>
20
+ spec?: Spec;
21
+ };
22
+
23
+
24
+ function isHandlerObj<
25
+ State extends ContextState = ContextState,
26
+ Spec extends ActionSpec = ActionSpec
27
+ >(handler: unknown): handler is HandlerObj<State, Spec> {
28
+ return isPopulatedObject(handler);
29
+ }
30
+
31
+ /**
32
+ * A handler definition which can be pulled from a registry, scope or action
33
+ * after an action is defined.
34
+ */
35
+ export class HandlerDefinition<
36
+ State extends ContextState = ContextState,
37
+ Spec extends ActionSpec = ActionSpec,
38
+ > {
39
+ name: string;
40
+ contentType: string;
41
+ handler: HandlerFn | HandlerValue;
42
+ meta: HandlerMeta;
43
+ action: ImplementedAction<State, Spec>;
44
+ cache: ReadonlyArray<CacheInstanceArgs>;
45
+
46
+ constructor(
47
+ name: string,
48
+ contentType: string,
49
+ handler: HandlerFn | HandlerValue,
50
+ meta: HandlerMeta,
51
+ action: ImplementedAction<State, Spec>,
52
+ actionMeta: ActionMeta,
53
+ ) {
54
+ this.name = name;
55
+ this.contentType = contentType;
56
+ this.handler = handler;
57
+ this.action = action;
58
+ this.meta = Object.freeze({ ...meta ?? {} });
59
+
60
+ const cache: CacheInstanceArgs[] = [];
61
+
62
+ for (let i = 0; i < actionMeta.cache.length; i++) {
63
+ cache.push(Object.freeze({ ...actionMeta.cache[i] }));
64
+ }
65
+
66
+ this.cache = Object.freeze(cache);
67
+
68
+ Object.freeze(this);
69
+ }
70
+
71
+ get [Symbol.toStringTag]() {
72
+ return `name=${this.name} contentType=${this.contentType}`;
73
+ }
74
+ }
75
+
76
+ export interface Handleable<
77
+ State extends ContextState = ContextState,
78
+ Spec extends ActionSpec = ActionSpec,
79
+ > {
80
+
81
+ /**
82
+ * Defines the final handler for this content type.
83
+ *
84
+ * An action can have multiple handlers defined
85
+ * each for a different set of content types.
86
+ */
87
+ handle(
88
+ contentType: string | string[],
89
+ handler: HandlerValue | HandlerFn<State, Spec>,
90
+ ): FinalizedAction<State, Spec>;
91
+
92
+ handle(
93
+ args: HandlerObj<State, Spec>,
94
+ ): FinalizedAction<State, Spec>;
95
+ }
96
+
97
+ export class FinalizedAction<
98
+ State extends ContextState = ContextState,
99
+ Spec extends ActionSpec = ActionSpec,
100
+ > implements
101
+ Handleable<State, Spec>,
102
+ ImplementedAction<State, Spec>
103
+ {
104
+ #spec: Spec;
105
+ #meta: ActionMeta<State, Spec>;
106
+ #typeDef?: TypeDef;
107
+ #handlers: Map<string, HandlerDefinition<State, Spec>>;
108
+
109
+ constructor(
110
+ typeDef: TypeDef | undefined,
111
+ spec: Spec,
112
+ meta: ActionMeta<State, Spec>,
113
+ handlerArgs: HandlerObj<State, Spec>,
114
+ ) {
115
+ this.#typeDef = typeDef;
116
+ this.#spec = spec ?? {} as Spec;
117
+ this.#meta = meta;
118
+
119
+ this.#meta.action = this as unknown as ImplementedAction<State, Spec>;
120
+
121
+ const handlers: Map<string, HandlerDefinition<State, Spec>> = new Map();
122
+
123
+ if (typeof handlerArgs.contentType === 'string') {
124
+ handlers.set(handlerArgs.contentType, new HandlerDefinition(
125
+ this.name,
126
+ handlerArgs.contentType,
127
+ handlerArgs.handler,
128
+ handlerArgs.meta,
129
+ this as unknown as ImplementedAction<State, Spec>,
130
+ this.#meta,
131
+ ));
132
+ } else if (isPopulatedObject(handlerArgs)) {
133
+ for (let i = 0; i < handlerArgs.contentType.length; i++) {
134
+ handlers.set(handlerArgs.contentType[i], new HandlerDefinition(
135
+ this.name,
136
+ handlerArgs.contentType[i],
137
+ handlerArgs.handler,
138
+ handlerArgs.meta,
139
+ this as unknown as ImplementedAction<State, Spec>,
140
+ this.#meta,
141
+ ));
142
+ }
143
+ }
144
+
145
+ this.#handlers = handlers;
146
+ }
147
+
148
+ static fromHandlers<
149
+ State extends ContextState = ContextState,
150
+ Spec extends ActionSpec = ActionSpec,
151
+ >(
152
+ typeDef: TypeDef | undefined,
153
+ spec: Spec,
154
+ meta: ActionMeta<State, Spec>,
155
+ contextType: string | string[],
156
+ handler: HandlerValue | HandlerFn<State, Spec>,
157
+ ): FinalizedAction<State, Spec>;
158
+
159
+ static fromHandlers<
160
+ State extends ContextState = ContextState,
161
+ Spec extends ActionSpec = ActionSpec,
162
+ >(
163
+ typeDef: TypeDef | undefined,
164
+ spec: Spec,
165
+ meta: ActionMeta<State, Spec>,
166
+ handlerArgs: HandlerObj<State, Spec>,
167
+ ): FinalizedAction<State, Spec>;
168
+
169
+ static fromHandlers<
170
+ State extends ContextState = ContextState,
171
+ Spec extends ActionSpec = ActionSpec,
172
+ >(
173
+ typeDef: TypeDef | undefined,
174
+ spec: Spec,
175
+ meta: ActionMeta<State, Spec>,
176
+ arg3: string | string[] | HandlerObj<State, Spec>,
177
+ arg4?: HandlerValue | HandlerFn<State, Spec>,
178
+ ): FinalizedAction<State, Spec> {
179
+ if (Array.isArray(arg3) || typeof arg3 === 'string') {
180
+ return new FinalizedAction<State, Spec>(typeDef, spec, meta, {
181
+ contentType: arg3,
182
+ handler: arg4,
183
+ });
184
+ }
185
+
186
+ return new FinalizedAction(typeDef, spec, meta, arg3);
187
+ }
188
+
189
+ static async toJSONLD(
190
+ action: ImplementedAction,
191
+ scope: Scope,
192
+ ): Promise<JSONObject | null> {
193
+ if (scope == null || action.typeDef == null) {
194
+ return null;
195
+ }
196
+
197
+ const apiSpec = await getPropertyValueSpecifications(action.spec);
198
+
199
+ return {
200
+ '@context': action.context,
201
+ '@id': joinPaths(action.registry.rootIRI, scope.path, action.name),
202
+ '@type': action.term,
203
+ target: {
204
+ '@type': 'https://schema.org/EntryPoint',
205
+ httpMethod: action.method,
206
+ urlTemplate: action.template,
207
+ contentType: 'application/ld+json',
208
+ },
209
+ ...apiSpec,
210
+ };
211
+ }
212
+
213
+ get public(): boolean {
214
+ return this.#meta.public;
215
+ }
216
+
217
+ get method(): string {
218
+ return this.#meta.method;
219
+ }
220
+
221
+ get term(): string | undefined {
222
+ return this.#typeDef?.term;
223
+ }
224
+
225
+ get type(): string | undefined {
226
+ return this.#typeDef?.type;
227
+ }
228
+
229
+ get typeDef(): TypeDef | undefined {
230
+ return this.#typeDef;
231
+ }
232
+
233
+ get name(): string {
234
+ return this.#meta.name;
235
+ }
236
+
237
+ get template(): string {
238
+ return this.#meta.uriTemplate;
239
+ }
240
+
241
+ get pattern(): URLPattern {
242
+ return this.#meta.path.pattern;
243
+ }
244
+
245
+ get spec(): Spec {
246
+ return this.#spec;
247
+ }
248
+
249
+ get scope(): Scope | undefined {
250
+ return this.#meta.scope
251
+ }
252
+
253
+ get registry(): Registry {
254
+ return this.#meta.registry;
255
+ }
256
+
257
+ get handlers(): HandlerDefinition<State, Spec>[] {
258
+ return Array.from(this.#handlers.values());
259
+ }
260
+
261
+ get contentTypes(): string[] {
262
+ return Array.from(this.#handlers.keys());
263
+ }
264
+
265
+ get context(): JSONObject {
266
+ return getActionContext({
267
+ spec: this.#spec,
268
+ //vocab: this.#vocab,
269
+ //aliases: this.#aliases,
270
+ });
271
+ }
272
+
273
+ url(): string {
274
+ return joinPaths(this.#meta.registry.rootIRI, this.#meta.path.normalized);
275
+ }
276
+
277
+ jsonld(): Promise<JSONObject | null> {
278
+ const scope = this.#meta.scope;
279
+
280
+ return FinalizedAction.toJSONLD(
281
+ this as unknown as ImplementedAction,
282
+ scope
283
+ );
284
+ }
285
+
286
+ jsonldPartial(): { '@type': string, '@id': string } | null {
287
+ const scope = this.#meta.scope;
288
+ const typeDef = this.#typeDef;
289
+
290
+ if (scope == null || typeDef == null) {
291
+ return null;
292
+ }
293
+
294
+ return {
295
+ '@type': typeDef.type,
296
+ '@id': joinPaths(scope.url(), this.#meta.name),
297
+ };
298
+ }
299
+
300
+ handle(
301
+ contentType: string | string[],
302
+ handler: HandlerFn<State, Spec> | HandlerValue,
303
+ ): FinalizedAction<State, Spec>;
304
+
305
+ handle(
306
+ args: HandlerObj<State, Spec>,
307
+ ): FinalizedAction<State, Spec>;
308
+
309
+ handle(
310
+ arg1: string | string[] | HandlerObj<State, Spec>,
311
+ arg2?: HandlerFn<State, Spec>,
312
+ ): FinalizedAction<State, Spec> {
313
+ let contentType: string | string[];
314
+ let handler: HandlerFn<State, Spec> | HandlerValue;
315
+ let meta: HandlerMeta;
316
+
317
+ if (isHandlerObj(arg1)) {
318
+ contentType = arg1.contentType;
319
+ handler = arg1.handler;
320
+ meta = Object.assign(Object.create(null), arg1.meta);
321
+
322
+ if (arg1.meta != null) {
323
+ for (const sym of Object.getOwnPropertySymbols(arg1.meta)) {
324
+ meta[sym] = arg1.meta[sym];
325
+ }
326
+ }
327
+ } else {
328
+ contentType = arg1;
329
+ handler = arg2;
330
+ meta = Object.create(null);
331
+ }
332
+
333
+ if (!Array.isArray(contentType)) {
334
+ this.#handlers.set(contentType, new HandlerDefinition(
335
+ this.#meta.name,
336
+ contentType,
337
+ handler,
338
+ meta,
339
+ this as unknown as ImplementedAction<State, Spec>,
340
+ this.#meta,
341
+ ));
342
+ } else {
343
+ for (let i = 0; i < contentType.length; i++) {
344
+ this.#handlers.set(contentType[i], new HandlerDefinition(
345
+ this.#meta.name,
346
+ contentType[i],
347
+ handler,
348
+ meta,
349
+ this as unknown as ImplementedAction<State, Spec>,
350
+ this.#meta,
351
+ ));
352
+ }
353
+ }
354
+
355
+ return this;
356
+ }
357
+
358
+ async handleRequest(args: HandleRequestArgs): Promise<ResponseTypes> {
359
+ const handler = this.#handlers.get(args.contentType as string);
360
+
361
+ return this.#meta.handleRequest({
362
+ ...args,
363
+ spec: this.#spec,
364
+ handler,
365
+ });
366
+ }
367
+ }
368
+
369
+ export interface Applicable<ActionType> {
370
+ use(): ActionType;
371
+ }
372
+
373
+ export class DefinedAction<
374
+ State extends ContextState = ContextState,
375
+ Term extends string = string,
376
+ Spec extends ActionSpec = ActionSpec,
377
+ > implements
378
+ Applicable<DefinedAction<State, Term, Spec>>,
379
+ Handleable<State, Spec>,
380
+ ImplementedAction<State, Spec>
381
+ {
382
+ #spec: Spec;
383
+ #meta: ActionMeta<State, Spec>;
384
+ #typeDef?: TypeDef;
385
+
386
+ constructor(
387
+ typeDef: TypeDef | undefined,
388
+ spec: Spec,
389
+ meta: ActionMeta<State, Spec>,
390
+ ) {
391
+ this.#spec = spec ?? {} as Spec;
392
+ this.#meta = meta;
393
+ this.#typeDef = typeDef;
394
+
395
+ this.#meta.action = this as unknown as ImplementedAction<State, Spec>;
396
+ }
397
+
398
+ get public(): boolean {
399
+ return this.#meta.public;
400
+ }
401
+
402
+ get method(): string {
403
+ return this.#meta.method;
404
+ }
405
+
406
+ get term(): string | undefined {
407
+ return this.#typeDef?.term;
408
+ }
409
+
410
+ get type(): string | undefined {
411
+ return this.#typeDef?.type;
412
+ }
413
+
414
+ get typeDef(): TypeDef | undefined {
415
+ return this.#typeDef;
416
+ }
417
+
418
+ get name(): string {
419
+ return this.#meta.name;
420
+ }
421
+
422
+ get template(): string {
423
+ return this.#meta.uriTemplate;
424
+ }
425
+
426
+ get pattern(): URLPattern {
427
+ return this.#meta.path.pattern;
428
+ }
429
+
430
+ get path(): string {
431
+ return this.#meta.path.normalized;
432
+ }
433
+
434
+ get spec(): Spec {
435
+ return this.#spec;
436
+ }
437
+
438
+ get scope(): Scope | undefined {
439
+ return this.#meta.scope;
440
+ }
441
+
442
+ get registry(): Registry {
443
+ return this.#meta.registry;
444
+ }
445
+
446
+ get handlers(): HandlerDefinition<State, Spec>[] {
447
+ return [];
448
+ }
449
+
450
+ get contentTypes(): string[] {
451
+ return [];
452
+ }
453
+
454
+ url(): string {
455
+ return '';
456
+ }
457
+
458
+ get context(): JSONLDContext {
459
+ return getActionContext({
460
+ spec: this.#spec,
461
+ // vocab: this.#vocab,
462
+ // aliases: this.#aliases,
463
+ });
464
+ }
465
+
466
+ jsonld(): Promise<JSONObject | null> {
467
+ const scope = this.#meta.scope;
468
+
469
+ return FinalizedAction.toJSONLD(
470
+ this as unknown as ImplementedAction,
471
+ scope
472
+ );
473
+ }
474
+
475
+ jsonldPartial(): { '@type': string, '@id': string } | null {
476
+ const scope = this.#meta.scope;
477
+ const typeDef = this.#typeDef;
478
+
479
+ if (scope == null || typeDef == null) {
480
+ return null;
481
+ }
482
+
483
+ return {
484
+ '@type': typeDef.type,
485
+ '@id': joinPaths(scope.url(), this.#meta.name),
486
+ };
487
+ }
488
+
489
+ /**
490
+ * Defines a cache handling rule for this action.
491
+ *
492
+ * Defining caching rules after the `action.define()` method is safer
493
+ * if validating and transforming the action payload might cause
494
+ * auth sensitive checks to be run which might reject the request.
495
+ */
496
+ cache(args: CacheInstanceArgs): DefinedAction<State, string, Spec> {
497
+ if (this.#meta.cache.length !== 0 &&
498
+ this.#meta.cacheOccurance === BeforeDefinition) {
499
+ throw new Error(
500
+ 'Action cache may be defined either before or after ' +
501
+ 'the definition method is called, but not both.');
502
+ } else if (this.#meta.cacheOccurance === BeforeDefinition) {
503
+ this.#meta.cacheOccurance = AfterDefinition;
504
+ }
505
+
506
+ this.#meta.cache.push(args);
507
+
508
+ return this;
509
+ }
510
+
511
+ meta(): DefinedAction<State, string, Spec> {
512
+ return this;
513
+ }
514
+
515
+ use(): DefinedAction<State, string, Spec> {
516
+ return this;
517
+ }
518
+
519
+ handle(contentType: string | string[], handler: HandlerValue | HandlerFn<State, Spec>): FinalizedAction<State, Spec>;
520
+ handle(args: HandlerObj<State, Spec>): FinalizedAction<State, Spec>;
521
+ handle(arg1: unknown, arg2?: unknown): FinalizedAction<State, Spec> {
522
+ return FinalizedAction.fromHandlers(
523
+ this.#typeDef,
524
+ this.#spec,
525
+ this.#meta,
526
+ arg1 as string | string[],
527
+ arg2 as HandlerFn<State, Spec>,
528
+ );
529
+ }
530
+
531
+ async handleRequest(args: HandleRequestArgs): Promise<ResponseTypes> {
532
+ return this.#meta.handleRequest({
533
+ ...args,
534
+ spec: this.#spec,
535
+ });
536
+ }
537
+
538
+ }
539
+
540
+ export class Action<
541
+ State extends ContextState = ContextState,
542
+ > implements
543
+ Applicable<Action>,
544
+ Handleable<State>,
545
+ ImplementedAction<State>
546
+ {
547
+ #spec: ActionSpec = {};
548
+ #meta: ActionMeta<State>;
549
+
550
+ constructor(
551
+ meta: ActionMeta<State>,
552
+ ) {
553
+ this.#meta = meta;
554
+ this.#meta.action = this as ImplementedAction<State, {}>;
555
+ }
556
+
557
+ get public(): boolean {
558
+ return this.#meta.public;
559
+ }
560
+
561
+ get method(): string {
562
+ return this.#meta.method;
563
+ }
564
+
565
+ get term(): string | undefined {
566
+ return undefined;
567
+ }
568
+
569
+ get type(): string | undefined {
570
+ return undefined;
571
+ }
572
+
573
+ get typeDef(): TypeDef | undefined {
574
+ return undefined;
575
+ }
576
+
577
+ get name(): string {
578
+ return this.#meta.name;
579
+ }
580
+
581
+ get template(): string {
582
+ return this.#meta.uriTemplate;
583
+ }
584
+
585
+ get pattern(): URLPattern {
586
+ return this.#meta.path.pattern;
587
+ }
588
+
589
+
590
+ get path(): string {
591
+ return this.#meta.path.normalized;
592
+ }
593
+
594
+ get spec(): ActionSpec {
595
+ return this.#spec;
596
+ }
597
+
598
+ get scope(): Scope | undefined {
599
+ return this.#meta.scope;
600
+ }
601
+
602
+ get registry(): Registry {
603
+ return this.#meta.registry;
604
+ }
605
+
606
+ get handlers(): HandlerDefinition[] {
607
+ return [];
608
+ }
609
+
610
+ get contentTypes(): string[] {
611
+ return [];
612
+ }
613
+
614
+ get context(): JSONObject {
615
+ return getActionContext({
616
+ spec: this.#spec,
617
+ //vocab: this.#vocab,
618
+ //aliases: this.#aliases,
619
+ });
620
+ }
621
+
622
+ url(): string {
623
+ return '';
624
+ }
625
+
626
+ jsonld(): Promise<null> {
627
+ return Promise.resolve(null);
628
+ }
629
+
630
+ jsonldPartial(): { '@type': string, '@id': string } | null {
631
+ return null;
632
+ }
633
+
634
+ use(): Action<State> {
635
+ return this;
636
+ }
637
+
638
+ define<
639
+ Term extends string = string,
640
+ Spec extends ActionSpec = ActionSpec,
641
+ >(args: DefineArgs<Term, Spec>): DefinedAction<State, Term, Spec> {
642
+ return new DefinedAction<State, Term, Spec>(
643
+ args.typeDef,
644
+ args.spec ?? {} as Spec,
645
+ this.#meta as unknown as ActionMeta<State, Spec>,
646
+ );
647
+ }
648
+
649
+ handle(contentType: string | string[], handler: HandlerValue | HandlerFn<State>): FinalizedAction<State>;
650
+ handle(args: HandlerObj<State>): FinalizedAction<State>;
651
+ handle(arg1: unknown, arg2?: unknown): FinalizedAction<State> {
652
+ return FinalizedAction.fromHandlers(
653
+ null,
654
+ this.#spec,
655
+ this.#meta,
656
+ arg1 as string | string[],
657
+ arg2 as HandlerFn<State>,
658
+ );
659
+ }
660
+
661
+ async handleRequest(args: HandleRequestArgs): Promise<ResponseTypes> {
662
+ return this.#meta.handleRequest({
663
+ ...args,
664
+ spec: this.#spec,
665
+ });
666
+ }
667
+
668
+ }
669
+
670
+ export class PreAction<
671
+ State extends ContextState = ContextState,
672
+ > implements
673
+ Applicable<Action>,
674
+ Handleable<State>
675
+ {
676
+ #meta: ActionMeta<State>;
677
+
678
+ constructor(
679
+ meta: ActionMeta<State>,
680
+ ) {
681
+ this.#meta = meta;
682
+ }
683
+
684
+ use() {
685
+ return new Action(
686
+ this.#meta,
687
+ );
688
+ }
689
+
690
+ define<
691
+ Term extends string = string,
692
+ Spec extends ActionSpec = ActionSpec,
693
+ >(args: DefineArgs<Term, Spec>): DefinedAction<State, Term, Spec> {
694
+ return new DefinedAction<State, Term, Spec>(
695
+ args.typeDef,
696
+ args.spec,
697
+ this.#meta as unknown as ActionMeta<State, Spec>,
698
+ );
699
+ }
700
+
701
+ handle(contentType: string | string[], handler: HandlerValue | HandlerFn<State>): FinalizedAction<State>;
702
+ handle(args: HandlerObj<State>): FinalizedAction<State>;
703
+ handle(arg1: unknown, arg2?: unknown): FinalizedAction<State> {
704
+ return FinalizedAction.fromHandlers(
705
+ null,
706
+ {},
707
+ this.#meta,
708
+ arg1 as string | string[],
709
+ arg2 as HandlerFn<State>,
710
+ );
711
+ }
712
+ }
713
+
714
+ export class Endpoint<
715
+ State extends ContextState = ContextState,
716
+ > implements
717
+ Applicable<Action>,
718
+ Handleable<State>
719
+ {
720
+ #meta: ActionMeta<State>;
721
+
722
+ constructor(
723
+ meta: ActionMeta<State>,
724
+ ) {
725
+ this.#meta = meta;
726
+ }
727
+
728
+ hint(hints: HintArgs): Endpoint<State> {
729
+ this.#meta.hints.push(hints);
730
+
731
+ return this;
732
+ }
733
+
734
+ compress(): Endpoint<State> {
735
+ return this;
736
+ }
737
+
738
+ cache(args: CacheInstanceArgs) {
739
+ this.#meta.cache.push(args);
740
+
741
+ return this;
742
+ }
743
+
744
+ etag() {
745
+ return this;
746
+ }
747
+
748
+ use(): Action<State> {
749
+ return new Action<State>(this.#meta);
750
+ }
751
+
752
+ define<
753
+ Term extends string = string,
754
+ Spec extends ActionSpec = ActionSpec,
755
+ >(args: DefineArgs<Term, Spec>): DefinedAction<State, Term, Spec> {
756
+ return new DefinedAction<State, Term, Spec>(
757
+ args.typeDef,
758
+ args.spec,
759
+ this.#meta as ActionMeta<State, Spec>,
760
+ );
761
+ }
762
+
763
+ handle(contentType: string | string[], handler: HandlerValue | HandlerFn<State>): FinalizedAction<State>;
764
+ handle(args: HandlerObj<State>): FinalizedAction<State>;
765
+ handle(arg1: unknown, arg2?: unknown): FinalizedAction<State> {
766
+ return FinalizedAction.fromHandlers(
767
+ undefined,
768
+ {},
769
+ this.#meta,
770
+ arg1 as string | string[],
771
+ arg2 as HandlerFn<State>,
772
+ );
773
+ }
774
+ }
775
+
776
+ export class ActionAuth<
777
+ State extends ContextState = ContextState,
778
+ > {
779
+ #meta: ActionMeta<State>;
780
+
781
+ constructor(meta: ActionMeta<State>) {
782
+ this.#meta = meta;
783
+ }
784
+
785
+ public(): Endpoint<State> {
786
+ this.#meta.public = true;
787
+
788
+ return new Endpoint(this.#meta);
789
+ }
790
+
791
+ private(): Endpoint<State> {
792
+ return new Endpoint(this.#meta);
793
+ }
794
+ }
795
+