@lowdefy/api 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/context/createEvaluateOperators.js +3 -1
  2. package/dist/context/getCurrentEnvironment.js +27 -0
  3. package/dist/index.js +2 -1
  4. package/dist/response/buildEndpointResult.js +3 -1
  5. package/dist/response/createWireProjection.js +88 -0
  6. package/dist/response/normalizeErrorSources.js +10 -13
  7. package/dist/response/redactErrorResponse.js +42 -8
  8. package/dist/response/redactResponse.js +10 -10
  9. package/dist/routes/agent/prepareAgent.js +6 -0
  10. package/dist/routes/auth/defaultAuthUrl.js +31 -0
  11. package/dist/routes/auth/getAuthConfig.js +5 -1
  12. package/dist/routes/endpoints/callEndpoint.js +1 -0
  13. package/dist/routes/endpoints/control/controlFor.js +4 -7
  14. package/dist/routes/endpoints/control/controlIf.js +4 -8
  15. package/dist/routes/endpoints/control/controlLog.js +6 -14
  16. package/dist/routes/endpoints/control/controlParallelFor.js +4 -7
  17. package/dist/routes/endpoints/control/controlReject.js +13 -15
  18. package/dist/routes/endpoints/control/controlReturn.js +4 -9
  19. package/dist/routes/endpoints/control/controlSetState.js +4 -8
  20. package/dist/routes/endpoints/control/controlSwitch.js +4 -8
  21. package/dist/routes/endpoints/control/controlThrow.js +17 -19
  22. package/dist/routes/endpoints/control/controlTry.js +20 -10
  23. package/dist/routes/endpoints/evaluateRoutineOperators.js +26 -0
  24. package/dist/routes/endpoints/forwardScheduledEndpoint.js +19 -14
  25. package/dist/routes/endpoints/getEnvironmentSchedules.js +5 -7
  26. package/dist/routes/endpoints/handleAgentCall.js +4 -7
  27. package/dist/routes/endpoints/handleEndpointCall.js +4 -7
  28. package/dist/routes/endpoints/handleRenderNotification.js +15 -8
  29. package/dist/routes/endpoints/handleRequest.js +1 -5
  30. package/dist/routes/endpoints/handleValidateSchema.js +12 -10
  31. package/dist/routes/endpoints/invokeEndpoint.js +1 -0
  32. package/dist/routes/endpoints/operatorScope.js +27 -0
  33. package/dist/routes/endpoints/resolveCronEnvironment.js +7 -6
  34. package/dist/routes/endpoints/runDetachedEndpoint.js +1 -0
  35. package/dist/routes/endpoints/runScheduledEndpoint.js +1 -0
  36. package/dist/routes/endpoints/runWebhookEndpoint.js +1 -0
  37. package/dist/routes/endpoints/test/runTest.js +17 -2
  38. package/dist/routes/mcp/createMcpServer.js +20 -2
  39. package/dist/routes/request/callRequest.js +9 -3
  40. package/dist/routes/request/callRequestResolver.js +6 -0
  41. package/dist/routes/request/evaluateOperators.js +8 -12
  42. package/dist/routes/websocket/createChannelRegistry.js +19 -5
  43. package/dist/routes/websocket/createWebSocketConnection.js +15 -3
  44. package/dist/test/testContext.js +4 -2
  45. package/package.json +9 -9
  46. package/dist/response/omitErrorProps.js +0 -51
@@ -13,6 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import { type } from '@lowdefy/helpers';
16
+ import redactErrorResponse from '../../response/redactErrorResponse.js';
16
17
  // Wraps one client websocket connection: parses frames, dispatches
17
18
  // subscribe/unsubscribe/publish to the channel registry, and answers every
18
19
  // frame with an ack or an error so client actions never hang.
@@ -21,7 +22,10 @@ function createWebSocketConnection(context, { registry, send }) {
21
22
  const subscriber = {
22
23
  id: context.rid,
23
24
  subscriptions: new Map(),
24
- send
25
+ send,
26
+ // A shared channel broadcasts to every subscriber, so each one carries its
27
+ // own locale for the error message it is sent.
28
+ i18n: context.i18n
25
29
  };
26
30
  function sendError({ message, requestId, websocketId }) {
27
31
  send(JSON.stringify({
@@ -31,6 +35,14 @@ function createWebSocketConnection(context, { registry, send }) {
31
35
  message
32
36
  }));
33
37
  }
38
+ function sendErrorPayload({ error, requestId, websocketId }) {
39
+ send(JSON.stringify({
40
+ type: 'error',
41
+ websocketId,
42
+ requestId,
43
+ error: redactErrorResponse(context, error)
44
+ }));
45
+ }
34
46
  async function handleFrame(frame) {
35
47
  const { payload, requestId, websocketId } = frame;
36
48
  if (!type.isString(websocketId)) {
@@ -104,8 +116,8 @@ function createWebSocketConnection(context, { registry, send }) {
104
116
  err: error
105
117
  }, error.message);
106
118
  context.handleError(error);
107
- sendError({
108
- message: error.message,
119
+ sendErrorPayload({
120
+ error,
109
121
  requestId: frame.requestId,
110
122
  websocketId: frame.websocketId
111
123
  });
@@ -18,9 +18,9 @@ function testContext({ appMeta = {}, config = {}, configDirectory, connections =
18
18
  error: ()=>{},
19
19
  info: ()=>{},
20
20
  warn: ()=>{}
21
- }, operators = {
21
+ }, mode = 'prod', operators = {
22
22
  _test: ()=>'test'
23
- }, readConfigFile, secrets = {}, session, system } = {}) {
23
+ }, readConfigFile, scrubSecrets = (value)=>value, secrets = {}, session, system } = {}) {
24
24
  return {
25
25
  appMeta,
26
26
  authorize: createAuthorize({
@@ -39,8 +39,10 @@ function testContext({ appMeta = {}, config = {}, configDirectory, connections =
39
39
  },
40
40
  headers,
41
41
  logger,
42
+ mode,
42
43
  operators,
43
44
  readConfigFile,
45
+ scrubSecrets,
44
46
  secrets,
45
47
  session,
46
48
  steps: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/api",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "",
6
6
  "homepage": "https://lowdefy.com",
@@ -34,14 +34,14 @@
34
34
  "dist/*"
35
35
  ],
36
36
  "dependencies": {
37
- "@lowdefy/ajv": "6.0.0",
38
- "@lowdefy/build": "6.0.0",
39
- "@lowdefy/errors": "6.0.0",
40
- "@lowdefy/helpers": "6.0.0",
41
- "@lowdefy/node-utils": "6.0.0",
42
- "@lowdefy/nunjucks": "6.0.0",
43
- "@lowdefy/operators": "6.0.0",
44
- "@lowdefy/operators-js": "6.0.0",
37
+ "@lowdefy/ajv": "6.1.0",
38
+ "@lowdefy/build": "6.1.0",
39
+ "@lowdefy/errors": "6.1.0",
40
+ "@lowdefy/helpers": "6.1.0",
41
+ "@lowdefy/node-utils": "6.1.0",
42
+ "@lowdefy/nunjucks": "6.1.0",
43
+ "@lowdefy/operators": "6.1.0",
44
+ "@lowdefy/operators-js": "6.1.0",
45
45
  "@modelcontextprotocol/sdk": "1.29.0"
46
46
  },
47
47
  "devDependencies": {
@@ -1,51 +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 { UserError } from '@lowdefy/errors';
16
- import { type } from '@lowdefy/helpers';
17
- // The client-bound error policy: which fields of an error may cross the wire.
18
- // Passed to serializer.serialize as `omitErrorProps`, so extractErrorProps applies
19
- // it at EVERY error node the walk emits - the cause chain, an Error-valued own
20
- // property, and an Error nested inside a plain object or array. The policy is
21
- // stated against the emitter rather than against a response shape, so it cannot
22
- // become depth-limited.
23
- //
24
- // `received` is not merely "may be sensitive": on the request path
25
- // callRequestResolver sets it to the EVALUATED request properties, so a _secret
26
- // resolved into a request header is in it. `stack` exposes server internals,
27
- // including absolute node_modules paths. Both are unbounded runtime data nobody
28
- // chose, in every environment - the full value stays in the server log, which is
29
- // where a developer on their own machine reads it.
30
- const ALWAYS_OMITTED = [
31
- 'received',
32
- 'stack'
33
- ];
34
- const OMITTED_WITH_CAUSE = [
35
- ...ALWAYS_OMITTED,
36
- 'cause'
37
- ];
38
- function omitErrorProps(error) {
39
- // An Error cause is the trace the browser renders (name + message per level),
40
- // so it is always kept - fields are taken from causes, causes are never pruned.
41
- // A non-Error cause is internal server config: the whole endpoint routine, a
42
- // control node, ajv errors. UserError is the exception, the one class whose
43
- // payload the author wrote for the client.
44
- //
45
- // type.isError is `instanceof Error`, the same test extractErrorProps uses to
46
- // decide which branch emits the cause - the two must agree.
47
- if (type.isError(error.cause)) return ALWAYS_OMITTED;
48
- if (error instanceof UserError) return ALWAYS_OMITTED;
49
- return OMITTED_WITH_CAUSE;
50
- }
51
- export default omitErrorProps;