liminal 0.17.14 → 0.17.16
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/Actor.ts +22 -34
- package/ActorHandle.ts +34 -0
- package/ActorNamespace.ts +188 -0
- package/ActorRuntime.ts +449 -0
- package/ActorTransport.ts +8 -6
- package/Audition.ts +87 -40
- package/BrowserActorNamespace.ts +257 -0
- package/CHANGELOG.md +17 -0
- package/Client.ts +374 -197
- package/ClientDirectory.ts +71 -49
- package/ClientHandle.ts +9 -7
- package/ClientHandleEncoders.ts +15 -0
- package/Fn.ts +94 -0
- package/Method.ts +11 -21
- package/Protocol.ts +44 -36
- package/Reducer.ts +22 -0
- package/Tracing.ts +45 -0
- package/dist/Actor.d.ts +3 -5
- package/dist/Actor.js +5 -9
- package/dist/Actor.js.map +1 -1
- package/dist/ActorHandle.d.ts +12 -0
- package/dist/ActorHandle.js +4 -0
- package/dist/ActorHandle.js.map +1 -0
- package/dist/ActorNamespace.d.ts +25 -0
- package/dist/ActorNamespace.js +60 -0
- package/dist/ActorNamespace.js.map +1 -0
- package/dist/ActorRuntime.d.ts +20 -0
- package/dist/ActorRuntime.js +210 -0
- package/dist/ActorRuntime.js.map +1 -0
- package/dist/ActorTransport.d.ts +5 -4
- package/dist/Audition.d.ts +16 -9
- package/dist/Audition.js +25 -9
- package/dist/Audition.js.map +1 -1
- package/dist/BrowserActorNamespace.d.ts +39 -0
- package/dist/BrowserActorNamespace.js +134 -0
- package/dist/BrowserActorNamespace.js.map +1 -0
- package/dist/Client.d.ts +26 -16
- package/dist/Client.js +186 -109
- package/dist/Client.js.map +1 -1
- package/dist/ClientDirectory.d.ts +15 -7
- package/dist/ClientDirectory.js +32 -23
- package/dist/ClientDirectory.js.map +1 -1
- package/dist/ClientHandle.d.ts +5 -4
- package/dist/ClientHandleEncoders.d.ts +7 -0
- package/dist/ClientHandleEncoders.js +2 -0
- package/dist/ClientHandleEncoders.js.map +1 -0
- package/dist/Fn.d.ts +24 -0
- package/dist/Fn.js +2 -0
- package/dist/Fn.js.map +1 -0
- package/dist/Method.d.ts +9 -14
- package/dist/Method.js +0 -1
- package/dist/Method.js.map +1 -1
- package/dist/Protocol.d.ts +19 -22
- package/dist/Protocol.js +20 -15
- package/dist/Protocol.js.map +1 -1
- package/dist/Reducer.d.ts +11 -0
- package/dist/Reducer.js +2 -0
- package/dist/Reducer.js.map +1 -0
- package/dist/Tracing.d.ts +37 -0
- package/dist/Tracing.js +33 -0
- package/dist/Tracing.js.map +1 -0
- package/dist/errors.d.ts +0 -4
- package/dist/errors.js.map +1 -1
- package/dist/experimental/L/append.js +1 -1
- package/dist/experimental/L/append.js.map +1 -1
- package/dist/experimental/L/history.js +1 -1
- package/dist/experimental/L/history.js.map +1 -1
- package/dist/experimental/TaggedTemplateFunction.js +1 -1
- package/dist/experimental/TaggedTemplateFunction.js.map +1 -1
- package/dist/index.common.d.ts +12 -0
- package/dist/index.common.js +13 -0
- package/dist/index.common.js.map +1 -0
- package/dist/index.d.ts +4 -11
- package/dist/index.js +4 -11
- package/dist/index.js.map +1 -1
- package/dist/index.non-workerd.d.ts +1 -0
- package/dist/index.non-workerd.js +2 -0
- package/dist/index.non-workerd.js.map +1 -0
- package/dist/package.json +20 -19
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/errors.ts +0 -6
- package/experimental/L/append.ts +1 -1
- package/experimental/L/history.ts +1 -1
- package/experimental/TaggedTemplateFunction.ts +1 -1
- package/index.common.ts +12 -0
- package/index.non-workerd.ts +1 -0
- package/index.ts +4 -11
- package/package.json +11 -23
- package/tsconfig.json +1 -1
- package/vitest.config.ts +7 -0
- package/Accumulator.ts +0 -103
- package/F.ts +0 -10
- package/_diagnostic.ts +0 -3
- package/_util/Mutex.ts +0 -13
- package/_util/schema.ts +0 -7
- package/browser/BrowserActorNamespace.ts +0 -213
- package/browser/index.ts +0 -1
- package/dist/Accumulator.d.ts +0 -22
- package/dist/Accumulator.js +0 -37
- package/dist/Accumulator.js.map +0 -1
- package/dist/F.d.ts +0 -4
- package/dist/F.js +0 -2
- package/dist/F.js.map +0 -1
- package/dist/_diagnostic.d.ts +0 -4
- package/dist/_diagnostic.js +0 -3
- package/dist/_diagnostic.js.map +0 -1
- package/dist/_util/Mutex.d.ts +0 -7
- package/dist/_util/Mutex.js +0 -9
- package/dist/_util/Mutex.js.map +0 -1
- package/dist/_util/schema.d.ts +0 -4
- package/dist/_util/schema.js +0 -5
- package/dist/_util/schema.js.map +0 -1
- package/dist/browser/BrowserActorNamespace.d.ts +0 -16
- package/dist/browser/BrowserActorNamespace.js +0 -112
- package/dist/browser/BrowserActorNamespace.js.map +0 -1
- package/dist/browser/index.d.ts +0 -1
- package/dist/browser/index.js +0 -2
- package/dist/browser/index.js.map +0 -1
- package/dist/workerd/WorkerdActorNamespace.d.ts +0 -25
- package/dist/workerd/WorkerdActorNamespace.js +0 -146
- package/dist/workerd/WorkerdActorNamespace.js.map +0 -1
- package/dist/workerd/index.d.ts +0 -1
- package/dist/workerd/index.js +0 -2
- package/dist/workerd/index.js.map +0 -1
- package/workerd/WorkerdActorNamespace.ts +0 -362
- package/workerd/index.ts +0 -1
package/Actor.ts
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { Context, Schema as S, Effect } from "effect"
|
|
2
|
+
import * as Boundary from "liminal-util/Boundary"
|
|
3
|
+
import type { TopFromString } from "liminal-util/schema"
|
|
2
4
|
|
|
3
|
-
import type { TopFromString } from "./_util/schema.ts"
|
|
4
5
|
import type * as ActorClient from "./Client.ts"
|
|
5
6
|
import type { ClientHandle, Sender } from "./ClientHandle.ts"
|
|
6
|
-
|
|
7
|
-
import { diagnostic } from "./_diagnostic.ts"
|
|
8
|
-
import * as Method from "./Method.ts"
|
|
9
7
|
import { type ProtocolDefinition } from "./Protocol.ts"
|
|
10
8
|
|
|
11
|
-
const { span } = diagnostic("Actor")
|
|
12
|
-
|
|
13
9
|
export const TypeId = "~liminal/Actor" as const
|
|
14
10
|
|
|
15
11
|
export interface Service<
|
|
@@ -54,14 +50,9 @@ export interface Actor<
|
|
|
54
50
|
|
|
55
51
|
readonly definition: ActorDefinition<Name, AttachmentFields, ActorClientSelf, ActorClientId, D>
|
|
56
52
|
|
|
57
|
-
readonly all: Sender<
|
|
58
|
-
|
|
59
|
-
readonly others: Sender<ActorSelf, D>
|
|
53
|
+
readonly all: Sender<D, ActorSelf>
|
|
60
54
|
|
|
61
|
-
readonly
|
|
62
|
-
tag: K,
|
|
63
|
-
f: Method.Handler<D["methods"][K], R>,
|
|
64
|
-
) => Method.Handler<D["methods"][K], R>
|
|
55
|
+
readonly others: Sender<D, ActorSelf>
|
|
65
56
|
}
|
|
66
57
|
|
|
67
58
|
export const Service =
|
|
@@ -79,45 +70,42 @@ export const Service =
|
|
|
79
70
|
): Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D> => {
|
|
80
71
|
const tag = Context.Service<ActorSelf, Service<ActorSelf, Name, AttachmentFields, D>>()(id)
|
|
81
72
|
|
|
82
|
-
const all: Sender<
|
|
73
|
+
const all: Sender<D, ActorSelf> = {
|
|
83
74
|
send: (key, payload) =>
|
|
84
|
-
tag.
|
|
75
|
+
tag.pipe(
|
|
85
76
|
Effect.flatMap(({ clients }) =>
|
|
86
77
|
Effect.forEach(clients, (client) => client.send(key, payload), { concurrency: "unbounded" }),
|
|
87
78
|
),
|
|
88
|
-
span("all.
|
|
79
|
+
Boundary.span("send-all", import.meta.url),
|
|
89
80
|
),
|
|
90
|
-
disconnect: tag.
|
|
81
|
+
disconnect: tag.pipe(
|
|
91
82
|
Effect.flatMap(({ clients }) => Effect.forEach(clients, ({ disconnect }) => disconnect)),
|
|
92
|
-
span("all.
|
|
83
|
+
Boundary.span("disconnect-all", import.meta.url),
|
|
93
84
|
),
|
|
94
85
|
}
|
|
95
86
|
|
|
96
|
-
const others: Sender<
|
|
97
|
-
send: Effect.fnUntraced(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
87
|
+
const others: Sender<D, ActorSelf> = {
|
|
88
|
+
send: Effect.fnUntraced(
|
|
89
|
+
function* (key, payload) {
|
|
90
|
+
const { clients, currentClient } = yield* tag
|
|
91
|
+
yield* Effect.forEach(
|
|
92
|
+
clients,
|
|
93
|
+
(client) => (client === currentClient ? Effect.void : client.send(key, payload)),
|
|
94
|
+
{ concurrency: "unbounded" },
|
|
95
|
+
)
|
|
96
|
+
},
|
|
97
|
+
Boundary.span("send-others", import.meta.url),
|
|
98
|
+
),
|
|
105
99
|
disconnect: Effect.gen(function* () {
|
|
106
100
|
const { clients, currentClient } = yield* tag
|
|
107
101
|
yield* Effect.forEach(clients, (client) => (client === currentClient ? Effect.void : client.disconnect))
|
|
108
|
-
}).pipe(span("others.
|
|
102
|
+
}).pipe(Boundary.span("disconnect-others", import.meta.url)),
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
const handler = <K extends keyof D["methods"], R>(
|
|
112
|
-
_tag: K,
|
|
113
|
-
f: Method.Handler<D["methods"][K], R>,
|
|
114
|
-
): Method.Handler<D["methods"][K], R> => f
|
|
115
|
-
|
|
116
105
|
return Object.assign(tag, {
|
|
117
106
|
[TypeId]: TypeId,
|
|
118
107
|
definition,
|
|
119
108
|
all,
|
|
120
109
|
others,
|
|
121
|
-
handler,
|
|
122
110
|
})
|
|
123
111
|
}
|
package/ActorHandle.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Schema as S, Effect, Cause, Encoding } from "effect"
|
|
2
|
+
import { NativeRequest } from "effect-workerd"
|
|
3
|
+
import { HttpServerResponse } from "effect/unstable/http"
|
|
4
|
+
import type { TopFromString } from "liminal-util/schema"
|
|
5
|
+
|
|
6
|
+
import type { Send } from "./ClientHandle.ts"
|
|
7
|
+
import type { Methods } from "./Method.ts"
|
|
8
|
+
import type { ProtocolDefinition } from "./Protocol.ts"
|
|
9
|
+
|
|
10
|
+
export interface ActorHandle<
|
|
11
|
+
NamespaceSelf,
|
|
12
|
+
Internal extends Methods,
|
|
13
|
+
Name extends TopFromString,
|
|
14
|
+
AttachmentFields extends S.Struct.Fields,
|
|
15
|
+
D extends ProtocolDefinition,
|
|
16
|
+
> {
|
|
17
|
+
readonly upgrade: (
|
|
18
|
+
attachments: S.Struct<AttachmentFields>["Type"],
|
|
19
|
+
) => Effect.Effect<
|
|
20
|
+
HttpServerResponse.HttpServerResponse,
|
|
21
|
+
S.SchemaError | Encoding.EncodingError | Cause.NoSuchElementError,
|
|
22
|
+
| NamespaceSelf
|
|
23
|
+
| NativeRequest.NativeRequest
|
|
24
|
+
| Name["EncodingServices"]
|
|
25
|
+
| S.Struct<AttachmentFields>["EncodingServices"]
|
|
26
|
+
>
|
|
27
|
+
|
|
28
|
+
readonly call: <K extends keyof Internal, M extends Internal[K]>(
|
|
29
|
+
method: K,
|
|
30
|
+
payload: M["payload"]["Type"],
|
|
31
|
+
) => Effect.Effect<M["success"]["Type"], M["failure"]["Type"], NamespaceSelf>
|
|
32
|
+
|
|
33
|
+
readonly proxySendAll: Send<D, NamespaceSelf>
|
|
34
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { Layer, Effect, Schema as S, Context, flow, String, Array, Encoding, Exit } from "effect"
|
|
2
|
+
import { Binding, Env, NativeRequest } from "effect-workerd"
|
|
3
|
+
import { SecWebSocketProtocol, close } from "effect-workerd/socket_util"
|
|
4
|
+
import { HttpServerResponse, HttpTraceContext } from "effect/unstable/http"
|
|
5
|
+
import * as Boundary from "liminal-util/Boundary"
|
|
6
|
+
import { type TopFromString, encodeJsonString } from "liminal-util/schema"
|
|
7
|
+
|
|
8
|
+
import type { Actor } from "./Actor.ts"
|
|
9
|
+
import type { ActorHandle } from "./ActorHandle.ts"
|
|
10
|
+
import type { Methods } from "./Method.ts"
|
|
11
|
+
import type { ProtocolDefinition } from "./Protocol.ts"
|
|
12
|
+
|
|
13
|
+
export interface ActorNamespaceDefinition<
|
|
14
|
+
Internal extends Methods,
|
|
15
|
+
ActorSelf,
|
|
16
|
+
ActorId extends string,
|
|
17
|
+
Name extends TopFromString,
|
|
18
|
+
AttachmentFields extends S.Struct.Fields,
|
|
19
|
+
ClientSelf,
|
|
20
|
+
ClientId extends string,
|
|
21
|
+
D extends ProtocolDefinition,
|
|
22
|
+
> {
|
|
23
|
+
readonly binding: string
|
|
24
|
+
|
|
25
|
+
readonly internal: Internal
|
|
26
|
+
|
|
27
|
+
readonly actor: Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ActorNamespace<
|
|
31
|
+
NamespaceSelf,
|
|
32
|
+
NamespaceId extends string,
|
|
33
|
+
Internal extends Methods,
|
|
34
|
+
ActorSelf,
|
|
35
|
+
ActorId extends string,
|
|
36
|
+
Name extends TopFromString,
|
|
37
|
+
AttachmentFields extends S.Struct.Fields,
|
|
38
|
+
ClientSelf,
|
|
39
|
+
ClientId extends string,
|
|
40
|
+
D extends ProtocolDefinition,
|
|
41
|
+
> {
|
|
42
|
+
new (
|
|
43
|
+
_: never,
|
|
44
|
+
): Context.ServiceClass.Shape<
|
|
45
|
+
NamespaceId,
|
|
46
|
+
DurableObjectNamespace<Rpc.DurableObjectBranded & ActorNamespace.MakeRpc<Internal, D>>
|
|
47
|
+
>
|
|
48
|
+
|
|
49
|
+
readonly definition: ActorNamespaceDefinition<
|
|
50
|
+
Methods,
|
|
51
|
+
ActorSelf,
|
|
52
|
+
ActorId,
|
|
53
|
+
Name,
|
|
54
|
+
AttachmentFields,
|
|
55
|
+
ClientSelf,
|
|
56
|
+
ClientId,
|
|
57
|
+
D
|
|
58
|
+
>
|
|
59
|
+
|
|
60
|
+
readonly bind: (name: Name["Type"]) => ActorHandle<NamespaceSelf, Internal, Name, AttachmentFields, D>
|
|
61
|
+
|
|
62
|
+
readonly layer: Layer.Layer<NamespaceSelf, S.SchemaError, Env>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export declare namespace ActorNamespace {
|
|
66
|
+
export type MakeRpc<Internal extends Methods, D extends ProtocolDefinition> = {
|
|
67
|
+
rpc: <K extends keyof Internal>(
|
|
68
|
+
method: K,
|
|
69
|
+
payload: Internal[K]["payload"]["Type"],
|
|
70
|
+
) => Promise<Exit.Exit<Internal[K]["success"]["Type"], Internal[K]["failure"]["Type"]>>
|
|
71
|
+
|
|
72
|
+
proxySendAll<K extends keyof D["events"]>(event: K, payload: S.Struct<D["events"][K]>["Type"]): void
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const Service =
|
|
77
|
+
<NamespaceSelf>() =>
|
|
78
|
+
<
|
|
79
|
+
NamespaceId extends string,
|
|
80
|
+
Internal extends Methods,
|
|
81
|
+
ActorSelf,
|
|
82
|
+
ActorId extends string,
|
|
83
|
+
Name extends TopFromString,
|
|
84
|
+
AttachmentFields extends S.Struct.Fields,
|
|
85
|
+
ClientSelf,
|
|
86
|
+
ClientId extends string,
|
|
87
|
+
D extends ProtocolDefinition,
|
|
88
|
+
>(
|
|
89
|
+
id: NamespaceId,
|
|
90
|
+
definition: ActorNamespaceDefinition<Internal, ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>,
|
|
91
|
+
): ActorNamespace<
|
|
92
|
+
NamespaceSelf,
|
|
93
|
+
NamespaceId,
|
|
94
|
+
Internal,
|
|
95
|
+
ActorSelf,
|
|
96
|
+
ActorId,
|
|
97
|
+
Name,
|
|
98
|
+
AttachmentFields,
|
|
99
|
+
ClientSelf,
|
|
100
|
+
ClientId,
|
|
101
|
+
D
|
|
102
|
+
> => {
|
|
103
|
+
const { binding, actor } = definition
|
|
104
|
+
const {
|
|
105
|
+
definition: {
|
|
106
|
+
name: Name,
|
|
107
|
+
client: { key: clientId, protocol: P },
|
|
108
|
+
attachments: AttachmentFields,
|
|
109
|
+
},
|
|
110
|
+
} = actor
|
|
111
|
+
|
|
112
|
+
const tag = Context.Service<
|
|
113
|
+
NamespaceSelf,
|
|
114
|
+
DurableObjectNamespace<Rpc.DurableObjectBranded & ActorNamespace.MakeRpc<Internal, D>>
|
|
115
|
+
>()(id)
|
|
116
|
+
|
|
117
|
+
const encodeName = S.encodeEffect(Name)
|
|
118
|
+
const Attachments = S.Struct(AttachmentFields)
|
|
119
|
+
const encodeAttachmentsString = encodeJsonString(Attachments)
|
|
120
|
+
const encodeAuditionFailure = encodeJsonString(P.Audition.Failure)
|
|
121
|
+
|
|
122
|
+
const bind = (name: Name["Type"]): ActorHandle<NamespaceSelf, Internal, Name, AttachmentFields, D> => {
|
|
123
|
+
const getStub = Effect.gen(function* () {
|
|
124
|
+
const namespace = yield* tag
|
|
125
|
+
const nameEncoded = yield* encodeName(name)
|
|
126
|
+
return namespace.getByName(nameEncoded)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const upgrade = (attachments: S.Struct<AttachmentFields>["Type"]) =>
|
|
130
|
+
Effect.gen({ self: this }, function* () {
|
|
131
|
+
const request = yield* NativeRequest.NativeRequest
|
|
132
|
+
const protocols = yield* Effect.fromNullishOr(request.headers.get(SecWebSocketProtocol)).pipe(
|
|
133
|
+
Effect.map(flow(String.split(","), Array.map(String.trim))),
|
|
134
|
+
)
|
|
135
|
+
const liminalTokenI = yield* Array.findFirstIndex(protocols, (v) => v === "liminal").pipe(Effect.fromOption)
|
|
136
|
+
const liminalClientId = yield* Effect.fromNullishOr(protocols[liminalTokenI + 1])
|
|
137
|
+
const requestClientId = yield* Effect.fromNullishOr(protocols[liminalTokenI + 2]).pipe(
|
|
138
|
+
Effect.flatMap((v) => Encoding.decodeBase64UrlString(v).pipe(Effect.fromResult)),
|
|
139
|
+
)
|
|
140
|
+
if (requestClientId !== clientId) {
|
|
141
|
+
return close(
|
|
142
|
+
yield* encodeAuditionFailure({
|
|
143
|
+
_tag: "Audition.Failure",
|
|
144
|
+
expected: clientId,
|
|
145
|
+
actual: requestClientId,
|
|
146
|
+
}),
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
const url = new URL(request.url)
|
|
150
|
+
url.searchParams.set("__liminal_attachments", yield* encodeAttachmentsString(attachments))
|
|
151
|
+
url.searchParams.set("__liminal_client_id", liminalClientId)
|
|
152
|
+
const actorRequest = new Request(url, request)
|
|
153
|
+
const traceHeaders = yield* Effect.currentSpan.pipe(Effect.map(HttpTraceContext.toHeaders))
|
|
154
|
+
for (const [key, value] of Object.entries(traceHeaders)) {
|
|
155
|
+
actorRequest.headers.set(key, value)
|
|
156
|
+
}
|
|
157
|
+
const stub = yield* getStub
|
|
158
|
+
return yield* Effect.promise(() => stub.fetch(actorRequest)).pipe(Effect.map(HttpServerResponse.raw))
|
|
159
|
+
}).pipe(Boundary.span("upgrade", import.meta.url, { kind: "client" }))
|
|
160
|
+
|
|
161
|
+
const call = Effect.fnUntraced(
|
|
162
|
+
function* <K extends keyof Internal, M extends Internal[K]>(
|
|
163
|
+
method: K,
|
|
164
|
+
payload: M["payload"]["Type"],
|
|
165
|
+
): Effect.fn.Return<M["success"]["Type"], M["failure"]["Type"], NamespaceSelf> {
|
|
166
|
+
const stub = yield* getStub
|
|
167
|
+
const exit = yield* Effect.promise(() => stub.rpc(method as never, payload as never))
|
|
168
|
+
return yield* exit as any
|
|
169
|
+
},
|
|
170
|
+
Boundary.span("call", import.meta.url),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
// TODO:
|
|
174
|
+
const proxySendAll = Effect.fnUntraced(
|
|
175
|
+
function* <K extends keyof D["events"]>(event: K, payload: S.Struct<D["events"][K]>["Type"]) {
|
|
176
|
+
const stub = yield* getStub
|
|
177
|
+
yield* Effect.promise(() => stub.proxySendAll(event as never, payload as never))
|
|
178
|
+
},
|
|
179
|
+
Boundary.span("proxySendAll", import.meta.url),
|
|
180
|
+
) as never
|
|
181
|
+
|
|
182
|
+
return { upgrade, call, proxySendAll }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const layer = Binding.layer(tag, ["idFromName", "idFromString", "newUniqueId", "get", "getByName"])(binding)
|
|
186
|
+
|
|
187
|
+
return Object.assign(tag, { definition, bind, layer })
|
|
188
|
+
}
|