@toa.io/definitions 1.0.0-alpha.292 → 1.0.0-alpha.294
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/digest/extensions.configuration.json +1 -1
- package/digest/extensions.exposition.json +1 -1
- package/package.json +24 -7
- package/readme.md +1 -0
- package/transpiled/bridges.node/exports.js +25 -2
- package/transpiled/bridges.node/exports.js.map +1 -1
- package/transpiled/digest/generate.js +23 -3
- package/transpiled/digest/generate.js.map +1 -1
- package/transpiled/digest/read.d.ts +8 -0
- package/transpiled/digest/read.js +11 -0
- package/transpiled/digest/read.js.map +1 -1
- package/transpiled/extensions.configuration/deployment.js +4 -2
- package/transpiled/extensions.configuration/deployment.js.map +1 -1
- package/transpiled/extensions.configuration/index.d.ts +1 -0
- package/transpiled/extensions.configuration/index.js +1 -0
- package/transpiled/extensions.configuration/index.js.map +1 -1
- package/transpiled/extensions.configuration/secrets.d.ts +4 -0
- package/transpiled/extensions.configuration/secrets.js +42 -0
- package/transpiled/extensions.configuration/secrets.js.map +1 -0
- package/transpiled/extensions.exposition/index.d.ts +1 -0
- package/transpiled/extensions.exposition/index.js +1 -0
- package/transpiled/extensions.exposition/index.js.map +1 -1
- package/transpiled/extensions.exposition/packages.d.ts +11 -0
- package/transpiled/extensions.exposition/packages.js +17 -0
- package/transpiled/extensions.exposition/packages.js.map +1 -0
- package/transpiled/extensions.storages/index.d.ts +1 -0
- package/transpiled/extensions.storages/index.js +1 -0
- package/transpiled/extensions.storages/index.js.map +1 -1
- package/transpiled/extensions.storages/packages.d.ts +19 -0
- package/transpiled/extensions.storages/packages.js +41 -0
- package/transpiled/extensions.storages/packages.js.map +1 -0
- package/CHANGELOG.md +0 -13
- package/source/bindings.amqp/annotation.ts +0 -26
- package/source/bindings.amqp/context.ts +0 -68
- package/source/bindings.amqp/deployment.ts +0 -14
- package/source/bindings.amqp/index.ts +0 -9
- package/source/bindings.amqp/instance.ts +0 -3
- package/source/bindings.amqp/sources.ts +0 -39
- package/source/bindings.loop/index.ts +0 -3
- package/source/bridges.bash/const.ts +0 -2
- package/source/bridges.bash/define.ts +0 -38
- package/source/bridges.bash/index.ts +0 -2
- package/source/bridges.node/define.ts +0 -69
- package/source/bridges.node/exports.ts +0 -175
- package/source/bridges.node/index.ts +0 -6
- package/source/bridges.node/operations.ts +0 -127
- package/source/bridges.node/sources.ts +0 -44
- package/source/definition.ts +0 -38
- package/source/digest/generate.ts +0 -77
- package/source/digest/read.ts +0 -39
- package/source/extensions.cadence/components.ts +0 -6
- package/source/extensions.cadence/const.ts +0 -31
- package/source/extensions.cadence/context.ts +0 -10
- package/source/extensions.cadence/deployment.ts +0 -37
- package/source/extensions.cadence/index.ts +0 -8
- package/source/extensions.cadence/manifest.ts +0 -64
- package/source/extensions.cadence/schemas.ts +0 -10
- package/source/extensions.cadence/types.ts +0 -41
- package/source/extensions.configuration/components.ts +0 -6
- package/source/extensions.configuration/const.ts +0 -30
- package/source/extensions.configuration/context.ts +0 -13
- package/source/extensions.configuration/deployment.ts +0 -159
- package/source/extensions.configuration/epoch.ts +0 -22
- package/source/extensions.configuration/index.ts +0 -10
- package/source/extensions.configuration/manifest.ts +0 -12
- package/source/extensions.configuration/schemas.ts +0 -9
- package/source/extensions.exposition/Annotation.ts +0 -91
- package/source/extensions.exposition/components.ts +0 -6
- package/source/extensions.exposition/const.ts +0 -45
- package/source/extensions.exposition/deployment.ts +0 -95
- package/source/extensions.exposition/index.ts +0 -16
- package/source/extensions.exposition/manifest.ts +0 -56
- package/source/extensions.exposition/schemas.ts +0 -16
- package/source/extensions.exposition/shortcuts.ts +0 -14
- package/source/extensions.exposition/syntax/index.ts +0 -2
- package/source/extensions.exposition/syntax/parse.ts +0 -171
- package/source/extensions.exposition/syntax/types.ts +0 -69
- package/source/extensions.fetch/context.ts +0 -10
- package/source/extensions.fetch/index.ts +0 -1
- package/source/extensions.introspection/annotation.ts +0 -87
- package/source/extensions.introspection/components.ts +0 -13
- package/source/extensions.introspection/const.ts +0 -46
- package/source/extensions.introspection/deployment.ts +0 -48
- package/source/extensions.introspection/index.ts +0 -6
- package/source/extensions.introspection/manifest.ts +0 -18
- package/source/extensions.introspection/schemas.ts +0 -12
- package/source/extensions.realtime/components.ts +0 -5
- package/source/extensions.realtime/deployment.ts +0 -89
- package/source/extensions.realtime/index.ts +0 -4
- package/source/extensions.stash/context.ts +0 -10
- package/source/extensions.stash/deployment.ts +0 -22
- package/source/extensions.stash/index.ts +0 -2
- package/source/extensions.state/context.ts +0 -9
- package/source/extensions.state/index.ts +0 -1
- package/source/extensions.storages/Annotation.ts +0 -57
- package/source/extensions.storages/context.ts +0 -14
- package/source/extensions.storages/deployment.ts +0 -91
- package/source/extensions.storages/index.ts +0 -9
- package/source/extensions.storages/manifest.ts +0 -7
- package/source/extensions.storages/schemas.ts +0 -15
- package/source/extensions.storages/secrets.ts +0 -22
- package/source/extensions.telemetry/const.ts +0 -6
- package/source/extensions.telemetry/context.ts +0 -11
- package/source/extensions.telemetry/deployment.ts +0 -91
- package/source/extensions.telemetry/index.ts +0 -5
- package/source/extensions.telemetry/ready.ts +0 -33
- package/source/index.ts +0 -2
- package/source/storages.mongodb/deployment.ts +0 -22
- package/source/storages.mongodb/index.ts +0 -1
- package/source/version.ts +0 -10
- package/transpiled/bindings.amqp/annotation.test.d.ts +0 -1
- package/transpiled/bindings.amqp/annotation.test.js +0 -36
- package/transpiled/bindings.amqp/annotation.test.js.map +0 -1
- package/transpiled/bindings.amqp/properties.test.d.ts +0 -1
- package/transpiled/bindings.amqp/properties.test.js +0 -7
- package/transpiled/bindings.amqp/properties.test.js.map +0 -1
- package/transpiled/bindings.loop/properties.test.d.ts +0 -1
- package/transpiled/bindings.loop/properties.test.js +0 -7
- package/transpiled/bindings.loop/properties.test.js.map +0 -1
- package/transpiled/bridges.node/exports.test.d.ts +0 -1
- package/transpiled/bridges.node/exports.test.js +0 -88
- package/transpiled/bridges.node/exports.test.js.map +0 -1
- package/transpiled/bridges.node/operations.test.d.ts +0 -1
- package/transpiled/bridges.node/operations.test.js +0 -108
- package/transpiled/bridges.node/operations.test.js.map +0 -1
- package/transpiled/extensions.cadence/manifest.test.d.ts +0 -1
- package/transpiled/extensions.cadence/manifest.test.js +0 -41
- package/transpiled/extensions.cadence/manifest.test.js.map +0 -1
- package/transpiled/extensions.configuration/deployment.test.d.ts +0 -1
- package/transpiled/extensions.configuration/deployment.test.js +0 -74
- package/transpiled/extensions.configuration/deployment.test.js.map +0 -1
- package/transpiled/extensions.configuration/manifest.test.d.ts +0 -1
- package/transpiled/extensions.configuration/manifest.test.js +0 -14
- package/transpiled/extensions.configuration/manifest.test.js.map +0 -1
- package/transpiled/extensions.exposition/manifest.test.d.ts +0 -1
- package/transpiled/extensions.exposition/manifest.test.js +0 -38
- package/transpiled/extensions.exposition/manifest.test.js.map +0 -1
- package/transpiled/extensions.exposition/schemas.test.d.ts +0 -1
- package/transpiled/extensions.exposition/schemas.test.js +0 -22
- package/transpiled/extensions.exposition/schemas.test.js.map +0 -1
- package/transpiled/extensions.exposition/syntax/parse.test.d.ts +0 -1
- package/transpiled/extensions.exposition/syntax/parse.test.js +0 -156
- package/transpiled/extensions.exposition/syntax/parse.test.js.map +0 -1
- package/transpiled/extensions.storages/schemas.test.d.ts +0 -1
- package/transpiled/extensions.storages/schemas.test.js +0 -59
- package/transpiled/extensions.storages/schemas.test.js.map +0 -1
- package/tsconfig.json +0 -10
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type Dependency } from '@toa.io/operations'
|
|
2
|
-
import { merge } from '@toa.io/generic'
|
|
3
|
-
import { type Declaration, normalize } from './annotation.js'
|
|
4
|
-
import * as sources from './sources.js'
|
|
5
|
-
import * as context from './context.js'
|
|
6
|
-
import { type Instance } from './instance.js'
|
|
7
|
-
|
|
8
|
-
export function deployment(instances: Instance[], declaration: Declaration): Dependency {
|
|
9
|
-
const annotation = normalize(declaration)
|
|
10
|
-
const contextDependency = context.createDependency(annotation.context)
|
|
11
|
-
const sourcesDependency = sources.createDependency(annotation.sources, instances)
|
|
12
|
-
|
|
13
|
-
return merge(contextDependency, sourcesDependency)
|
|
14
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { bindings } from '@toa.io/core/types'
|
|
2
|
-
|
|
3
|
-
export const properties: bindings.Properties = { async: true }
|
|
4
|
-
|
|
5
|
-
export { deployment } from './deployment.js'
|
|
6
|
-
export { ID as CONTEXT, VARIABLE as CONTEXT_VARIABLE } from './context.js'
|
|
7
|
-
export { ID as SOURCES } from './sources.js'
|
|
8
|
-
|
|
9
|
-
export type { Annotation, Declaration } from './annotation.js'
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { createVariables, type Request } from '@toa.io/pointer'
|
|
2
|
-
import { type Manifest } from '@toa.io/norm'
|
|
3
|
-
import { type Dependency } from '@toa.io/operations'
|
|
4
|
-
import { type Instance } from './instance.js'
|
|
5
|
-
import { type Annotation } from './annotation.js'
|
|
6
|
-
|
|
7
|
-
export function createDependency(sources: Sources, instances: Instance[]): Dependency {
|
|
8
|
-
const requests = []
|
|
9
|
-
|
|
10
|
-
for (const instance of instances) {
|
|
11
|
-
const request = createRequest(instance)
|
|
12
|
-
|
|
13
|
-
if (request !== null) requests.push(request)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const variables = createVariables(ID, sources, requests)
|
|
17
|
-
|
|
18
|
-
return { variables }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function createRequest(instance: Instance): Request | null {
|
|
22
|
-
const group = instance.locator.label
|
|
23
|
-
const selectors = createSelectors(instance.component)
|
|
24
|
-
|
|
25
|
-
if (selectors === null) return null
|
|
26
|
-
else return { group, selectors }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function createSelectors(component: Manifest): string[] | null {
|
|
30
|
-
if (component.receivers === undefined) return null
|
|
31
|
-
|
|
32
|
-
const sources = Object.values(component.receivers).map((receiver) => receiver.source)
|
|
33
|
-
|
|
34
|
-
return sources.filter((source) => source !== undefined) as string[]
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const ID = 'amqp-sources'
|
|
38
|
-
|
|
39
|
-
type Sources = Annotation['sources']
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises'
|
|
2
|
-
import { join, extname } from 'node:path'
|
|
3
|
-
import { DIR, EXT } from './const.js'
|
|
4
|
-
import type { component } from '@toa.io/norm'
|
|
5
|
-
|
|
6
|
-
export async function operations(root: string): Promise<component.Operations> {
|
|
7
|
-
const path = join(root, DIR)
|
|
8
|
-
const names = await list(path)
|
|
9
|
-
|
|
10
|
-
const promises = names.map(async (name) => operation(root, name))
|
|
11
|
-
|
|
12
|
-
const operations = await Promise.all(promises)
|
|
13
|
-
|
|
14
|
-
return operations.reduce<component.Operations>((acc, operation, index) => {
|
|
15
|
-
acc[names[index]] = operation
|
|
16
|
-
|
|
17
|
-
return acc
|
|
18
|
-
}, {})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function operation(
|
|
22
|
-
root: string,
|
|
23
|
-
name: string
|
|
24
|
-
): Promise<component.Operation> {
|
|
25
|
-
const path = join(root, DIR, name + EXT)
|
|
26
|
-
|
|
27
|
-
await fs.access(path, fs.constants.F_OK)
|
|
28
|
-
|
|
29
|
-
return { type: 'computation' }
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function list(path: string): Promise<string[]> {
|
|
33
|
-
const files = await fs.readdir(path)
|
|
34
|
-
|
|
35
|
-
return files
|
|
36
|
-
.filter((file) => extname(file) === EXT)
|
|
37
|
-
.map((file) => file.slice(0, -EXT.length))
|
|
38
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises'
|
|
2
|
-
import { sources } from './sources.js'
|
|
3
|
-
import { exports, type Exports } from './exports.js'
|
|
4
|
-
import { algorithm, type Definition } from './operations.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* What a component's modules declare, read from their source and never by importing them: a
|
|
8
|
-
* deploy reads a component whose dependencies are not installed, and a booting process reads
|
|
9
|
-
* the same, so the two cannot disagree.
|
|
10
|
-
*/
|
|
11
|
-
export async function operations(root: string): Promise<Record<string, Definition>> {
|
|
12
|
-
const algorithms: Record<string, Definition> = {}
|
|
13
|
-
|
|
14
|
-
for (const [name, exported, path] of await read(root, 'operations')) {
|
|
15
|
-
const definition = algorithm(exported, path)
|
|
16
|
-
|
|
17
|
-
if (definition !== null) algorithms[name] = definition
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return algorithms
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function events(root: string): Promise<Record<string, Event>> {
|
|
24
|
-
const events: Record<string, Event> = {}
|
|
25
|
-
|
|
26
|
-
for (const [name, exported] of await read(root, 'events'))
|
|
27
|
-
events[name] = { conditioned: exported.has('condition'), subjective: exported.has('payload') }
|
|
28
|
-
|
|
29
|
-
return events
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function receivers(root: string): Promise<Record<string, Receiver>> {
|
|
33
|
-
const receivers: Record<string, Receiver> = {}
|
|
34
|
-
|
|
35
|
-
for (const [name, exported] of await read(root, 'receivers'))
|
|
36
|
-
receivers[name] = { conditioned: exported.has('condition'), adaptive: exported.has('request') }
|
|
37
|
-
|
|
38
|
-
return receivers
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export async function guards(root: string): Promise<Record<string, object>> {
|
|
42
|
-
const guards: Record<string, object> = {}
|
|
43
|
-
|
|
44
|
-
for (const [name, exported] of await read(root, 'guards')) if (exported.has('guard')) guards[name] = {}
|
|
45
|
-
|
|
46
|
-
return guards
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function read(root: string, directory: string): Promise<Array<[string, Exports, string]>> {
|
|
50
|
-
const modules = await sources(root, directory)
|
|
51
|
-
|
|
52
|
-
return Promise.all(
|
|
53
|
-
[...modules].map(async ([name, path]): Promise<[string, Exports, string]> => [
|
|
54
|
-
name,
|
|
55
|
-
exports(path, await readFile(path, 'utf8')),
|
|
56
|
-
path
|
|
57
|
-
])
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface Event {
|
|
62
|
-
conditioned: boolean
|
|
63
|
-
subjective: boolean
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface Receiver {
|
|
67
|
-
conditioned: boolean
|
|
68
|
-
adaptive: boolean
|
|
69
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { parseSync } from 'oxc-parser'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* What a module exports, read from its source: the name, and what the value is declared as.
|
|
5
|
-
* Nothing is imported, so what a module depends on need not be installed to read it.
|
|
6
|
-
*/
|
|
7
|
-
export function exports(path: string, text: string): Exports {
|
|
8
|
-
const { program, errors } = parseSync(path, text)
|
|
9
|
-
|
|
10
|
-
if (errors.length > 0) throw new Error(`${path}: ${errors[0].message}`)
|
|
11
|
-
|
|
12
|
-
const locals = declarations(program.body)
|
|
13
|
-
const exported: Exports = new Map()
|
|
14
|
-
|
|
15
|
-
for (const node of program.body) {
|
|
16
|
-
if (node.type === 'ExportNamedDeclaration') named(node, locals, exported)
|
|
17
|
-
else if (node.type === 'ExportDefaultDeclaration')
|
|
18
|
-
exported.set('default', binding(node.declaration, locals))
|
|
19
|
-
else if (node.type === 'ExpressionStatement') assigned(node.expression, locals, exported)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return exported
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type Exports = Map<string, Binding>
|
|
26
|
-
|
|
27
|
-
export interface Binding {
|
|
28
|
-
/** what the value is declared as, or `other` where it is computed rather than written */
|
|
29
|
-
kind: 'function' | 'class' | 'other'
|
|
30
|
-
/** the name a function or class is declared with, which a default export is known by */
|
|
31
|
-
declared?: string
|
|
32
|
-
/** the parameters' names, `undefined` for one that is not a plain identifier */
|
|
33
|
-
params?: Array<string | undefined>
|
|
34
|
-
/** a class's methods with their parameters */
|
|
35
|
-
methods?: Record<string, Array<string | undefined>>
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function named(node: any, locals: Locals, exported: Exports): void {
|
|
39
|
-
if (node.exportKind === 'type') return
|
|
40
|
-
|
|
41
|
-
const declaration = node.declaration
|
|
42
|
-
|
|
43
|
-
if (declaration !== null && declaration !== undefined)
|
|
44
|
-
for (const [name, bound] of declared(declaration)) exported.set(name, bound)
|
|
45
|
-
|
|
46
|
-
for (const specifier of node.specifiers ?? []) {
|
|
47
|
-
if (specifier.exportKind === 'type') return
|
|
48
|
-
|
|
49
|
-
exported.set(name(specifier.exported), binding(specifier.local, locals))
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** `module.exports = { … }`, `module.exports.x = …` and `exports.x = …` */
|
|
54
|
-
function assigned(expression: any, locals: Locals, exported: Exports): void {
|
|
55
|
-
if (expression.type !== 'AssignmentExpression' || expression.operator !== '=') return
|
|
56
|
-
|
|
57
|
-
const target = expression.left
|
|
58
|
-
|
|
59
|
-
if (target.type !== 'MemberExpression') return
|
|
60
|
-
|
|
61
|
-
if (isModuleExports(target)) {
|
|
62
|
-
if (expression.right.type === 'ObjectExpression')
|
|
63
|
-
properties(expression.right, locals, exported)
|
|
64
|
-
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const object = target.object
|
|
69
|
-
|
|
70
|
-
if (isModuleExports(object) || (object.type === 'Identifier' && object.name === 'exports'))
|
|
71
|
-
exported.set(name(target.property), binding(expression.right, locals))
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** `{ computation, condition: () => … }` — each property is an export. */
|
|
75
|
-
function properties(object: any, locals: Locals, exported: Exports): void {
|
|
76
|
-
for (const property of object.properties) {
|
|
77
|
-
if (property.type !== 'Property') continue
|
|
78
|
-
|
|
79
|
-
exported.set(name(property.key), binding(property.value, locals))
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function isModuleExports(node: any): boolean {
|
|
84
|
-
return (
|
|
85
|
-
node.type === 'MemberExpression' &&
|
|
86
|
-
node.object.type === 'Identifier' &&
|
|
87
|
-
node.object.name === 'module' &&
|
|
88
|
-
name(node.property) === 'exports'
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Every top-level declaration, which a specifier or a shorthand property refers to by name. */
|
|
93
|
-
function declarations(body: any[]): Locals {
|
|
94
|
-
const locals: Locals = new Map()
|
|
95
|
-
|
|
96
|
-
for (const node of body) {
|
|
97
|
-
const declaration =
|
|
98
|
-
node.type === 'ExportNamedDeclaration' ? node.declaration : node
|
|
99
|
-
|
|
100
|
-
if (declaration === null || declaration === undefined) continue
|
|
101
|
-
|
|
102
|
-
for (const [name, bound] of declared(declaration)) locals.set(name, bound)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return locals
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function declared(node: any): Array<[string, Binding]> {
|
|
109
|
-
switch (node.type) {
|
|
110
|
-
case 'FunctionDeclaration':
|
|
111
|
-
case 'ClassDeclaration':
|
|
112
|
-
return node.id === null ? [] : [[node.id.name, binding(node)]]
|
|
113
|
-
case 'VariableDeclaration':
|
|
114
|
-
return node.declarations
|
|
115
|
-
.filter((declarator: any) => declarator.id.type === 'Identifier')
|
|
116
|
-
.map((declarator: any) => [
|
|
117
|
-
declarator.id.name,
|
|
118
|
-
declarator.init === null ? OTHER : binding(declarator.init)
|
|
119
|
-
])
|
|
120
|
-
default:
|
|
121
|
-
return []
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function binding(node: any, locals?: Locals): Binding {
|
|
126
|
-
switch (node.type) {
|
|
127
|
-
case 'FunctionDeclaration':
|
|
128
|
-
case 'FunctionExpression':
|
|
129
|
-
case 'ArrowFunctionExpression':
|
|
130
|
-
return { kind: 'function', declared: node.id?.name, params: parameters(node.params) }
|
|
131
|
-
case 'ClassDeclaration':
|
|
132
|
-
case 'ClassExpression':
|
|
133
|
-
return { kind: 'class', declared: node.id?.name, methods: methods(node.body.body) }
|
|
134
|
-
case 'Identifier':
|
|
135
|
-
return locals?.get(node.name) ?? OTHER
|
|
136
|
-
default:
|
|
137
|
-
return OTHER
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function methods(body: any[]): Record<string, Array<string | undefined>> {
|
|
142
|
-
const methods: Record<string, Array<string | undefined>> = {}
|
|
143
|
-
|
|
144
|
-
for (const member of body) {
|
|
145
|
-
if (member.key === undefined || member.key.type === 'PrivateIdentifier') continue
|
|
146
|
-
|
|
147
|
-
if (member.type === 'MethodDefinition') methods[name(member.key)] = parameters(member.value.params)
|
|
148
|
-
else if (
|
|
149
|
-
member.type === 'PropertyDefinition' &&
|
|
150
|
-
member.value !== null &&
|
|
151
|
-
(member.value.type === 'ArrowFunctionExpression' ||
|
|
152
|
-
member.value.type === 'FunctionExpression')
|
|
153
|
-
)
|
|
154
|
-
methods[name(member.key)] = parameters(member.value.params)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return methods
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** A name is what is read: a pattern, a rest or a `this` annotation is not a name. */
|
|
161
|
-
function parameters(params: any[]): Array<string | undefined> {
|
|
162
|
-
return params.map((param) => {
|
|
163
|
-
const pattern = param.type === 'AssignmentPattern' ? param.left : param
|
|
164
|
-
|
|
165
|
-
return pattern.type === 'Identifier' ? pattern.name : undefined
|
|
166
|
-
})
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function name(key: any): string {
|
|
170
|
-
return key.type === 'Identifier' ? key.name : String(key.value)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
type Locals = Map<string, Binding>
|
|
174
|
-
|
|
175
|
-
const OTHER: Binding = { kind: 'other' }
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import type { Binding, Exports } from './exports.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* What an algorithm module declares, by the conventions the bridge reads a module by: the
|
|
5
|
-
* exported name is the type, the second parameter's name is the scope. `null` where the module
|
|
6
|
-
* exports no algorithm.
|
|
7
|
-
*/
|
|
8
|
-
export function algorithm(exported: Exports, path: string): Definition | null {
|
|
9
|
-
const entry = find(exported, path)
|
|
10
|
-
|
|
11
|
-
if (entry === null) return null
|
|
12
|
-
|
|
13
|
-
const [name, bound] = entry
|
|
14
|
-
|
|
15
|
-
if (FACTORY.test(name)) return factory(name, bound, path)
|
|
16
|
-
if (CLASSES.has(name)) return klass(name, bound, path)
|
|
17
|
-
if (TYPES.has(name)) return func(name, bound)
|
|
18
|
-
|
|
19
|
-
throw new Error(`${path}: exported '${name}' does not match conventions`)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface Definition {
|
|
23
|
-
type: string
|
|
24
|
-
scope?: string
|
|
25
|
-
input?: null
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A module names its algorithm by exporting it, and it exports one. What a value is cannot
|
|
30
|
-
* always be read from its source — `export const computation = wrap(fn)` — so a name written the
|
|
31
|
-
* way an algorithm's is counts, whatever it is bound to.
|
|
32
|
-
*/
|
|
33
|
-
function find(exported: Exports, path: string): [string, Binding] | null {
|
|
34
|
-
const candidates = [...exported].filter(
|
|
35
|
-
([name, bound]) => name !== '__esModule' && (bound.kind !== 'other' || conventional(name))
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
if (candidates.length === 0) return null
|
|
39
|
-
|
|
40
|
-
if (candidates.length === 1) return resolve(candidates[0])
|
|
41
|
-
|
|
42
|
-
const named = candidates.filter(([name]) => name !== 'default')
|
|
43
|
-
|
|
44
|
-
if (named.length === 1) return named[0]
|
|
45
|
-
|
|
46
|
-
throw new Error(
|
|
47
|
-
`${path}: a module must export one algorithm, and this one exports ` +
|
|
48
|
-
named.map(([name]) => `'${name}'`).join(', ')
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** `export default function transition` says its name in the function itself. */
|
|
53
|
-
function resolve([name, bound]: [string, Binding]): [string, Binding] {
|
|
54
|
-
return name === 'default' ? [bound.declared ?? '', bound] : [name, bound]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function conventional(name: string): boolean {
|
|
58
|
-
return TYPES.has(name) || CLASSES.has(name) || FACTORY.test(name)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function func(type: string, bound: Binding): Definition {
|
|
62
|
-
const definition: Definition = { type }
|
|
63
|
-
|
|
64
|
-
// computed rather than written: the scope is the manifest's to declare
|
|
65
|
-
if (bound.kind === 'other') return definition
|
|
66
|
-
|
|
67
|
-
if (bound.kind !== 'function' || bound.params === undefined)
|
|
68
|
-
throw new Error(`Exported '${type}' does not match conventions`)
|
|
69
|
-
|
|
70
|
-
return signature(definition, bound.params)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function klass(name: string, bound: Binding, path: string): Definition {
|
|
74
|
-
if (bound.kind !== 'class') throw new Error(`${path}: '${name}' does not match conventions`)
|
|
75
|
-
|
|
76
|
-
const params = bound.methods?.execute
|
|
77
|
-
|
|
78
|
-
if (params === undefined) throw new Error(`${path}: Method 'execute' not found in '${name}'`)
|
|
79
|
-
|
|
80
|
-
return signature({ type: name.toLowerCase() }, params)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function factory(name: string, bound: Binding, path: string): Definition {
|
|
84
|
-
if (bound.kind !== 'class') throw new Error(`${path}: '${name}' does not match conventions`)
|
|
85
|
-
|
|
86
|
-
const match = name.match(FACTORY)!
|
|
87
|
-
const definition: Definition = { type: match.groups!.type.toLowerCase() }
|
|
88
|
-
const scope = match.groups!.scope?.toLowerCase()
|
|
89
|
-
|
|
90
|
-
if (scope !== undefined) definition.scope = scope
|
|
91
|
-
|
|
92
|
-
return definition
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function signature(definition: Definition, params: Array<string | undefined>): Definition {
|
|
96
|
-
definition.scope = params.length > 1 ? scope(params[1]) : 'none'
|
|
97
|
-
|
|
98
|
-
if (params.length === 0) definition.input = null
|
|
99
|
-
|
|
100
|
-
return definition
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function scope(name: string | undefined): string | undefined {
|
|
104
|
-
if (name === undefined) return undefined
|
|
105
|
-
if (SCOPES.has(name)) return name
|
|
106
|
-
if (name === 'context') return 'none'
|
|
107
|
-
|
|
108
|
-
return undefined
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export const TYPES: ReadonlySet<string> = new Set([
|
|
112
|
-
'transition',
|
|
113
|
-
'observation',
|
|
114
|
-
'assignment',
|
|
115
|
-
'computation',
|
|
116
|
-
'effect',
|
|
117
|
-
'unmanaged'
|
|
118
|
-
])
|
|
119
|
-
|
|
120
|
-
const SCOPES: ReadonlySet<string> = new Set(['object', 'objects', 'changeset', 'stream'])
|
|
121
|
-
|
|
122
|
-
const CLASSES: ReadonlySet<string> = new Set(
|
|
123
|
-
[...TYPES].map((type) => type[0].toUpperCase() + type.slice(1))
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
const FACTORY =
|
|
127
|
-
/^(?<scope>Objects?|Changeset)?(?<type>Transition|Observation|Assignment|Computation|Effect)Factory$/
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { readdir } from 'node:fs/promises'
|
|
2
|
-
import { basename, extname, join } from 'node:path'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A component's modules by name, whatever extension each was written with.
|
|
6
|
-
*
|
|
7
|
-
* Two files that resolve to one name are a conflict rather than a race: which of them a scan
|
|
8
|
-
* reached first is not something a component may depend on.
|
|
9
|
-
*/
|
|
10
|
-
export async function sources(root: string, directory: string): Promise<Map<string, string>> {
|
|
11
|
-
const path = join(root, directory)
|
|
12
|
-
const files = (await list(path)).filter((file) => EXTENSIONS.has(extname(file))).sort()
|
|
13
|
-
const modules = new Map<string, string>()
|
|
14
|
-
|
|
15
|
-
// sorted, so the two files a conflict names are the same two on every machine
|
|
16
|
-
for (const file of files) {
|
|
17
|
-
const name = basename(file, extname(file))
|
|
18
|
-
const found = modules.get(name)
|
|
19
|
-
|
|
20
|
-
if (found !== undefined)
|
|
21
|
-
throw new Error(
|
|
22
|
-
`Component at '${root}' has more than one ${directory}/${name}: ` +
|
|
23
|
-
`${basename(found)} and ${file}`
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
modules.set(name, join(path, file))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return modules
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function list(path: string): Promise<string[]> {
|
|
33
|
-
try {
|
|
34
|
-
const entries = await readdir(path, { withFileTypes: true })
|
|
35
|
-
|
|
36
|
-
return entries.filter((entry) => entry.isFile()).map((entry) => entry.name)
|
|
37
|
-
} catch (error: any) {
|
|
38
|
-
if (error.code === 'ENOENT') return []
|
|
39
|
-
|
|
40
|
-
throw error
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const EXTENSIONS = new Set(['.js', '.mjs', '.cjs', '.ts'])
|
package/source/definition.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A first-party package's definition, by the reference a manifest or a context names it by.
|
|
3
|
-
* `undefined` for a package this one does not define, which norm then reads on its own.
|
|
4
|
-
*/
|
|
5
|
-
export async function definition(reference: string): Promise<object | undefined> {
|
|
6
|
-
if (!reference.startsWith(SCOPE)) return undefined
|
|
7
|
-
|
|
8
|
-
const suffix = reference.slice(SCOPE.length)
|
|
9
|
-
|
|
10
|
-
if (!DEFINED.has(suffix)) return undefined
|
|
11
|
-
|
|
12
|
-
cache[suffix] ??= import(`./${suffix}/index.js`)
|
|
13
|
-
|
|
14
|
-
return cache[suffix]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const cache: Record<string, Promise<object>> = {}
|
|
18
|
-
|
|
19
|
-
const SCOPE = '@toa.io/'
|
|
20
|
-
|
|
21
|
-
/** Every package defined here, by its directory, which is its name within the scope. */
|
|
22
|
-
export const DEFINED: ReadonlySet<string> = new Set([
|
|
23
|
-
'bindings.amqp',
|
|
24
|
-
'bindings.loop',
|
|
25
|
-
'bridges.bash',
|
|
26
|
-
'bridges.node',
|
|
27
|
-
'extensions.cadence',
|
|
28
|
-
'extensions.configuration',
|
|
29
|
-
'extensions.exposition',
|
|
30
|
-
'extensions.fetch',
|
|
31
|
-
'extensions.introspection',
|
|
32
|
-
'extensions.realtime',
|
|
33
|
-
'extensions.stash',
|
|
34
|
-
'extensions.state',
|
|
35
|
-
'extensions.storages',
|
|
36
|
-
'extensions.telemetry',
|
|
37
|
-
'storages.mongodb'
|
|
38
|
-
])
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { createRequire } from 'node:module'
|
|
2
|
-
import { dirname, join, relative, resolve, sep } from 'node:path'
|
|
3
|
-
import { mkdirSync, readdirSync, writeFileSync } from 'node:fs'
|
|
4
|
-
import type { Entry } from './read.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Writes the digest of the components each extension ships: their manifests as norm reads
|
|
8
|
-
* them, with every path that reaches into a package replaced by that package's name — so the
|
|
9
|
-
* digest reads the same wherever this package is installed.
|
|
10
|
-
*
|
|
11
|
-
* Runs after the workspace transpiled, from the workspace, where every extension resolves.
|
|
12
|
-
*/
|
|
13
|
-
const require = createRequire(import.meta.url)
|
|
14
|
-
|
|
15
|
-
// norm types its manifests, not its functions
|
|
16
|
-
const { component } = (await import('@toa.io/norm')) as unknown as {
|
|
17
|
-
component: (path: string) => Promise<object>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const DIGESTED = [
|
|
21
|
-
'extensions.cadence',
|
|
22
|
-
'extensions.configuration',
|
|
23
|
-
'extensions.exposition',
|
|
24
|
-
'extensions.introspection',
|
|
25
|
-
'extensions.realtime'
|
|
26
|
-
]
|
|
27
|
-
|
|
28
|
-
const OUT = resolve(import.meta.dirname, '../../digest')
|
|
29
|
-
|
|
30
|
-
mkdirSync(OUT, { recursive: true })
|
|
31
|
-
|
|
32
|
-
const packages = ['@toa.io/prototype', ...DIGESTED.map((suffix) => '@toa.io/' + suffix)]
|
|
33
|
-
const roots = new Map(packages.map((name) => [root(name), name]))
|
|
34
|
-
|
|
35
|
-
for (const suffix of DIGESTED) {
|
|
36
|
-
const directory = join(root('@toa.io/' + suffix), 'components')
|
|
37
|
-
const entries: Entry[] = []
|
|
38
|
-
|
|
39
|
-
for (const dirent of readdirSync(directory, { withFileTypes: true })) {
|
|
40
|
-
if (!dirent.isDirectory()) continue
|
|
41
|
-
|
|
42
|
-
const manifest = await component(join(directory, dirent.name))
|
|
43
|
-
|
|
44
|
-
entries.push({ label: dirent.name.replace('.', '-'), manifest: relativize(manifest) })
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
writeFileSync(join(OUT, suffix + '.json'), JSON.stringify(entries))
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function root(name: string): string {
|
|
51
|
-
return dirname(require.resolve(name + '/package.json'))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Absolute paths into a package become `<name>/<inside>`; the locator norm rebuilds. */
|
|
55
|
-
function relativize(value: unknown): any {
|
|
56
|
-
if (typeof value === 'string') return specifier(value)
|
|
57
|
-
if (Array.isArray(value)) return value.map(relativize)
|
|
58
|
-
|
|
59
|
-
if (value !== null && typeof value === 'object') {
|
|
60
|
-
const object: Record<string, unknown> = {}
|
|
61
|
-
|
|
62
|
-
for (const [key, item] of Object.entries(value))
|
|
63
|
-
if (key !== 'locator') object[key] = relativize(item)
|
|
64
|
-
|
|
65
|
-
return object
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return value
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function specifier(value: string): string {
|
|
72
|
-
for (const [directory, name] of roots)
|
|
73
|
-
if (value === directory || value.startsWith(directory + sep))
|
|
74
|
-
return [name, ...relative(directory, value).split(sep)].filter(Boolean).join('/')
|
|
75
|
-
|
|
76
|
-
return value
|
|
77
|
-
}
|