@skipruntime/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/binding.d.ts +70 -0
- package/dist/binding.d.ts.map +1 -0
- package/dist/binding.js +11 -0
- package/dist/binding.js.map +1 -0
- package/dist/errors.d.ts +3 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +3 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +206 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +707 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +38 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -0
- package/dist/remote.d.ts +22 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +71 -0
- package/dist/remote.js.map +1 -0
- package/dist/utils.d.ts +22 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +40 -0
- package/dist/utils.js.map +1 -0
- package/eslint.config.js +3 -0
- package/package.json +18 -0
- package/src/binding.ts +258 -0
- package/src/errors.ts +1 -0
- package/src/index.ts +1134 -0
- package/src/internal.ts +54 -0
- package/src/remote.ts +94 -0
- package/src/utils.ts +48 -0
- package/tsconfig.json +3 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,707 @@
|
|
|
1
|
+
import { isObjectProxy, sk_freeze, isSkFrozen } from "@skiplang/json";
|
|
2
|
+
import { NonUniqueValueException, } from "@skipruntime/api";
|
|
3
|
+
import { Frozen } from "@skipruntime/api/internals.js";
|
|
4
|
+
import { UnknownCollectionError } from "./errors.js";
|
|
5
|
+
import { ResourceBuilder, } from "./binding.js";
|
|
6
|
+
export { UnknownCollectionError, sk_freeze, isSkFrozen };
|
|
7
|
+
export { SkipExternalService } from "./remote.js";
|
|
8
|
+
export { Sum, Min, Max, CountMapper } from "./utils.js";
|
|
9
|
+
class SkFrozen extends Frozen {
|
|
10
|
+
freeze() {
|
|
11
|
+
sk_freeze(this);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function checkOrCloneParam(value) {
|
|
15
|
+
if (typeof value == "string" ||
|
|
16
|
+
typeof value == "number" ||
|
|
17
|
+
typeof value == "boolean")
|
|
18
|
+
return value;
|
|
19
|
+
if (typeof value == "object") {
|
|
20
|
+
if (value === null)
|
|
21
|
+
return value;
|
|
22
|
+
if (isObjectProxy(value))
|
|
23
|
+
return value.clone();
|
|
24
|
+
if (isSkFrozen(value))
|
|
25
|
+
return value;
|
|
26
|
+
throw new Error("Invalid object: must be deep-frozen.");
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`'${typeof value}' cannot be deep-frozen.`);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* _Deep-freeze_ an object, returning the same object that was passed in.
|
|
32
|
+
*
|
|
33
|
+
* This function is similar to
|
|
34
|
+
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze | `Object.freeze()`}
|
|
35
|
+
* but freezes the object and deep-freezes all its properties,
|
|
36
|
+
* recursively. The object is then not only _immutable_ but also
|
|
37
|
+
* _constant_. Note that as a result all objects reachable from the
|
|
38
|
+
* parameter will be frozen and no longer mutable or extensible, even from
|
|
39
|
+
* other references.
|
|
40
|
+
*
|
|
41
|
+
* The argument object and all its properties, recursively, must not already
|
|
42
|
+
* be frozen by `Object.freeze` (or else `deepFreeze` cannot mark them
|
|
43
|
+
* deep-frozen). Undefined, function (and hence class) values cannot be
|
|
44
|
+
* deep-frozen.
|
|
45
|
+
*
|
|
46
|
+
* The primary use for this function is to satisfy the requirement that all
|
|
47
|
+
* parameters to Skip `Mapper` constructors must be deep-frozen: objects
|
|
48
|
+
* that have not been constructed by Skip can be passed to `deepFreeze()`
|
|
49
|
+
* before passing them to a `Mapper` constructor.
|
|
50
|
+
*
|
|
51
|
+
* @param value - The object to deep-freeze.
|
|
52
|
+
* @returns The same object that was passed in.
|
|
53
|
+
*/
|
|
54
|
+
export function deepFreeze(value) {
|
|
55
|
+
if (typeof value == "bigint" ||
|
|
56
|
+
typeof value == "boolean" ||
|
|
57
|
+
typeof value == "number" ||
|
|
58
|
+
typeof value == "string" ||
|
|
59
|
+
typeof value == "symbol") {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
else if (typeof value == "object") {
|
|
63
|
+
if (value === null) {
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
else if (isSkFrozen(value)) {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
else if (Object.isFrozen(value)) {
|
|
70
|
+
throw new Error(`Cannot deep-freeze an Object.frozen value.`);
|
|
71
|
+
}
|
|
72
|
+
else if (Array.isArray(value)) {
|
|
73
|
+
for (const elt of value) {
|
|
74
|
+
deepFreeze(elt);
|
|
75
|
+
}
|
|
76
|
+
return Object.freeze(sk_freeze(value));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
for (const val of Object.values(value)) {
|
|
80
|
+
deepFreeze(val);
|
|
81
|
+
}
|
|
82
|
+
return Object.freeze(sk_freeze(value));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// typeof value == "function" || typeof value == "undefined"
|
|
87
|
+
throw new Error(`'${typeof value}' values cannot be deep-frozen.`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
class Handles {
|
|
91
|
+
constructor() {
|
|
92
|
+
this.nextID = 1;
|
|
93
|
+
this.objects = [];
|
|
94
|
+
this.freeIDs = [];
|
|
95
|
+
}
|
|
96
|
+
register(v) {
|
|
97
|
+
const freeID = this.freeIDs.pop();
|
|
98
|
+
const id = freeID ?? this.nextID++;
|
|
99
|
+
this.objects[id] = v;
|
|
100
|
+
return id;
|
|
101
|
+
}
|
|
102
|
+
get(id) {
|
|
103
|
+
return this.objects[id];
|
|
104
|
+
}
|
|
105
|
+
apply(id, parameters) {
|
|
106
|
+
const fn = this.get(id);
|
|
107
|
+
return fn.apply(null, parameters);
|
|
108
|
+
}
|
|
109
|
+
deleteHandle(id) {
|
|
110
|
+
const current = this.get(id);
|
|
111
|
+
this.objects[id] = null;
|
|
112
|
+
this.freeIDs.push(id);
|
|
113
|
+
return current;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export class Stack {
|
|
117
|
+
constructor() {
|
|
118
|
+
this.stack = [];
|
|
119
|
+
}
|
|
120
|
+
push(pointer) {
|
|
121
|
+
this.stack.push(pointer);
|
|
122
|
+
}
|
|
123
|
+
get() {
|
|
124
|
+
if (this.stack.length == 0)
|
|
125
|
+
return null;
|
|
126
|
+
return this.stack[this.stack.length - 1];
|
|
127
|
+
}
|
|
128
|
+
pop() {
|
|
129
|
+
this.stack.pop();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export class Refs {
|
|
133
|
+
constructor(binding, skjson, handles, needGC, runWithGC) {
|
|
134
|
+
this.binding = binding;
|
|
135
|
+
this.skjson = skjson;
|
|
136
|
+
this.handles = handles;
|
|
137
|
+
this.needGC = needGC;
|
|
138
|
+
this.runWithGC = runWithGC;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
class LazyCollectionImpl extends SkFrozen {
|
|
142
|
+
constructor(lazyCollection, refs) {
|
|
143
|
+
super();
|
|
144
|
+
this.lazyCollection = lazyCollection;
|
|
145
|
+
this.refs = refs;
|
|
146
|
+
Object.freeze(this);
|
|
147
|
+
}
|
|
148
|
+
getArray(key) {
|
|
149
|
+
return this.refs.skjson.importJSON(this.refs.binding.SkipRuntime_LazyCollection__getArray(this.lazyCollection, this.refs.skjson.exportJSON(key)));
|
|
150
|
+
}
|
|
151
|
+
getUnique(key) {
|
|
152
|
+
const v = this.refs.skjson.importOptJSON(this.refs.binding.SkipRuntime_LazyCollection__getUnique(this.lazyCollection, this.refs.skjson.exportJSON(key)));
|
|
153
|
+
if (v == null)
|
|
154
|
+
throw new NonUniqueValueException();
|
|
155
|
+
return v;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
class EagerCollectionImpl extends SkFrozen {
|
|
159
|
+
constructor(collection, refs) {
|
|
160
|
+
super();
|
|
161
|
+
this.collection = collection;
|
|
162
|
+
this.refs = refs;
|
|
163
|
+
this.size = () => {
|
|
164
|
+
return Number(this.refs.binding.SkipRuntime_Collection__size(this.collection));
|
|
165
|
+
};
|
|
166
|
+
Object.freeze(this);
|
|
167
|
+
}
|
|
168
|
+
getArray(key) {
|
|
169
|
+
return this.refs.skjson.importJSON(this.refs.binding.SkipRuntime_Collection__getArray(this.collection, this.refs.skjson.exportJSON(key)));
|
|
170
|
+
}
|
|
171
|
+
getUnique(key) {
|
|
172
|
+
const v = this.refs.skjson.importOptJSON(this.refs.binding.SkipRuntime_Collection__getUnique(this.collection, this.refs.skjson.exportJSON(key)));
|
|
173
|
+
if (v == null)
|
|
174
|
+
throw new NonUniqueValueException();
|
|
175
|
+
return v;
|
|
176
|
+
}
|
|
177
|
+
slice(start, end) {
|
|
178
|
+
return this.slices([start, end]);
|
|
179
|
+
}
|
|
180
|
+
slices(...ranges) {
|
|
181
|
+
const skcollection = this.refs.binding.SkipRuntime_Collection__slice(this.collection, this.refs.skjson.exportJSON(ranges));
|
|
182
|
+
return this.derive(skcollection);
|
|
183
|
+
}
|
|
184
|
+
take(limit) {
|
|
185
|
+
const skcollection = this.refs.binding.SkipRuntime_Collection__take(this.collection, BigInt(limit));
|
|
186
|
+
return this.derive(skcollection);
|
|
187
|
+
}
|
|
188
|
+
map(mapper, ...params) {
|
|
189
|
+
const mapperParams = params.map(checkOrCloneParam);
|
|
190
|
+
const mapperObj = new mapper(...mapperParams);
|
|
191
|
+
Object.freeze(mapperObj);
|
|
192
|
+
if (!mapperObj.constructor.name) {
|
|
193
|
+
throw new Error("Mapper classes must be defined at top-level.");
|
|
194
|
+
}
|
|
195
|
+
const skmapper = this.refs.binding.SkipRuntime_createMapper(this.refs.handles.register(mapperObj));
|
|
196
|
+
const mapped = this.refs.binding.SkipRuntime_Collection__map(this.collection, skmapper);
|
|
197
|
+
return this.derive(mapped);
|
|
198
|
+
}
|
|
199
|
+
mapReduce(mapper, ...mapperParams) {
|
|
200
|
+
return (reducer, ...reducerParams) => {
|
|
201
|
+
const mParams = mapperParams.map(checkOrCloneParam);
|
|
202
|
+
const rParams = reducerParams.map(checkOrCloneParam);
|
|
203
|
+
const mapperObj = new mapper(...mParams);
|
|
204
|
+
const reducerObj = new reducer(...rParams);
|
|
205
|
+
Object.freeze(mapperObj);
|
|
206
|
+
Object.freeze(reducerObj);
|
|
207
|
+
if (!mapperObj.constructor.name) {
|
|
208
|
+
throw new Error("Mapper classes must be defined at top-level.");
|
|
209
|
+
}
|
|
210
|
+
if (!reducerObj.constructor.name) {
|
|
211
|
+
throw new Error("Reducer classes must be defined at top-level.");
|
|
212
|
+
}
|
|
213
|
+
const skmapper = this.refs.binding.SkipRuntime_createMapper(this.refs.handles.register(mapperObj));
|
|
214
|
+
const skreducer = this.refs.binding.SkipRuntime_createReducer(this.refs.handles.register(reducerObj), this.refs.skjson.exportJSON(reducerObj.default));
|
|
215
|
+
const mapped = this.refs.binding.SkipRuntime_Collection__mapReduce(this.collection, skmapper, skreducer);
|
|
216
|
+
return this.derive(mapped);
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
reduce(reducer, ...params) {
|
|
220
|
+
const reducerParams = params.map(checkOrCloneParam);
|
|
221
|
+
const reducerObj = new reducer(...reducerParams);
|
|
222
|
+
Object.freeze(reducerObj);
|
|
223
|
+
if (!reducerObj.constructor.name) {
|
|
224
|
+
throw new Error("Reducer classes must be defined at top-level.");
|
|
225
|
+
}
|
|
226
|
+
const skreducer = this.refs.binding.SkipRuntime_createReducer(this.refs.handles.register(reducerObj), this.refs.skjson.exportJSON(reducerObj.default));
|
|
227
|
+
return this.derive(this.refs.binding.SkipRuntime_Collection__reduce(this.collection, skreducer));
|
|
228
|
+
}
|
|
229
|
+
merge(...others) {
|
|
230
|
+
const otherNames = others.map((other) => other.collection);
|
|
231
|
+
const mapped = this.refs.binding.SkipRuntime_Collection__merge(this.collection, this.refs.skjson.exportJSON(otherNames));
|
|
232
|
+
return this.derive(mapped);
|
|
233
|
+
}
|
|
234
|
+
derive(collection) {
|
|
235
|
+
return new EagerCollectionImpl(collection, this.refs);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
class CollectionWriter {
|
|
239
|
+
constructor(collection, refs) {
|
|
240
|
+
this.collection = collection;
|
|
241
|
+
this.refs = refs;
|
|
242
|
+
}
|
|
243
|
+
update(values, isInit) {
|
|
244
|
+
const update_ = () => {
|
|
245
|
+
return this.refs.binding.SkipRuntime_CollectionWriter__update(this.collection, this.refs.skjson.exportJSON(values), isInit);
|
|
246
|
+
};
|
|
247
|
+
if (this.refs.needGC()) {
|
|
248
|
+
this.refs.runWithGC(update_);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
update_();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
loading() {
|
|
255
|
+
const loading_ = () => {
|
|
256
|
+
return this.refs.binding.SkipRuntime_CollectionWriter__loading(this.collection);
|
|
257
|
+
};
|
|
258
|
+
if (this.refs.needGC())
|
|
259
|
+
this.refs.runWithGC(loading_);
|
|
260
|
+
else
|
|
261
|
+
loading_();
|
|
262
|
+
}
|
|
263
|
+
error(error) {
|
|
264
|
+
const error_ = () => {
|
|
265
|
+
return this.refs.binding.SkipRuntime_CollectionWriter__error(this.collection, this.refs.skjson.exportJSON(error));
|
|
266
|
+
};
|
|
267
|
+
if (this.refs.needGC())
|
|
268
|
+
this.refs.runWithGC(error_);
|
|
269
|
+
else
|
|
270
|
+
error_();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
class ContextImpl extends SkFrozen {
|
|
274
|
+
constructor(refs) {
|
|
275
|
+
super();
|
|
276
|
+
this.refs = refs;
|
|
277
|
+
Object.freeze(this);
|
|
278
|
+
}
|
|
279
|
+
createLazyCollection(compute, ...params) {
|
|
280
|
+
const mapperParams = params.map(checkOrCloneParam);
|
|
281
|
+
const computeObj = new compute(...mapperParams);
|
|
282
|
+
Object.freeze(computeObj);
|
|
283
|
+
if (!computeObj.constructor.name) {
|
|
284
|
+
throw new Error("LazyCompute classes must be defined at top-level.");
|
|
285
|
+
}
|
|
286
|
+
const skcompute = this.refs.binding.SkipRuntime_createLazyCompute(this.refs.handles.register(computeObj));
|
|
287
|
+
const lazyCollection = this.refs.binding.SkipRuntime_Context__createLazyCollection(skcompute);
|
|
288
|
+
return new LazyCollectionImpl(lazyCollection, this.refs);
|
|
289
|
+
}
|
|
290
|
+
useExternalResource(resource) {
|
|
291
|
+
const collection = this.refs.binding.SkipRuntime_Context__useExternalResource(resource.service, resource.identifier, this.refs.skjson.exportJSON(resource.params ?? {}));
|
|
292
|
+
return new EagerCollectionImpl(collection, this.refs);
|
|
293
|
+
}
|
|
294
|
+
jsonExtract(value, pattern) {
|
|
295
|
+
return this.refs.skjson.importJSON(this.refs.binding.SkipRuntime_Context__jsonExtract(this.refs.skjson.exportJSON(value), pattern));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
export class ServiceInstanceFactory {
|
|
299
|
+
constructor(init) {
|
|
300
|
+
this.init = init;
|
|
301
|
+
}
|
|
302
|
+
initService(service) {
|
|
303
|
+
return this.init(service);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
class AllChecker {
|
|
307
|
+
constructor(service, executor, resource, params) {
|
|
308
|
+
this.service = service;
|
|
309
|
+
this.executor = executor;
|
|
310
|
+
this.resource = resource;
|
|
311
|
+
this.params = params;
|
|
312
|
+
}
|
|
313
|
+
check(request) {
|
|
314
|
+
const result = this.service.getAll(this.resource, this.params, request);
|
|
315
|
+
if (result.errors.length > 0) {
|
|
316
|
+
this.executor.reject(new Error(JSON.stringify(result.errors)));
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
this.executor.resolve(result.payload);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
class OneChecker {
|
|
324
|
+
constructor(service, executor, resource, params, key) {
|
|
325
|
+
this.service = service;
|
|
326
|
+
this.executor = executor;
|
|
327
|
+
this.resource = resource;
|
|
328
|
+
this.params = params;
|
|
329
|
+
this.key = key;
|
|
330
|
+
}
|
|
331
|
+
check(request) {
|
|
332
|
+
const result = this.service.getArray(this.resource, this.key, this.params, request);
|
|
333
|
+
if (result.errors.length > 0) {
|
|
334
|
+
this.executor.reject(new Error(JSON.stringify(result.errors)));
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
this.executor.resolve(result.payload);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* A `ServiceInstance` is a running instance of a `SkipService`, providing access to its resources
|
|
343
|
+
* and operations to manage susbscriptions and the service itself.
|
|
344
|
+
*/
|
|
345
|
+
export class ServiceInstance {
|
|
346
|
+
constructor(refs) {
|
|
347
|
+
this.refs = refs;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Instantiate a resource with some parameters and client session authentication token
|
|
351
|
+
* @param identifier - The resource instance identifier
|
|
352
|
+
* @param resource - A resource name, which must correspond to a key in this `SkipService`'s `resources` field
|
|
353
|
+
* @param params - Resource parameters, which will be passed to the resource constructor specified in this `SkipService`'s `resources` field
|
|
354
|
+
*/
|
|
355
|
+
instantiateResource(identifier, resource, params) {
|
|
356
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
357
|
+
return this.refs.binding.SkipRuntime_Runtime__createResource(identifier, resource, this.refs.skjson.exportJSON(params));
|
|
358
|
+
});
|
|
359
|
+
if (errorHdl)
|
|
360
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Creates if not exists and get all current values of specified resource
|
|
364
|
+
* @param resource - the resource name corresponding to a key in remotes field of SkipService
|
|
365
|
+
* @param params - the parameters of the resource used to build the resource with the corresponding constructor specified in remotes field of SkipService
|
|
366
|
+
* @returns The current values of the corresponding resource with reactive responce token to allow subscription
|
|
367
|
+
*/
|
|
368
|
+
getAll(resource, params = {}, request) {
|
|
369
|
+
const get_ = () => {
|
|
370
|
+
return this.refs.skjson.importJSON(this.refs.binding.SkipRuntime_Runtime__getAll(resource, this.refs.skjson.exportJSON(params), request !== undefined
|
|
371
|
+
? typeof request == "string"
|
|
372
|
+
? this.refs.binding.SkipRuntime_createIdentifier(request)
|
|
373
|
+
: this.refs.binding.SkipRuntime_createChecker(this.refs.handles.register(new AllChecker(this, request, resource, params)))
|
|
374
|
+
: null), true);
|
|
375
|
+
};
|
|
376
|
+
const result = this.refs.needGC() ? this.refs.runWithGC(get_) : get_();
|
|
377
|
+
if (typeof result == "number")
|
|
378
|
+
throw this.refs.handles.deleteHandle(result);
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Get the current value of a key in the specified resource instance, creating it if it doesn't already exist
|
|
383
|
+
* @param resource - A resource name, which must correspond to a key in this `SkipService`'s `resources` field
|
|
384
|
+
* @param key - A key to look up in the resource instance
|
|
385
|
+
* @param params - Resource parameters, passed to the resource constructor specified in this `SkipService`'s `resources` field
|
|
386
|
+
* @returns The current value(s) for this key in the specified resource instance
|
|
387
|
+
*/
|
|
388
|
+
getArray(resource, key, params = {}, request) {
|
|
389
|
+
const get_ = () => {
|
|
390
|
+
return this.refs.skjson.importJSON(this.refs.binding.SkipRuntime_Runtime__getForKey(resource, this.refs.skjson.exportJSON(params), this.refs.skjson.exportJSON(key), request !== undefined
|
|
391
|
+
? typeof request == "string"
|
|
392
|
+
? this.refs.binding.SkipRuntime_createIdentifier(request)
|
|
393
|
+
: this.refs.binding.SkipRuntime_createChecker(this.refs.handles.register(new OneChecker(this, request, resource, params, key)))
|
|
394
|
+
: null), true);
|
|
395
|
+
};
|
|
396
|
+
const needGC = this.refs.needGC();
|
|
397
|
+
const result = needGC ? this.refs.runWithGC(get_) : get_();
|
|
398
|
+
if (typeof result == "number")
|
|
399
|
+
throw this.refs.handles.deleteHandle(result);
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Close the specified resource instance
|
|
404
|
+
* @param resourceInstanceId - The resource identifier
|
|
405
|
+
*/
|
|
406
|
+
closeResourceInstance(resourceInstanceId) {
|
|
407
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
408
|
+
return this.refs.binding.SkipRuntime_Runtime__closeResource(resourceInstanceId);
|
|
409
|
+
});
|
|
410
|
+
if (errorHdl)
|
|
411
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Initiate reactive subscription on a resource instance
|
|
415
|
+
* @param resourceInstanceId - the resource instance identifier
|
|
416
|
+
* @param notifier - the object containing subscription callbacks
|
|
417
|
+
* @param notifier.subscribed - A callback to execute when subscription effectivly done
|
|
418
|
+
* @param notifier.notify - A callback to execute on collection updates
|
|
419
|
+
* @param notifier.close - A callback to execute on resource close
|
|
420
|
+
* @param watermark - the watermark where to start the subscription
|
|
421
|
+
* @returns A subcription identifier
|
|
422
|
+
*/
|
|
423
|
+
subscribe(resourceInstanceId, notifier, watermark) {
|
|
424
|
+
const session = this.refs.runWithGC(() => {
|
|
425
|
+
const sknotifier = this.refs.binding.SkipRuntime_createNotifier(this.refs.handles.register(notifier));
|
|
426
|
+
return this.refs.binding.SkipRuntime_Runtime__subscribe(resourceInstanceId, sknotifier, watermark ?? null);
|
|
427
|
+
});
|
|
428
|
+
if (session == -1n) {
|
|
429
|
+
throw new UnknownCollectionError(`Unknown resource instance '${resourceInstanceId}'`);
|
|
430
|
+
}
|
|
431
|
+
else if (session < 0n) {
|
|
432
|
+
throw new Error("Unknown error");
|
|
433
|
+
}
|
|
434
|
+
return session;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Terminate a client's subscription to a reactive resource instance
|
|
438
|
+
* @param id - The subcription identifier returned by a call to `subscribe`
|
|
439
|
+
*/
|
|
440
|
+
unsubscribe(id) {
|
|
441
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
442
|
+
return this.refs.binding.SkipRuntime_Runtime__unsubscribe(id);
|
|
443
|
+
});
|
|
444
|
+
if (errorHdl) {
|
|
445
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Update an input collection
|
|
450
|
+
* @param collection - the name of the input collection to update
|
|
451
|
+
* @param entries - entries to update in the collection.
|
|
452
|
+
*/
|
|
453
|
+
update(collection, entries) {
|
|
454
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
455
|
+
return this.refs.binding.SkipRuntime_Runtime__update(collection, this.refs.skjson.exportJSON(entries));
|
|
456
|
+
});
|
|
457
|
+
if (errorHdl) {
|
|
458
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Close all resources and shut down the service.
|
|
463
|
+
* Any subsequent calls on the service will result in errors.
|
|
464
|
+
*/
|
|
465
|
+
close() {
|
|
466
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
467
|
+
return this.refs.binding.SkipRuntime_closeService();
|
|
468
|
+
});
|
|
469
|
+
if (errorHdl) {
|
|
470
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
export class NonEmptyIteratorImpl {
|
|
475
|
+
constructor(skjson, binding, pointer) {
|
|
476
|
+
this.skjson = skjson;
|
|
477
|
+
this.binding = binding;
|
|
478
|
+
this.pointer = pointer;
|
|
479
|
+
this.toArray = () => {
|
|
480
|
+
return Array.from(this);
|
|
481
|
+
};
|
|
482
|
+
this.skjson = skjson;
|
|
483
|
+
this.binding = binding;
|
|
484
|
+
this.pointer = pointer;
|
|
485
|
+
}
|
|
486
|
+
next() {
|
|
487
|
+
return this.skjson.importOptJSON(this.binding.SkipRuntime_NonEmptyIterator__next(this.pointer));
|
|
488
|
+
}
|
|
489
|
+
getUnique() {
|
|
490
|
+
const value = this.skjson.importOptJSON(this.binding.SkipRuntime_NonEmptyIterator__uniqueValue(this.pointer));
|
|
491
|
+
if (value == null)
|
|
492
|
+
throw new NonUniqueValueException();
|
|
493
|
+
return value;
|
|
494
|
+
}
|
|
495
|
+
[Symbol.iterator]() {
|
|
496
|
+
const cloned_iter = new NonEmptyIteratorImpl(this.skjson, this.binding, this.binding.SkipRuntime_NonEmptyIterator__clone(this.pointer));
|
|
497
|
+
return {
|
|
498
|
+
next() {
|
|
499
|
+
const value = cloned_iter.next();
|
|
500
|
+
return { value, done: value == null };
|
|
501
|
+
},
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
map(f, thisObj) {
|
|
505
|
+
return this.toArray().map(f, thisObj);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
export class ToBinding {
|
|
509
|
+
constructor(binding, runWithGC, getConverter, getError) {
|
|
510
|
+
this.binding = binding;
|
|
511
|
+
this.runWithGC = runWithGC;
|
|
512
|
+
this.getConverter = getConverter;
|
|
513
|
+
this.getError = getError;
|
|
514
|
+
this.stack = new Stack();
|
|
515
|
+
this.handles = new Handles();
|
|
516
|
+
}
|
|
517
|
+
register(v) {
|
|
518
|
+
return this.handles.register(v);
|
|
519
|
+
}
|
|
520
|
+
deleteHandle(id) {
|
|
521
|
+
return this.handles.deleteHandle(id);
|
|
522
|
+
}
|
|
523
|
+
SkipRuntime_getErrorHdl(exn) {
|
|
524
|
+
return this.handles.register(this.getError(exn));
|
|
525
|
+
}
|
|
526
|
+
SkipRuntime_pushContext(context) {
|
|
527
|
+
this.stack.push(context);
|
|
528
|
+
}
|
|
529
|
+
SkipRuntime_popContext() {
|
|
530
|
+
this.stack.pop();
|
|
531
|
+
}
|
|
532
|
+
SkipRuntime_getContext() {
|
|
533
|
+
return this.stack.get();
|
|
534
|
+
}
|
|
535
|
+
// Mapper
|
|
536
|
+
SkipRuntime_Mapper__mapEntry(skmapper, key, values) {
|
|
537
|
+
const skjson = this.getJsonConverter();
|
|
538
|
+
const mapper = this.handles.get(skmapper);
|
|
539
|
+
const result = mapper.mapEntry(skjson.importJSON(key), new NonEmptyIteratorImpl(skjson, this.binding, values));
|
|
540
|
+
return skjson.exportJSON(Array.from(result));
|
|
541
|
+
}
|
|
542
|
+
SkipRuntime_deleteMapper(mapper) {
|
|
543
|
+
this.handles.deleteHandle(mapper);
|
|
544
|
+
}
|
|
545
|
+
// LazyCompute
|
|
546
|
+
SkipRuntime_LazyCompute__compute(sklazyCompute, self, skkey) {
|
|
547
|
+
const skjson = this.getJsonConverter();
|
|
548
|
+
const lazyCompute = this.handles.get(sklazyCompute);
|
|
549
|
+
const computed = lazyCompute.compute(new LazyCollectionImpl(self, this.refs()), skjson.importJSON(skkey));
|
|
550
|
+
return skjson.exportJSON(computed ? [computed] : []);
|
|
551
|
+
}
|
|
552
|
+
SkipRuntime_deleteLazyCompute(lazyCompute) {
|
|
553
|
+
this.handles.deleteHandle(lazyCompute);
|
|
554
|
+
}
|
|
555
|
+
// Resource
|
|
556
|
+
SkipRuntime_Resource__instantiate(skresource, skcollections) {
|
|
557
|
+
const skjson = this.getJsonConverter();
|
|
558
|
+
const resource = this.handles.get(skresource);
|
|
559
|
+
const collections = {};
|
|
560
|
+
const keysIds = skjson.importJSON(skcollections);
|
|
561
|
+
const refs = this.refs();
|
|
562
|
+
for (const [key, name] of Object.entries(keysIds)) {
|
|
563
|
+
collections[key] = new EagerCollectionImpl(name, refs);
|
|
564
|
+
}
|
|
565
|
+
const collection = resource.instantiate(collections, new ContextImpl(refs));
|
|
566
|
+
return collection.collection;
|
|
567
|
+
}
|
|
568
|
+
SkipRuntime_deleteResource(resource) {
|
|
569
|
+
this.handles.deleteHandle(resource);
|
|
570
|
+
}
|
|
571
|
+
// ResourceBuilder
|
|
572
|
+
SkipRuntime_ResourceBuilder__build(skbuilder, skparams) {
|
|
573
|
+
const skjson = this.getJsonConverter();
|
|
574
|
+
const builder = this.handles.get(skbuilder);
|
|
575
|
+
const resource = builder.build(skjson.importJSON(skparams));
|
|
576
|
+
return this.binding.SkipRuntime_createResource(this.handles.register(resource));
|
|
577
|
+
}
|
|
578
|
+
SkipRuntime_deleteResourceBuilder(builder) {
|
|
579
|
+
this.handles.deleteHandle(builder);
|
|
580
|
+
}
|
|
581
|
+
// Service
|
|
582
|
+
SkipRuntime_Service__createGraph(skservice, skcollections) {
|
|
583
|
+
const skjson = this.getJsonConverter();
|
|
584
|
+
const service = this.handles.get(skservice);
|
|
585
|
+
const collections = {};
|
|
586
|
+
const keysIds = skjson.importJSON(skcollections);
|
|
587
|
+
const refs = this.refs();
|
|
588
|
+
for (const [key, name] of Object.entries(keysIds)) {
|
|
589
|
+
collections[key] = new EagerCollectionImpl(name, refs);
|
|
590
|
+
}
|
|
591
|
+
const result = service.createGraph(collections, new ContextImpl(refs));
|
|
592
|
+
const collectionsNames = {};
|
|
593
|
+
for (const [name, collection] of Object.entries(result)) {
|
|
594
|
+
collectionsNames[name] = collection.collection;
|
|
595
|
+
}
|
|
596
|
+
return skjson.exportJSON(collectionsNames);
|
|
597
|
+
}
|
|
598
|
+
SkipRuntime_deleteService(service) {
|
|
599
|
+
this.handles.deleteHandle(service);
|
|
600
|
+
}
|
|
601
|
+
// Notifier
|
|
602
|
+
SkipRuntime_Notifier__subscribed(sknotifier) {
|
|
603
|
+
const notifier = this.handles.get(sknotifier);
|
|
604
|
+
notifier.subscribed();
|
|
605
|
+
}
|
|
606
|
+
SkipRuntime_Notifier__notify(sknotifier, skvalues, watermark, isUpdates) {
|
|
607
|
+
const skjson = this.getJsonConverter();
|
|
608
|
+
const notifier = this.handles.get(sknotifier);
|
|
609
|
+
const values = skjson.importJSON(skvalues, true);
|
|
610
|
+
const isInitial = isUpdates ? false : true;
|
|
611
|
+
notifier.notify({
|
|
612
|
+
values,
|
|
613
|
+
watermark,
|
|
614
|
+
isInitial,
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
SkipRuntime_Notifier__close(sknotifier) {
|
|
618
|
+
const notifier = this.handles.get(sknotifier);
|
|
619
|
+
notifier.close();
|
|
620
|
+
}
|
|
621
|
+
SkipRuntime_deleteNotifier(notifier) {
|
|
622
|
+
this.handles.deleteHandle(notifier);
|
|
623
|
+
}
|
|
624
|
+
// Reducer
|
|
625
|
+
SkipRuntime_Reducer__add(skreducer, skacc, skvalue) {
|
|
626
|
+
const skjson = this.getJsonConverter();
|
|
627
|
+
const reducer = this.handles.get(skreducer);
|
|
628
|
+
return skjson.exportJSON(reducer.add(skacc ? skjson.importJSON(skacc) : null, skjson.importJSON(skvalue)));
|
|
629
|
+
}
|
|
630
|
+
SkipRuntime_Reducer__remove(skreducer, skacc, skvalue) {
|
|
631
|
+
const skjson = this.getJsonConverter();
|
|
632
|
+
const reducer = this.handles.get(skreducer);
|
|
633
|
+
return skjson.exportJSON(reducer.remove(skjson.importJSON(skacc), skjson.importJSON(skvalue)));
|
|
634
|
+
}
|
|
635
|
+
SkipRuntime_deleteReducer(reducer) {
|
|
636
|
+
this.handles.deleteHandle(reducer);
|
|
637
|
+
}
|
|
638
|
+
// ExternalService
|
|
639
|
+
SkipRuntime_ExternalService__subscribe(sksupplier, writerId, resource, skparams) {
|
|
640
|
+
const skjson = this.getJsonConverter();
|
|
641
|
+
const supplier = this.handles.get(sksupplier);
|
|
642
|
+
const writer = new CollectionWriter(writerId, this.refs());
|
|
643
|
+
const params = skjson.importJSON(skparams, true);
|
|
644
|
+
supplier.subscribe(resource, params, {
|
|
645
|
+
update: writer.update.bind(writer),
|
|
646
|
+
error: writer.error.bind(writer),
|
|
647
|
+
loading: writer.loading.bind(writer),
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
SkipRuntime_ExternalService__unsubscribe(sksupplier, resource, skparams) {
|
|
651
|
+
const skjson = this.getJsonConverter();
|
|
652
|
+
const supplier = this.handles.get(sksupplier);
|
|
653
|
+
const params = skjson.importJSON(skparams, true);
|
|
654
|
+
supplier.unsubscribe(resource, params);
|
|
655
|
+
}
|
|
656
|
+
SkipRuntime_ExternalService__shutdown(sksupplier) {
|
|
657
|
+
const supplier = this.handles.get(sksupplier);
|
|
658
|
+
supplier.shutdown();
|
|
659
|
+
}
|
|
660
|
+
SkipRuntime_deleteExternalService(supplier) {
|
|
661
|
+
this.handles.deleteHandle(supplier);
|
|
662
|
+
}
|
|
663
|
+
// Checker
|
|
664
|
+
SkipRuntime_Checker__check(skchecker, request) {
|
|
665
|
+
const checker = this.handles.get(skchecker);
|
|
666
|
+
checker.check(request);
|
|
667
|
+
}
|
|
668
|
+
SkipRuntime_deleteChecker(checker) {
|
|
669
|
+
this.handles.deleteHandle(checker);
|
|
670
|
+
}
|
|
671
|
+
initService(service) {
|
|
672
|
+
const refs = this.refs();
|
|
673
|
+
const errorHdl = refs.runWithGC(() => {
|
|
674
|
+
const skExternalServices = refs.binding.SkipRuntime_ExternalServiceMap__create();
|
|
675
|
+
if (service.externalServices) {
|
|
676
|
+
for (const [name, remote] of Object.entries(service.externalServices)) {
|
|
677
|
+
const skremote = refs.binding.SkipRuntime_createExternalService(refs.handles.register(remote));
|
|
678
|
+
refs.binding.SkipRuntime_ExternalServiceMap__add(skExternalServices, name, skremote);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
const skresources = refs.binding.SkipRuntime_ResourceBuilderMap__create();
|
|
682
|
+
for (const [name, builder] of Object.entries(service.resources)) {
|
|
683
|
+
const skbuilder = refs.binding.SkipRuntime_createResourceBuilder(refs.handles.register(new ResourceBuilder(builder)));
|
|
684
|
+
refs.binding.SkipRuntime_ResourceBuilderMap__add(skresources, name, skbuilder);
|
|
685
|
+
}
|
|
686
|
+
const skservice = refs.binding.SkipRuntime_createService(refs.handles.register(service), refs.skjson.exportJSON(service.initialData ?? {}), skresources, skExternalServices);
|
|
687
|
+
return refs.binding.SkipRuntime_initService(skservice);
|
|
688
|
+
});
|
|
689
|
+
if (errorHdl)
|
|
690
|
+
throw refs.handles.deleteHandle(errorHdl);
|
|
691
|
+
return new ServiceInstance(refs);
|
|
692
|
+
}
|
|
693
|
+
//
|
|
694
|
+
getJsonConverter() {
|
|
695
|
+
if (this.skjson == undefined) {
|
|
696
|
+
this.skjson = this.getConverter();
|
|
697
|
+
}
|
|
698
|
+
return this.skjson;
|
|
699
|
+
}
|
|
700
|
+
needGC() {
|
|
701
|
+
return this.SkipRuntime_getContext() == null;
|
|
702
|
+
}
|
|
703
|
+
refs() {
|
|
704
|
+
return new Refs(this.binding, this.getConverter(), this.handles, this.needGC.bind(this), this.runWithGC);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
//# sourceMappingURL=index.js.map
|