@owlmeans/entrypoint 0.1.3

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 (48) hide show
  1. package/README.md +95 -0
  2. package/build/consts.d.ts +7 -0
  3. package/build/consts.d.ts.map +1 -0
  4. package/build/consts.js +8 -0
  5. package/build/consts.js.map +1 -0
  6. package/build/entrypoint.d.ts +5 -0
  7. package/build/entrypoint.d.ts.map +1 -0
  8. package/build/entrypoint.js +80 -0
  9. package/build/entrypoint.js.map +1 -0
  10. package/build/filter.d.ts +8 -0
  11. package/build/filter.d.ts.map +1 -0
  12. package/build/filter.js +20 -0
  13. package/build/filter.js.map +1 -0
  14. package/build/helper.d.ts +7 -0
  15. package/build/helper.d.ts.map +1 -0
  16. package/build/helper.js +26 -0
  17. package/build/helper.js.map +1 -0
  18. package/build/index.d.ts +6 -0
  19. package/build/index.d.ts.map +1 -0
  20. package/build/index.js +5 -0
  21. package/build/index.js.map +1 -0
  22. package/build/types.d.ts +81 -0
  23. package/build/types.d.ts.map +1 -0
  24. package/build/types.js +2 -0
  25. package/build/types.js.map +1 -0
  26. package/build/utils/entrypoint.d.ts +3 -0
  27. package/build/utils/entrypoint.d.ts.map +1 -0
  28. package/build/utils/entrypoint.js +2 -0
  29. package/build/utils/entrypoint.js.map +1 -0
  30. package/build/utils/index.d.ts +3 -0
  31. package/build/utils/index.d.ts.map +1 -0
  32. package/build/utils/index.js +3 -0
  33. package/build/utils/index.js.map +1 -0
  34. package/build/utils/types.d.ts +6 -0
  35. package/build/utils/types.d.ts.map +1 -0
  36. package/build/utils/types.js +2 -0
  37. package/build/utils/types.js.map +1 -0
  38. package/package.json +45 -0
  39. package/src/consts.ts +7 -0
  40. package/src/entrypoint.ts +106 -0
  41. package/src/filter.ts +26 -0
  42. package/src/helper.ts +37 -0
  43. package/src/index.ts +6 -0
  44. package/src/types.ts +94 -0
  45. package/src/utils/entrypoint.ts +4 -0
  46. package/src/utils/index.ts +3 -0
  47. package/src/utils/types.ts +6 -0
  48. package/tsconfig.json +10 -0
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # @owlmeans/entrypoint
2
+
3
+ Entrypoint system — the URL unit abstraction shared between server and client in OwlMeans apps.
4
+
5
+ ## Overview
6
+
7
+ - An **entrypoint** is a URL unit: an alias + path + optional guards/gates/filters
8
+ - On the server, entrypoints become API routes with attached handlers
9
+ - On the client, entrypoints provide URL generation and navigation
10
+ - All AJV validation schemas are defined at entrypoint level, keeping data contracts consistent fullstack
11
+ - Most commonly used via re-exports in `@owlmeans/server-app` or `@owlmeans/client-entrypoint`
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ bun add @owlmeans/entrypoint
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Define an entrypoint with body validation and a guard:
22
+
23
+ ```typescript
24
+ import { entrypoint, guard, filter, body, params } from '@owlmeans/server-app'
25
+ import { route } from '@owlmeans/route'
26
+
27
+ const createStoryModule = entrypoint(
28
+ route('story-create', '/stories', { method: 'POST', parent: 'api' }),
29
+ filter(body({
30
+ type: 'object',
31
+ properties: { story: { type: 'string' }, projectId: { type: 'string' } },
32
+ required: ['story', 'projectId']
33
+ }), guard('authenticated'))
34
+ )
35
+ ```
36
+
37
+ Use `AbstractRequest` type in a handler:
38
+
39
+ ```typescript
40
+ import type { AbstractRequest } from '@owlmeans/entrypoint'
41
+
42
+ export const create = handleBody(async (body, context, request) => {
43
+ const req = request as AbstractRequest<{ id: string }>
44
+ const projectId = req.params.id
45
+ })
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `entrypoint(route, opts?): CommonEntrypoint`
51
+
52
+ Creates an entrypoint. `opts` is typically produced by `filter()`, `guard()`, or `gate()`.
53
+
54
+ ### `guard(guard, opts?): CommonEntrypointOptions`
55
+
56
+ Adds an authentication guard requirement.
57
+
58
+ ### `gate(gate, params, opts?): CommonEntrypointOptions`
59
+
60
+ Adds an authorization gate with parameters.
61
+
62
+ ### `filter(filter, opts?): CommonEntrypointOptions`
63
+
64
+ Attaches validation schemas (AJV format) to the entrypoint.
65
+
66
+ ### `body(schema, filter?) / query(schema, filter?) / params(schema, filter?)`
67
+
68
+ Build a `Filter` object with the given AJV schema applied to the corresponding request part.
69
+
70
+ ### `parent(entrypoint, parentAlias): CommonEntrypoint`
71
+
72
+ Sets a parent-child relationship so child entrypoints inherit guards/gates.
73
+
74
+ ### `provideResponse<T>(): AbstractResponse<T>`
75
+
76
+ Creates a response object for use in non-elevated handlers.
77
+
78
+ ### `EntrypointOutcome`
79
+
80
+ ```typescript
81
+ enum EntrypointOutcome { Ok, Accepted, Created, Finished }
82
+ ```
83
+
84
+ ### Types
85
+
86
+ - `AbstractRequest<T>` — request with `params`, `body`, `query`, `headers`, `auth`
87
+ - `AbstractResponse<T>` — response with `resolve(value, outcome?)` and `reject(error)`
88
+ - `CommonEntrypoint` — entrypoint with `getAlias()`, `getPath()`, `getGuards()`, `handle`
89
+
90
+ ## Related Packages
91
+
92
+ - [`@owlmeans/route`](../route) — `route()` factory used in `entrypoint(route(...), ...)`
93
+ - [`@owlmeans/server-entrypoint`](../server-entrypoint) — server-side `elevate()` to attach handlers
94
+ - [`@owlmeans/client-entrypoint`](../client-entrypoint) — client-side entrypoint with API call support
95
+ - [`@owlmeans/server-app`](../server-app) — re-exports everything from this package
@@ -0,0 +1,7 @@
1
+ export declare enum EntrypointOutcome {
2
+ Ok = "ok",
3
+ Accepted = "accepted",
4
+ Created = "created",
5
+ Finished = "finished"
6
+ }
7
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,oBAAY,iBAAiB;IAC3B,EAAE,OAAO;IACT,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB"}
@@ -0,0 +1,8 @@
1
+ export var EntrypointOutcome;
2
+ (function (EntrypointOutcome) {
3
+ EntrypointOutcome["Ok"] = "ok";
4
+ EntrypointOutcome["Accepted"] = "accepted";
5
+ EntrypointOutcome["Created"] = "created";
6
+ EntrypointOutcome["Finished"] = "finished";
7
+ })(EntrypointOutcome || (EntrypointOutcome = {}));
8
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,iBAKX;AALD,WAAY,iBAAiB;IAC3B,8BAAS,CAAA;IACT,0CAAqB,CAAA;IACrB,wCAAmB,CAAA;IACnB,0CAAqB,CAAA;AACvB,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,QAK5B"}
@@ -0,0 +1,5 @@
1
+ import type { CommonEntrypoint } from './types.js';
2
+ import type { CreateEntrypointSignature } from './utils/types.js';
3
+ export declare const entrypoint: CreateEntrypointSignature<CommonEntrypoint>;
4
+ export declare const parent: <T extends CommonEntrypoint | CommonEntrypoint[]>(ep: T, aliasOrParent: string, _parent?: string) => T;
5
+ //# sourceMappingURL=entrypoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAEjE,eAAO,MAAM,UAAU,EAAE,yBAAyB,CAAC,gBAAgB,CAqFlE,CAAA;AAED,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,MAAM,EAAE,UAAU,MAAM,KAAG,CAcxH,CAAA"}
@@ -0,0 +1,80 @@
1
+ import { appendContextual } from '@owlmeans/context';
2
+ export const entrypoint = (route, opts) => {
3
+ let guards = null;
4
+ let gates = null;
5
+ const ep = appendContextual(route.route.alias, {
6
+ _entrypoint: true,
7
+ _module: true,
8
+ sticky: false,
9
+ route,
10
+ getAlias: () => ep.route.route.alias,
11
+ getPath: () => ep.route.route.path,
12
+ getParentAlias: () => ep.route.route.parent ?? null,
13
+ hasParent: () => ep.getParentAlias() != null,
14
+ resolve: async () => {
15
+ if (ep.ctx == null) {
16
+ throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`);
17
+ }
18
+ await ep.route.resolve(ep.ctx);
19
+ return ep;
20
+ },
21
+ getParent: () => {
22
+ const parentAlias = ep.getParentAlias();
23
+ if (parentAlias == null) {
24
+ throw new SyntaxError(`Entrypoint has no parent - ${ep.getAlias()}`);
25
+ }
26
+ if (ep.ctx == null) {
27
+ throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`);
28
+ }
29
+ return ep.ctx.entrypoint(parentAlias);
30
+ },
31
+ setService: service => {
32
+ if (ep.route.route.resolved) {
33
+ throw new SyntaxError(`Cannot update a resolved entrypoint - ${ep.getAlias()}`);
34
+ }
35
+ ep.route.route.service = service;
36
+ },
37
+ getGuards: () => {
38
+ if (guards != null) {
39
+ return guards;
40
+ }
41
+ guards = ep.guards ?? [];
42
+ if (ep.hasParent()) {
43
+ guards.push(...ep.getParent().getGuards().filter(guard => !guards?.includes(guard)));
44
+ }
45
+ return guards;
46
+ },
47
+ getGates: () => {
48
+ if (gates != null) {
49
+ return gates;
50
+ }
51
+ gates = ep.gate != null ? [[
52
+ ep.gate, ep.gateParams == null
53
+ ? [] : Array.isArray(ep.gateParams)
54
+ ? ep.gateParams : [ep.gateParams]
55
+ ]] : [];
56
+ if (ep.hasParent()) {
57
+ gates.push(...ep.getParent().getGates()
58
+ .filter(([gate]) => !gates?.some(([g]) => g === gate)));
59
+ }
60
+ return gates;
61
+ },
62
+ ...opts
63
+ });
64
+ return ep;
65
+ };
66
+ export const parent = (ep, aliasOrParent, _parent) => {
67
+ if (Array.isArray(ep)) {
68
+ if (_parent == null) {
69
+ throw SyntaxError('Elevating parent requires parent name to be specified');
70
+ }
71
+ ep = ep.find(e => e.route.route.alias === aliasOrParent);
72
+ if (ep == null) {
73
+ throw SyntaxError(`Entrypoint not found ${aliasOrParent}`);
74
+ }
75
+ return parent(ep, _parent);
76
+ }
77
+ ep.route.route.parent = aliasOrParent;
78
+ return ep;
79
+ };
80
+ //# sourceMappingURL=entrypoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { JSONSchemaType } from 'ajv';
2
+ import type { Filter } from './types.js';
3
+ export declare const body: <T>(schema: JSONSchemaType<T>, filter?: Filter) => Filter;
4
+ export declare const query: <T>(schema: JSONSchemaType<T>, filter?: Filter) => Filter;
5
+ export declare const params: <T>(schema: JSONSchemaType<T>, filter?: Filter) => Filter;
6
+ export declare const response: <T>(schema: JSONSchemaType<T>, code?: number, filter?: Filter) => Filter;
7
+ export declare const headers: <T>(schema: JSONSchemaType<T>, filter?: Filter) => Filter;
8
+ //# sourceMappingURL=filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAEpE,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAErE,CAAA;AAED,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAEtE,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,MAAM,EAAE,SAAS,MAAM,KAAG,MAMvF,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAEvE,CAAA"}
@@ -0,0 +1,20 @@
1
+ export const body = (schema, filter) => {
2
+ return { ...filter, body: schema };
3
+ };
4
+ export const query = (schema, filter) => {
5
+ return { ...filter, query: schema };
6
+ };
7
+ export const params = (schema, filter) => {
8
+ return { ...filter, params: schema };
9
+ };
10
+ export const response = (schema, code, filter) => {
11
+ let _schema = schema;
12
+ if (filter?.response != null && code != null) {
13
+ _schema = { ...filter.response, [code]: schema };
14
+ }
15
+ return { ...filter, response: _schema };
16
+ };
17
+ export const headers = (schema, filter) => {
18
+ return { ...filter, headers: schema };
19
+ };
20
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,IAAI,GAAG,CAAI,MAAyB,EAAE,MAAe,EAAU,EAAE;IAC5E,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAa,EAAE,CAAA;AAC3C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAI,MAAyB,EAAE,MAAe,EAAU,EAAE;IAC7E,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAa,EAAE,CAAA;AAC5C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,CAAI,MAAyB,EAAE,MAAe,EAAU,EAAE;IAC9E,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAa,EAAE,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAI,MAAyB,EAAE,IAAa,EAAE,MAAe,EAAU,EAAE;IAC/F,IAAI,OAAO,GAAQ,MAAM,CAAA;IACzB,IAAI,MAAM,EAAE,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QAC7C,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IAClD,CAAC;IACD,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;AACzC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,MAAyB,EAAE,MAAe,EAAU,EAAE;IAC/E,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAa,EAAE,CAAA;AAC9C,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { Filter, CommonEntrypointOptions, AbstractResponse, CommonEntrypoint } from './types.js';
2
+ export declare const filter: (filter: Filter, opts?: CommonEntrypointOptions) => CommonEntrypointOptions;
3
+ export declare const guard: (guard: string, opts?: CommonEntrypointOptions) => CommonEntrypointOptions;
4
+ export declare const gate: (gate: string, params: string | string[], opts?: CommonEntrypointOptions) => CommonEntrypointOptions;
5
+ export declare const provideResponse: <T>(originalResponse?: unknown) => AbstractResponse<T>;
6
+ export declare const clone: <M extends CommonEntrypoint>(entrypoints: M[], from: string, to: string, service: string) => void;
7
+ //# sourceMappingURL=helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAGhG,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,OAAO,uBAAuB,KAAG,uBAAgD,CAAA;AAExH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,OAAO,uBAAuB,KAAG,uBACC,CAAA;AAEvE,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,QAAQ,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,uBAAuB,KAAG,uBACtD,CAAA;AAEzC,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,mBAAmB,OAAO,KAAG,gBAAgB,CAAC,CAAC,CAejF,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,gBAAgB,EAAE,aAAa,CAAC,EAAE,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,EAAE,SAAS,MAAM,SAO5G,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { route } from '@owlmeans/route';
2
+ import { entrypoint } from './entrypoint.js';
3
+ export const filter = (filter, opts) => ({ filter, ...opts });
4
+ export const guard = (guard, opts) => ({ ...opts, guards: [...new Set([guard, ...(opts?.guards ?? [])])] });
5
+ export const gate = (gate, params, opts) => ({ ...opts, gate, gateParams: params });
6
+ export const provideResponse = (originalResponse) => {
7
+ const handler = {
8
+ responseProvider: originalResponse,
9
+ resolve: (value, outcome) => {
10
+ handler.value = value;
11
+ handler.outcome = outcome;
12
+ },
13
+ reject: (error) => {
14
+ handler.error = error;
15
+ }
16
+ };
17
+ return handler;
18
+ };
19
+ export const clone = (entrypoints, from, to, service) => {
20
+ const source = entrypoints.find(e => e.alias === from);
21
+ if (source?.route.route != null) {
22
+ const _route = { ...source.route.route, service, resolved: false, alias: to };
23
+ entrypoints.push(entrypoint(route(to, _route.path, _route)));
24
+ }
25
+ };
26
+ //# sourceMappingURL=helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,IAA8B,EAA2B,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;AAExH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,IAA8B,EAA2B,EAAE,CAC9F,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,MAAyB,EAAE,IAA8B,EAA2B,EAAE,CACvH,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAI,gBAA0B,EAAuB,EAAE;IACpF,MAAM,OAAO,GAAwB;QACnC,gBAAgB,EAAE,gBAAgB;QAElC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1B,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;YACrB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;QAC3B,CAAC;QAED,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAChB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;QACvB,CAAC;KACF,CAAA;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAA6B,WAAgB,EAAE,IAAY,EAAE,EAAU,EAAE,OAAe,EAAE,EAAE;IAC/G,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAA;IAEtD,IAAI,MAAM,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;QAC7E,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAM,CAAC,CAAA;IACnE,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ export type * from './types.js';
2
+ export * from './entrypoint.js';
3
+ export * from './filter.js';
4
+ export * from './helper.js';
5
+ export * from './consts.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
package/build/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './entrypoint.js';
2
+ export * from './filter.js';
3
+ export * from './helper.js';
4
+ export * from './consts.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
@@ -0,0 +1,81 @@
1
+ import type { CommonRouteModel } from '@owlmeans/route';
2
+ import type { InitializedService, LazyService, BasicEntrypoint } from '@owlmeans/context';
3
+ import type { AnySchemaObject } from 'ajv';
4
+ import type { EntrypointOutcome } from './consts.js';
5
+ import type { Auth } from '@owlmeans/auth';
6
+ export interface CommonEntrypoint extends BasicEntrypoint {
7
+ route: CommonRouteModel;
8
+ /**
9
+ * @property {boolean} - if true — router attaches this entrypoint unconditionally
10
+ * @default false
11
+ */
12
+ sticky: boolean;
13
+ filter?: Filter;
14
+ guards?: string[];
15
+ gate?: string;
16
+ gateParams?: string | string[];
17
+ handle?: EntrypointHandler;
18
+ getAlias: () => string;
19
+ getPath: () => string;
20
+ getParentAlias: () => string | null;
21
+ hasParent: () => boolean;
22
+ resolve: <M extends CommonEntrypoint>() => Promise<M>;
23
+ getParent: <M extends CommonEntrypoint>() => M;
24
+ setService: (service: string) => void;
25
+ getGuards: () => string[];
26
+ getGates: () => [string, string[]][];
27
+ }
28
+ export interface CommonEntrypointOptions extends Partial<CommonEntrypoint> {
29
+ }
30
+ export interface EntrypointMatch {
31
+ <R extends AbstractRequest, P extends AbstractResponse<any>>(req: R, res: P): Promise<boolean>;
32
+ }
33
+ export interface EntrypointHandler {
34
+ <T, R extends AbstractRequest<any> = AbstractRequest<any>, P extends AbstractResponse<any> = AbstractResponse<any>>(req: R, res: P): T | Promise<T>;
35
+ }
36
+ export interface EntrypointAssert {
37
+ <R extends AbstractRequest, P extends AbstractResponse<any>>(req: R, res: P, params: string[]): Promise<void>;
38
+ }
39
+ export interface AbstractRequest<T extends {} = {}> {
40
+ alias: string;
41
+ auth?: Auth;
42
+ params: Record<string, string | number | undefined | null> | Partial<T>;
43
+ body?: Record<string, any> | Partial<T>;
44
+ headers: Record<string, string[] | string | undefined>;
45
+ query: Record<string, string | number | undefined | null> | Partial<T>;
46
+ path: string;
47
+ original?: any;
48
+ canceled?: boolean;
49
+ cancel?: () => void;
50
+ host?: string;
51
+ base?: string | boolean;
52
+ unsecure?: boolean;
53
+ }
54
+ export interface AbstractResponse<T> {
55
+ responseProvider?: any;
56
+ value?: T;
57
+ outcome?: EntrypointOutcome;
58
+ error?: Error;
59
+ resolve: (value: T, outcome?: EntrypointOutcome) => void;
60
+ reject: (error: Error) => void;
61
+ }
62
+ export interface GuardService extends InitializedService {
63
+ token?: string;
64
+ authenticated: (req?: Partial<AbstractRequest>) => Promise<string | null>;
65
+ match: EntrypointMatch;
66
+ handle: EntrypointHandler;
67
+ }
68
+ export interface GateService extends LazyService {
69
+ /**
70
+ * @throws {Error}
71
+ */
72
+ assert: EntrypointAssert;
73
+ }
74
+ export interface Filter {
75
+ query?: AnySchemaObject;
76
+ params?: AnySchemaObject;
77
+ body?: AnySchemaObject;
78
+ response?: AnySchemaObject;
79
+ headers?: AnySchemaObject;
80
+ }
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAA;AAC1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,KAAK,EAAE,gBAAgB,CAAA;IACvB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC9B,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,QAAQ,EAAE,MAAM,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,CAAA;IACnC,SAAS,EAAE,MAAM,OAAO,CAAA;IACxB,OAAO,EAAE,CAAC,CAAC,SAAS,gBAAgB,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;IACrD,SAAS,EAAE,CAAC,CAAC,SAAS,gBAAgB,OAAO,CAAC,CAAA;IAC9C,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,MAAM,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAA;CACrC;AAED,MAAM,WAAW,uBAAwB,SAAQ,OAAO,CAAC,gBAAgB,CAAC;CAAI;AAE9E,MAAM,WAAW,eAAe;IAC9B,CAAC,CAAC,SAAS,eAAe,EAAE,CAAC,SAAS,gBAAgB,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC/F;AAED,MAAM,WAAW,iBAAiB;IAChC,CACE,CAAC,EAAE,CAAC,SAAS,eAAe,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,EACxD,CAAC,SAAS,gBAAgB,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,EACvD,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,CAAC,SAAS,eAAe,EAAE,CAAC,SAAS,gBAAgB,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9G;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC,CAAA;IACtD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACtE,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,GAAG,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,gBAAgB,CAAC,EAAE,GAAG,CAAA;IACtB,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACxD,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,YAAa,SAAQ,kBAAkB;IAEtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAEzE,KAAK,EAAE,eAAe,CAAA;IACtB,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,OAAO,CAAC,EAAE,eAAe,CAAA;CAC1B"}
package/build/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import { CommonEntrypoint } from '../types.js';
2
+ export declare const isEntrypoint: (obj: object) => obj is CommonEntrypoint;
3
+ //# sourceMappingURL=entrypoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,GAAG,IAAI,gBACR,CAAA"}
@@ -0,0 +1,2 @@
1
+ export const isEntrypoint = (obj) => '_entrypoint' in obj || '_module' in obj;
2
+ //# sourceMappingURL=entrypoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAA2B,EAAE,CACnE,aAAa,IAAI,GAAG,IAAI,SAAS,IAAI,GAAG,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './entrypoint.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './entrypoint.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { CommonRouteModel } from '@owlmeans/route';
2
+ import { CommonEntrypointOptions } from '../types.js';
3
+ export interface CreateEntrypointSignature<M> {
4
+ (route: CommonRouteModel, opts?: CommonEntrypointOptions): M;
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAErD,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,uBAAuB,GAAG,CAAC,CAAC;CAC9D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@owlmeans/entrypoint",
3
+ "version": "0.1.3",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "tsc -b",
8
+ "dev": "sleep 186 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
9
+ "watch": "tsc -b -w --preserveWatchOutput --pretty"
10
+ },
11
+ "main": "build/index.js",
12
+ "module": "build/index.js",
13
+ "types": "build/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "import": "./build/index.js",
17
+ "require": "./build/index.js",
18
+ "default": "./build/index.js",
19
+ "module": "./build/index.js",
20
+ "types": "./build/index.d.ts"
21
+ },
22
+ "./utils": {
23
+ "default": "./build/utils/index.js",
24
+ "types": "./build/utils/index.js",
25
+ "import": "./build/utils/index.js",
26
+ "require": "./build/utils/index.js",
27
+ "module": "./build/utils/index.js"
28
+ }
29
+ },
30
+ "dependencies": {
31
+ "@owlmeans/auth": "^0.1.3",
32
+ "@owlmeans/context": "^0.1.3",
33
+ "@owlmeans/route": "^0.1.3",
34
+ "ajv": "^8.17.1"
35
+ },
36
+ "devDependencies": {
37
+ "@owlmeans/dep-config": "workspace:*",
38
+ "nodemon": "^3.1.11",
39
+ "npm-check": "^6.0.1",
40
+ "typescript": "^6.0.2"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }
package/src/consts.ts ADDED
@@ -0,0 +1,7 @@
1
+
2
+ export enum EntrypointOutcome {
3
+ Ok = 'ok',
4
+ Accepted = 'accepted',
5
+ Created = 'created',
6
+ Finished = 'finished'
7
+ }
@@ -0,0 +1,106 @@
1
+ import type { CommonEntrypoint } from './types.js'
2
+ import { appendContextual } from '@owlmeans/context'
3
+ import type { CreateEntrypointSignature } from './utils/types.js'
4
+
5
+ export const entrypoint: CreateEntrypointSignature<CommonEntrypoint> = (route, opts) => {
6
+ let guards: string[] | null = null
7
+ let gates: [string, string[]][] | null = null
8
+ const ep: CommonEntrypoint = appendContextual<CommonEntrypoint>(route.route.alias, {
9
+ _entrypoint: true,
10
+ _module: true,
11
+
12
+ sticky: false,
13
+
14
+ route,
15
+
16
+ getAlias: () => ep.route.route.alias,
17
+ getPath: () => ep.route.route.path,
18
+ getParentAlias: () => ep.route.route.parent ?? null,
19
+ hasParent: () => ep.getParentAlias() != null,
20
+
21
+ resolve: async <M extends CommonEntrypoint>() => {
22
+ if (ep.ctx == null) {
23
+ throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`)
24
+ }
25
+
26
+ await ep.route.resolve(ep.ctx)
27
+
28
+ return ep as M
29
+ },
30
+
31
+ getParent: () => {
32
+ const parentAlias = ep.getParentAlias()
33
+ if (parentAlias == null) {
34
+ throw new SyntaxError(`Entrypoint has no parent - ${ep.getAlias()}`)
35
+ }
36
+ if (ep.ctx == null) {
37
+ throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`)
38
+ }
39
+
40
+ return ep.ctx.entrypoint(parentAlias)
41
+ },
42
+
43
+ setService: service => {
44
+ if (ep.route.route.resolved) {
45
+ throw new SyntaxError(`Cannot update a resolved entrypoint - ${ep.getAlias()}`)
46
+ }
47
+ ep.route.route.service = service
48
+ },
49
+
50
+ getGuards: () => {
51
+ if (guards != null) {
52
+ return guards
53
+ }
54
+ guards = ep.guards ?? []
55
+
56
+ if (ep.hasParent()) {
57
+ guards.push(
58
+ ...ep.getParent().getGuards().filter(guard => !guards?.includes(guard))
59
+ )
60
+ }
61
+
62
+ return guards
63
+ },
64
+
65
+ getGates: () => {
66
+ if (gates != null) {
67
+ return gates
68
+ }
69
+
70
+ gates = ep.gate != null ? [[
71
+ ep.gate, ep.gateParams == null
72
+ ? [] : Array.isArray(ep.gateParams)
73
+ ? ep.gateParams : [ep.gateParams]
74
+ ]] : []
75
+
76
+ if (ep.hasParent()) {
77
+ gates.push(
78
+ ...ep.getParent().getGates()
79
+ .filter(([gate]) => !gates?.some(([g]) => g === gate))
80
+ )
81
+ }
82
+
83
+ return gates
84
+ },
85
+
86
+ ...opts
87
+ })
88
+
89
+ return ep
90
+ }
91
+
92
+ export const parent = <T extends CommonEntrypoint | CommonEntrypoint[]>(ep: T, aliasOrParent: string, _parent?: string): T => {
93
+ if (Array.isArray(ep)) {
94
+ if (_parent == null) {
95
+ throw SyntaxError('Elevating parent requires parent name to be specified')
96
+ }
97
+ ep = ep.find(e => e.route.route.alias === aliasOrParent) as T
98
+ if (ep == null) {
99
+ throw SyntaxError(`Entrypoint not found ${aliasOrParent}`)
100
+ }
101
+ return parent(ep, _parent)
102
+ }
103
+ ep.route.route.parent = aliasOrParent
104
+
105
+ return ep
106
+ }
package/src/filter.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { JSONSchemaType } from 'ajv'
2
+ import type { Filter } from './types.js'
3
+
4
+ export const body = <T>(schema: JSONSchemaType<T>, filter?: Filter): Filter => {
5
+ return { ...filter, body: schema as any }
6
+ }
7
+
8
+ export const query = <T>(schema: JSONSchemaType<T>, filter?: Filter): Filter => {
9
+ return { ...filter, query: schema as any }
10
+ }
11
+
12
+ export const params = <T>(schema: JSONSchemaType<T>, filter?: Filter): Filter => {
13
+ return { ...filter, params: schema as any }
14
+ }
15
+
16
+ export const response = <T>(schema: JSONSchemaType<T>, code?: number, filter?: Filter): Filter => {
17
+ let _schema: any = schema
18
+ if (filter?.response != null && code != null) {
19
+ _schema = { ...filter.response, [code]: schema }
20
+ }
21
+ return { ...filter, response: _schema }
22
+ }
23
+
24
+ export const headers = <T>(schema: JSONSchemaType<T>, filter?: Filter): Filter => {
25
+ return { ...filter, headers: schema as any }
26
+ }
package/src/helper.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { route } from '@owlmeans/route'
2
+ import { Filter, CommonEntrypointOptions, AbstractResponse, CommonEntrypoint } from './types.js'
3
+ import { entrypoint } from './entrypoint.js'
4
+
5
+ export const filter = (filter: Filter, opts?: CommonEntrypointOptions): CommonEntrypointOptions => ({ filter, ...opts })
6
+
7
+ export const guard = (guard: string, opts?: CommonEntrypointOptions): CommonEntrypointOptions =>
8
+ ({ ...opts, guards: [...new Set([guard, ...(opts?.guards ?? [])])] })
9
+
10
+ export const gate = (gate: string, params: string | string[], opts?: CommonEntrypointOptions): CommonEntrypointOptions =>
11
+ ({ ...opts, gate, gateParams: params })
12
+
13
+ export const provideResponse = <T>(originalResponse?: unknown): AbstractResponse<T> => {
14
+ const handler: AbstractResponse<T> = {
15
+ responseProvider: originalResponse,
16
+
17
+ resolve: (value, outcome) => {
18
+ handler.value = value
19
+ handler.outcome = outcome
20
+ },
21
+
22
+ reject: (error) => {
23
+ handler.error = error
24
+ }
25
+ }
26
+
27
+ return handler
28
+ }
29
+
30
+ export const clone = <M extends CommonEntrypoint>(entrypoints: M[], from: string, to: string, service: string) => {
31
+ const source = entrypoints.find(e => e.alias === from)
32
+
33
+ if (source?.route.route != null) {
34
+ const _route = { ...source.route.route, service, resolved: false, alias: to }
35
+ entrypoints.push(entrypoint(route(to, _route.path, _route)) as M)
36
+ }
37
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+
2
+ export type * from './types.js'
3
+ export * from './entrypoint.js'
4
+ export * from './filter.js'
5
+ export * from './helper.js'
6
+ export * from './consts.js'
package/src/types.ts ADDED
@@ -0,0 +1,94 @@
1
+ import type { CommonRouteModel } from '@owlmeans/route'
2
+ import type { InitializedService, LazyService, BasicEntrypoint } from '@owlmeans/context'
3
+ import type { AnySchemaObject } from 'ajv'
4
+ import type { EntrypointOutcome } from './consts.js'
5
+ import type { Auth } from '@owlmeans/auth'
6
+
7
+ export interface CommonEntrypoint extends BasicEntrypoint {
8
+ route: CommonRouteModel
9
+ /**
10
+ * @property {boolean} - if true — router attaches this entrypoint unconditionally
11
+ * @default false
12
+ */
13
+ sticky: boolean
14
+ filter?: Filter
15
+ guards?: string[]
16
+ gate?: string
17
+ gateParams?: string | string[]
18
+ handle?: EntrypointHandler
19
+ getAlias: () => string
20
+ getPath: () => string
21
+ getParentAlias: () => string | null
22
+ hasParent: () => boolean
23
+ resolve: <M extends CommonEntrypoint>() => Promise<M>
24
+ getParent: <M extends CommonEntrypoint>() => M
25
+ setService: (service: string) => void
26
+ getGuards: () => string[]
27
+ getGates: () => [string, string[]][]
28
+ }
29
+
30
+ export interface CommonEntrypointOptions extends Partial<CommonEntrypoint> { }
31
+
32
+ export interface EntrypointMatch {
33
+ <R extends AbstractRequest, P extends AbstractResponse<any>>(req: R, res: P): Promise<boolean>
34
+ }
35
+
36
+ export interface EntrypointHandler {
37
+ <
38
+ T, R extends AbstractRequest<any> = AbstractRequest<any>,
39
+ P extends AbstractResponse<any> = AbstractResponse<any>,
40
+ >(req: R, res: P): T | Promise<T>
41
+ }
42
+
43
+ export interface EntrypointAssert {
44
+ <R extends AbstractRequest, P extends AbstractResponse<any>>(req: R, res: P, params: string[]): Promise<void>
45
+ }
46
+
47
+ export interface AbstractRequest<T extends {} = {}> {
48
+ alias: string
49
+ auth?: Auth
50
+ params: Record<string, string | number | undefined | null> | Partial<T>
51
+ body?: Record<string, any> | Partial<T>
52
+ headers: Record<string, string[] | string | undefined>
53
+ query: Record<string, string | number | undefined | null> | Partial<T>
54
+ path: string
55
+ original?: any
56
+ canceled?: boolean
57
+ cancel?: () => void
58
+ host?: string
59
+ base?: string | boolean
60
+ unsecure?: boolean
61
+ }
62
+
63
+ export interface AbstractResponse<T> {
64
+ responseProvider?: any
65
+ value?: T,
66
+ outcome?: EntrypointOutcome
67
+ error?: Error
68
+ resolve: (value: T, outcome?: EntrypointOutcome) => void
69
+ reject: (error: Error) => void
70
+ }
71
+
72
+ export interface GuardService extends InitializedService {
73
+ // Client guard
74
+ token?: string
75
+ authenticated: (req?: Partial<AbstractRequest>) => Promise<string | null>
76
+ // Server guard
77
+ match: EntrypointMatch
78
+ handle: EntrypointHandler
79
+ }
80
+
81
+ export interface GateService extends LazyService {
82
+ /**
83
+ * @throws {Error}
84
+ */
85
+ assert: EntrypointAssert
86
+ }
87
+
88
+ export interface Filter {
89
+ query?: AnySchemaObject
90
+ params?: AnySchemaObject
91
+ body?: AnySchemaObject
92
+ response?: AnySchemaObject
93
+ headers?: AnySchemaObject
94
+ }
@@ -0,0 +1,4 @@
1
+ import { CommonEntrypoint } from '../types.js'
2
+
3
+ export const isEntrypoint = (obj: object): obj is CommonEntrypoint =>
4
+ '_entrypoint' in obj || '_module' in obj
@@ -0,0 +1,3 @@
1
+
2
+ export * from './types.js'
3
+ export * from './entrypoint.js'
@@ -0,0 +1,6 @@
1
+ import { CommonRouteModel } from '@owlmeans/route'
2
+ import { CommonEntrypointOptions } from '../types.js'
3
+
4
+ export interface CreateEntrypointSignature<M> {
5
+ (route: CommonRouteModel, opts?: CommonEntrypointOptions): M,
6
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": [
3
+ "@owlmeans/dep-config/tsconfig.base.json"
4
+ ],
5
+ "compilerOptions": {
6
+ "rootDir": "./src/",
7
+ "outDir": "./build/"
8
+ },
9
+ "exclude": ["./dist/**/*", "./build/**/*", "./*.ts"]
10
+ }