@lowdefy/engine 0.0.0-experimental-20260720072521 → 0.0.0-experimental-20260720135014

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/Actions.js CHANGED
@@ -15,14 +15,6 @@
15
15
  */ import { ActionError, ConfigError, UserError } from '@lowdefy/errors';
16
16
  import { type } from '@lowdefy/helpers';
17
17
  import getActionMethods from './actions/getActionMethods.js';
18
- const CONTROL_KEYS = [
19
- ':if',
20
- ':switch',
21
- ':return'
22
- ];
23
- function isControl(item) {
24
- return type.isObject(item) && CONTROL_KEYS.some((key)=>key in item);
25
- }
26
18
  let Actions = class Actions {
27
19
  logActionError({ error, action }) {
28
20
  const handleError = this.context._internal.lowdefy._internal.handleError;
@@ -60,32 +52,8 @@ let Actions = class Actions {
60
52
  this.logActionError(err);
61
53
  }
62
54
  }
63
- // Returns true when a ':return' control ended the list, so callers can end the event.
64
- async callActionLoop({ actions, arrayIndices, block, controls, counters, event, progress, responses }) {
65
- for (const [position, action] of actions.entries()){
66
- if (isControl(action)) {
67
- const returned = await this.callControl({
68
- arrayIndices,
69
- block,
70
- control: action,
71
- controls,
72
- counters,
73
- event,
74
- progress,
75
- responses
76
- });
77
- if (returned === true) {
78
- this.recordSkippedActions({
79
- actions: actions.slice(position + 1),
80
- counters,
81
- responses
82
- });
83
- return true;
84
- }
85
- continue;
86
- }
87
- const index = counters.action;
88
- counters.action += 1;
55
+ async callActionLoop({ actions, arrayIndices, block, event, progress, responses }) {
56
+ for (const [index, action] of actions.entries()){
89
57
  try {
90
58
  if (action.async === true) {
91
59
  this.callAsyncAction({
@@ -115,242 +83,26 @@ let Actions = class Actions {
115
83
  throw err;
116
84
  }
117
85
  }
118
- return false;
119
- }
120
- async callControl({ arrayIndices, block, control, controls, counters, event, progress, responses }) {
121
- const index = counters.control;
122
- counters.control += 1;
123
- if (':return' in control) {
124
- const value = this.evaluateControlValue({
125
- arrayIndices,
126
- block,
127
- event,
128
- input: control[':return'],
129
- node: control,
130
- responses
131
- });
132
- controls.push({
133
- index,
134
- type: ':return',
135
- taken: value
136
- });
137
- return true;
138
- }
139
- if (':if' in control) {
140
- const condition = this.evaluateControlValue({
141
- arrayIndices,
142
- block,
143
- event,
144
- input: control[':if'],
145
- node: control,
146
- responses
147
- });
148
- // JS truthiness, matching the routine ':if' - not skip's strict === true.
149
- if (condition) {
150
- controls.push({
151
- index,
152
- type: ':if',
153
- taken: 'then'
154
- });
155
- const returned = await this.callActionLoop({
156
- actions: control[':then'],
157
- arrayIndices,
158
- block,
159
- controls,
160
- counters,
161
- event,
162
- progress,
163
- responses
164
- });
165
- this.recordSkippedActions({
166
- actions: control[':else'] ?? [],
167
- counters,
168
- responses
169
- });
170
- return returned;
171
- }
172
- controls.push({
173
- index,
174
- type: ':if',
175
- taken: 'else'
176
- });
177
- this.recordSkippedActions({
178
- actions: control[':then'],
179
- counters,
180
- responses
181
- });
182
- return this.callActionLoop({
183
- actions: control[':else'] ?? [],
184
- arrayIndices,
185
- block,
186
- controls,
187
- counters,
188
- event,
189
- progress,
190
- responses
191
- });
192
- }
193
- // ':switch' - cases are evaluated in order and lazily: the first truthy ':case' wins,
194
- // later cases are never evaluated, matching the routine ':switch'.
195
- let matched = false;
196
- let returned = false;
197
- for (const [casePosition, caseObject] of control[':switch'].entries()){
198
- if (!matched) {
199
- const condition = this.evaluateControlValue({
200
- arrayIndices,
201
- block,
202
- event,
203
- input: caseObject[':case'],
204
- node: caseObject,
205
- responses
206
- });
207
- if (condition) {
208
- matched = true;
209
- controls.push({
210
- index,
211
- type: ':switch',
212
- taken: casePosition
213
- });
214
- returned = await this.callActionLoop({
215
- actions: caseObject[':then'],
216
- arrayIndices,
217
- block,
218
- controls,
219
- counters,
220
- event,
221
- progress,
222
- responses
223
- });
224
- continue;
225
- }
226
- }
227
- this.recordSkippedActions({
228
- actions: caseObject[':then'],
229
- counters,
230
- responses
231
- });
232
- }
233
- if (matched) {
234
- this.recordSkippedActions({
235
- actions: control[':default'] ?? [],
236
- counters,
237
- responses
238
- });
239
- return returned;
240
- }
241
- controls.push({
242
- index,
243
- type: ':switch',
244
- taken: 'default'
245
- });
246
- return this.callActionLoop({
247
- actions: control[':default'] ?? [],
248
- arrayIndices,
249
- block,
250
- controls,
251
- counters,
252
- event,
253
- progress,
254
- responses
255
- });
256
- }
257
- evaluateControlValue({ arrayIndices, block, event, input, node, responses }) {
258
- const { output, errors: parserErrors } = this.context._internal.parser.parse({
259
- actions: responses,
260
- event,
261
- arrayIndices,
262
- input,
263
- location: block.blockId
264
- });
265
- if (parserErrors.length > 0) {
266
- const error = parserErrors[0];
267
- // Report against the nearest node's '~k' when the operator carries none.
268
- if (type.isNone(error.configKey)) {
269
- error.configKey = node['~k'];
270
- }
271
- // Controls are anonymous - no responses entry, so only {error} is thrown.
272
- throw {
273
- error
274
- };
275
- }
276
- return output;
277
- }
278
- // Records actions the chain does not execute for a control-flow reason as skipped,
279
- // without parsing their operators. Controls record no responses entry, but still
280
- // consume a control index so reached controls keep their depth-first numbering.
281
- recordSkippedActions({ actions, counters, responses }) {
282
- for (const action of actions){
283
- if (isControl(action)) {
284
- counters.control += 1;
285
- if (':if' in action) {
286
- this.recordSkippedActions({
287
- actions: action[':then'],
288
- counters,
289
- responses
290
- });
291
- this.recordSkippedActions({
292
- actions: action[':else'] ?? [],
293
- counters,
294
- responses
295
- });
296
- }
297
- if (':switch' in action) {
298
- action[':switch'].forEach((caseObject)=>{
299
- this.recordSkippedActions({
300
- actions: caseObject[':then'],
301
- counters,
302
- responses
303
- });
304
- });
305
- this.recordSkippedActions({
306
- actions: action[':default'] ?? [],
307
- counters,
308
- responses
309
- });
310
- }
311
- continue;
312
- }
313
- responses[action.id] = {
314
- type: action.type,
315
- skipped: true,
316
- index: counters.action
317
- };
318
- counters.action += 1;
319
- }
320
86
  }
321
87
  async callActions({ actions, arrayIndices, block, catchActions, event, eventName, progress }) {
322
88
  const startTimestamp = new Date();
323
89
  const responses = {};
324
- // Only events with controls gain a 'controls' array - flat chains keep their result shape.
325
- const hasControls = actions.some(isControl) || catchActions.some(isControl);
326
- const controls = hasControls ? [] : undefined;
327
- const counters = {
328
- action: 0,
329
- control: 0
330
- };
331
90
  try {
332
91
  await this.callActionLoop({
333
92
  actions,
334
93
  arrayIndices,
335
94
  block,
336
- controls,
337
- counters,
338
95
  event,
339
96
  responses,
340
97
  progress
341
98
  });
342
99
  } catch (error) {
343
100
  this.logActionError(error);
344
- // Catch actions restart action numbering, matching flat-chain history; the control
345
- // counter continues so every control entry keeps a unique index within the event.
346
- counters.action = 0;
347
101
  try {
348
102
  await this.callActionLoop({
349
103
  actions: catchActions,
350
104
  arrayIndices,
351
105
  block,
352
- controls,
353
- counters,
354
106
  event,
355
107
  responses,
356
108
  progress
@@ -360,9 +112,6 @@ let Actions = class Actions {
360
112
  return {
361
113
  blockId: block.blockId,
362
114
  bounced: false,
363
- ...controls && {
364
- controls
365
- },
366
115
  endTimestamp: new Date(),
367
116
  error,
368
117
  errorCatch,
@@ -376,9 +125,6 @@ let Actions = class Actions {
376
125
  return {
377
126
  blockId: block.blockId,
378
127
  bounced: false,
379
- ...controls && {
380
- controls
381
- },
382
128
  endTimestamp: new Date(),
383
129
  error,
384
130
  event,
@@ -391,9 +137,6 @@ let Actions = class Actions {
391
137
  return {
392
138
  blockId: block.blockId,
393
139
  bounced: false,
394
- ...controls && {
395
- controls
396
- },
397
140
  endTimestamp: new Date(),
398
141
  event,
399
142
  eventName,
@@ -530,7 +273,6 @@ let Actions = class Actions {
530
273
  this.callAction = this.callAction.bind(this);
531
274
  this.callActionLoop = this.callActionLoop.bind(this);
532
275
  this.callActions = this.callActions.bind(this);
533
- this.callControl = this.callControl.bind(this);
534
276
  this.displayMessage = this.displayMessage.bind(this);
535
277
  this.logActionError = this.logActionError.bind(this);
536
278
  this.actions = context._internal.lowdefy._internal.actions;
package/dist/Block.js CHANGED
@@ -424,10 +424,7 @@ let Block = class Block {
424
424
  value: type.isNone(this.value) ? null : this.value,
425
425
  visible: this.visibleEval.output
426
426
  };
427
- // Updaters register per context — a context under construction has none,
428
- // so construction-time evals never setState mounted components from a
429
- // previous context.
430
- this.context._internal.updaters[this.id]?.();
427
+ this.context._internal.lowdefy._internal.updateBlock(this.id);
431
428
  });
432
429
  const { id, blockId, class: blockClass, events, layout, loading, properties, required, skeleton, style, validate, visible, type: blockType, slots } = blockConfig;
433
430
  this.context = context;
@@ -12,10 +12,8 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ import createAcceptInvitation from './createAcceptInvitation.js';
16
- import createCallMethod from './createCallMethod.js';
15
+ */ import createCallMethod from './createCallMethod.js';
17
16
  import createCallAPI from './createCallAPI.js';
18
- import createChangePassword from './createChangePassword.js';
19
17
  import createGetActions from './createGetActions.js';
20
18
  import createGetBlockId from './createGetBlockId.js';
21
19
  import createGetEvent from './createGetEvent.js';
@@ -27,43 +25,22 @@ import createGetRequestDetails from './createGetRequestDetails.js';
27
25
  import createGetState from './createGetState.js';
28
26
  import createGetUrlQuery from './createGetUrlQuery.js';
29
27
  import createGetUser from './createGetUser.js';
30
- import createImpersonateUser from './createImpersonateUser.js';
31
28
  import createLink from './createLink.js';
32
29
  import createLogin from './createLogin.js';
33
30
  import createLogout from './createLogout.js';
34
31
  import createDisplayMessage from './createDisplayMessage.js';
35
- import createPasskeyDelete from './createPasskeyDelete.js';
36
- import createPasskeyRegister from './createPasskeyRegister.js';
37
- import createPasskeySignIn from './createPasskeySignIn.js';
38
- import createPhoneNumberSendOtp from './createPhoneNumberSendOtp.js';
39
- import createPhoneNumberVerify from './createPhoneNumberVerify.js';
40
- import createPublish from './createPublish.js';
41
32
  import createRequest from './createRequest.js';
42
- import createRequestPasswordReset from './createRequestPasswordReset.js';
43
33
  import createReset from './createReset.js';
44
- import createResetPassword from './createResetPassword.js';
45
34
  import createResetValidation from './createResetValidation.js';
46
- import createRevokeOtherSessions from './createRevokeOtherSessions.js';
47
- import createSendVerificationEmail from './createSendVerificationEmail.js';
48
- import createSetActiveOrganization from './createSetActiveOrganization.js';
49
35
  import createSetGlobal from './createSetGlobal.js';
50
36
  import createSetState from './createSetState.js';
51
- import createSignUp from './createSignUp.js';
52
- import createStopImpersonating from './createStopImpersonating.js';
53
- import createSubscribe from './createSubscribe.js';
54
37
  import createTranslate from './createTranslate.js';
55
- import createTwoFactorDisable from './createTwoFactorDisable.js';
56
- import createTwoFactorEnable from './createTwoFactorEnable.js';
57
- import createTwoFactorVerify from './createTwoFactorVerify.js';
58
- import createUnsubscribe from './createUnsubscribe.js';
59
38
  import createUpdateSession from './createUpdateSession.js';
60
39
  import createValidate from './createValidate.js';
61
40
  function getActionMethods(props) {
62
41
  return {
63
- acceptInvitation: createAcceptInvitation(props),
64
42
  callAPI: createCallAPI(props),
65
43
  callMethod: createCallMethod(props),
66
- changePassword: createChangePassword(props),
67
44
  displayMessage: createDisplayMessage(props),
68
45
  getActions: createGetActions(props),
69
46
  getBlockId: createGetBlockId(props),
@@ -76,34 +53,15 @@ function getActionMethods(props) {
76
53
  getState: createGetState(props),
77
54
  getUrlQuery: createGetUrlQuery(props),
78
55
  getUser: createGetUser(props),
79
- impersonateUser: createImpersonateUser(props),
80
56
  link: createLink(props),
81
57
  login: createLogin(props),
82
58
  logout: createLogout(props),
83
- passkeyDelete: createPasskeyDelete(props),
84
- passkeyRegister: createPasskeyRegister(props),
85
- passkeySignIn: createPasskeySignIn(props),
86
- phoneNumberSendOtp: createPhoneNumberSendOtp(props),
87
- phoneNumberVerify: createPhoneNumberVerify(props),
88
- publish: createPublish(props),
89
59
  request: createRequest(props),
90
- requestPasswordReset: createRequestPasswordReset(props),
91
60
  reset: createReset(props),
92
- resetPassword: createResetPassword(props),
93
61
  resetValidation: createResetValidation(props),
94
- revokeOtherSessions: createRevokeOtherSessions(props),
95
- sendVerificationEmail: createSendVerificationEmail(props),
96
- setActiveOrganization: createSetActiveOrganization(props),
97
62
  setGlobal: createSetGlobal(props),
98
63
  setState: createSetState(props),
99
- signUp: createSignUp(props),
100
- stopImpersonating: createStopImpersonating(props),
101
- subscribe: createSubscribe(props),
102
64
  translate: createTranslate(props),
103
- twoFactorDisable: createTwoFactorDisable(props),
104
- twoFactorEnable: createTwoFactorEnable(props),
105
- twoFactorVerify: createTwoFactorVerify(props),
106
- unsubscribe: createUnsubscribe(props),
107
65
  updateSession: createUpdateSession(props),
108
66
  validate: createValidate(props)
109
67
  };
@@ -17,9 +17,8 @@ import Actions from './Actions.js';
17
17
  import Slots from './Slots.js';
18
18
  import Requests from './Requests.js';
19
19
  import State from './State.js';
20
- import WebSockets from './WebSockets.js';
21
20
  const blockData = (config)=>{
22
- const { slots, blockId, blocks, events, field, id, layout, pageId, properties, requests, required, style, subscriptions, type, validate, visible } = config;
21
+ const { slots, blockId, blocks, events, field, id, layout, pageId, properties, requests, required, style, type, validate, visible } = config;
23
22
  const result = {
24
23
  slots,
25
24
  blockId,
@@ -33,7 +32,6 @@ const blockData = (config)=>{
33
32
  requests,
34
33
  required,
35
34
  style,
36
- subscriptions,
37
35
  type,
38
36
  validate,
39
37
  visible
@@ -57,24 +55,12 @@ function getContext({ config, jsMap = {}, lowdefy, resetContext = {
57
55
  throw new Error('A page must be provided to get context.');
58
56
  }
59
57
  const { id } = config;
60
- // Dynamic pages are server-resolved per request — a context memoized across
61
- // navigations would render the previous request's content. Rebuild when a
62
- // new config object arrives (a fresh fetch), but stay memoized across
63
- // re-renders of the same config: getContext runs in the render body, so
64
- // rebuilding per render would loop.
65
- const sameDynamicConfig = config.dynamic !== true || lowdefy.contexts[id]?._internal.pageConfig === config;
66
- if (lowdefy.contexts[id] && !resetContext.reset && sameDynamicConfig) {
58
+ if (lowdefy.contexts[id] && !resetContext.reset) {
67
59
  // memoize context if already created, eg between page transitions, unless the reset flag is raised
68
60
  lowdefy.contexts[id]._internal.update();
69
61
  return lowdefy.contexts[id];
70
62
  }
71
- // Lower the context reset flag — only when raised: setReset is a React
72
- // state setter on the Reload component, and getContext runs in the render
73
- // body, so skip the redundant cross-component setState on rebuilds where
74
- // the flag is already down.
75
- if (resetContext.reset) {
76
- resetContext.setReset(false);
77
- }
63
+ resetContext.setReset(false); // lower context reset flag.
78
64
  if (!lowdefy.inputs[id]) {
79
65
  lowdefy.inputs[id] = {};
80
66
  }
@@ -87,16 +73,8 @@ function getContext({ config, jsMap = {}, lowdefy, resetContext = {
87
73
  state: {},
88
74
  _internal: {
89
75
  lowdefy,
90
- // Config object reference for dynamic page memoization — identity marks
91
- // which fetch this context was built from.
92
- pageConfig: config,
93
76
  rootBlock: blockData(config),
94
- update: ()=>{},
95
- // React updaters register here per block id when the context's Block
96
- // components mount — scoped per context so rebuilding over a live
97
- // context (dynamic page navigation, reset) never notifies the previous
98
- // context's still-mounted components.
99
- updaters: {}
77
+ update: ()=>{}
100
78
  }
101
79
  };
102
80
  const _internal = ctx._internal;
@@ -107,7 +85,6 @@ function getContext({ config, jsMap = {}, lowdefy, resetContext = {
107
85
  _internal.State = new State(ctx);
108
86
  _internal.Actions = new Actions(ctx);
109
87
  _internal.Requests = new Requests(ctx);
110
- _internal.WebSockets = new WebSockets(ctx);
111
88
  _internal.RootSlots = new Slots({
112
89
  slots: {
113
90
  root: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/engine",
3
- "version": "0.0.0-experimental-20260720072521",
3
+ "version": "0.0.0-experimental-20260720135014",
4
4
  "license": "Apache-2.0",
5
5
  "description": "",
6
6
  "homepage": "https://lowdefy.com",
@@ -30,18 +30,18 @@
30
30
  "dist/*"
31
31
  ],
32
32
  "dependencies": {
33
- "@lowdefy/errors": "0.0.0-experimental-20260720072521",
34
- "@lowdefy/helpers": "0.0.0-experimental-20260720072521",
35
- "@lowdefy/operators": "0.0.0-experimental-20260720072521"
33
+ "@lowdefy/errors": "0.0.0-experimental-20260720135014",
34
+ "@lowdefy/helpers": "0.0.0-experimental-20260720135014",
35
+ "@lowdefy/operators": "0.0.0-experimental-20260720135014"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@jest/globals": "28.1.3",
39
- "@lowdefy/actions-core": "0.0.0-experimental-20260720072521",
40
- "@lowdefy/build": "0.0.0-experimental-20260720072521",
41
- "@lowdefy/operators-js": "0.0.0-experimental-20260720072521",
42
- "@lowdefy/operators-mql": "0.0.0-experimental-20260720072521",
43
- "@swc/cli": "0.8.1",
44
- "@swc/core": "1.15.32",
39
+ "@lowdefy/actions-core": "0.0.0-experimental-20260720135014",
40
+ "@lowdefy/build": "0.0.0-experimental-20260720135014",
41
+ "@lowdefy/operators-js": "0.0.0-experimental-20260720135014",
42
+ "@lowdefy/operators-mql": "0.0.0-experimental-20260720135014",
43
+ "@swc/cli": "0.8.0",
44
+ "@swc/core": "1.15.18",
45
45
  "@swc/jest": "0.2.39",
46
46
  "jest": "28.1.3"
47
47
  },
@@ -1,242 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ import { serializer, type } from '@lowdefy/helpers';
16
- import Events from './Events.js';
17
- const DEFAULT_MAX_MESSAGES = 100;
18
- const DEFAULT_THROTTLE_RENDER = 250;
19
- const MIN_THROTTLE_RENDER = 100;
20
- let WebSockets = class WebSockets {
21
- client() {
22
- return this.context._internal.lowdefy._internal.websocketClient;
23
- }
24
- initChannelState(websocketId) {
25
- this.context.websockets[websocketId] = {
26
- connected: false,
27
- error: null,
28
- lastMessage: null,
29
- messageCount: 0,
30
- messages: []
31
- };
32
- }
33
- getEvents(websocketId, config) {
34
- if (!this.subscriptionEvents[websocketId]) {
35
- this.subscriptionEvents[websocketId] = new Events({
36
- arrayIndices: [],
37
- block: {
38
- blockId: `subscription:${websocketId}`,
39
- events: config.events ?? {}
40
- },
41
- context: this.context
42
- });
43
- }
44
- return this.subscriptionEvents[websocketId];
45
- }
46
- flush({ websocketId, maxMessages }) {
47
- const buffer = this.buffers[websocketId];
48
- const channel = this.context.websockets[websocketId];
49
- if (!buffer || buffer.length === 0 || !channel) {
50
- return;
51
- }
52
- const batch = buffer.splice(0, buffer.length);
53
- channel.messages.push(...batch);
54
- if (channel.messages.length > maxMessages) {
55
- channel.messages.splice(0, channel.messages.length - maxMessages);
56
- }
57
- channel.lastMessage = batch[batch.length - 1];
58
- channel.messageCount += batch.length;
59
- this.context._internal.update();
60
- this.subscriptionEvents[websocketId]?.triggerEvent({
61
- name: 'onMessage',
62
- event: {
63
- messages: batch
64
- }
65
- });
66
- }
67
- handleMessage({ websocketId, maxMessages, serializedPayload, throttleMs }) {
68
- if (!this.active.has(websocketId)) {
69
- return;
70
- }
71
- const data = serializer.deserialize(serializedPayload)?.data;
72
- this.buffers[websocketId].push(data);
73
- // Leading-edge throttle: the first message in a window renders
74
- // immediately, the rest batch until the window closes.
75
- if (!this.flushTimers[websocketId]) {
76
- this.flush({
77
- websocketId,
78
- maxMessages
79
- });
80
- const arm = ()=>{
81
- this.flushTimers[websocketId] = setTimeout(()=>{
82
- if ((this.buffers[websocketId] ?? []).length > 0) {
83
- this.flush({
84
- websocketId,
85
- maxMessages
86
- });
87
- arm();
88
- return;
89
- }
90
- this.flushTimers[websocketId] = null;
91
- }, throttleMs);
92
- };
93
- arm();
94
- }
95
- }
96
- async subscribe({ actions, arrayIndices, event, websocketId }) {
97
- if (!type.isString(websocketId)) {
98
- throw new Error('Subscribe requires a websocketId.');
99
- }
100
- if (this.active.has(websocketId)) {
101
- return;
102
- }
103
- const config = this.subscriptionConfig[websocketId] ?? {
104
- client: {},
105
- events: {},
106
- payload: {},
107
- websocketId
108
- };
109
- if (!this.context.websockets[websocketId]) {
110
- this.initChannelState(websocketId);
111
- }
112
- const { output: payload, errors: parserErrors } = this.context._internal.parser.parse({
113
- actions,
114
- arrayIndices,
115
- event,
116
- input: config.payload ?? {},
117
- location: `subscription:${websocketId}`
118
- });
119
- if (parserErrors.length > 0) {
120
- throw parserErrors[0];
121
- }
122
- const events = this.getEvents(websocketId, config);
123
- const channel = this.context.websockets[websocketId];
124
- const throttleMs = Math.max(config.client?.throttleRender ?? DEFAULT_THROTTLE_RENDER, MIN_THROTTLE_RENDER);
125
- const maxMessages = config.client?.maxMessages ?? DEFAULT_MAX_MESSAGES;
126
- this.active.add(websocketId);
127
- this.buffers[websocketId] = [];
128
- try {
129
- await this.client().subscribe({
130
- websocketId,
131
- payload: serializer.serialize(payload),
132
- handlers: {
133
- onConnected: ()=>{
134
- channel.connected = true;
135
- channel.error = null;
136
- this.context._internal.update();
137
- events.triggerEvent({
138
- name: 'onSubscribe',
139
- event: {}
140
- });
141
- },
142
- onDisconnected: ()=>{
143
- channel.connected = false;
144
- this.context._internal.update();
145
- },
146
- onError: (message)=>{
147
- channel.error = {
148
- message
149
- };
150
- this.context._internal.update();
151
- events.triggerEvent({
152
- name: 'onError',
153
- event: {
154
- message
155
- }
156
- });
157
- },
158
- onMessage: (serializedPayload)=>{
159
- this.handleMessage({
160
- websocketId,
161
- maxMessages,
162
- serializedPayload,
163
- throttleMs
164
- });
165
- }
166
- }
167
- });
168
- } catch (error) {
169
- this.active.delete(websocketId);
170
- channel.error = {
171
- message: error.message
172
- };
173
- this.context._internal.update();
174
- throw error;
175
- }
176
- }
177
- subscribeAll() {
178
- Object.keys(this.subscriptionConfig).forEach((websocketId)=>{
179
- this.subscribe({
180
- websocketId
181
- }).catch((error)=>{
182
- this.context._internal.lowdefy._internal.handleError(error);
183
- });
184
- });
185
- }
186
- unsubscribe({ websocketId }) {
187
- if (!type.isString(websocketId)) {
188
- throw new Error('Unsubscribe requires a websocketId.');
189
- }
190
- if (!this.active.has(websocketId)) {
191
- return;
192
- }
193
- this.active.delete(websocketId);
194
- if (this.flushTimers[websocketId]) {
195
- clearTimeout(this.flushTimers[websocketId]);
196
- this.flushTimers[websocketId] = null;
197
- }
198
- this.buffers[websocketId] = [];
199
- this.client().unsubscribe({
200
- websocketId
201
- });
202
- this.initChannelState(websocketId);
203
- this.context._internal.update();
204
- }
205
- unsubscribeAll() {
206
- [
207
- ...this.active
208
- ].forEach((websocketId)=>{
209
- this.unsubscribe({
210
- websocketId
211
- });
212
- });
213
- }
214
- async publish({ payload, websocketId }) {
215
- if (!type.isString(websocketId)) {
216
- throw new Error('Publish requires a websocketId.');
217
- }
218
- await this.client().publish({
219
- websocketId,
220
- payload: serializer.serialize(payload ?? {})
221
- });
222
- }
223
- constructor(context){
224
- this.context = context;
225
- this.subscriptionConfig = {};
226
- this.subscriptionEvents = {};
227
- this.buffers = {};
228
- this.flushTimers = {};
229
- this.active = new Set();
230
- this.publish = this.publish.bind(this);
231
- this.subscribe = this.subscribe.bind(this);
232
- this.subscribeAll = this.subscribeAll.bind(this);
233
- this.unsubscribe = this.unsubscribe.bind(this);
234
- this.unsubscribeAll = this.unsubscribeAll.bind(this);
235
- this.context.websockets = {};
236
- (this.context._internal.rootBlock.subscriptions ?? []).forEach((subscription)=>{
237
- this.subscriptionConfig[subscription.websocketId] = subscription;
238
- this.initChannelState(subscription.websocketId);
239
- });
240
- }
241
- };
242
- export default WebSockets;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createAcceptInvitation({ context }) {
16
- return function acceptInvitation(params) {
17
- return context._internal.lowdefy._internal.auth.acceptInvitation(params);
18
- };
19
- }
20
- export default createAcceptInvitation;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createChangePassword({ context }) {
16
- return function changePassword(params) {
17
- return context._internal.lowdefy._internal.auth.changePassword(params);
18
- };
19
- }
20
- export default createChangePassword;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createImpersonateUser({ context }) {
16
- return function impersonateUser(params) {
17
- return context._internal.lowdefy._internal.auth.impersonateUser(params);
18
- };
19
- }
20
- export default createImpersonateUser;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createPasskeyDelete({ context }) {
16
- return function passkeyDelete(params) {
17
- return context._internal.lowdefy._internal.auth.passkeyDelete(params);
18
- };
19
- }
20
- export default createPasskeyDelete;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createPasskeyRegister({ context }) {
16
- return function passkeyRegister(params) {
17
- return context._internal.lowdefy._internal.auth.passkeyRegister(params);
18
- };
19
- }
20
- export default createPasskeyRegister;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createPasskeySignIn({ context }) {
16
- return function passkeySignIn(params) {
17
- return context._internal.lowdefy._internal.auth.passkeySignIn(params);
18
- };
19
- }
20
- export default createPasskeySignIn;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createPhoneNumberSendOtp({ context }) {
16
- return function phoneNumberSendOtp(params) {
17
- return context._internal.lowdefy._internal.auth.phoneNumberSendOtp(params);
18
- };
19
- }
20
- export default createPhoneNumberSendOtp;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createPhoneNumberVerify({ context }) {
16
- return function phoneNumberVerify(params) {
17
- return context._internal.lowdefy._internal.auth.phoneNumberVerify(params);
18
- };
19
- }
20
- export default createPhoneNumberVerify;
@@ -1,23 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createPublish({ context }) {
16
- return function publish({ payload, websocketId }) {
17
- return context._internal.WebSockets.publish({
18
- payload,
19
- websocketId
20
- });
21
- };
22
- }
23
- export default createPublish;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createRequestPasswordReset({ context }) {
16
- return function requestPasswordReset(params) {
17
- return context._internal.lowdefy._internal.auth.requestPasswordReset(params);
18
- };
19
- }
20
- export default createRequestPasswordReset;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createResetPassword({ context }) {
16
- return function resetPassword(params) {
17
- return context._internal.lowdefy._internal.auth.resetPassword(params);
18
- };
19
- }
20
- export default createResetPassword;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createRevokeOtherSessions({ context }) {
16
- return function revokeOtherSessions() {
17
- return context._internal.lowdefy._internal.auth.revokeOtherSessions();
18
- };
19
- }
20
- export default createRevokeOtherSessions;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createSendVerificationEmail({ context }) {
16
- return function sendVerificationEmail(params) {
17
- return context._internal.lowdefy._internal.auth.sendVerificationEmail(params);
18
- };
19
- }
20
- export default createSendVerificationEmail;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createSetActiveOrganization({ context }) {
16
- return function setActiveOrganization(params) {
17
- return context._internal.lowdefy._internal.auth.setActiveOrganization(params);
18
- };
19
- }
20
- export default createSetActiveOrganization;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createSignUp({ context }) {
16
- return function signUp(params) {
17
- return context._internal.lowdefy._internal.auth.signUp(params);
18
- };
19
- }
20
- export default createSignUp;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createStopImpersonating({ context }) {
16
- return function stopImpersonating(params) {
17
- return context._internal.lowdefy._internal.auth.stopImpersonating(params);
18
- };
19
- }
20
- export default createStopImpersonating;
@@ -1,25 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createSubscribe({ actions, arrayIndices, context, event }) {
16
- return function subscribe({ websocketId }) {
17
- return context._internal.WebSockets.subscribe({
18
- actions,
19
- arrayIndices,
20
- event,
21
- websocketId
22
- });
23
- };
24
- }
25
- export default createSubscribe;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createTwoFactorDisable({ context }) {
16
- return function twoFactorDisable(params) {
17
- return context._internal.lowdefy._internal.auth.twoFactorDisable(params);
18
- };
19
- }
20
- export default createTwoFactorDisable;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createTwoFactorEnable({ context }) {
16
- return function twoFactorEnable(params) {
17
- return context._internal.lowdefy._internal.auth.twoFactorEnable(params);
18
- };
19
- }
20
- export default createTwoFactorEnable;
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createTwoFactorVerify({ context }) {
16
- return function twoFactorVerify(params) {
17
- return context._internal.lowdefy._internal.auth.twoFactorVerify(params);
18
- };
19
- }
20
- export default createTwoFactorVerify;
@@ -1,22 +0,0 @@
1
- /*
2
- Copyright 2020-2026 Lowdefy, Inc
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */ function createUnsubscribe({ context }) {
16
- return function unsubscribe({ websocketId }) {
17
- return context._internal.WebSockets.unsubscribe({
18
- websocketId
19
- });
20
- };
21
- }
22
- export default createUnsubscribe;