@lowdefy/build 5.5.1 → 6.0.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 (107) hide show
  1. package/dist/build/buildAgents.js +70 -17
  2. package/dist/build/buildApi/buildApi.js +4 -1
  3. package/dist/build/buildApi/buildEndpoint.js +8 -2
  4. package/dist/build/buildApi/buildRoutine/countStepTypes.js +1 -1
  5. package/dist/build/buildApi/buildRoutine/setStepId.js +2 -0
  6. package/dist/build/buildApi/buildRoutine/validateStep.js +61 -0
  7. package/dist/build/buildApi/resolveEndpointSchedules.js +37 -0
  8. package/dist/build/buildApi/validateEndpoint.js +96 -1
  9. package/dist/build/buildApp.js +13 -20
  10. package/dist/build/buildAppMeta.js +130 -0
  11. package/dist/build/buildAuth/buildAgentAuth.js +69 -0
  12. package/dist/build/buildAuth/buildAuth.js +14 -0
  13. package/dist/build/buildAuth/buildAuthPlugins.js +6 -0
  14. package/dist/build/buildAuth/buildAuthStrategies.js +117 -0
  15. package/dist/build/buildAuth/buildWebsocketAuth.js +55 -0
  16. package/dist/build/buildAuth/getAgentRoles.js +39 -0
  17. package/dist/build/buildAuth/getProtectedAgents.js +29 -0
  18. package/dist/build/buildAuth/getProtectedWebsockets.js +29 -0
  19. package/dist/build/buildAuth/getWebsocketRoles.js +39 -0
  20. package/dist/build/buildAuth/rejectReservedEntityIds.js +52 -0
  21. package/dist/build/buildAuth/validateAuthConfig.js +15 -3
  22. package/dist/build/buildImports/buildImportsDev.js +15 -0
  23. package/dist/build/buildImports/buildImportsProd.js +4 -1
  24. package/dist/build/buildJs/generateClientJsModule.js +27 -0
  25. package/dist/build/buildJs/writeJs.js +3 -5
  26. package/dist/build/buildMcp.js +73 -0
  27. package/dist/build/buildModuleDefs.js +90 -48
  28. package/dist/build/buildModules.js +61 -14
  29. package/dist/build/buildNotifications.js +98 -0
  30. package/dist/build/buildPages/buildBlock/buildBlock.js +3 -1
  31. package/dist/build/buildPages/buildBlock/buildDynamicBlock.js +131 -0
  32. package/dist/build/buildPages/buildBlock/buildEvents.js +197 -22
  33. package/dist/build/buildPages/buildBlock/buildRequests.js +9 -0
  34. package/dist/build/buildPages/buildBlock/normalizeClassAndStyles.js +2 -11
  35. package/dist/build/buildPages/buildBlock/setBlockId.js +5 -2
  36. package/dist/build/buildPages/buildBlock/validateBlock.js +19 -1
  37. package/dist/build/buildPages/buildPage.js +27 -3
  38. package/dist/build/buildPages/buildSubscriptions.js +145 -0
  39. package/dist/build/buildPages/validateDynamicBlockRefs.js +30 -0
  40. package/dist/build/buildPages/validateStateReferences.js +4 -2
  41. package/dist/build/buildPages/validateWebsocketRefs.js +30 -0
  42. package/dist/build/buildRefs/buildRefs.js +21 -12
  43. package/dist/build/buildRefs/cloneWithMarkers.js +57 -0
  44. package/dist/build/buildRefs/deferredRegions.js +80 -0
  45. package/dist/build/buildRefs/deferredRegistry.js +292 -0
  46. package/dist/build/buildRefs/getKey.js +16 -5
  47. package/dist/build/buildRefs/getModuleRefContent.js +21 -6
  48. package/dist/build/buildRefs/getUserJavascriptFunction.js +1 -1
  49. package/dist/build/buildRefs/parseRefContent.js +24 -0
  50. package/dist/build/buildRefs/{evaluateStaticOperators.js → precomputeRuntimeOperators.js} +7 -6
  51. package/dist/build/buildRefs/walker.js +490 -209
  52. package/dist/build/buildTypes.js +22 -1
  53. package/dist/build/buildWebsockets.js +99 -0
  54. package/dist/build/collectPageContent.js +7 -1
  55. package/dist/build/copyAgentFileSystems.js +2 -2
  56. package/dist/build/fetchModules.js +18 -4
  57. package/dist/build/full/buildPages.js +16 -0
  58. package/dist/build/full/updateServerPackageJson.js +21 -0
  59. package/dist/build/jit/buildPageJit.js +46 -6
  60. package/dist/build/jit/collectSkeletonSourceFiles.js +14 -0
  61. package/dist/build/jit/pageContentKeys.js +1 -0
  62. package/dist/build/jit/shallowBuild.js +81 -1
  63. package/dist/build/jit/writePageJit.js +11 -8
  64. package/dist/build/registerModules.js +149 -42
  65. package/dist/build/validateCallAgentSteps.js +58 -0
  66. package/dist/build/validateConfig.js +4 -0
  67. package/dist/build/validateCronConfig.js +110 -0
  68. package/dist/build/validateRenderNotificationSteps.js +50 -0
  69. package/dist/build/writeApi.js +58 -1
  70. package/dist/build/writeI18n.js +8 -1
  71. package/dist/build/writeMcp.js +21 -0
  72. package/dist/build/writeNotifications.js +30 -0
  73. package/dist/build/writePluginImports/importPluginModule.js +39 -0
  74. package/dist/build/writePluginImports/writeActionSchemaMap.js +6 -7
  75. package/dist/build/writePluginImports/writeAuthImports.js +4 -0
  76. package/dist/build/writePluginImports/writeAvailableTypes.js +99 -0
  77. package/dist/build/writePluginImports/writeBlockSchemaMap.js +10 -9
  78. package/dist/build/writePluginImports/writeConnectionSchemaMap.js +101 -0
  79. package/dist/build/writePluginImports/writeGlobalsCss.js +20 -11
  80. package/dist/build/writePluginImports/writeNotificationImports.js +31 -0
  81. package/dist/build/writePluginImports/writeOperatorSchemaMap.js +6 -7
  82. package/dist/build/writePluginImports/writePluginImports.js +18 -4
  83. package/dist/build/writePluginImports/writeWebsocketImports.js +22 -0
  84. package/dist/build/writeWebsockets.js +30 -0
  85. package/dist/createContext.js +6 -1
  86. package/dist/defaultPackages.js +7 -1
  87. package/dist/defaultTypesMap.js +689 -386
  88. package/dist/dynamic/buildDynamicBlocks.js +120 -0
  89. package/dist/index.js +78 -8
  90. package/dist/indexDev.js +4 -0
  91. package/dist/lowdefySchema.js +861 -6
  92. package/dist/scripts/generateDefaultTypes.js +5 -2
  93. package/dist/test-utils/expectTerminates.js +33 -0
  94. package/dist/test-utils/runBuild.js +20 -1
  95. package/dist/test-utils/runBuildForSnapshots.js +34 -4
  96. package/dist/test-utils/testContext.js +8 -2
  97. package/dist/utils/countOperators.js +5 -17
  98. package/dist/utils/createPluginTypesMap.js +21 -0
  99. package/dist/utils/getCronEnvironmentNames.js +25 -0
  100. package/dist/utils/logCollectedErrors.js +44 -10
  101. package/dist/utils/serializeBuildException.js +29 -0
  102. package/dist/utils/validateCronExpression.js +131 -0
  103. package/dist/utils/validateId.js +11 -0
  104. package/dist/utils/writeBuildArtifact.js +5 -2
  105. package/package.json +66 -59
  106. package/dist/build/writePluginImports/writeServerExternalPackages.js +0 -121
  107. /package/dist/build/{resolveModuleOperators.js → buildRefs/scopeMenuItemIds.js} +0 -0
@@ -1,3 +1,47 @@
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
+ */ const apiScheduleSchema = {
16
+ type: 'object',
17
+ additionalProperties: false,
18
+ required: [
19
+ 'cron'
20
+ ],
21
+ properties: {
22
+ '~k': {},
23
+ '~r': {},
24
+ '~l': {},
25
+ cron: {
26
+ type: 'string',
27
+ errorMessage: {
28
+ type: 'Api endpoint "schedules[].cron" should be a cron expression string.'
29
+ }
30
+ },
31
+ payload: {
32
+ type: 'object',
33
+ errorMessage: {
34
+ type: 'Api endpoint "schedules[].payload" should be an object.'
35
+ }
36
+ }
37
+ },
38
+ errorMessage: {
39
+ type: 'Api endpoint "schedules[]" should be an object.',
40
+ required: {
41
+ cron: 'Api endpoint schedule should have required property "cron".'
42
+ }
43
+ }
44
+ };
1
45
  export default {
2
46
  $schema: 'http://json-schema.org/draft-07/schema#',
3
47
  $id: 'http://lowdefy.com/appSchema.json',
@@ -67,6 +111,132 @@ export default {
67
111
  }
68
112
  }
69
113
  },
114
+ actionOrControl: {
115
+ anyOf: [
116
+ {
117
+ $ref: '#/definitions/action'
118
+ },
119
+ {
120
+ $ref: '#/definitions/controlIf'
121
+ },
122
+ {
123
+ $ref: '#/definitions/controlSwitch'
124
+ },
125
+ {
126
+ $ref: '#/definitions/controlReturn'
127
+ }
128
+ ]
129
+ },
130
+ controlIf: {
131
+ type: 'object',
132
+ additionalProperties: false,
133
+ required: [
134
+ ':if',
135
+ ':then'
136
+ ],
137
+ properties: {
138
+ '~r': {},
139
+ '~l': {},
140
+ ':if': {},
141
+ ':then': {
142
+ type: 'array',
143
+ items: {
144
+ $ref: '#/definitions/actionOrControl'
145
+ },
146
+ errorMessage: {
147
+ type: 'Control ":then" should be an array of actions.'
148
+ }
149
+ },
150
+ ':else': {
151
+ type: 'array',
152
+ items: {
153
+ $ref: '#/definitions/actionOrControl'
154
+ },
155
+ errorMessage: {
156
+ type: 'Control ":else" should be an array of actions.'
157
+ }
158
+ }
159
+ },
160
+ errorMessage: {
161
+ type: 'Control ":if" should be an object.',
162
+ required: {
163
+ ':then': 'Control ":if" should have required property ":then".'
164
+ }
165
+ }
166
+ },
167
+ controlReturn: {
168
+ type: 'object',
169
+ additionalProperties: false,
170
+ required: [
171
+ ':return'
172
+ ],
173
+ properties: {
174
+ '~r': {},
175
+ '~l': {},
176
+ ':return': {}
177
+ },
178
+ errorMessage: {
179
+ type: 'Control ":return" should be an object.'
180
+ }
181
+ },
182
+ controlSwitch: {
183
+ type: 'object',
184
+ additionalProperties: false,
185
+ required: [
186
+ ':switch'
187
+ ],
188
+ properties: {
189
+ '~r': {},
190
+ '~l': {},
191
+ ':switch': {
192
+ type: 'array',
193
+ items: {
194
+ type: 'object',
195
+ additionalProperties: false,
196
+ required: [
197
+ ':case',
198
+ ':then'
199
+ ],
200
+ properties: {
201
+ '~r': {},
202
+ '~l': {},
203
+ ':case': {},
204
+ ':then': {
205
+ type: 'array',
206
+ items: {
207
+ $ref: '#/definitions/actionOrControl'
208
+ },
209
+ errorMessage: {
210
+ type: 'Control ":then" should be an array of actions.'
211
+ }
212
+ }
213
+ },
214
+ errorMessage: {
215
+ type: 'Control ":switch" cases should be objects.',
216
+ required: {
217
+ ':case': 'Control ":switch" case should have required property ":case".',
218
+ ':then': 'Control ":switch" case should have required property ":then".'
219
+ }
220
+ }
221
+ },
222
+ errorMessage: {
223
+ type: 'Control ":switch" should be an array of case objects.'
224
+ }
225
+ },
226
+ ':default': {
227
+ type: 'array',
228
+ items: {
229
+ $ref: '#/definitions/actionOrControl'
230
+ },
231
+ errorMessage: {
232
+ type: 'Control ":default" should be an array of actions.'
233
+ }
234
+ }
235
+ },
236
+ errorMessage: {
237
+ type: 'Control ":switch" should be an object.'
238
+ }
239
+ },
70
240
  agent: {
71
241
  type: 'object',
72
242
  additionalProperties: false,
@@ -141,6 +311,9 @@ export default {
141
311
  endpointId: {
142
312
  type: 'string'
143
313
  },
314
+ name: {
315
+ type: 'string'
316
+ },
144
317
  confirm: {
145
318
  const: true
146
319
  }
@@ -265,6 +438,9 @@ export default {
265
438
  agentId: {
266
439
  type: 'string'
267
440
  },
441
+ name: {
442
+ type: 'string'
443
+ },
268
444
  description: {
269
445
  type: 'string'
270
446
  },
@@ -319,6 +495,44 @@ export default {
319
495
  },
320
496
  '~r': {},
321
497
  '~l': {},
498
+ email: {
499
+ type: 'object',
500
+ errorMessage: {
501
+ type: 'App "app.email" should be an object.'
502
+ },
503
+ properties: {
504
+ logo: {
505
+ type: 'string',
506
+ errorMessage: {
507
+ type: 'App "app.email.logo" should be a string.'
508
+ }
509
+ },
510
+ companyName: {
511
+ type: 'string',
512
+ errorMessage: {
513
+ type: 'App "app.email.companyName" should be a string.'
514
+ }
515
+ },
516
+ primaryColor: {
517
+ type: 'string',
518
+ errorMessage: {
519
+ type: 'App "app.email.primaryColor" should be a string.'
520
+ }
521
+ },
522
+ signature: {
523
+ type: 'string',
524
+ errorMessage: {
525
+ type: 'App "app.email.signature" should be a string.'
526
+ }
527
+ },
528
+ footer: {
529
+ type: 'string',
530
+ errorMessage: {
531
+ type: 'App "app.email.footer" should be a string.'
532
+ }
533
+ }
534
+ }
535
+ },
322
536
  html: {
323
537
  type: 'object',
324
538
  errorMessage: {
@@ -376,6 +590,12 @@ export default {
376
590
  advanced: {
377
591
  type: 'object',
378
592
  properties: {
593
+ cookiePrefix: {
594
+ type: 'string',
595
+ errorMessage: {
596
+ type: 'Auth "advanced.cookiePrefix" should be a string.'
597
+ }
598
+ },
379
599
  cookies: {
380
600
  type: 'object'
381
601
  }
@@ -495,6 +715,89 @@ export default {
495
715
  }
496
716
  }
497
717
  },
718
+ websockets: {
719
+ type: 'object',
720
+ additionalProperties: false,
721
+ errorMessage: {
722
+ type: 'App "config.auth.websockets" should be an object.'
723
+ },
724
+ properties: {
725
+ '~ignoreBuildChecks': {
726
+ oneOf: [
727
+ {
728
+ const: true
729
+ },
730
+ {
731
+ type: 'array',
732
+ items: {
733
+ type: 'string',
734
+ enum: [
735
+ 'state-refs',
736
+ 'payload-refs',
737
+ 'step-refs',
738
+ 'link-refs',
739
+ 'request-refs',
740
+ 'connection-refs',
741
+ 'types',
742
+ 'schema'
743
+ ]
744
+ }
745
+ }
746
+ ]
747
+ },
748
+ '~r': {},
749
+ '~l': {},
750
+ protected: {
751
+ type: [
752
+ 'array',
753
+ 'boolean'
754
+ ],
755
+ errorMessage: {
756
+ type: 'App "auth.websockets.protected.$" should be an array of strings.'
757
+ },
758
+ items: {
759
+ type: 'string',
760
+ description: 'Websocket ids for which authentication is required. When specified, all unspecified websockets will be public.',
761
+ errorMessage: {
762
+ type: 'App "auth.websockets.protected.$" should be an array of strings.'
763
+ }
764
+ }
765
+ },
766
+ public: {
767
+ type: [
768
+ 'array',
769
+ 'boolean'
770
+ ],
771
+ errorMessage: {
772
+ type: 'App "auth.websockets.public.$" should be an array of strings.'
773
+ },
774
+ items: {
775
+ type: 'string',
776
+ description: 'Websocket ids for which authentication is not required. When specified, all unspecified websockets will be protected.',
777
+ errorMessage: {
778
+ type: 'App "auth.websockets.public.$" should be an array of strings.'
779
+ }
780
+ }
781
+ },
782
+ roles: {
783
+ type: 'object',
784
+ patternProperties: {
785
+ '^.*$': {
786
+ type: 'array',
787
+ items: {
788
+ type: 'string'
789
+ },
790
+ errorMessage: {
791
+ type: 'App "auth.websockets.roles.[role]" should be an array of strings.'
792
+ }
793
+ }
794
+ },
795
+ errorMessage: {
796
+ type: 'App "auth.websockets.roles" should be an object.'
797
+ }
798
+ }
799
+ }
800
+ },
498
801
  authPages: {
499
802
  type: 'object',
500
803
  additionalProperties: false,
@@ -743,6 +1046,68 @@ export default {
743
1046
  session: {
744
1047
  type: 'object'
745
1048
  },
1049
+ strategies: {
1050
+ type: 'array',
1051
+ errorMessage: {
1052
+ type: 'Auth "strategies" should be an array.'
1053
+ },
1054
+ items: {
1055
+ type: 'object',
1056
+ additionalProperties: false,
1057
+ required: [
1058
+ 'id',
1059
+ 'type'
1060
+ ],
1061
+ properties: {
1062
+ '~ignoreBuildChecks': {},
1063
+ '~r': {},
1064
+ '~l': {},
1065
+ id: {
1066
+ type: 'string',
1067
+ errorMessage: {
1068
+ type: 'Auth strategy "id" should be a string.'
1069
+ }
1070
+ },
1071
+ type: {
1072
+ type: 'string',
1073
+ errorMessage: {
1074
+ type: 'Auth strategy "type" should be a string.'
1075
+ }
1076
+ },
1077
+ properties: {
1078
+ type: 'object',
1079
+ errorMessage: {
1080
+ type: 'Auth strategy "properties" should be an object.'
1081
+ }
1082
+ },
1083
+ roles: {
1084
+ type: 'array',
1085
+ items: {
1086
+ type: 'string',
1087
+ errorMessage: {
1088
+ type: 'Auth strategy "roles" should be an array of role names.'
1089
+ }
1090
+ },
1091
+ errorMessage: {
1092
+ type: 'Auth strategy "roles" should be an array of role names.'
1093
+ }
1094
+ },
1095
+ attributes: {
1096
+ type: 'object',
1097
+ errorMessage: {
1098
+ type: 'Auth strategy "attributes" should be an object.'
1099
+ }
1100
+ }
1101
+ },
1102
+ errorMessage: {
1103
+ type: 'Auth strategy should be an object.',
1104
+ required: {
1105
+ id: 'Auth strategy should have required property "id".',
1106
+ type: 'Auth strategy should have required property "type".'
1107
+ }
1108
+ }
1109
+ }
1110
+ },
746
1111
  theme: {
747
1112
  type: 'object'
748
1113
  },
@@ -888,11 +1253,20 @@ export default {
888
1253
  type: 'Block "requests" should be an array.'
889
1254
  }
890
1255
  },
891
- required: {},
892
- validate: {
1256
+ subscriptions: {
893
1257
  type: 'array',
894
1258
  items: {
895
- type: 'object',
1259
+ $ref: '#/definitions/subscription'
1260
+ },
1261
+ errorMessage: {
1262
+ type: 'Page "subscriptions" should be an array.'
1263
+ }
1264
+ },
1265
+ required: {},
1266
+ validate: {
1267
+ type: 'array',
1268
+ items: {
1269
+ type: 'object',
896
1270
  errorMessage: {
897
1271
  type: 'Block "validate" should be an array of objects.'
898
1272
  }
@@ -909,7 +1283,7 @@ export default {
909
1283
  {
910
1284
  type: 'array',
911
1285
  items: {
912
- $ref: '#/definitions/action'
1286
+ $ref: '#/definitions/actionOrControl'
913
1287
  }
914
1288
  },
915
1289
  {
@@ -944,13 +1318,13 @@ export default {
944
1318
  try: {
945
1319
  type: 'array',
946
1320
  items: {
947
- $ref: '#/definitions/action'
1321
+ $ref: '#/definitions/actionOrControl'
948
1322
  }
949
1323
  },
950
1324
  catch: {
951
1325
  type: 'array',
952
1326
  items: {
953
- $ref: '#/definitions/action'
1327
+ $ref: '#/definitions/actionOrControl'
954
1328
  }
955
1329
  },
956
1330
  debounce: {
@@ -1155,6 +1529,270 @@ export default {
1155
1529
  }
1156
1530
  }
1157
1531
  ]
1532
+ },
1533
+ async: {
1534
+ type: 'boolean',
1535
+ description: 'Run the endpoint routine in the background. The endpoint returns { accepted: true } immediately and the routine runs after the response (kept alive via the platform request context on Vercel fluid compute, still bounded by the function maxDuration); the outcome is observable only through logs and whatever the routine writes.',
1536
+ errorMessage: {
1537
+ type: 'Api endpoint "async" should be a boolean.'
1538
+ }
1539
+ },
1540
+ webhook: {
1541
+ type: 'boolean',
1542
+ description: 'Make this endpoint a third-party webhook receiver (SNS, Event Grid, Stripe, ...). It stays on the standard POST /api/endpoints/<endpointId> route but takes the request RAW: the routine receives { body, query, headers } as payload (no { payload } envelope), runs as a system context, must authenticate the caller itself (shared-secret query param or signature), and its return value is sent back verbatim as the response body — webhook handshakes require exact response shapes.',
1543
+ errorMessage: {
1544
+ type: 'Api endpoint "webhook" should be a boolean.'
1545
+ }
1546
+ },
1547
+ schedules: {
1548
+ description: 'Cron schedules that run the routine on a timer: an array (the same in every environment), or with config.cron.environments declared an object keyed by environment name with an optional "default" key that every other environment inherits ("staging: []" turns crons off for staging).',
1549
+ anyOf: [
1550
+ {
1551
+ type: 'array',
1552
+ items: apiScheduleSchema,
1553
+ errorMessage: {
1554
+ type: 'Api endpoint "schedules" should be an array or an object keyed by environment.'
1555
+ }
1556
+ },
1557
+ {
1558
+ type: 'object',
1559
+ properties: {
1560
+ '~k': {},
1561
+ '~r': {},
1562
+ '~l': {}
1563
+ },
1564
+ additionalProperties: {
1565
+ type: 'array',
1566
+ items: apiScheduleSchema,
1567
+ errorMessage: {
1568
+ type: 'Api endpoint "schedules.<environment>" should be an array.'
1569
+ }
1570
+ },
1571
+ errorMessage: {
1572
+ type: 'Api endpoint "schedules" should be an array or an object keyed by environment.'
1573
+ }
1574
+ }
1575
+ ]
1576
+ }
1577
+ }
1578
+ },
1579
+ websocket: {
1580
+ type: 'object',
1581
+ additionalProperties: false,
1582
+ required: [
1583
+ 'id',
1584
+ 'type'
1585
+ ],
1586
+ properties: {
1587
+ '~ignoreBuildChecks': {
1588
+ oneOf: [
1589
+ {
1590
+ const: true
1591
+ },
1592
+ {
1593
+ type: 'array',
1594
+ items: {
1595
+ type: 'string',
1596
+ enum: [
1597
+ 'state-refs',
1598
+ 'payload-refs',
1599
+ 'step-refs',
1600
+ 'link-refs',
1601
+ 'request-refs',
1602
+ 'connection-refs',
1603
+ 'types',
1604
+ 'schema'
1605
+ ]
1606
+ }
1607
+ }
1608
+ ]
1609
+ },
1610
+ '~r': {},
1611
+ '~l': {},
1612
+ id: {
1613
+ type: 'string',
1614
+ errorMessage: {
1615
+ type: 'Websocket "id" should be a string.'
1616
+ }
1617
+ },
1618
+ type: {
1619
+ type: 'string',
1620
+ errorMessage: {
1621
+ type: 'Websocket "type" should be a string.'
1622
+ }
1623
+ },
1624
+ connectionId: {
1625
+ type: 'string',
1626
+ errorMessage: {
1627
+ type: 'Websocket "connectionId" should be a string.'
1628
+ }
1629
+ },
1630
+ properties: {
1631
+ type: 'object',
1632
+ errorMessage: {
1633
+ type: 'Websocket "properties" should be an object.'
1634
+ }
1635
+ }
1636
+ },
1637
+ errorMessage: {
1638
+ type: 'Websocket should be an object.',
1639
+ required: {
1640
+ id: 'Websocket should have required property "id".',
1641
+ type: 'Websocket should have required property "type".'
1642
+ }
1643
+ }
1644
+ },
1645
+ notification: {
1646
+ type: 'object',
1647
+ additionalProperties: false,
1648
+ required: [
1649
+ 'id',
1650
+ 'type'
1651
+ ],
1652
+ properties: {
1653
+ '~ignoreBuildChecks': {
1654
+ oneOf: [
1655
+ {
1656
+ const: true
1657
+ },
1658
+ {
1659
+ type: 'array',
1660
+ items: {
1661
+ type: 'string',
1662
+ enum: [
1663
+ 'state-refs',
1664
+ 'payload-refs',
1665
+ 'step-refs',
1666
+ 'link-refs',
1667
+ 'request-refs',
1668
+ 'connection-refs',
1669
+ 'types',
1670
+ 'schema'
1671
+ ]
1672
+ }
1673
+ }
1674
+ ]
1675
+ },
1676
+ '~r': {},
1677
+ '~l': {},
1678
+ id: {
1679
+ type: 'string',
1680
+ errorMessage: {
1681
+ type: 'Notification "id" should be a string.'
1682
+ }
1683
+ },
1684
+ type: {
1685
+ type: 'string',
1686
+ errorMessage: {
1687
+ type: 'Notification "type" should be a string.'
1688
+ }
1689
+ },
1690
+ theme: {
1691
+ type: 'object',
1692
+ errorMessage: {
1693
+ type: 'Notification "theme" should be an object.'
1694
+ }
1695
+ },
1696
+ testData: {
1697
+ type: 'object',
1698
+ errorMessage: {
1699
+ type: 'Notification "testData" should be an object.'
1700
+ }
1701
+ },
1702
+ properties: {
1703
+ type: 'object',
1704
+ errorMessage: {
1705
+ type: 'Notification "properties" should be an object.'
1706
+ }
1707
+ }
1708
+ },
1709
+ errorMessage: {
1710
+ type: 'Notification should be an object.',
1711
+ required: {
1712
+ id: 'Notification should have required property "id".',
1713
+ type: 'Notification should have required property "type".'
1714
+ }
1715
+ }
1716
+ },
1717
+ subscription: {
1718
+ type: 'object',
1719
+ additionalProperties: false,
1720
+ required: [
1721
+ 'websocketId'
1722
+ ],
1723
+ properties: {
1724
+ '~ignoreBuildChecks': {
1725
+ oneOf: [
1726
+ {
1727
+ const: true
1728
+ },
1729
+ {
1730
+ type: 'array',
1731
+ items: {
1732
+ type: 'string',
1733
+ enum: [
1734
+ 'state-refs',
1735
+ 'payload-refs',
1736
+ 'step-refs',
1737
+ 'link-refs',
1738
+ 'request-refs',
1739
+ 'connection-refs',
1740
+ 'types',
1741
+ 'schema'
1742
+ ]
1743
+ }
1744
+ }
1745
+ ]
1746
+ },
1747
+ '~r': {},
1748
+ '~l': {},
1749
+ websocketId: {
1750
+ type: 'string',
1751
+ errorMessage: {
1752
+ type: 'Subscription "websocketId" should be a string.'
1753
+ }
1754
+ },
1755
+ payload: {
1756
+ type: 'object',
1757
+ errorMessage: {
1758
+ type: 'Subscription "payload" should be an object.'
1759
+ }
1760
+ },
1761
+ events: {
1762
+ type: 'object',
1763
+ errorMessage: {
1764
+ type: 'Subscription "events" should be an object.'
1765
+ }
1766
+ },
1767
+ client: {
1768
+ type: 'object',
1769
+ additionalProperties: false,
1770
+ properties: {
1771
+ '~r': {},
1772
+ '~l': {},
1773
+ maxMessages: {
1774
+ type: 'integer',
1775
+ minimum: 1,
1776
+ errorMessage: {
1777
+ type: 'Subscription "client.maxMessages" should be a positive integer.'
1778
+ }
1779
+ },
1780
+ throttleRender: {
1781
+ type: 'number',
1782
+ errorMessage: {
1783
+ type: 'Subscription "client.throttleRender" should be a number.'
1784
+ }
1785
+ }
1786
+ },
1787
+ errorMessage: {
1788
+ type: 'Subscription "client" should be an object.'
1789
+ }
1790
+ }
1791
+ },
1792
+ errorMessage: {
1793
+ type: 'Subscription should be an object.',
1794
+ required: {
1795
+ websocketId: 'Subscription should have required property "websocketId".'
1158
1796
  }
1159
1797
  }
1160
1798
  },
@@ -1789,6 +2427,98 @@ export default {
1789
2427
  type: 'App "config.basePath" should be a string.'
1790
2428
  }
1791
2429
  },
2430
+ vercel: {
2431
+ type: 'object',
2432
+ additionalProperties: false,
2433
+ description: 'Vercel deployment function settings, applied by the CLI vercelOutput assembly.',
2434
+ errorMessage: {
2435
+ type: 'App "config.vercel" should be an object.'
2436
+ },
2437
+ properties: {
2438
+ maxDuration: {
2439
+ type: 'number',
2440
+ minimum: 1,
2441
+ description: 'Maximum function execution time in seconds for the deployed serverless function. Defaults to 60. Plan limits apply (Vercel rejects over-limit values at deploy).',
2442
+ errorMessage: {
2443
+ type: 'App "config.vercel.maxDuration" should be a number.'
2444
+ }
2445
+ },
2446
+ memory: {
2447
+ type: 'number',
2448
+ description: 'Function memory in MB. Omit to use the Vercel default.',
2449
+ errorMessage: {
2450
+ type: 'App "config.vercel.memory" should be a number.'
2451
+ }
2452
+ }
2453
+ }
2454
+ },
2455
+ cron: {
2456
+ type: 'object',
2457
+ additionalProperties: false,
2458
+ description: "Deployment environments for scheduled endpoints. Vercel fires cron jobs only on the production deployment, so every environment's schedules are registered there and production forwards the ones for other environments to their own /api/cron route.",
2459
+ required: [
2460
+ 'environments'
2461
+ ],
2462
+ errorMessage: {
2463
+ type: 'App "config.cron" should be an object.',
2464
+ required: {
2465
+ environments: 'App "config.cron" should have required property "environments".'
2466
+ }
2467
+ },
2468
+ properties: {
2469
+ '~k': {},
2470
+ '~r': {},
2471
+ '~l': {},
2472
+ environments: {
2473
+ type: 'object',
2474
+ description: 'Environments keyed by name. Exactly one environment has no "url": the deployment whose crons Vercel fires. Every other environment needs a "url" (its deployment origin) and a "secret" (the Lowdefy secret name holding that environment\'s CRON_SECRET, set on the production deployment).',
2475
+ additionalProperties: {
2476
+ type: 'object',
2477
+ additionalProperties: false,
2478
+ properties: {
2479
+ '~k': {},
2480
+ '~r': {},
2481
+ '~l': {},
2482
+ url: {
2483
+ type: 'string',
2484
+ description: 'The environment deployment origin, e.g. https://staging.example.com.',
2485
+ errorMessage: {
2486
+ type: 'App "config.cron.environments.<name>.url" should be a string.'
2487
+ }
2488
+ },
2489
+ secret: {
2490
+ type: 'string',
2491
+ description: "Lowdefy secret name (LOWDEFY_SECRET_<name> env var) holding this environment's CRON_SECRET.",
2492
+ errorMessage: {
2493
+ type: 'App "config.cron.environments.<name>.secret" should be a string.'
2494
+ }
2495
+ },
2496
+ enabled: {
2497
+ type: 'boolean',
2498
+ description: 'Set false to register no cron jobs for this environment. Defaults to true.',
2499
+ errorMessage: {
2500
+ type: 'App "config.cron.environments.<name>.enabled" should be a boolean.'
2501
+ }
2502
+ }
2503
+ },
2504
+ errorMessage: {
2505
+ type: 'App "config.cron.environments.<name>" should be an object.'
2506
+ }
2507
+ },
2508
+ errorMessage: {
2509
+ type: 'App "config.cron.environments" should be an object.'
2510
+ }
2511
+ }
2512
+ }
2513
+ },
2514
+ requestTimeout: {
2515
+ type: 'number',
2516
+ minimum: 0,
2517
+ description: 'Maximum time in milliseconds a request may run before the server returns a timeout. Protects against hung upstream calls (database, SMTP, external APIs) running to the platform function limit — important on serverless hosts billed by duration. Defaults to 30000 (30s). Set to 0 to disable. Agent streaming routes are exempt.',
2518
+ errorMessage: {
2519
+ type: 'App "config.requestTimeout" should be a number.'
2520
+ }
2521
+ },
1792
2522
  homePageId: {
1793
2523
  type: 'string',
1794
2524
  description: 'Page id to use as homepage. When visiting home route "/", the router will redirect to this page. If not provided, the first page in default or first menu will be used as the homePageId.',
@@ -1927,6 +2657,131 @@ export default {
1927
2657
  type: 'App "api" should be an array.'
1928
2658
  }
1929
2659
  },
2660
+ mcp: {
2661
+ type: 'object',
2662
+ additionalProperties: false,
2663
+ errorMessage: {
2664
+ type: 'App "mcp" should be an object.',
2665
+ additionalProperties: 'App "mcp" contains an unknown property. The known properties are "name", "version", "title", "websiteUrl", "icons" and "endpoints".'
2666
+ },
2667
+ properties: {
2668
+ '~ignoreBuildChecks': {},
2669
+ '~r': {},
2670
+ '~l': {},
2671
+ name: {
2672
+ type: 'string',
2673
+ errorMessage: {
2674
+ type: 'MCP "name" should be a string.'
2675
+ }
2676
+ },
2677
+ version: {
2678
+ type: 'string',
2679
+ errorMessage: {
2680
+ type: 'MCP "version" should be a string.'
2681
+ }
2682
+ },
2683
+ // Server branding advertised in the initialize result's serverInfo
2684
+ // (MCP Implementation: title, websiteUrl, icons). Clients that render
2685
+ // a connector card prefer these over guessing from the host's favicon.
2686
+ title: {
2687
+ type: 'string',
2688
+ errorMessage: {
2689
+ type: 'MCP "title" should be a string.'
2690
+ }
2691
+ },
2692
+ websiteUrl: {
2693
+ type: 'string',
2694
+ errorMessage: {
2695
+ type: 'MCP "websiteUrl" should be a string.'
2696
+ }
2697
+ },
2698
+ icons: {
2699
+ type: 'array',
2700
+ items: {
2701
+ type: 'object',
2702
+ additionalProperties: false,
2703
+ required: [
2704
+ 'src'
2705
+ ],
2706
+ properties: {
2707
+ '~ignoreBuildChecks': {},
2708
+ '~r': {},
2709
+ '~l': {},
2710
+ src: {
2711
+ type: 'string',
2712
+ errorMessage: {
2713
+ type: 'MCP icon "src" should be a string.'
2714
+ }
2715
+ },
2716
+ mimeType: {
2717
+ type: 'string',
2718
+ errorMessage: {
2719
+ type: 'MCP icon "mimeType" should be a string.'
2720
+ }
2721
+ },
2722
+ sizes: {
2723
+ type: 'array',
2724
+ items: {
2725
+ type: 'string'
2726
+ },
2727
+ errorMessage: {
2728
+ type: 'MCP icon "sizes" should be an array of strings like "512x512".'
2729
+ }
2730
+ },
2731
+ theme: {
2732
+ type: 'string',
2733
+ enum: [
2734
+ 'light',
2735
+ 'dark'
2736
+ ],
2737
+ errorMessage: {
2738
+ type: 'MCP icon "theme" should be a string.',
2739
+ enum: 'MCP icon "theme" should be "light" or "dark".'
2740
+ }
2741
+ }
2742
+ },
2743
+ errorMessage: {
2744
+ type: 'MCP "icons" items should be objects with a "src" property.',
2745
+ required: {
2746
+ src: 'MCP icon should have required property "src".'
2747
+ },
2748
+ additionalProperties: 'MCP icon contains an unknown property. The known properties are "src", "mimeType", "sizes" and "theme".'
2749
+ }
2750
+ },
2751
+ errorMessage: {
2752
+ type: 'MCP "icons" should be an array.'
2753
+ }
2754
+ },
2755
+ endpoints: {
2756
+ type: 'array',
2757
+ items: {
2758
+ type: 'string',
2759
+ description: 'Api endpoint ids exposed as MCP tools.'
2760
+ },
2761
+ errorMessage: {
2762
+ type: 'MCP "endpoints" should be an array of endpoint id strings.'
2763
+ }
2764
+ }
2765
+ }
2766
+ },
2767
+ websockets: {
2768
+ type: 'array',
2769
+ items: {
2770
+ $ref: '#/definitions/websocket'
2771
+ },
2772
+ errorMessage: {
2773
+ type: 'App "websockets" should be an array.'
2774
+ }
2775
+ },
2776
+ notifications: {
2777
+ type: 'array',
2778
+ items: {
2779
+ $ref: '#/definitions/notification'
2780
+ },
2781
+ errorMessage: {
2782
+ type: 'App "notifications" should be an array.'
2783
+ }
2784
+ },
1930
2785
  menus: {
1931
2786
  type: 'array',
1932
2787
  items: {