@lowdefy/build 5.1.0 → 5.2.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 (53) hide show
  1. package/dist/build/buildApi/buildRoutine/countStepTypes.js +3 -0
  2. package/dist/build/buildApi/buildRoutine/setStepId.js +3 -2
  3. package/dist/build/buildApi/buildRoutine/validateStep.js +19 -0
  4. package/dist/build/buildApi/validateEndpoint.js +10 -0
  5. package/dist/build/buildApi/validateStepReferences.js +4 -4
  6. package/dist/build/buildAuth/buildApiAuth.js +2 -1
  7. package/dist/build/buildAuth/buildPageAuth.js +2 -1
  8. package/dist/build/buildAuth/getApiRoles.js +12 -6
  9. package/dist/build/buildAuth/getPageRoles.js +12 -6
  10. package/dist/build/buildAuth/getProtectedApi.js +3 -2
  11. package/dist/build/buildAuth/getProtectedPages.js +3 -2
  12. package/dist/build/buildAuth/matchPattern.js +22 -0
  13. package/dist/build/buildConnections.js +42 -4
  14. package/dist/build/buildJs/jsMapParser.js +25 -12
  15. package/dist/build/buildJs/writeJs.js +2 -2
  16. package/dist/build/buildMenu.js +41 -0
  17. package/dist/build/buildModuleDefs.js +97 -0
  18. package/dist/build/buildModules.js +96 -0
  19. package/dist/build/buildPages/buildBlock/buildBlock.js +2 -2
  20. package/dist/build/buildPages/buildBlock/buildEvents.js +16 -1
  21. package/dist/build/buildPages/buildBlock/buildSubBlocks.js +2 -1
  22. package/dist/build/buildPages/buildBlock/validateBlock.js +3 -3
  23. package/dist/build/buildPages/buildPage.js +1 -0
  24. package/dist/build/buildPages/validateCallApiRefs.js +31 -0
  25. package/dist/build/buildRefs/getModuleRefContent.js +81 -0
  26. package/dist/build/buildRefs/makeRefDefinition.js +6 -0
  27. package/dist/build/buildRefs/walker.js +424 -44
  28. package/dist/build/fetchGitHubModule.js +94 -0
  29. package/dist/build/fetchModules.js +60 -0
  30. package/dist/build/full/buildPages.js +10 -1
  31. package/dist/build/full/writePages.js +1 -1
  32. package/dist/build/jit/buildPageJit.js +34 -4
  33. package/dist/build/jit/collectSkeletonSourceFiles.js +8 -0
  34. package/dist/build/jit/createPageRegistry.js +10 -1
  35. package/dist/build/jit/shallowBuild.js +22 -11
  36. package/dist/build/jit/writePageJit.js +2 -2
  37. package/dist/build/jit/writeSourcelessPages.js +1 -1
  38. package/dist/build/parseModuleSource.js +48 -0
  39. package/dist/build/registerModules.js +242 -0
  40. package/dist/build/resolveDepTarget.js +43 -0
  41. package/dist/build/resolveModuleDependencies.js +60 -0
  42. package/dist/build/resolveModuleOperators.js +27 -0
  43. package/dist/build/testSchema.js +22 -11
  44. package/dist/build/writePluginImports/writeGlobalsCss.js +1 -1
  45. package/dist/createContext.js +4 -0
  46. package/dist/defaultPackages.js +51 -0
  47. package/dist/defaultTypesMap.js +399 -357
  48. package/dist/index.js +16 -1
  49. package/dist/indexDev.js +3 -1
  50. package/dist/lowdefySchema.js +58 -0
  51. package/dist/scripts/generateDefaultTypes.js +1 -35
  52. package/package.json +46 -42
  53. package/dist/build/jit/stripPageContent.js +0 -29
@@ -23,7 +23,7 @@ const BROWSER_DEFAULT_SHORTCUTS = new Set([
23
23
  'mod+q',
24
24
  'mod+l'
25
25
  ]);
26
- function checkAction(action, { blockId, checkDuplicateActionId, eventId, linkActionRefs, pageId, requestActionRefs, typeCounters }) {
26
+ function checkAction(action, { blockId, callApiActionRefs, checkDuplicateActionId, eventId, linkActionRefs, pageId, requestActionRefs, typeCounters }) {
27
27
  const configKey = action['~k'];
28
28
  if (type.isUndefined(action.id)) {
29
29
  throw new ConfigError(`Action id missing on event "${eventId}" on block "${blockId}" on page "${pageId}".`, {
@@ -95,6 +95,19 @@ function checkAction(action, { blockId, checkDuplicateActionId, eventId, linkAct
95
95
  });
96
96
  }
97
97
  }
98
+ // Collect static CallAPI action references for validation
99
+ if (action.type === 'CallAPI' && !type.isNone(action.params)) {
100
+ const params = action.params;
101
+ if (type.isObject(params) && type.isString(params.endpointId)) {
102
+ callApiActionRefs.push({
103
+ endpointId: params.endpointId,
104
+ action,
105
+ blockId,
106
+ eventId,
107
+ sourcePageId: pageId
108
+ });
109
+ }
110
+ }
98
111
  }
99
112
  function buildEvents(block, pageContext) {
100
113
  if (block.events) {
@@ -133,6 +146,7 @@ function buildEvents(block, pageContext) {
133
146
  block.events[key].try.map((action)=>checkAction(action, {
134
147
  eventId: key,
135
148
  blockId: block.blockId,
149
+ callApiActionRefs: pageContext.callApiActionRefs,
136
150
  typeCounters: pageContext.typeCounters,
137
151
  pageId: pageContext.pageId,
138
152
  linkActionRefs: pageContext.linkActionRefs,
@@ -142,6 +156,7 @@ function buildEvents(block, pageContext) {
142
156
  block.events[key].catch.map((action)=>checkAction(action, {
143
157
  eventId: key,
144
158
  blockId: block.blockId,
159
+ callApiActionRefs: pageContext.callApiActionRefs,
145
160
  typeCounters: pageContext.typeCounters,
146
161
  pageId: pageContext.pageId,
147
162
  linkActionRefs: pageContext.linkActionRefs,
@@ -27,7 +27,8 @@ function buildSubBlocks(block, pageContext) {
27
27
  configKey: block.slots[key]['~k'] ?? block['~k']
28
28
  });
29
29
  }
30
- block.slots[key].blocks.map((blk)=>buildBlock(blk, pageContext));
30
+ const slotConfigKey = block.slots[key].blocks['~k'] ?? block.slots[key]['~k'] ?? block['~k'];
31
+ block.slots[key].blocks.map((blk)=>buildBlock(blk, pageContext, slotConfigKey));
31
32
  });
32
33
  }
33
34
  }
@@ -14,10 +14,10 @@
14
14
  limitations under the License.
15
15
  */ import { type } from '@lowdefy/helpers';
16
16
  import { ConfigError } from '@lowdefy/errors';
17
- function validateBlock(block, { pageId }) {
18
- const configKey = block?.['~k'];
17
+ function validateBlock(block, { pageId }, parentConfigKey) {
18
+ const configKey = block?.['~k'] ?? parentConfigKey;
19
19
  if (!type.isObject(block)) {
20
- throw new ConfigError(`Expected block to be an object on page "${pageId}".`, {
20
+ throw new ConfigError(`Block should be an object on page "${pageId}".`, {
21
21
  received: block,
22
22
  configKey
23
23
  });
@@ -57,6 +57,7 @@ function buildPage({ page, index, context, checkDuplicatePageId }) {
57
57
  buildBlock(page, {
58
58
  auth: page.auth,
59
59
  blockIdCounter: createCounter(),
60
+ callApiActionRefs: context.callApiActionRefs ?? [],
60
61
  checkDuplicateRequestId: createCheckDuplicateId({
61
62
  message: 'Duplicate requestId "{{ id }}" on page "{{ pageId }}".'
62
63
  }),
@@ -0,0 +1,31 @@
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 { ConfigWarning } from '@lowdefy/errors';
16
+ function validateCallApiRefs({ callApiActionRefs, endpointConfigs, context }) {
17
+ const internalEndpoints = new Set(endpointConfigs.filter((config)=>config.type === 'InternalApi').map((config)=>config.endpointId));
18
+ callApiActionRefs.forEach(({ endpointId, action, sourcePageId })=>{
19
+ if (action.skip === true) {
20
+ return;
21
+ }
22
+ if (internalEndpoints.has(endpointId)) {
23
+ context.handleWarning(new ConfigWarning(`CallAPI action on page "${sourcePageId}" targets InternalApi endpoint "${endpointId}". InternalApi endpoints are not accessible from client pages.`, {
24
+ configKey: action['~k'],
25
+ prodError: true,
26
+ checkSlug: 'callapi-internal-refs'
27
+ }));
28
+ }
29
+ });
30
+ }
31
+ export default validateCallApiRefs;
@@ -0,0 +1,81 @@
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 { ConfigError } from '@lowdefy/errors';
16
+ function describeRef(refDef) {
17
+ const parts = [];
18
+ if (refDef.module) parts.push(`module: "${refDef.module}"`);
19
+ if (refDef.component) parts.push(`component: "${refDef.component}"`);
20
+ if (refDef.menu) parts.push(`menu: "${refDef.menu}"`);
21
+ if (refDef.page) parts.push(`page: "${refDef.page}"`);
22
+ if (refDef.connection) parts.push(`connection: "${refDef.connection}"`);
23
+ if (refDef.api) parts.push(`api: "${refDef.api}"`);
24
+ return `_ref { ${parts.join(', ')} }`;
25
+ }
26
+ async function getModuleRefContent({ context, refDef, referencedFrom, walkCtx, configKey }) {
27
+ const rawName = refDef.module;
28
+ let entryId;
29
+ if (walkCtx?.moduleDependencies && rawName in walkCtx.moduleDependencies) {
30
+ entryId = walkCtx.moduleDependencies[rawName];
31
+ } else {
32
+ entryId = rawName;
33
+ }
34
+ const moduleEntry = context.modules[entryId];
35
+ if (!moduleEntry) {
36
+ throw new ConfigError(`${describeRef(refDef)} references module "${rawName}" but no module with that entry id was registered` + (entryId !== rawName ? ` ("${rawName}" was mapped to "${entryId}" via dependency wiring).` : '.'), {
37
+ configKey
38
+ });
39
+ }
40
+ const manifest = moduleEntry.manifest;
41
+ // Cross-module _ref is limited to component and menu.
42
+ // Reject page, connection, api with a clear error pointing to the ID operators.
43
+ if (refDef.page || refDef.connection || refDef.api) {
44
+ const refType = refDef.page ? 'page' : refDef.connection ? 'connection' : 'api';
45
+ const operator = refDef.page ? '_module.pageId' : refDef.connection ? '_module.connectionId' : '_module.endpointId';
46
+ throw new ConfigError(`Cross-module _ref does not support "${refType}". ` + `Use ${operator}: { id: "${refDef[refType]}", module: "${rawName}" } instead.`, {
47
+ configKey
48
+ });
49
+ }
50
+ const exportTypes = [
51
+ 'component',
52
+ 'menu'
53
+ ];
54
+ const exportType = exportTypes.find((t)=>refDef[t]) ?? null;
55
+ if (!exportType) {
56
+ throw new ConfigError('Module _ref requires "component" or "menu" property.', {
57
+ configKey
58
+ });
59
+ }
60
+ const exportName = refDef[exportType];
61
+ const manifestArray = {
62
+ component: manifest.components,
63
+ menu: manifest.menus
64
+ }[exportType] ?? [];
65
+ let content;
66
+ if (exportType === 'component') {
67
+ content = manifestArray.find((item)=>item.id === exportName)?.component;
68
+ } else if (exportType === 'menu') {
69
+ content = manifestArray.find((item)=>item.id === exportName)?.links;
70
+ }
71
+ if (!content) {
72
+ throw new ConfigError(`Module "${entryId}" does not export ${exportType} "${exportName}".`, {
73
+ configKey
74
+ });
75
+ }
76
+ return {
77
+ content,
78
+ entryId
79
+ };
80
+ }
81
+ export default getModuleRefContent;
@@ -39,6 +39,12 @@ function makeRefDefinition(refDefinition, parent, refMap, lineNumber, walkerPath
39
39
  vars: get(refDefinition, 'vars', {
40
40
  default: {}
41
41
  }),
42
+ module: get(refDefinition, 'module'),
43
+ component: get(refDefinition, 'component'),
44
+ menu: get(refDefinition, 'menu'),
45
+ page: get(refDefinition, 'page'),
46
+ connection: get(refDefinition, 'connection'),
47
+ api: get(refDefinition, 'api'),
42
48
  ...ignoreBuildChecks !== undefined && {
43
49
  ignoreBuildChecks
44
50
  }