meno-core 1.0.53 → 1.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.
- package/.claude/settings.local.json +1 -3
- package/bin/cli.ts +66 -261
- package/build-astro.ts +150 -128
- package/dist/bin/cli.js +42 -185
- package/dist/bin/cli.js.map +2 -2
- package/dist/chunks/chunk-2AR55GYH.js +42 -0
- package/dist/chunks/chunk-2AR55GYH.js.map +7 -0
- package/dist/chunks/{chunk-JGWFTO6P.js → chunk-2IIQK7T3.js} +2624 -1389
- package/dist/chunks/chunk-2IIQK7T3.js.map +7 -0
- package/dist/chunks/chunk-4ZRU52J2.js +169 -0
- package/dist/chunks/chunk-4ZRU52J2.js.map +7 -0
- package/dist/chunks/{chunk-UB44F4Z2.js → chunk-5X4HCN7J.js} +5 -7
- package/dist/chunks/chunk-5X4HCN7J.js.map +7 -0
- package/dist/chunks/{chunk-WQFG7PAH.js → chunk-7CCVOL5M.js} +15 -19
- package/dist/chunks/chunk-7CCVOL5M.js.map +7 -0
- package/dist/chunks/{chunk-YBLHKYFF.js → chunk-AR7LHIFY.js} +8 -2
- package/dist/chunks/chunk-AR7LHIFY.js.map +7 -0
- package/dist/chunks/{chunk-O3NAGJP4.js → chunk-NUP7H7D3.js} +135 -41
- package/dist/chunks/chunk-NUP7H7D3.js.map +7 -0
- package/dist/chunks/{chunk-X754AHS5.js → chunk-QWTQZHG3.js} +194 -90
- package/dist/chunks/chunk-QWTQZHG3.js.map +7 -0
- package/dist/chunks/{chunk-H3GJ4H2U.js → chunk-XTKNX4FW.js} +216 -87
- package/dist/chunks/chunk-XTKNX4FW.js.map +7 -0
- package/dist/chunks/{fs-JGINUXGL.js → fs-G3ANWEFP.js} +2 -2
- package/dist/lib/client/index.js +1003 -475
- package/dist/lib/client/index.js.map +3 -3
- package/dist/lib/server/index.js +14393 -6371
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +342 -101
- package/dist/lib/shared/index.js.map +4 -4
- package/dist/lib/shared/richtext/index.js +1 -1
- package/dist/lib/test-utils/index.js +64 -80
- package/dist/lib/test-utils/index.js.map +2 -2
- package/entries/client-router.tsx +10 -8
- package/lib/client/ClientInitializer.ts +8 -8
- package/lib/client/ErrorBoundary.test.tsx +246 -186
- package/lib/client/ErrorBoundary.tsx +183 -132
- package/lib/client/componentRegistry.test.ts +96 -108
- package/lib/client/componentRegistry.ts +1 -3
- package/lib/client/contexts/ThemeContext.tsx +3 -2
- package/lib/client/core/ComponentBuilder.test.ts +663 -560
- package/lib/client/core/ComponentBuilder.ts +427 -155
- package/lib/client/core/ComponentRenderer.test.tsx +2 -4
- package/lib/client/core/ComponentRenderer.tsx +46 -33
- package/lib/client/core/builders/embedBuilder.ts +242 -54
- package/lib/client/core/builders/linkBuilder.ts +72 -45
- package/lib/client/core/builders/linkNodeBuilder.ts +79 -54
- package/lib/client/core/builders/listBuilder.ts +155 -89
- package/lib/client/core/builders/localeListBuilder.ts +97 -62
- package/lib/client/core/builders/types.ts +5 -5
- package/lib/client/core/cmsTemplateProcessor.ts +8 -9
- package/lib/client/elementRegistry.ts +3 -3
- package/lib/client/fontFamiliesService.test.ts +2 -10
- package/lib/client/fontFamiliesService.ts +3 -3
- package/lib/client/hmr/HMRManager.tsx +47 -30
- package/lib/client/hmrCssReload.ts +49 -14
- package/lib/client/hmrWebSocket.ts +14 -19
- package/lib/client/hooks/useColorVariables.test.ts +21 -21
- package/lib/client/hooks/useColorVariables.ts +23 -18
- package/lib/client/hooks/usePropertyAutocomplete.ts +4 -6
- package/lib/client/hooks/useVariables.ts +6 -4
- package/lib/client/hydration/HydrationUtils.test.ts +24 -25
- package/lib/client/hydration/HydrationUtils.ts +3 -4
- package/lib/client/i18nConfigService.test.ts +2 -7
- package/lib/client/i18nConfigService.ts +2 -2
- package/lib/client/meno-filter/MenoFilter.test.ts +47 -49
- package/lib/client/meno-filter/MenoFilter.ts +14 -15
- package/lib/client/meno-filter/bindings.ts +18 -43
- package/lib/client/meno-filter/init.ts +4 -4
- package/lib/client/meno-filter/renderer.ts +30 -32
- package/lib/client/meno-filter/script.generated.ts +1 -3
- package/lib/client/meno-filter/ui.ts +4 -6
- package/lib/client/meno-filter/updates.ts +18 -23
- package/lib/client/meno-filter/utils.ts +1 -1
- package/lib/client/navigation.test.ts +174 -178
- package/lib/client/navigation.ts +0 -1
- package/lib/client/responsiveStyleResolver.knownTokens.test.ts +71 -0
- package/lib/client/responsiveStyleResolver.test.ts +234 -232
- package/lib/client/responsiveStyleResolver.ts +74 -20
- package/lib/client/routing/RouteLoader.test.ts +24 -25
- package/lib/client/routing/RouteLoader.ts +27 -35
- package/lib/client/routing/Router.tsx +210 -153
- package/lib/client/scripts/ScriptExecutor.test.ts +157 -158
- package/lib/client/scripts/ScriptExecutor.ts +18 -36
- package/lib/client/services/PrefetchService.test.ts +3 -3
- package/lib/client/services/PrefetchService.ts +23 -29
- package/lib/client/styleProcessor.test.ts +9 -9
- package/lib/client/styleProcessor.ts +24 -15
- package/lib/client/styles/StyleInjector.test.ts +122 -115
- package/lib/client/styles/StyleInjector.ts +10 -7
- package/lib/client/styles/UtilityClassCollector.ts +62 -28
- package/lib/client/styles/cspNonce.test.ts +2 -5
- package/lib/client/templateEngine.test.ts +554 -488
- package/lib/client/templateEngine.ts +203 -73
- package/lib/client/theme.test.ts +1 -1
- package/lib/client/theme.ts +0 -1
- package/lib/client/utils/toast.ts +0 -1
- package/lib/server/__integration__/api-routes.test.ts +8 -4
- package/lib/server/__integration__/cms-integration.test.ts +1 -4
- package/lib/server/__integration__/server-lifecycle.test.ts +4 -5
- package/lib/server/__integration__/ssr-rendering.test.ts +47 -37
- package/lib/server/__integration__/static-assets.test.ts +3 -3
- package/lib/server/__integration__/test-helpers.ts +87 -74
- package/lib/server/ab/generateFunctions.ts +12 -10
- package/lib/server/astro/cmsPageEmitter.ts +26 -42
- package/lib/server/astro/componentEmitter.ts +35 -43
- package/lib/server/astro/cssCollector.ts +10 -26
- package/lib/server/astro/nodeToAstro.test.ts +1754 -34
- package/lib/server/astro/nodeToAstro.ts +232 -216
- package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +115 -119
- package/lib/server/astro/normalizeOrphanTemplateProps.ts +11 -18
- package/lib/server/astro/pageEmitter.ts +9 -13
- package/lib/server/astro/tailwindMapper.test.ts +10 -37
- package/lib/server/astro/tailwindMapper.ts +33 -40
- package/lib/server/astro/templateTransformer.ts +17 -20
- package/lib/server/createServer.ts +7 -19
- package/lib/server/cssGenerator.test.ts +35 -44
- package/lib/server/cssGenerator.ts +8 -19
- package/lib/server/fileWatcher.test.ts +164 -13
- package/lib/server/fileWatcher.ts +209 -124
- package/lib/server/index.ts +14 -17
- package/lib/server/jsonLoader.test.ts +39 -2
- package/lib/server/jsonLoader.ts +39 -34
- package/lib/server/middleware/cors.test.ts +21 -21
- package/lib/server/middleware/cors.ts +28 -4
- package/lib/server/middleware/errorHandler.test.ts +7 -5
- package/lib/server/middleware/errorHandler.ts +3 -8
- package/lib/server/middleware/index.ts +0 -1
- package/lib/server/middleware/logger.test.ts +10 -8
- package/lib/server/middleware/logger.ts +17 -29
- package/lib/server/migrateTemplates.ts +3 -3
- package/lib/server/pageCache.test.ts +76 -77
- package/lib/server/pageCache.ts +0 -1
- package/lib/server/projectContext.ts +5 -4
- package/lib/server/providers/fileSystemCMSProvider.test.ts +142 -99
- package/lib/server/providers/fileSystemCMSProvider.ts +62 -38
- package/lib/server/routes/api/cms.test.ts +26 -14
- package/lib/server/routes/api/cms.ts +9 -14
- package/lib/server/routes/api/colors.test.ts +2 -2
- package/lib/server/routes/api/components.ts +31 -35
- package/lib/server/routes/api/config.ts +3 -4
- package/lib/server/routes/api/core-routes.ts +49 -76
- package/lib/server/routes/api/enums.test.ts +2 -2
- package/lib/server/routes/api/functions.ts +9 -17
- package/lib/server/routes/api/index.ts +3 -6
- package/lib/server/routes/api/pages.ts +8 -11
- package/lib/server/routes/api/shared.test.ts +1 -1
- package/lib/server/routes/api/shared.ts +12 -9
- package/lib/server/routes/api/variables.test.ts +3 -5
- package/lib/server/routes/api/variables.ts +1 -1
- package/lib/server/routes/index.ts +25 -28
- package/lib/server/routes/pages.ts +35 -31
- package/lib/server/routes/static.ts +17 -6
- package/lib/server/runtime/bundler.ts +98 -61
- package/lib/server/runtime/fs.ts +16 -26
- package/lib/server/runtime/httpServer.ts +8 -12
- package/lib/server/services/ColorService.test.ts +3 -3
- package/lib/server/services/ColorService.ts +37 -29
- package/lib/server/services/EnumService.test.ts +4 -8
- package/lib/server/services/EnumService.ts +11 -3
- package/lib/server/services/VariableService.test.ts +8 -12
- package/lib/server/services/VariableService.ts +11 -3
- package/lib/server/services/cmsService.test.ts +158 -120
- package/lib/server/services/cmsService.ts +36 -146
- package/lib/server/services/componentService.test.ts +125 -45
- package/lib/server/services/componentService.ts +70 -46
- package/lib/server/services/configService.test.ts +22 -45
- package/lib/server/services/configService.ts +50 -27
- package/lib/server/services/fileWatcherService.ts +42 -8
- package/lib/server/services/index.ts +0 -1
- package/lib/server/services/pageService.test.ts +8 -10
- package/lib/server/services/pageService.ts +32 -18
- package/lib/server/ssr/attributeBuilder.ts +18 -8
- package/lib/server/ssr/buildErrorOverlay.ts +11 -12
- package/lib/server/ssr/clientDataInjector.ts +7 -21
- package/lib/server/ssr/cmsSSRProcessor.ts +4 -8
- package/lib/server/ssr/cssCollector.ts +1 -1
- package/lib/server/ssr/errorOverlay.test.ts +1 -1
- package/lib/server/ssr/errorOverlay.ts +3 -9
- package/lib/server/ssr/htmlGenerator.nonce.test.ts +9 -14
- package/lib/server/ssr/htmlGenerator.test.ts +120 -44
- package/lib/server/ssr/htmlGenerator.ts +126 -91
- package/lib/server/ssr/imageMetadata.test.ts +3 -1
- package/lib/server/ssr/imageMetadata.ts +27 -21
- package/lib/server/ssr/jsCollector.test.ts +8 -18
- package/lib/server/ssr/jsCollector.ts +3 -8
- package/lib/server/ssr/liveReloadIntegration.test.ts +76 -36
- package/lib/server/ssr/metaTagGenerator.ts +2 -2
- package/lib/server/ssr/ssrRenderer.branches.test.ts +1103 -0
- package/lib/server/ssr/ssrRenderer.test.ts +316 -256
- package/lib/server/ssr/ssrRenderer.ts +795 -243
- package/lib/server/ssrRenderer.test.ts +1048 -954
- package/lib/server/utils/jsonLineMapper.test.ts +28 -28
- package/lib/server/utils/jsonLineMapper.ts +7 -7
- package/lib/server/validateStyleCoverage.ts +18 -21
- package/lib/server/websocketManager.ts +28 -19
- package/lib/shared/attributeNodeUtils.test.ts +15 -15
- package/lib/shared/attributeNodeUtils.ts +5 -12
- package/lib/shared/breakpoints.test.ts +5 -5
- package/lib/shared/breakpoints.ts +4 -11
- package/lib/shared/cmsQuery.test.ts +81 -0
- package/lib/shared/cmsQuery.ts +92 -0
- package/lib/shared/cmsQueryParser.test.ts +50 -42
- package/lib/shared/cmsQueryParser.ts +60 -38
- package/lib/shared/colorConversions.ts +9 -9
- package/lib/shared/colorVariableUtils.test.ts +27 -5
- package/lib/shared/colorVariableUtils.ts +21 -12
- package/lib/shared/componentRefs.ts +1 -5
- package/lib/shared/constants.test.ts +3 -3
- package/lib/shared/constants.ts +8 -8
- package/lib/shared/cssGeneration.test.ts +285 -144
- package/lib/shared/cssGeneration.ts +217 -531
- package/lib/shared/cssNamedColors.ts +152 -30
- package/lib/shared/cssProperties.test.ts +69 -70
- package/lib/shared/cssProperties.ts +298 -114
- package/lib/shared/elementClassName.test.ts +109 -109
- package/lib/shared/elementClassName.ts +3 -3
- package/lib/shared/elementUtils.ts +12 -16
- package/lib/shared/errorLogger.test.ts +12 -12
- package/lib/shared/errorLogger.ts +2 -10
- package/lib/shared/errors.test.ts +2 -13
- package/lib/shared/errors.ts +2 -8
- package/lib/shared/expressionEvaluator.test.ts +145 -0
- package/lib/shared/expressionEvaluator.ts +52 -24
- package/lib/shared/fontLoader.test.ts +32 -18
- package/lib/shared/fontLoader.ts +2 -2
- package/lib/shared/friendlyError.ts +2 -3
- package/lib/shared/gradientUtils.test.ts +3 -7
- package/lib/shared/gradientUtils.ts +17 -14
- package/lib/shared/hrefRefs.test.ts +2 -2
- package/lib/shared/hrefRefs.ts +2 -10
- package/lib/shared/i18n.test.ts +4 -4
- package/lib/shared/i18n.ts +18 -38
- package/lib/shared/index.ts +27 -0
- package/lib/shared/inlineSvgStyleRules.ts +14 -13
- package/lib/shared/interactiveStyleMappings.test.ts +32 -54
- package/lib/shared/interactiveStyleMappings.ts +11 -24
- package/lib/shared/interactiveStyles.test.ts +165 -188
- package/lib/shared/interfaces/contentProvider.ts +1 -1
- package/lib/shared/itemTemplateUtils.test.ts +11 -17
- package/lib/shared/itemTemplateUtils.ts +27 -39
- package/lib/shared/jsonRepair.ts +16 -10
- package/lib/shared/libraryLoader.test.ts +21 -55
- package/lib/shared/libraryLoader.ts +7 -22
- package/lib/shared/linkUtils.ts +1 -1
- package/lib/shared/logger.test.ts +66 -0
- package/lib/shared/logger.ts +94 -0
- package/lib/shared/markdown.ts +25 -0
- package/lib/shared/netlifyLocale404.test.ts +179 -0
- package/lib/shared/netlifyLocale404.ts +110 -0
- package/lib/shared/nodeUtils.test.ts +28 -16
- package/lib/shared/nodeUtils.ts +76 -23
- package/lib/shared/pathArrayUtils.test.ts +1 -2
- package/lib/shared/pathArrayUtils.ts +1 -1
- package/lib/shared/pathSecurity.ts +2 -2
- package/lib/shared/pathUtils.test.ts +4 -6
- package/lib/shared/pathUtils.ts +42 -49
- package/lib/shared/paths/Path.test.ts +2 -2
- package/lib/shared/paths/Path.ts +0 -1
- package/lib/shared/paths/PathConverter.test.ts +1 -1
- package/lib/shared/paths/PathConverter.ts +17 -20
- package/lib/shared/paths/PathUtils.ts +13 -13
- package/lib/shared/paths/PathValidator.test.ts +2 -15
- package/lib/shared/paths/PathValidator.ts +12 -10
- package/lib/shared/paths/index.ts +1 -2
- package/lib/shared/permissions.test.ts +168 -0
- package/lib/shared/permissions.ts +162 -0
- package/lib/shared/propResolver.test.ts +240 -244
- package/lib/shared/propResolver.ts +15 -26
- package/lib/shared/pxToRem.test.ts +7 -6
- package/lib/shared/pxToRem.ts +2 -5
- package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +12 -6
- package/lib/shared/registry/ClientRegistry.ts +0 -2
- package/lib/shared/registry/ComponentRegistry.test.ts +46 -32
- package/lib/shared/registry/ComponentRegistry.ts +12 -9
- package/lib/shared/registry/NodeTypeDefinition.ts +16 -9
- package/lib/shared/registry/RegistryManager.ts +1 -2
- package/lib/shared/registry/SSRRegistry.ts +0 -2
- package/lib/shared/registry/createNodeType.ts +7 -9
- package/lib/shared/registry/defineNodeType.ts +2 -6
- package/lib/shared/registry/fieldPresets.ts +3 -1
- package/lib/shared/registry/index.ts +0 -1
- package/lib/shared/registry/nodeTypes/ComponentInstanceNodeType.ts +14 -15
- package/lib/shared/registry/nodeTypes/CustomNodeType.ts +103 -0
- package/lib/shared/registry/nodeTypes/EmbedNodeType.ts +18 -11
- package/lib/shared/registry/nodeTypes/HtmlNodeType.ts +48 -19
- package/lib/shared/registry/nodeTypes/IslandNodeType.ts +129 -0
- package/lib/shared/registry/nodeTypes/LinkNodeType.ts +21 -19
- package/lib/shared/registry/nodeTypes/ListNodeType.ts +117 -77
- package/lib/shared/registry/nodeTypes/LocaleListNodeType.ts +27 -21
- package/lib/shared/registry/nodeTypes/MarkdownNodeType.ts +78 -0
- package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +12 -8
- package/lib/shared/registry/nodeTypes/index.ts +26 -3
- package/lib/shared/responsiveScaling.test.ts +16 -34
- package/lib/shared/responsiveScaling.ts +61 -42
- package/lib/shared/responsiveStyleUtils.test.ts +0 -1
- package/lib/shared/responsiveStyleUtils.ts +11 -13
- package/lib/shared/richtext/htmlToTiptap.test.ts +139 -130
- package/lib/shared/richtext/htmlToTiptap.ts +2 -4
- package/lib/shared/richtext/tiptapToHtml.test.ts +5 -6
- package/lib/shared/richtext/types.ts +1 -8
- package/lib/shared/slugTranslator.test.ts +13 -13
- package/lib/shared/slugTranslator.ts +12 -16
- package/lib/shared/slugify.ts +9 -15
- package/lib/shared/styleNodeUtils.test.ts +8 -8
- package/lib/shared/styleNodeUtils.ts +18 -20
- package/lib/shared/styleUtils.test.ts +87 -61
- package/lib/shared/styleUtils.ts +5 -6
- package/lib/shared/themeDefaults.test.ts +11 -14
- package/lib/shared/themeDefaults.ts +3 -4
- package/lib/shared/tree/PathBuilder.test.ts +63 -145
- package/lib/shared/tree/PathBuilder.ts +59 -47
- package/lib/shared/treePathUtils.test.ts +51 -12
- package/lib/shared/treePathUtils.ts +91 -60
- package/lib/shared/types/api.ts +105 -8
- package/lib/shared/types/cms.test.ts +34 -0
- package/lib/shared/types/cms.ts +90 -34
- package/lib/shared/types/comment.ts +49 -16
- package/lib/shared/types/components.ts +51 -25
- package/lib/shared/types/errors.test.ts +1 -6
- package/lib/shared/types/errors.ts +3 -7
- package/lib/shared/types/experiments.ts +28 -28
- package/lib/shared/types/index.ts +25 -2
- package/lib/shared/types/permissions.ts +139 -0
- package/lib/shared/types/styles.ts +0 -1
- package/lib/shared/types/variables.test.ts +4 -13
- package/lib/shared/types/variables.ts +51 -30
- package/lib/shared/types.ts +1 -2
- package/lib/shared/utilityClassConfig.ts +751 -321
- package/lib/shared/utilityClassMapper.durability.test.ts +117 -0
- package/lib/shared/utilityClassMapper.test.ts +433 -95
- package/lib/shared/utilityClassMapper.ts +322 -249
- package/lib/shared/utilityClassNames.test.ts +38 -0
- package/lib/shared/utilityClassNames.ts +458 -0
- package/lib/shared/utils.test.ts +2 -10
- package/lib/shared/utils.ts +19 -10
- package/lib/shared/validation/cmsValidators.ts +2 -1
- package/lib/shared/validation/commentValidators.test.ts +53 -0
- package/lib/shared/validation/commentValidators.ts +12 -1
- package/lib/shared/validation/index.ts +1 -0
- package/lib/shared/validation/permissionsValidators.test.ts +49 -0
- package/lib/shared/validation/permissionsValidators.ts +49 -0
- package/lib/shared/validation/propValidator.test.ts +19 -21
- package/lib/shared/validation/propValidator.ts +13 -18
- package/lib/shared/validation/schemas.test.ts +64 -32
- package/lib/shared/validation/schemas.ts +616 -345
- package/lib/shared/validation/validators.test.ts +3 -8
- package/lib/shared/validation/validators.ts +89 -68
- package/lib/shared/viewportUnits.integration.test.ts +14 -10
- package/lib/shared/viewportUnits.test.ts +24 -23
- package/lib/shared/viewportUnits.ts +12 -5
- package/lib/test-utils/dom-setup.ts +1 -1
- package/lib/test-utils/factories/ConsoleMockFactory.ts +10 -14
- package/lib/test-utils/factories/DomMockFactory.ts +17 -23
- package/lib/test-utils/factories/EventMockFactory.ts +7 -13
- package/lib/test-utils/factories/FetchMockFactory.ts +39 -57
- package/lib/test-utils/factories/ServerMockFactory.ts +6 -10
- package/lib/test-utils/factories/StoreMockFactory.ts +18 -29
- package/lib/test-utils/fixtures.ts +45 -45
- package/lib/test-utils/helpers/asyncHelpers.test.ts +15 -18
- package/lib/test-utils/helpers/asyncHelpers.ts +11 -20
- package/lib/test-utils/helpers.ts +1 -5
- package/lib/test-utils/index.ts +0 -4
- package/lib/test-utils/mockFactories.ts +13 -19
- package/lib/test-utils/mocks.ts +6 -4
- package/package.json +3 -5
- package/scripts/build-for-publish.mjs +2 -4
- package/scripts/build-meno-filter.ts +4 -7
- package/tsconfig.json +1 -0
- package/vite.config.ts +4 -4
- package/build-next.ts +0 -1361
- package/build-static.test.ts +0 -424
- package/build-static.ts +0 -1074
- package/dist/build-static.js +0 -36
- package/dist/chunks/chunk-2MHDV5BF.js +0 -251
- package/dist/chunks/chunk-2MHDV5BF.js.map +0 -7
- package/dist/chunks/chunk-AZQYF6KE.js +0 -559
- package/dist/chunks/chunk-AZQYF6KE.js.map +0 -7
- package/dist/chunks/chunk-GZHGVVW3.js +0 -322
- package/dist/chunks/chunk-GZHGVVW3.js.map +0 -7
- package/dist/chunks/chunk-H3GJ4H2U.js.map +0 -7
- package/dist/chunks/chunk-I7YIGZXT.js +0 -467
- package/dist/chunks/chunk-I7YIGZXT.js.map +0 -7
- package/dist/chunks/chunk-IGYR22T6.js +0 -6192
- package/dist/chunks/chunk-IGYR22T6.js.map +0 -7
- package/dist/chunks/chunk-JGP5A3Y5.js +0 -1136
- package/dist/chunks/chunk-JGP5A3Y5.js.map +0 -7
- package/dist/chunks/chunk-JGWFTO6P.js.map +0 -7
- package/dist/chunks/chunk-O3NAGJP4.js.map +0 -7
- package/dist/chunks/chunk-QB2LNO4W.js +0 -77
- package/dist/chunks/chunk-QB2LNO4W.js.map +0 -7
- package/dist/chunks/chunk-R6XHAFBF.js +0 -3821
- package/dist/chunks/chunk-R6XHAFBF.js.map +0 -7
- package/dist/chunks/chunk-UB44F4Z2.js.map +0 -7
- package/dist/chunks/chunk-WQFG7PAH.js.map +0 -7
- package/dist/chunks/chunk-X754AHS5.js.map +0 -7
- package/dist/chunks/chunk-YBLHKYFF.js.map +0 -7
- package/dist/chunks/configService-R3OGU2UD.js +0 -13
- package/dist/chunks/configService-R3OGU2UD.js.map +0 -7
- package/dist/chunks/constants-STK2YBIW.js +0 -46
- package/dist/chunks/constants-STK2YBIW.js.map +0 -7
- package/dist/chunks/fs-JGINUXGL.js.map +0 -7
- package/dist/entries/server-router.js +0 -67
- package/dist/entries/server-router.js.map +0 -7
- package/entries/server-router.tsx +0 -81
- package/lib/server/providers/fileSystemPageProvider.ts +0 -160
- package/lib/server/webflow/buildWebflow.ts +0 -635
- package/lib/server/webflow/index.ts +0 -23
- package/lib/server/webflow/nodeToWebflow.test.ts +0 -3170
- package/lib/server/webflow/nodeToWebflow.ts +0 -2435
- package/lib/server/webflow/styleMapper.test.ts +0 -389
- package/lib/server/webflow/styleMapper.ts +0 -695
- package/lib/server/webflow/templateWrapper.ts +0 -49
- package/lib/server/webflow/types.ts +0 -396
- /package/dist/{build-static.js.map → chunks/fs-G3ANWEFP.js.map} +0 -0
|
@@ -35,7 +35,7 @@ export interface CoreRouteContext {
|
|
|
35
35
|
export async function handleCoreApiRoutes(
|
|
36
36
|
req: Request,
|
|
37
37
|
url: URL,
|
|
38
|
-
context: CoreRouteContext
|
|
38
|
+
context: CoreRouteContext,
|
|
39
39
|
): Promise<Response | undefined> {
|
|
40
40
|
const { pageService, componentService, cmsService } = context;
|
|
41
41
|
|
|
@@ -55,21 +55,21 @@ export async function handleCoreApiRoutes(
|
|
|
55
55
|
if (url.pathname === API_ROUTES.PAGES && req.method === 'GET') {
|
|
56
56
|
return await handleRouteError(
|
|
57
57
|
() => Promise.resolve(pagesRoutes.handlePagesRoute(pageService)),
|
|
58
|
-
'Failed to fetch pages list'
|
|
58
|
+
'Failed to fetch pages list',
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
if (url.pathname.startsWith(API_ROUTES.PAGE_DATA) && req.method === 'GET') {
|
|
63
63
|
return await handleRouteError(
|
|
64
64
|
() => Promise.resolve(pagesRoutes.handlePageDataRoute(url, pageService)),
|
|
65
|
-
'Failed to fetch page data'
|
|
65
|
+
'Failed to fetch page data',
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (url.pathname === API_ROUTES.PAGE_CONTENT && req.method === 'GET') {
|
|
70
70
|
return await handleRouteError(
|
|
71
71
|
() => Promise.resolve(pagesRoutes.handlePageContentRoute(req, url, pageService)),
|
|
72
|
-
'Failed to fetch page content'
|
|
72
|
+
'Failed to fetch page content',
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -77,135 +77,108 @@ export async function handleCoreApiRoutes(
|
|
|
77
77
|
if (url.pathname === API_ROUTES.COMPONENTS && req.method === 'GET') {
|
|
78
78
|
return await handleRouteError(
|
|
79
79
|
() => Promise.resolve(componentsRoutes.handleComponentsRoute(req, componentService)),
|
|
80
|
-
'Failed to fetch components list'
|
|
80
|
+
'Failed to fetch components list',
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
if (url.pathname.startsWith('/api/component-data/') && req.method === 'GET') {
|
|
85
85
|
return await handleRouteError(
|
|
86
86
|
() => Promise.resolve(componentsRoutes.handleComponentDataRoute(url, componentService)),
|
|
87
|
-
'Failed to fetch component data'
|
|
87
|
+
'Failed to fetch component data',
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
if (url.pathname.startsWith('/api/component-js/') && req.method === 'GET') {
|
|
92
92
|
return await handleRouteError(
|
|
93
93
|
() => componentsRoutes.handleComponentJavaScriptRoute(url, componentService),
|
|
94
|
-
'Failed to fetch component JavaScript'
|
|
94
|
+
'Failed to fetch component JavaScript',
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// Config API routes (read-only)
|
|
99
99
|
if (url.pathname === '/api/config' && req.method === 'GET') {
|
|
100
|
-
return await handleRouteError(
|
|
101
|
-
() => configRoutes.handleConfigRoute(),
|
|
102
|
-
'Failed to fetch config'
|
|
103
|
-
);
|
|
100
|
+
return await handleRouteError(() => configRoutes.handleConfigRoute(), 'Failed to fetch config');
|
|
104
101
|
}
|
|
105
102
|
|
|
106
103
|
if (url.pathname === '/api/components-config' && req.method === 'GET') {
|
|
107
104
|
return await handleRouteError(
|
|
108
105
|
() => configRoutes.handleComponentsConfigRoute(),
|
|
109
|
-
'Failed to fetch components config'
|
|
106
|
+
'Failed to fetch components config',
|
|
110
107
|
);
|
|
111
108
|
}
|
|
112
109
|
|
|
113
110
|
// Colors API routes (read-only)
|
|
114
111
|
if (url.pathname === '/api/colors' && req.method === 'GET') {
|
|
115
|
-
return await handleRouteError(
|
|
116
|
-
() => colorsRoutes.handleColorsRoute(url),
|
|
117
|
-
'Failed to fetch colors'
|
|
118
|
-
);
|
|
112
|
+
return await handleRouteError(() => colorsRoutes.handleColorsRoute(url), 'Failed to fetch colors');
|
|
119
113
|
}
|
|
120
114
|
|
|
121
115
|
if (url.pathname === '/api/themes' && req.method === 'GET') {
|
|
122
|
-
return await handleRouteError(
|
|
123
|
-
() => colorsRoutes.handleThemesRoute(),
|
|
124
|
-
'Failed to fetch themes'
|
|
125
|
-
);
|
|
116
|
+
return await handleRouteError(() => colorsRoutes.handleThemesRoute(), 'Failed to fetch themes');
|
|
126
117
|
}
|
|
127
118
|
|
|
128
119
|
if (url.pathname === '/api/colors-config' && req.method === 'GET') {
|
|
129
|
-
return await handleRouteError(
|
|
130
|
-
() => colorsRoutes.handleColorsConfigRoute(),
|
|
131
|
-
'Failed to fetch colors config'
|
|
132
|
-
);
|
|
120
|
+
return await handleRouteError(() => colorsRoutes.handleColorsConfigRoute(), 'Failed to fetch colors config');
|
|
133
121
|
}
|
|
134
122
|
|
|
135
123
|
if (url.pathname === '/api/colors-status' && req.method === 'GET') {
|
|
136
|
-
return await handleRouteError(
|
|
137
|
-
() => colorsRoutes.handleColorsStatusRoute(),
|
|
138
|
-
'Failed to fetch colors status'
|
|
139
|
-
);
|
|
124
|
+
return await handleRouteError(() => colorsRoutes.handleColorsStatusRoute(), 'Failed to fetch colors status');
|
|
140
125
|
}
|
|
141
126
|
|
|
142
127
|
// Variables API routes (read-only)
|
|
143
128
|
if (url.pathname === '/api/variables-status' && req.method === 'GET') {
|
|
144
129
|
return await handleRouteError(
|
|
145
130
|
() => variablesRoutes.handleVariablesStatusRoute(),
|
|
146
|
-
'Failed to fetch variables status'
|
|
131
|
+
'Failed to fetch variables status',
|
|
147
132
|
);
|
|
148
133
|
}
|
|
149
134
|
|
|
150
135
|
if (url.pathname === '/api/variables-css' && req.method === 'GET') {
|
|
151
|
-
return await handleRouteError(
|
|
152
|
-
() => variablesRoutes.handleVariablesCSSRoute(),
|
|
153
|
-
'Failed to generate variables CSS'
|
|
154
|
-
);
|
|
136
|
+
return await handleRouteError(() => variablesRoutes.handleVariablesCSSRoute(), 'Failed to generate variables CSS');
|
|
155
137
|
}
|
|
156
138
|
|
|
157
139
|
// Fonts CSS route (read-only)
|
|
158
140
|
if (url.pathname === '/api/fonts-css' && req.method === 'GET') {
|
|
159
|
-
return await handleRouteError(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
'Failed to generate fonts CSS'
|
|
168
|
-
);
|
|
141
|
+
return await handleRouteError(async () => {
|
|
142
|
+
await loadProjectConfig();
|
|
143
|
+
const css = generateFontCSS();
|
|
144
|
+
return new Response(css, {
|
|
145
|
+
headers: { 'Content-Type': 'text/css' },
|
|
146
|
+
});
|
|
147
|
+
}, 'Failed to generate fonts CSS');
|
|
169
148
|
}
|
|
170
149
|
|
|
171
150
|
// Enums API route (read-only)
|
|
172
151
|
if (url.pathname === '/api/enums' && req.method === 'GET') {
|
|
173
|
-
return await handleRouteError(
|
|
174
|
-
() => enumsRoutes.handleEnumsRoute(),
|
|
175
|
-
'Failed to fetch enums'
|
|
176
|
-
);
|
|
152
|
+
return await handleRouteError(() => enumsRoutes.handleEnumsRoute(), 'Failed to fetch enums');
|
|
177
153
|
}
|
|
178
154
|
|
|
179
155
|
// Usage API route (for license limit checks)
|
|
180
156
|
if (url.pathname === '/api/usage' && req.method === 'GET') {
|
|
181
|
-
return await handleRouteError(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
},
|
|
200
|
-
'Failed to fetch usage stats'
|
|
201
|
-
);
|
|
157
|
+
return await handleRouteError(() => {
|
|
158
|
+
// Count CMS collections
|
|
159
|
+
const cmsCollections = cmsService ? cmsService.getAllSchemas().size : 0;
|
|
160
|
+
|
|
161
|
+
// Count pages (exclude templates directory)
|
|
162
|
+
const allPages = pageService.getAllPagePaths();
|
|
163
|
+
const pages = allPages.filter((p) => !p.includes('/templates/')).length;
|
|
164
|
+
|
|
165
|
+
// Count locales from config
|
|
166
|
+
const i18n = configService.getI18n();
|
|
167
|
+
const locales = i18n.locales.length;
|
|
168
|
+
|
|
169
|
+
return Promise.resolve(
|
|
170
|
+
new Response(JSON.stringify({ cmsCollections, pages, locales }), {
|
|
171
|
+
headers: { 'Content-Type': 'application/json' },
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
174
|
+
}, 'Failed to fetch usage stats');
|
|
202
175
|
}
|
|
203
176
|
|
|
204
177
|
// Component usage API route (read-only)
|
|
205
178
|
if (url.pathname === API_ROUTES.COMPONENT_USAGE && req.method === 'GET') {
|
|
206
179
|
return await handleRouteError(
|
|
207
180
|
() => Promise.resolve(componentsRoutes.handleComponentUsageRoute(pageService, componentService)),
|
|
208
|
-
'Failed to fetch component usage'
|
|
181
|
+
'Failed to fetch component usage',
|
|
209
182
|
);
|
|
210
183
|
}
|
|
211
184
|
|
|
@@ -213,7 +186,7 @@ export async function handleCoreApiRoutes(
|
|
|
213
186
|
if (url.pathname === '/api/slug-mappings' && req.method === 'GET') {
|
|
214
187
|
return await handleRouteError(
|
|
215
188
|
() => Promise.resolve(pagesRoutes.handleSlugMappingsRoute(pageService)),
|
|
216
|
-
'Failed to fetch slug mappings'
|
|
189
|
+
'Failed to fetch slug mappings',
|
|
217
190
|
);
|
|
218
191
|
}
|
|
219
192
|
|
|
@@ -223,23 +196,23 @@ export async function handleCoreApiRoutes(
|
|
|
223
196
|
if (url.pathname === '/api/cms/collections' && req.method === 'GET') {
|
|
224
197
|
return await handleRouteError(
|
|
225
198
|
() => Promise.resolve(cmsRoutes.handleCollectionsRoute(cmsService)),
|
|
226
|
-
'Failed to fetch CMS collections'
|
|
199
|
+
'Failed to fetch CMS collections',
|
|
227
200
|
);
|
|
228
201
|
}
|
|
229
202
|
|
|
230
203
|
// GET /api/cms/collections/:collection - Get collection schema
|
|
231
204
|
const collectionSchemaMatch = url.pathname.match(/^\/api\/cms\/collections\/([^/]+)$/);
|
|
232
|
-
if (collectionSchemaMatch && req.method === 'GET') {
|
|
205
|
+
if (collectionSchemaMatch && collectionSchemaMatch[1] !== undefined && req.method === 'GET') {
|
|
233
206
|
const collection = collectionSchemaMatch[1];
|
|
234
207
|
return await handleRouteError(
|
|
235
208
|
() => Promise.resolve(cmsRoutes.handleCollectionSchemaRoute(collection, cmsService)),
|
|
236
|
-
'Failed to fetch collection schema'
|
|
209
|
+
'Failed to fetch collection schema',
|
|
237
210
|
);
|
|
238
211
|
}
|
|
239
212
|
|
|
240
213
|
// Parse collection and slug from path: /api/cms/:collection/:slug?
|
|
241
214
|
const cmsPathMatch = url.pathname.match(/^\/api\/cms\/([^/]+)(?:\/([^/]+))?$/);
|
|
242
|
-
if (cmsPathMatch) {
|
|
215
|
+
if (cmsPathMatch && cmsPathMatch[1] !== undefined) {
|
|
243
216
|
const collection = cmsPathMatch[1];
|
|
244
217
|
const slug = cmsPathMatch[2];
|
|
245
218
|
|
|
@@ -252,7 +225,7 @@ export async function handleCoreApiRoutes(
|
|
|
252
225
|
if (!slug && req.method === 'GET') {
|
|
253
226
|
return await handleRouteError(
|
|
254
227
|
() => cmsRoutes.handleItemsRoute(collection, cmsService, url.searchParams),
|
|
255
|
-
'Failed to fetch CMS items'
|
|
228
|
+
'Failed to fetch CMS items',
|
|
256
229
|
);
|
|
257
230
|
}
|
|
258
231
|
|
|
@@ -260,7 +233,7 @@ export async function handleCoreApiRoutes(
|
|
|
260
233
|
if (slug && req.method === 'GET') {
|
|
261
234
|
return await handleRouteError(
|
|
262
235
|
() => cmsRoutes.handleItemRoute(collection, slug, cmsService),
|
|
263
|
-
'Failed to fetch CMS item'
|
|
236
|
+
'Failed to fetch CMS item',
|
|
264
237
|
);
|
|
265
238
|
}
|
|
266
239
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { mkdirSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { setProjectRoot, getProjectRoot } from '../../projectContext';
|
|
5
5
|
import { enumService } from '../../services/EnumService';
|
|
6
6
|
import { handleEnumsRoute } from './enums';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { projectPaths } from '../../projectContext';
|
|
10
|
-
import path from 'path';
|
|
10
|
+
import path from 'node:path';
|
|
11
11
|
import { readTextFile, fileExists } from '../../runtime';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -38,8 +38,7 @@ async function loadProjectEnv(): Promise<Record<string, string>> {
|
|
|
38
38
|
if (key) {
|
|
39
39
|
// Remove quotes from value if present
|
|
40
40
|
let value = valueParts.join('=');
|
|
41
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
42
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
41
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
43
42
|
value = value.slice(1, -1);
|
|
44
43
|
}
|
|
45
44
|
env[key.trim()] = value;
|
|
@@ -58,10 +57,7 @@ async function loadProjectEnv(): Promise<Record<string, string>> {
|
|
|
58
57
|
* Handle API function requests in development
|
|
59
58
|
* Routes like /api/contact are mapped to /functions/api/contact.ts
|
|
60
59
|
*/
|
|
61
|
-
export async function handleFunctionsRoute(
|
|
62
|
-
req: Request,
|
|
63
|
-
url: URL
|
|
64
|
-
): Promise<Response | undefined> {
|
|
60
|
+
export async function handleFunctionsRoute(req: Request, url: URL): Promise<Response | undefined> {
|
|
65
61
|
// Only handle /api/* routes
|
|
66
62
|
if (!url.pathname.startsWith('/api/')) {
|
|
67
63
|
return undefined;
|
|
@@ -75,11 +71,7 @@ export async function handleFunctionsRoute(
|
|
|
75
71
|
// Extract function path from URL
|
|
76
72
|
// /api/contact -> functions/api/contact.ts
|
|
77
73
|
const functionPath = url.pathname.replace('/api/', '');
|
|
78
|
-
const functionFilePath = path.join(
|
|
79
|
-
projectPaths.functions(),
|
|
80
|
-
'api',
|
|
81
|
-
`${functionPath}.ts`
|
|
82
|
-
);
|
|
74
|
+
const functionFilePath = path.join(projectPaths.functions(), 'api', `${functionPath}.ts`);
|
|
83
75
|
|
|
84
76
|
// Check if function file exists
|
|
85
77
|
if (!(await fileExists(functionFilePath))) {
|
|
@@ -104,10 +96,10 @@ export async function handleFunctionsRoute(
|
|
|
104
96
|
const handler = functionModule[handlerName] || functionModule.onRequest;
|
|
105
97
|
|
|
106
98
|
if (!handler || typeof handler !== 'function') {
|
|
107
|
-
return new Response(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
);
|
|
99
|
+
return new Response(JSON.stringify({ error: `No handler found for ${method} request` }), {
|
|
100
|
+
status: 405,
|
|
101
|
+
headers: { 'Content-Type': 'application/json' },
|
|
102
|
+
});
|
|
111
103
|
}
|
|
112
104
|
|
|
113
105
|
// Load environment variables
|
|
@@ -143,7 +135,7 @@ export async function handleFunctionsRoute(
|
|
|
143
135
|
error: 'Function execution error',
|
|
144
136
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
145
137
|
}),
|
|
146
|
-
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
138
|
+
{ status: 500, headers: { 'Content-Type': 'application/json' } },
|
|
147
139
|
);
|
|
148
140
|
}
|
|
149
141
|
}
|
|
@@ -30,7 +30,7 @@ export async function handleApiRoutes(
|
|
|
30
30
|
url: URL,
|
|
31
31
|
pageService: PageService,
|
|
32
32
|
componentService: ComponentService,
|
|
33
|
-
cmsContext?: CMSRouteContext
|
|
33
|
+
cmsContext?: CMSRouteContext,
|
|
34
34
|
): Promise<Response | undefined> {
|
|
35
35
|
try {
|
|
36
36
|
const coreContext: CoreRouteContext = {
|
|
@@ -42,10 +42,7 @@ export async function handleApiRoutes(
|
|
|
42
42
|
return await handleCoreApiRoutes(req, url, coreContext);
|
|
43
43
|
} catch (error) {
|
|
44
44
|
// This catch is a fallback - individual routes should handle their own errors
|
|
45
|
-
return handleRouteError(
|
|
46
|
-
() => Promise.reject(error),
|
|
47
|
-
'API route error'
|
|
48
|
-
);
|
|
45
|
+
return handleRouteError(() => Promise.reject(error), 'API route error');
|
|
49
46
|
}
|
|
50
47
|
}
|
|
51
48
|
|
|
@@ -57,7 +54,7 @@ export async function handleCoreOnlyApiRoutes(
|
|
|
57
54
|
url: URL,
|
|
58
55
|
pageService: PageService,
|
|
59
56
|
componentService: ComponentService,
|
|
60
|
-
cmsService?: CMSService
|
|
57
|
+
cmsService?: CMSService,
|
|
61
58
|
): Promise<Response | undefined> {
|
|
62
59
|
const context: CoreRouteContext = {
|
|
63
60
|
pageService,
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { PageService } from '../../services/pageService';
|
|
7
7
|
import { API_ROUTES } from '../../../shared/constants';
|
|
8
8
|
import { parseJSON } from '../../jsonLoader';
|
|
9
|
+
import { logRuntimeError } from '../../../shared/errorLogger';
|
|
9
10
|
import { createCorsHeaders } from '../../middleware/cors';
|
|
10
11
|
import { jsonResponse, cachedJsonResponse } from './shared';
|
|
11
12
|
|
|
@@ -21,10 +22,7 @@ export function handlePagesRoute(pageService: PageService): Response {
|
|
|
21
22
|
/**
|
|
22
23
|
* Handle page data API endpoint - GET /api/page-data/:path
|
|
23
24
|
*/
|
|
24
|
-
export function handlePageDataRoute(
|
|
25
|
-
url: URL,
|
|
26
|
-
pageService: PageService
|
|
27
|
-
): Response {
|
|
25
|
+
export function handlePageDataRoute(url: URL, pageService: PageService): Response {
|
|
28
26
|
const pagePath = url.pathname.replace(API_ROUTES.PAGE_DATA, '') || '/';
|
|
29
27
|
const content = pageService.getPage(pagePath);
|
|
30
28
|
|
|
@@ -41,7 +39,11 @@ export function handlePageDataRoute(
|
|
|
41
39
|
}
|
|
42
40
|
return jsonResponse({ ...(parsedContent as Record<string, unknown>), _lineMap: lineMapObj });
|
|
43
41
|
} catch (error) {
|
|
44
|
-
|
|
42
|
+
// The stored page content failed to parse — a server-side data-integrity
|
|
43
|
+
// problem (corrupt file / partial write), so this stays a 5xx. Surface the
|
|
44
|
+
// parser message + path instead of an opaque "Invalid JSON".
|
|
45
|
+
logRuntimeError('api.pageData.parse', error, { pagePath });
|
|
46
|
+
return jsonResponse({ error: error instanceof Error ? error.message : 'Invalid JSON' }, { status: 500 });
|
|
45
47
|
}
|
|
46
48
|
} else {
|
|
47
49
|
return jsonResponse({ error: 'Page not found' }, { status: 404 });
|
|
@@ -56,11 +58,7 @@ export function handlePageDataRoute(
|
|
|
56
58
|
* Uses ETag revalidation so repeat navigations to the same page get a 304
|
|
57
59
|
* instead of re-transmitting an unchanged body.
|
|
58
60
|
*/
|
|
59
|
-
export function handlePageContentRoute(
|
|
60
|
-
req: Request,
|
|
61
|
-
url: URL,
|
|
62
|
-
pageService: PageService
|
|
63
|
-
): Response {
|
|
61
|
+
export function handlePageContentRoute(req: Request, url: URL, pageService: PageService): Response {
|
|
64
62
|
const page = url.searchParams.get('page') || '/';
|
|
65
63
|
const content = pageService.getPage(page);
|
|
66
64
|
|
|
@@ -86,4 +84,3 @@ export function handleSlugMappingsRoute(pageService: PageService): Response {
|
|
|
86
84
|
const mappings = pageService.getSlugMappings();
|
|
87
85
|
return jsonResponse({ mappings });
|
|
88
86
|
}
|
|
89
|
-
|
|
@@ -2,21 +2,25 @@
|
|
|
2
2
|
* Shared utilities for API routes
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { createCorsHeaders } from '../../middleware/cors';
|
|
5
|
+
import { createCorsHeaders, type CorsOptions } from '../../middleware/cors';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Helper function for JSON responses with CORS headers
|
|
8
|
+
* Helper function for JSON responses with CORS headers.
|
|
9
|
+
*
|
|
10
|
+
* `options.cors` lets a caller scope CORS for a sensitive route (e.g. pass a
|
|
11
|
+
* localhost-only `origin` allow-list + the request `Origin`); when omitted the
|
|
12
|
+
* default permissive `*` headers are used, so existing callers are unaffected.
|
|
9
13
|
*/
|
|
10
|
-
export function jsonResponse(data: unknown, options: { status?: number } = {}): Response {
|
|
11
|
-
const corsHeaders = createCorsHeaders();
|
|
14
|
+
export function jsonResponse(data: unknown, options: { status?: number; cors?: CorsOptions } = {}): Response {
|
|
15
|
+
const corsHeaders = createCorsHeaders(options.cors);
|
|
12
16
|
|
|
13
17
|
return new Response(JSON.stringify(data), {
|
|
14
18
|
status: options.status || 200,
|
|
15
19
|
headers: {
|
|
16
20
|
'Content-Type': 'application/json',
|
|
17
21
|
'Cache-Control': 'no-store, max-age=0',
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
Pragma: 'no-cache',
|
|
23
|
+
Expires: '0',
|
|
20
24
|
...corsHeaders,
|
|
21
25
|
},
|
|
22
26
|
});
|
|
@@ -65,7 +69,7 @@ export function cachedJsonResponse(
|
|
|
65
69
|
return new Response(null, {
|
|
66
70
|
status: 304,
|
|
67
71
|
headers: {
|
|
68
|
-
|
|
72
|
+
ETag: etag,
|
|
69
73
|
'Cache-Control': 'no-cache',
|
|
70
74
|
...corsHeaders,
|
|
71
75
|
},
|
|
@@ -76,7 +80,7 @@ export function cachedJsonResponse(
|
|
|
76
80
|
status: options.status ?? 200,
|
|
77
81
|
headers: {
|
|
78
82
|
'Content-Type': contentType,
|
|
79
|
-
|
|
83
|
+
ETag: etag,
|
|
80
84
|
// `no-cache` (not `no-store`) — browser may keep the body but must
|
|
81
85
|
// revalidate every time. Pairs with the 304 branch above.
|
|
82
86
|
'Cache-Control': 'no-cache',
|
|
@@ -84,4 +88,3 @@ export function cachedJsonResponse(
|
|
|
84
88
|
},
|
|
85
89
|
});
|
|
86
90
|
}
|
|
87
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { mkdirSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { setProjectRoot, getProjectRoot } from '../../projectContext';
|
|
5
5
|
import { variableService } from '../../services/VariableService';
|
|
6
6
|
import { handleVariablesStatusRoute, handleVariablesCSSRoute } from './variables';
|
|
@@ -9,9 +9,7 @@ import type { VariablesConfig } from '../../../shared/types';
|
|
|
9
9
|
const TEST_DIR = join('/tmp', `variablesRoute-test-${process.pid}`);
|
|
10
10
|
|
|
11
11
|
const VALID_CONFIG: VariablesConfig = {
|
|
12
|
-
variables: [
|
|
13
|
-
{ name: 'heading-size', cssVar: '--heading-size', value: '2rem', type: 'fontSize', group: 'font-size' },
|
|
14
|
-
],
|
|
12
|
+
variables: [{ name: 'heading-size', cssVar: '--heading-size', value: '2rem', type: 'fontSize', group: 'font-size' }],
|
|
15
13
|
};
|
|
16
14
|
|
|
17
15
|
function writeVariables(config: VariablesConfig): void {
|
|
@@ -29,6 +29,6 @@ export async function handleVariablesCSSRoute(): Promise<Response> {
|
|
|
29
29
|
const responsiveScalesConfig = configService.getResponsiveScales();
|
|
30
30
|
const css = generateVariablesCSS(variablesConfig, breakpointConfig, responsiveScalesConfig);
|
|
31
31
|
return new Response(css, {
|
|
32
|
-
headers: { 'Content-Type': 'text/css' }
|
|
32
|
+
headers: { 'Content-Type': 'text/css' },
|
|
33
33
|
});
|
|
34
34
|
}
|
|
@@ -55,8 +55,8 @@ export interface RouteContext {
|
|
|
55
55
|
export async function handleRoutes(
|
|
56
56
|
req: Request,
|
|
57
57
|
url: URL,
|
|
58
|
-
|
|
59
|
-
context: RouteContext
|
|
58
|
+
_server: any,
|
|
59
|
+
context: RouteContext,
|
|
60
60
|
): Promise<Response | undefined> {
|
|
61
61
|
const startTime = Date.now();
|
|
62
62
|
const { pageService, componentService, cmsService, cmsProvider } = context;
|
|
@@ -96,7 +96,7 @@ export async function handleRoutes(
|
|
|
96
96
|
return new Response(null, { status: 204, headers: corsHeaders });
|
|
97
97
|
}
|
|
98
98
|
try {
|
|
99
|
-
const body = await req.json() as { path?: string; content?: string };
|
|
99
|
+
const body = (await req.json()) as { path?: string; content?: string };
|
|
100
100
|
if (typeof body.path === 'string' && typeof body.content === 'string' && body.path.startsWith('/')) {
|
|
101
101
|
store.set(body.path, body.content);
|
|
102
102
|
// Nudge connected tabs to refetch. The existing live-reload
|
|
@@ -116,14 +116,16 @@ export async function handleRoutes(
|
|
|
116
116
|
const store = context.draftPageStore;
|
|
117
117
|
if (store) {
|
|
118
118
|
try {
|
|
119
|
-
const body = await req.json() as { path?: string };
|
|
119
|
+
const body = (await req.json()) as { path?: string };
|
|
120
120
|
if (typeof body.path === 'string') {
|
|
121
121
|
store.clear(body.path);
|
|
122
122
|
// External tabs viewing this path should refetch the disk
|
|
123
123
|
// version now that the draft is gone.
|
|
124
124
|
context.wsManager?.broadcastUpdate(body.path);
|
|
125
125
|
}
|
|
126
|
-
} catch {
|
|
126
|
+
} catch {
|
|
127
|
+
/* ignore */
|
|
128
|
+
}
|
|
127
129
|
}
|
|
128
130
|
logResponseTime(startTime, req);
|
|
129
131
|
return new Response(null, { status: 204, headers: corsHeaders });
|
|
@@ -143,19 +145,10 @@ export async function handleRoutes(
|
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
// Build CMS context if CMS service and provider are available
|
|
146
|
-
const cmsContext: CMSRouteContext | undefined =
|
|
147
|
-
cmsService && cmsProvider
|
|
148
|
-
? { cmsService, cmsProvider }
|
|
149
|
-
: undefined;
|
|
148
|
+
const cmsContext: CMSRouteContext | undefined = cmsService && cmsProvider ? { cmsService, cmsProvider } : undefined;
|
|
150
149
|
|
|
151
150
|
// API Routes
|
|
152
|
-
const apiResponse = await handleApiRoutes(
|
|
153
|
-
req,
|
|
154
|
-
url,
|
|
155
|
-
pageService,
|
|
156
|
-
componentService,
|
|
157
|
-
cmsContext
|
|
158
|
-
);
|
|
151
|
+
const apiResponse = await handleApiRoutes(req, url, pageService, componentService, cmsContext);
|
|
159
152
|
if (apiResponse) {
|
|
160
153
|
logResponseTime(startTime, req);
|
|
161
154
|
return apiResponse;
|
|
@@ -165,7 +158,7 @@ export async function handleRoutes(
|
|
|
165
158
|
// Pattern: /data/{collection}/index.json
|
|
166
159
|
if (url.pathname.startsWith('/data/') && url.pathname.endsWith('/index.json') && cmsService) {
|
|
167
160
|
const match = url.pathname.match(/^\/data\/([^/]+)\/index\.json$/);
|
|
168
|
-
if (match) {
|
|
161
|
+
if (match && match[1] !== undefined) {
|
|
169
162
|
const collectionId = match[1];
|
|
170
163
|
try {
|
|
171
164
|
// Resolve locale to filter draft items
|
|
@@ -174,7 +167,9 @@ export async function handleRoutes(
|
|
|
174
167
|
try {
|
|
175
168
|
const referer = req.headers.get('referer');
|
|
176
169
|
if (referer) refererPath = new URL(referer).pathname;
|
|
177
|
-
} catch {
|
|
170
|
+
} catch {
|
|
171
|
+
/* ignore malformed referer */
|
|
172
|
+
}
|
|
178
173
|
const { locale } = parseLocaleFromPath(refererPath, i18nConfig);
|
|
179
174
|
const items = await cmsService.queryItems({ collection: collectionId, excludeDraftLocale: locale });
|
|
180
175
|
logResponseTime(startTime, req);
|
|
@@ -209,7 +204,13 @@ export async function handleRoutes(
|
|
|
209
204
|
}
|
|
210
205
|
|
|
211
206
|
// Static asset directories - serve before page routes
|
|
212
|
-
if (
|
|
207
|
+
if (
|
|
208
|
+
url.pathname.startsWith('/images/') ||
|
|
209
|
+
url.pathname.startsWith('/videos/') ||
|
|
210
|
+
url.pathname.startsWith('/assets/') ||
|
|
211
|
+
url.pathname.startsWith('/public/') ||
|
|
212
|
+
url.pathname.startsWith('/icons/')
|
|
213
|
+
) {
|
|
213
214
|
const response = await handleStaticRoute(url, req);
|
|
214
215
|
if (response) {
|
|
215
216
|
logResponseTime(startTime, req);
|
|
@@ -223,10 +224,10 @@ export async function handleRoutes(
|
|
|
223
224
|
// route wiring look like a working endpoint to API clients.
|
|
224
225
|
if (url.pathname.startsWith('/api/')) {
|
|
225
226
|
logResponseTime(startTime, req);
|
|
226
|
-
return new Response(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
);
|
|
227
|
+
return new Response(JSON.stringify({ error: 'Not Found', path: url.pathname }), {
|
|
228
|
+
status: 404,
|
|
229
|
+
headers: { 'Content-Type': 'application/json' },
|
|
230
|
+
});
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
// Page routes (SSR)
|
|
@@ -242,10 +243,6 @@ export async function handleRoutes(
|
|
|
242
243
|
return response;
|
|
243
244
|
} catch (error) {
|
|
244
245
|
logResponseTime(startTime, req);
|
|
245
|
-
return handleRouteError(
|
|
246
|
-
() => Promise.reject(error),
|
|
247
|
-
`Error handling route: ${url.pathname}`
|
|
248
|
-
);
|
|
246
|
+
return handleRouteError(() => Promise.reject(error), `Error handling route: ${url.pathname}`);
|
|
249
247
|
}
|
|
250
248
|
}
|
|
251
|
-
|