@toa.io/definitions 1.0.0-alpha.324 → 1.0.0-alpha.326

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 (34) hide show
  1. package/digest/extensions.cadence.json +1 -1
  2. package/digest/extensions.configuration.json +1 -1
  3. package/digest/extensions.exposition.json +1 -1
  4. package/package.json +12 -11
  5. package/schemas/extensions.cadence/declaration.cos.yaml +7 -20
  6. package/schemas/extensions.cadence/pulse.cos.yaml +26 -0
  7. package/schemas/extensions.cadence/schedule.cos.yaml +25 -0
  8. package/schemas/extensions.exposition/routes.cos.yaml +6 -3
  9. package/transpiled/extensions.cadence/const.d.ts +2 -0
  10. package/transpiled/extensions.cadence/const.js +5 -1
  11. package/transpiled/extensions.cadence/const.js.map +1 -1
  12. package/transpiled/extensions.cadence/deployment.js +12 -5
  13. package/transpiled/extensions.cadence/deployment.js.map +1 -1
  14. package/transpiled/extensions.cadence/index.d.ts +3 -1
  15. package/transpiled/extensions.cadence/index.js +1 -0
  16. package/transpiled/extensions.cadence/index.js.map +1 -1
  17. package/transpiled/extensions.cadence/manifest.d.ts +3 -3
  18. package/transpiled/extensions.cadence/manifest.js +68 -15
  19. package/transpiled/extensions.cadence/manifest.js.map +1 -1
  20. package/transpiled/extensions.cadence/schedule.d.ts +11 -0
  21. package/transpiled/extensions.cadence/schedule.js +25 -0
  22. package/transpiled/extensions.cadence/schedule.js.map +1 -0
  23. package/transpiled/extensions.cadence/schemas.d.ts +3 -1
  24. package/transpiled/extensions.cadence/schemas.js +2 -0
  25. package/transpiled/extensions.cadence/schemas.js.map +1 -1
  26. package/transpiled/extensions.cadence/types.d.ts +26 -6
  27. package/transpiled/extensions.exposition/manifest.js +3 -3
  28. package/transpiled/extensions.exposition/manifest.js.map +1 -1
  29. package/transpiled/extensions.exposition/realtime/index.d.ts +1 -1
  30. package/transpiled/extensions.exposition/realtime/index.js +1 -1
  31. package/transpiled/extensions.exposition/realtime/index.js.map +1 -1
  32. package/transpiled/extensions.exposition/realtime/routes.d.ts +10 -1
  33. package/transpiled/extensions.exposition/realtime/routes.js +17 -5
  34. package/transpiled/extensions.exposition/realtime/routes.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/definitions",
3
- "version": "1.0.0-alpha.324",
3
+ "version": "1.0.0-alpha.326",
4
4
  "type": "module",
5
5
  "description": "What Toa packages declare, read without running them",
6
6
  "author": "temich <tema.gurtovoy@gmail.com>",
@@ -31,8 +31,9 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@toa.io/generic": "1.0.0-alpha.311",
34
- "@toa.io/pointer": "1.0.0-alpha.311",
35
- "@toa.io/schemas": "1.0.0-alpha.311"
34
+ "@toa.io/pointer": "1.0.0-alpha.326",
35
+ "@toa.io/schemas": "1.0.0-alpha.326",
36
+ "croner": "10.0.1"
36
37
  },
37
38
  "scripts": {
38
39
  "transpile": "tsc",
@@ -44,18 +45,18 @@
44
45
  "./*": "./transpiled/*/index.js"
45
46
  },
46
47
  "devDependencies": {
47
- "@aws-sdk/client-s3": "3.1140.0",
48
- "@aws-sdk/lib-storage": "3.1140.0",
49
- "@toa.io/core": "1.0.0-alpha.323",
48
+ "@aws-sdk/client-s3": "3.1145.0",
49
+ "@aws-sdk/lib-storage": "3.1145.0",
50
+ "@toa.io/core": "1.0.0-alpha.326",
50
51
  "cloudinary": "2.11.0",
51
52
  "openspan": "1.0.0-alpha.323",
52
- "oxc-parser": "0.151.0"
53
+ "oxc-parser": "0.152.0"
53
54
  },
54
55
  "peerDependencies": {
55
- "@aws-sdk/client-s3": "3.1140.0",
56
- "@aws-sdk/lib-storage": "3.1140.0",
56
+ "@aws-sdk/client-s3": "3.1145.0",
57
+ "@aws-sdk/lib-storage": "3.1145.0",
57
58
  "cloudinary": "2.11.0",
58
- "oxc-parser": "0.151.0"
59
+ "oxc-parser": "0.152.0"
59
60
  },
60
61
  "peerDependenciesMeta": {
61
62
  "@aws-sdk/client-s3": {
@@ -71,5 +72,5 @@
71
72
  "optional": true
72
73
  }
73
74
  },
74
- "gitHead": "eedcbb7b90b3ea759f200b0d03c7ae13a8487b9d"
75
+ "gitHead": "60f11bdc805d0c39bcb06064b2218b11114a35ad"
75
76
  }
@@ -1,25 +1,12 @@
1
- # manifest.toa.yaml cadence declaration: the operations called on a cadence
1
+ # manifest.toa.yaml cadence declaration: the operations called on a cadence or at the moments
2
+ # of a calendar, each by the entries it was given. What an entry may state is its kind's own
3
+ # schema, `pulse` or `schedule`.
2
4
  type: object
3
5
  propertyNames:
4
6
  pattern: ^[a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?$
5
7
  patternProperties:
6
8
  ".*":
7
- type: object
8
- properties:
9
- cycle:
10
- description: Seconds one whole cycle takes
11
- type: integer
12
- minimum: 1
13
- intervals:
14
- description: >
15
- Intervals the cycle is split into. The gap between calls is `cycle / intervals`,
16
- and the operation is told which interval it is running for.
17
- type: integer
18
- minimum: 1
19
- scope:
20
- description: >
21
- Whose work this is: the component's, which one replica makes each call of, or every
22
- replica's, for what lives inside a process.
23
- enum: [group, replica]
24
- required: [cycle]
25
- additionalProperties: false
9
+ type: array
10
+ minItems: 1
11
+ items:
12
+ type: object
@@ -0,0 +1,26 @@
1
+ # an entry of a cadence declaration that states a cycle
2
+ type: object
3
+ properties:
4
+ cycle:
5
+ description: Seconds one whole cycle takes
6
+ type: integer
7
+ minimum: 1
8
+ intervals:
9
+ description: >
10
+ Intervals the cycle is split into. The gap between calls is `cycle / intervals`,
11
+ and the operation is told which interval it is running for.
12
+ type: integer
13
+ minimum: 1
14
+ scope:
15
+ description: >
16
+ Whose work this is: the component's, which one replica makes each call of, or every
17
+ replica's, for what lives inside a process.
18
+ enum: [group, replica]
19
+ region:
20
+ description: >
21
+ The rank of the region that makes the calls, where the work is one for an application
22
+ deployed as several. Every region makes them where none is stated.
23
+ type: integer
24
+ minimum: 0
25
+ required: [cycle, intervals, scope]
26
+ additionalProperties: false
@@ -0,0 +1,25 @@
1
+ # an entry of a cadence declaration that states a schedule
2
+ type: object
3
+ properties:
4
+ schedule:
5
+ description: >
6
+ A cron expression of five fields, or of six where the first is seconds. The operation is
7
+ told the moment each call was scheduled for.
8
+ type: string
9
+ zone:
10
+ description: The time zone the expression is read in, as the IANA database names it
11
+ type: string
12
+ overdue:
13
+ description: >
14
+ Seconds a call may be late and still be made. Where none is stated it is made until the
15
+ next one comes due.
16
+ type: integer
17
+ minimum: 0
18
+ region:
19
+ description: >
20
+ The rank of the region that makes the calls, where the work is one for an application
21
+ deployed as several. Every region makes them where none is stated.
22
+ type: integer
23
+ minimum: 0
24
+ required: [schedule, zone]
25
+ additionalProperties: false
@@ -5,14 +5,17 @@ additionalProperties:
5
5
  type: object
6
6
  properties:
7
7
  key:
8
- description: The properties of the event that are the keys of the streams it goes to
8
+ description: >-
9
+ The properties of the event that are the keys of the streams it goes to, or literal keys:
10
+ `~` and the key
11
+ # a property, or `~` and at least one character of a literal
9
12
  oneOf:
10
13
  - type: string
11
- minLength: 1
14
+ pattern: ^(?:[^~]|~.)
12
15
  - type: array
13
16
  items:
14
17
  type: string
15
- minLength: 1
18
+ pattern: ^(?:[^~]|~.)
16
19
  minItems: 1
17
20
  expose:
18
21
  description: What of the event its streams are given; nothing is given that is not named
@@ -33,3 +33,5 @@ export declare const REGIONS = "TOA_CADENCE_REGIONS";
33
33
  * carry.
34
34
  */
35
35
  export declare function regions(): number[];
36
+ /** The rank of the region this deployment is, which is zero where it is no region at all. */
37
+ export declare function rank(): number;
@@ -40,7 +40,11 @@ export const REGIONS = 'TOA_CADENCE_REGIONS';
40
40
  export function regions() {
41
41
  const declared = environment.get(REGIONS);
42
42
  if (declared === undefined)
43
- return [Number(environment.get(REGION) ?? 0)];
43
+ return [rank()];
44
44
  return declared.split(' ').map(Number);
45
45
  }
46
+ /** The rank of the region this deployment is, which is zero where it is no region at all. */
47
+ export function rank() {
48
+ return Number(environment.get(REGION) ?? 0);
49
+ }
46
50
  //# sourceMappingURL=const.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"const.js","sourceRoot":"","sources":["../../source/extensions.cadence/const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAA;AAE3D,+DAA+D;AAC/D,MAAM,CAAC,MAAM,SAAS,GAAG,SAAS,CAAA;AAClC,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAA;AAEpC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB,+FAA+F;AAC/F,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAA;AAE9B,gCAAgC;AAChC,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB,oFAAoF;AACpF,MAAM,UAAU,MAAM,CAAC,QAAgB,EAAE,QAAgB;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IAE/C,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7D,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,qBAAqB,CAAA;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAEzC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAEzE,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACxC,CAAC"}
1
+ {"version":3,"file":"const.js","sourceRoot":"","sources":["../../source/extensions.cadence/const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAA;AAE3D,+DAA+D;AAC/D,MAAM,CAAC,MAAM,SAAS,GAAG,SAAS,CAAA;AAClC,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAA;AAEpC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB,+FAA+F;AAC/F,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAA;AAE9B,gCAAgC;AAChC,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB,oFAAoF;AACpF,MAAM,UAAU,MAAM,CAAC,QAAgB,EAAE,QAAgB;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IAE/C,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7D,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,qBAAqB,CAAA;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAEzC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IAE3C,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACxC,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,IAAI;IAClB,OAAO,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAC7C,CAAC"}
@@ -14,10 +14,6 @@ export function deployment(_, annotation) {
14
14
  const variables = [
15
15
  { name: 'TOA_CADENCE_DISCRETENESS', value: String(discreteness) }
16
16
  ];
17
- // absent, the metronome makes the calls of the region it is deployed as, which is what a
18
- // deployment that has never heard of regions does anyway
19
- if (annotation?.regions !== undefined)
20
- variables.push({ name: REGIONS, value: annotation.regions.join(' ') });
21
17
  const service = {
22
18
  group: NAMESPACE,
23
19
  name: 'metronome',
@@ -25,7 +21,18 @@ export function deployment(_, annotation) {
25
21
  components: components().labels,
26
22
  variables
27
23
  };
28
- return { services: [service] };
24
+ // absent, a deployment makes the calls of the region it is deployed as, which is what one
25
+ // that has never heard of regions does anyway
26
+ if (annotation?.regions === undefined)
27
+ return { services: [service] };
28
+ const regions = { name: REGIONS, value: annotation.regions.join(' ') };
29
+ variables.push(regions);
30
+ /*
31
+ * Every composition is given it as well as the metronome: a pulse and a schedule that name a
32
+ * region are made by the components that declare them, and the region that takes over the
33
+ * delayed calls of one that is gone has to take those over with them.
34
+ */
35
+ return { services: [service], variables: { global: [regions] } };
29
36
  }
30
37
  /** The extension is deployed for the sake of `delay`, which nothing has to declare to use. */
31
38
  export const standalone = true;
@@ -1 +1 @@
1
- {"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../source/extensions.cadence/deployment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAIvC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,CAAU,EAAE,UAA8B;IACnE,OAAO,CAAC,UAAU,CAAC,QAAQ,CACzB,UAAU,IAAI,IAAI,EAClB,4BAA4B,CAC7B,CAAA;IAED,4FAA4F;IAC5F,uCAAuC;IACvC,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,YAAY,IAAI,YAAY,CAAC,GAAG,IAAI,CAAA;IACtE,MAAM,SAAS,GAAe;QAC5B,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE;KAClE,CAAA;IAED,yFAAyF;IACzF,yDAAyD;IACzD,IAAI,UAAU,EAAE,OAAO,KAAK,SAAS;QACnC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAExE,MAAM,OAAO,GAAY;QACvB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,WAAW;QACjB,OAAO;QACP,UAAU,EAAE,UAAU,EAAE,CAAC,MAAM;QAC/B,SAAS;KACV,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAA;AAChC,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAA"}
1
+ {"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../source/extensions.cadence/deployment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAIvC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,CAAU,EAAE,UAA8B;IACnE,OAAO,CAAC,UAAU,CAAC,QAAQ,CACzB,UAAU,IAAI,IAAI,EAClB,4BAA4B,CAC7B,CAAA;IAED,4FAA4F;IAC5F,uCAAuC;IACvC,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,YAAY,IAAI,YAAY,CAAC,GAAG,IAAI,CAAA;IACtE,MAAM,SAAS,GAAe;QAC5B,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE;KAClE,CAAA;IAED,MAAM,OAAO,GAAY;QACvB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,WAAW;QACjB,OAAO;QACP,UAAU,EAAE,UAAU,EAAE,CAAC,MAAM;QAC/B,SAAS;KACV,CAAA;IAED,0FAA0F;IAC1F,8CAA8C;IAC9C,IAAI,UAAU,EAAE,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAA;IAErE,MAAM,OAAO,GAAa,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;IAEhF,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAEvB;;;;OAIG;IACH,OAAO,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,CAAA;AAClE,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAA"}
@@ -2,6 +2,8 @@ export { manifest } from './manifest.ts';
2
2
  export { components } from './components.ts';
3
3
  export { deployment, standalone } from './deployment.ts';
4
4
  export { context } from './context.ts';
5
+ export { occurrences } from './schedule.ts';
5
6
  export * from './const.ts';
6
7
  export * as schemas from './schemas.ts';
7
- export type { Annotation, Declaration, Declared, Delay, Options, Pulse, Scope } from './types.ts';
8
+ export type { Annotation, Declaration, Declared, Delay, Entry, Options, Pulse, Schedule, Scope, Stated } from './types.ts';
9
+ export type { Occurrences } from './schedule.ts';
@@ -2,6 +2,7 @@ export { manifest } from './manifest.js';
2
2
  export { components } from './components.js';
3
3
  export { deployment, standalone } from './deployment.js';
4
4
  export { context } from './context.js';
5
+ export { occurrences } from './schedule.js';
5
6
  export * from './const.js';
6
7
  export * as schemas from './schemas.js';
7
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/extensions.cadence/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,cAAc,YAAY,CAAA;AAC1B,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/extensions.cadence/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,cAAc,YAAY,CAAA;AAC1B,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA"}
@@ -1,9 +1,9 @@
1
1
  import type { Declaration, Declared } from './types.ts';
2
2
  import type { Manifest } from '@toa.io/norm';
3
3
  /**
4
- * The `cadence:` block of a component manifest: the operations called on a cadence, by the
5
- * operation each one calls. Norm hands over the whole manifest, so what the declaration refers
6
- * to is checked here rather than left to fail at boot.
4
+ * The `cadence:` block of a component manifest: the operations called on a cadence or at the
5
+ * moments of a calendar, by the operation each entry calls. Norm hands over the whole manifest,
6
+ * so what the declaration refers to is checked here rather than left to fail at boot.
7
7
  *
8
8
  * A component that declares nothing still has a declaration. `cadence: ~` is how one that only
9
9
  * delays calls says so, and it has to produce a value or norm rejects the extension.
@@ -1,8 +1,9 @@
1
1
  import * as schemas from './schemas.js';
2
+ import { occurrences } from './schedule.js';
2
3
  /**
3
- * The `cadence:` block of a component manifest: the operations called on a cadence, by the
4
- * operation each one calls. Norm hands over the whole manifest, so what the declaration refers
5
- * to is checked here rather than left to fail at boot.
4
+ * The `cadence:` block of a component manifest: the operations called on a cadence or at the
5
+ * moments of a calendar, by the operation each entry calls. Norm hands over the whole manifest,
6
+ * so what the declaration refers to is checked here rather than left to fail at boot.
6
7
  *
7
8
  * A component that declares nothing still has a declaration. `cadence: ~` is how one that only
8
9
  * delays calls says so, and it has to produce a value or norm rejects the extension.
@@ -10,31 +11,83 @@ import * as schemas from './schemas.js';
10
11
  export function manifest(declaration, component) {
11
12
  const normalized = expand(declaration);
12
13
  schemas.declaration.validate(normalized, 'Invalid cadence declaration');
13
- for (const [endpoint, pulse] of Object.entries(normalized)) {
14
+ for (const [endpoint, entries] of Object.entries(normalized)) {
14
15
  const operation = component.operations?.[endpoint];
15
16
  if (operation === undefined)
16
- throw new Error(`Pulse refers to undefined operation '${endpoint}'`);
17
+ throw new Error(`Cadence refers to undefined operation '${endpoint}'`);
17
18
  if (!TYPES.has(operation.type))
18
- throw new Error(`Pulse '${endpoint}' must refer to an operation of the allowed types: ` +
19
+ throw new Error(`Cadence of '${endpoint}' must refer to an operation of the allowed types: ` +
19
20
  [...TYPES].join(', '));
20
- if (pulse.intervals > pulse.cycle)
21
- throw new Error(`Pulse '${endpoint}' splits a cycle of ${pulse.cycle} seconds into ` +
22
- `${pulse.intervals} intervals, which is less than a second each`);
21
+ for (const entry of entries)
22
+ check(endpoint, entry);
23
23
  }
24
24
  return normalized;
25
25
  }
26
- /** A pulse whose cycle is not split has nothing to state but the cycle. */
26
+ /**
27
+ * An entry is one kind or the other, and each kind is a closed shape: what belongs to a pulse
28
+ * is refused beside a schedule and the other way round, by the schema of the kind it is.
29
+ */
30
+ function check(endpoint, entry) {
31
+ const pulse = 'cycle' in entry;
32
+ const schedule = 'schedule' in entry;
33
+ if (pulse && schedule)
34
+ throw new Error(`Cadence of '${endpoint}' states both a cycle and a schedule`);
35
+ if (schedule)
36
+ return scheduled(endpoint, entry);
37
+ if (pulse)
38
+ return pulsed(endpoint, entry);
39
+ throw new Error(`Cadence of '${endpoint}' states neither a cycle nor a schedule`);
40
+ }
41
+ function pulsed(endpoint, pulse) {
42
+ schemas.pulse.validate(pulse, `Invalid pulse '${endpoint}'`);
43
+ if (pulse.intervals > pulse.cycle)
44
+ throw new Error(`Pulse '${endpoint}' splits a cycle of ${pulse.cycle} seconds into ` +
45
+ `${pulse.intervals} intervals, which is less than a second each`);
46
+ // what lives in a process is that process's own in every region
47
+ if (pulse.scope === 'replica' && pulse.region !== undefined)
48
+ throw new Error(`Pulse '${endpoint}' is every replica's and cannot name a region`);
49
+ }
50
+ function scheduled(endpoint, schedule) {
51
+ // read before the schema, which takes a null for the number it coerces it to: no bound at all
52
+ // is what a delay may state and a schedule may not, because nothing would then keep the
53
+ // occurrences of an outage from all being owed at once
54
+ if (schedule.overdue === null)
55
+ throw new Error(`Invalid schedule '${endpoint}': a schedule states a bound or none, not null`);
56
+ schemas.schedule.validate(schedule, `Invalid schedule '${endpoint}'`);
57
+ try {
58
+ occurrences(schedule.schedule, schedule.zone);
59
+ }
60
+ catch (error) {
61
+ throw new Error(`Invalid schedule '${endpoint}': ${error.message}`, {
62
+ cause: error
63
+ });
64
+ }
65
+ }
66
+ /** An operation has a list of entries, and an entry states everything its kind has. */
27
67
  function expand(declaration) {
28
68
  if (declaration === null || declaration === undefined)
29
69
  return {};
30
- // a cycle nothing splits is one interval, which is what the shorthand declares
31
- return Object.fromEntries(Object.entries(declaration).map(([endpoint, pulse]) => {
32
- const declared = typeof pulse === 'number' ? { cycle: pulse } : { ...pulse };
70
+ return Object.fromEntries(Object.entries(declaration).map(([endpoint, stated]) => [
71
+ endpoint,
72
+ (Array.isArray(stated) ? stated : [stated]).map(entry)
73
+ ]));
74
+ }
75
+ function entry(stated) {
76
+ // a number is a cycle nothing splits and a string is an expression, which is what the
77
+ // shorthands declare
78
+ const declared = typeof stated === 'number'
79
+ ? { cycle: stated }
80
+ : typeof stated === 'string'
81
+ ? { schedule: stated }
82
+ : { ...stated };
83
+ if ('schedule' in declared)
84
+ declared.zone ??= 'UTC';
85
+ else if ('cycle' in declared) {
33
86
  declared.intervals ??= 1;
34
87
  // a pulse that does not say whose work it is is the component's, as every pulse was
35
88
  declared.scope ??= 'group';
36
- return [endpoint, declared];
37
- }));
89
+ }
90
+ return declared;
38
91
  }
39
92
  /**
40
93
  * The types a receiver may refer to. An operation that produces no side effects has nothing to
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../source/extensions.cadence/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAIvC;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,WAAwC,EACxC,SAAmB;IAEnB,MAAM,UAAU,GAA4B,MAAM,CAAC,WAAW,CAAC,CAAA;IAE/D,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAc,UAAU,EAAE,6BAA6B,CAAC,CAAA;IAEpF,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3D,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAA;QAElD,IAAI,SAAS,KAAK,SAAS;YACzB,MAAM,IAAI,KAAK,CAAC,wCAAwC,QAAQ,GAAG,CAAC,CAAA;QAEtE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,qDAAqD;gBACrE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACxB,CAAA;QAEH,IAAI,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK;YAC/B,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,uBAAuB,KAAK,CAAC,KAAK,gBAAgB;gBAClE,GAAG,KAAK,CAAC,SAAS,8CAA8C,CACnE,CAAA;IACL,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,2EAA2E;AAC3E,SAAS,MAAM,CAAC,WAAwC;IACtD,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IAEhE,+EAA+E;IAC/E,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;QACpD,MAAM,QAAQ,GACZ,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAA;QAE7D,QAAQ,CAAC,SAAS,KAAK,CAAC,CAAA;QAExB,oFAAoF;QACpF,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAA;QAE1B,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC7B,CAAC,CAAC,CACH,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../source/extensions.cadence/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The moments a schedule states, as a function of the clock: what comes first after a moment,
3
+ * in milliseconds since the epoch. Nothing is kept between two questions, so every process that
4
+ * holds the same expression answers the same.
5
+ *
6
+ * Raises where the expression or the zone does not parse, and where the expression names a
7
+ * moment no calendar has — which is what reading a manifest refuses.
8
+ */
9
+ export declare function occurrences(expression: string, zone: string): Occurrences;
10
+ /** What comes first after `after`, or `null` where nothing ever does again. */
11
+ export type Occurrences = (after: number) => number | null;
@@ -0,0 +1,25 @@
1
+ import { Cron } from 'croner';
2
+ /**
3
+ * The moments a schedule states, as a function of the clock: what comes first after a moment,
4
+ * in milliseconds since the epoch. Nothing is kept between two questions, so every process that
5
+ * holds the same expression answers the same.
6
+ *
7
+ * Raises where the expression or the zone does not parse, and where the expression names a
8
+ * moment no calendar has — which is what reading a manifest refuses.
9
+ */
10
+ export function occurrences(expression, zone) {
11
+ const fields = expression.trim().split(/\s+/).length;
12
+ // what the parser reads beyond these — a year, a nickname — is not what is documented
13
+ if (fields !== 5 && fields !== 6)
14
+ throw new Error(`'${expression}' is not a cron expression of five or six fields`);
15
+ // given nothing to run, so it keeps no timer and is only ever asked
16
+ const cron = new Cron(expression, { timezone: zone });
17
+ function next(after) {
18
+ return cron.nextRun(new Date(after))?.getTime() ?? null;
19
+ }
20
+ // the zone is not read until a moment is asked for
21
+ if (next(Date.now()) === null)
22
+ throw new Error(`'${expression}' never comes due`);
23
+ return next;
24
+ }
25
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../source/extensions.cadence/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,IAAY;IAC1D,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAA;IAEpD,sFAAsF;IACtF,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,IAAI,UAAU,kDAAkD,CAAC,CAAA;IAEnF,oEAAoE;IACpE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAErD,SAAS,IAAI,CAAC,KAAa;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,IAAI,CAAA;IACzD,CAAC;IAED,mDAAmD;IACnD,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,UAAU,mBAAmB,CAAC,CAAA;IAEjF,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import type { Schema } from '@toa.io/schemas';
2
- import type { Annotation, Declaration } from './types.ts';
2
+ import type { Annotation, Declaration, Pulse, Schedule } from './types.ts';
3
3
  export declare const declaration: Schema<Declaration>;
4
+ export declare const pulse: Schema<Pulse>;
5
+ export declare const schedule: Schema<Schedule>;
4
6
  export declare const annotation: Schema<Annotation>;
@@ -3,5 +3,7 @@ import * as schemas from '@toa.io/schemas';
3
3
  const path = resolve(import.meta.dirname, '../../schemas/extensions.cadence');
4
4
  const namespace = schemas.namespace(path);
5
5
  export const declaration = namespace.schema('declaration');
6
+ export const pulse = namespace.schema('pulse');
7
+ export const schedule = namespace.schema('schedule');
6
8
  export const annotation = namespace.schema('annotation');
7
9
  //# sourceMappingURL=schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../source/extensions.cadence/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAA;AAI1C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAA;AAC7E,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAwB,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAuB,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA"}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../source/extensions.cadence/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAA;AAI1C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAA;AAC7E,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAwB,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;AAC/E,MAAM,CAAC,MAAM,KAAK,GAAkB,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAC7D,MAAM,CAAC,MAAM,QAAQ,GAAqB,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AACtE,MAAM,CAAC,MAAM,UAAU,GAAuB,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA"}
@@ -1,12 +1,17 @@
1
- /** What one component declares under `cadence:`, by the operation each one calls. */
2
- export type Declaration = Record<string, Pulse>;
1
+ /** What one component declares under `cadence:`, by the operation each entry calls. */
2
+ export type Declaration = Record<string, Entry[]>;
3
+ /** One way an operation is called: on a cadence, or at the moments of a calendar. */
4
+ export type Entry = Pulse | Schedule;
3
5
  /**
4
- * What a manifest may state: a whole pulse, one with what it leaves to the default left out,
5
- * or the cycle alone.
6
+ * What a manifest may state for an operation: one entry or a list of them, each a whole entry,
7
+ * one with what it leaves to the default left out, or its cycle or its expression alone.
6
8
  */
7
- export type Declared = Record<string, number | (Partial<Pulse> & {
9
+ export type Declared = Record<string, Stated | Stated[]>;
10
+ export type Stated = number | string | (Partial<Pulse> & {
8
11
  cycle: number;
9
- })>;
12
+ }) | (Partial<Schedule> & {
13
+ schedule: string;
14
+ });
10
15
  export interface Pulse {
11
16
  /** seconds one whole cycle takes */
12
17
  cycle: number;
@@ -17,6 +22,21 @@ export interface Pulse {
17
22
  * is every replica's own, for what lives inside a process.
18
23
  */
19
24
  scope: Scope;
25
+ /** the rank of the region that makes the calls; every region makes them where absent */
26
+ region?: number;
27
+ }
28
+ export interface Schedule {
29
+ /** a cron expression of five fields, or of six where the first is seconds */
30
+ schedule: string;
31
+ /** the time zone the expression is read in */
32
+ zone: string;
33
+ /**
34
+ * Seconds a call may be late and still be made. Absent, it is made until the next one comes
35
+ * due, so that at most one occurrence is ever owed.
36
+ */
37
+ overdue?: number;
38
+ /** the rank of the region that makes the calls; every region makes them where absent */
39
+ region?: number;
20
40
  }
21
41
  export type Scope = 'group' | 'replica';
22
42
  /** `context.delay` — a call to be made later, answering the id that cancels it. */
@@ -31,9 +31,9 @@ function specifyMethod(method, manifest) {
31
31
  throw new Error(`Operation '${method.mapping.endpoint}' not found`);
32
32
  if (method.mapping.query === undefined)
33
33
  method.mapping.query = operation.query === false ? null : {};
34
- // a page is taken of a collection, and of nothing else: an operation that answers one object
35
- // takes no `omit` and no `limit`, and refuses a request that carries them
36
- method.mapping.paged = operation.type === 'observation' && operation.scope === 'entries';
34
+ // a page is taken of a set, whatever is done with it, and of nothing else: an operation over
35
+ // one object takes no `omit` and no `limit`, and refuses a request that carries them
36
+ method.mapping.paged = operation.scope === 'entries';
37
37
  method.mapping.streamed = operation.scope === 'stream';
38
38
  projects(method, operation.type);
39
39
  streams(method, operation);
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../source/extensions.exposition/manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../source/extensions.exposition/manifest.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export { deployment } from './deployment.ts';
2
2
  export { manifest } from './manifest.ts';
3
- export { parse } from './routes.ts';
3
+ export { literal, parse } from './routes.ts';
4
4
  export { EXPIRE, STREAMS } from './const.ts';
5
5
  export type { Annotation } from './deployment.ts';
6
6
  export type { Declaration, Route, RouteDeclaration } from './routes.ts';
@@ -1,5 +1,5 @@
1
1
  export { deployment } from './deployment.js';
2
2
  export { manifest } from './manifest.js';
3
- export { parse } from './routes.js';
3
+ export { literal, parse } from './routes.js';
4
4
  export { EXPIRE, STREAMS } from './const.js';
5
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../source/extensions.exposition/realtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../source/extensions.exposition/realtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA"}
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * A realtime route: an event of a component, the properties of its payload that are the keys of
3
- * the streams it goes to, and what of it they are given.
3
+ * the streams it goes to, the literal keys it goes to whatever its payload, and what of it they
4
+ * are given.
4
5
  */
5
6
  export interface Route {
6
7
  /** the event's label within its component */
7
8
  event: string;
8
9
  properties: string[];
10
+ /** keys as they are, `~` included */
11
+ literals: string[];
9
12
  expose: string[];
10
13
  }
11
14
  /** A component's `realtime` declaration, by event label. */
@@ -16,3 +19,9 @@ export interface RouteDeclaration {
16
19
  expose: string[];
17
20
  }
18
21
  export declare function parse(declaration: Declaration): Route[];
22
+ /**
23
+ * A key that begins with `~` is the key itself. No property is named so, and no value of a
24
+ * property is taken for a key so, which keeps a literal's stream out of reach of whoever writes
25
+ * the values.
26
+ */
27
+ export declare function literal(key: string): boolean;
@@ -1,8 +1,20 @@
1
1
  export function parse(declaration) {
2
- return Object.entries(declaration).map(([event, { key, expose }]) => ({
3
- event,
4
- properties: Array.isArray(key) ? key : [key],
5
- expose
6
- }));
2
+ return Object.entries(declaration).map(([event, { key, expose }]) => {
3
+ const keys = Array.isArray(key) ? key : [key];
4
+ return {
5
+ event,
6
+ properties: keys.filter((one) => !literal(one)),
7
+ literals: keys.filter(literal),
8
+ expose
9
+ };
10
+ });
11
+ }
12
+ /**
13
+ * A key that begins with `~` is the key itself. No property is named so, and no value of a
14
+ * property is taken for a key so, which keeps a literal's stream out of reach of whoever writes
15
+ * the values.
16
+ */
17
+ export function literal(key) {
18
+ return key.startsWith('~');
7
19
  }
8
20
  //# sourceMappingURL=routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../source/extensions.exposition/realtime/routes.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,KAAK,CAAC,WAAwB;IAC5C,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACpE,KAAK;QACL,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5C,MAAM;KACP,CAAC,CAAC,CAAA;AACL,CAAC"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../source/extensions.exposition/realtime/routes.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,KAAK,CAAC,WAAwB;IAC5C,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAE7C,OAAO;YACL,KAAK;YACL,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC/C,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YAC9B,MAAM;SACP,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AAC5B,CAAC"}