@qwickapps/react-framework 1.3.4 → 1.4.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/README.md +1688 -2
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +7 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/Html.d.ts +28 -18
- package/dist/components/Html.d.ts.map +1 -1
- package/dist/components/Logo.d.ts +12 -35
- package/dist/components/Logo.d.ts.map +1 -1
- package/dist/components/Markdown.d.ts +18 -13
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/QwickApp.d.ts +16 -3
- package/dist/components/QwickApp.d.ts.map +1 -1
- package/dist/components/QwickIcon.d.ts +23 -0
- package/dist/components/QwickIcon.d.ts.map +1 -0
- package/dist/components/SafeSpan.d.ts +12 -5
- package/dist/components/SafeSpan.d.ts.map +1 -1
- package/dist/components/Scaffold.d.ts.map +1 -1
- package/dist/components/base/ModelView.d.ts +101 -0
- package/dist/components/base/ModelView.d.ts.map +1 -0
- package/dist/components/base/index.d.ts +11 -0
- package/dist/components/base/index.d.ts.map +1 -0
- package/dist/components/blocks/Article.d.ts +12 -2
- package/dist/components/blocks/Article.d.ts.map +1 -1
- package/dist/components/blocks/Code.d.ts +13 -2
- package/dist/components/blocks/Code.d.ts.map +1 -1
- package/dist/components/blocks/Content.d.ts.map +1 -1
- package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
- package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
- package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
- package/dist/components/blocks/Footer.d.ts.map +1 -1
- package/dist/components/blocks/HeroBlock.d.ts +27 -13
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
- package/dist/components/blocks/Image.d.ts +41 -0
- package/dist/components/blocks/Image.d.ts.map +1 -0
- package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
- package/dist/components/blocks/ProductCard.d.ts.map +1 -1
- package/dist/components/blocks/Section.d.ts +16 -2
- package/dist/components/blocks/Section.d.ts.map +1 -1
- package/dist/components/blocks/Text.d.ts +41 -0
- package/dist/components/blocks/Text.d.ts.map +1 -0
- package/dist/components/blocks/index.d.ts +4 -0
- package/dist/components/blocks/index.d.ts.map +1 -1
- package/dist/components/buttons/Button.d.ts +23 -7
- package/dist/components/buttons/Button.d.ts.map +1 -1
- package/dist/components/forms/FormBlock.d.ts +19 -13
- package/dist/components/forms/FormBlock.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input/ChoiceInputField.d.ts +17 -11
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
- package/dist/components/input/HtmlInputField.d.ts +17 -11
- package/dist/components/input/HtmlInputField.d.ts.map +1 -1
- package/dist/components/input/SelectInputField.d.ts +16 -10
- package/dist/components/input/SelectInputField.d.ts.map +1 -1
- package/dist/components/input/SwitchInputField.d.ts +16 -10
- package/dist/components/input/SwitchInputField.d.ts.map +1 -1
- package/dist/components/input/TextField.d.ts.map +1 -1
- package/dist/components/input/TextInputField.d.ts +16 -11
- package/dist/components/input/TextInputField.d.ts.map +1 -1
- package/dist/components/layout/GridCell.d.ts +23 -6
- package/dist/components/layout/GridCell.d.ts.map +1 -1
- package/dist/components/layout/GridLayout.d.ts +24 -23
- package/dist/components/layout/GridLayout.d.ts.map +1 -1
- package/dist/components/pages/FormPage.d.ts.map +1 -1
- package/dist/components/pages/Page.d.ts +49 -87
- package/dist/components/pages/Page.d.ts.map +1 -1
- package/dist/components/pages/index.d.ts +2 -2
- package/dist/components/pages/index.d.ts.map +1 -1
- package/dist/config/AppConfig.d.ts +49 -0
- package/dist/config/AppConfig.d.ts.map +1 -0
- package/dist/config/AppConfigBuilder.d.ts +75 -0
- package/dist/config/AppConfigBuilder.d.ts.map +1 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/types.d.ts +130 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.esm.js +451 -0
- package/dist/config.js +455 -0
- package/dist/contexts/PrintModeContext.d.ts +27 -0
- package/dist/contexts/PrintModeContext.d.ts.map +1 -0
- package/dist/contexts/QwickAppContext.d.ts +2 -2
- package/dist/contexts/QwickAppContext.d.ts.map +1 -1
- package/dist/contexts/ThemeContext.d.ts.map +1 -1
- package/dist/contexts/index.d.ts +2 -0
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/usePrintMode.d.ts +39 -0
- package/dist/hooks/usePrintMode.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +20722 -16021
- package/dist/index.js +20725 -16010
- package/dist/schemas/CodeSchema.d.ts +2 -1
- package/dist/schemas/CodeSchema.d.ts.map +1 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
- package/dist/schemas/ContentSchema.d.ts +2 -1
- package/dist/schemas/ContentSchema.d.ts.map +1 -1
- package/dist/schemas/GridCellSchema.d.ts +25 -0
- package/dist/schemas/GridCellSchema.d.ts.map +1 -0
- package/dist/schemas/GridLayoutSchema.d.ts +23 -0
- package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
- package/dist/schemas/HtmlSchema.d.ts +14 -0
- package/dist/schemas/HtmlSchema.d.ts.map +1 -0
- package/dist/schemas/ImageSchema.d.ts +32 -0
- package/dist/schemas/ImageSchema.d.ts.map +1 -0
- package/dist/schemas/LogoSchema.d.ts +35 -0
- package/dist/schemas/LogoSchema.d.ts.map +1 -0
- package/dist/schemas/MarkdownSchema.d.ts +14 -0
- package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
- package/dist/schemas/PageTemplateSchema.d.ts +31 -0
- package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
- package/dist/schemas/PrintConfigSchema.d.ts +31 -0
- package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
- package/dist/schemas/SectionSchema.d.ts +2 -1
- package/dist/schemas/SectionSchema.d.ts.map +1 -1
- package/dist/schemas/TextSchema.d.ts +37 -0
- package/dist/schemas/TextSchema.d.ts.map +1 -0
- package/dist/schemas/ViewModelSchema.d.ts +23 -0
- package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +15 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
- package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
- package/dist/schemas/transformers/registry.d.ts +15 -0
- package/dist/schemas/transformers/registry.d.ts.map +1 -0
- package/dist/schemas/types/Serializable.d.ts +46 -0
- package/dist/schemas/types/Serializable.d.ts.map +1 -0
- package/dist/utils/htmlTransform.d.ts.map +1 -1
- package/dist/utils/reactUtils.d.ts +12 -3
- package/dist/utils/reactUtils.d.ts.map +1 -1
- package/package.json +17 -3
- package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
- package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
- package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
- package/src/__tests__/components/Logo.test.js +3 -3
- package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
- package/src/__tests__/components/base/ModelView.test.tsx +220 -0
- package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
- package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
- package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
- package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
- package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
- package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
- package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
- package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
- package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
- package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
- package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
- package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
- package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
- package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
- package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
- package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
- package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
- package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
- package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
- package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
- package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
- package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
- package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
- package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
- package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
- package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
- package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
- package/src/components/ErrorBoundary.tsx +8 -8
- package/src/components/Html.tsx +147 -44
- package/src/components/Logo.tsx +198 -100
- package/src/components/Markdown.tsx +125 -16
- package/src/components/QwickApp.tsx +64 -31
- package/src/components/QwickIcon.tsx +59 -0
- package/src/components/SafeSpan.tsx +65 -10
- package/src/components/Scaffold.tsx +2 -8
- package/src/components/base/ModelView.tsx +199 -0
- package/src/components/base/index.ts +11 -0
- package/src/components/blocks/Article.tsx +57 -18
- package/src/components/blocks/Code.md +529 -0
- package/src/components/blocks/Code.tsx +102 -15
- package/src/components/blocks/Content.tsx +25 -77
- package/src/components/blocks/CoverImageHeader.tsx +9 -4
- package/src/components/blocks/FeatureCard.tsx +1 -2
- package/src/components/blocks/FeatureGrid.tsx +19 -1
- package/src/components/blocks/Footer.tsx +13 -1
- package/src/components/blocks/HeroBlock.tsx +87 -20
- package/src/components/blocks/Image.tsx +395 -0
- package/src/components/blocks/PageBannerHeader.tsx +14 -12
- package/src/components/blocks/ProductCard.tsx +51 -52
- package/src/components/blocks/Section.tsx +113 -8
- package/src/components/blocks/Text.tsx +285 -0
- package/src/components/blocks/index.ts +4 -0
- package/src/components/buttons/Button.tsx +184 -15
- package/src/components/forms/FormBlock.tsx +70 -17
- package/src/components/index.ts +5 -0
- package/src/components/input/ChoiceInputField.tsx +48 -18
- package/src/components/input/HtmlInputField.tsx +48 -18
- package/src/components/input/SelectInputField.tsx +48 -16
- package/src/components/input/SwitchInputField.tsx +48 -17
- package/src/components/input/TextField.tsx +41 -1
- package/src/components/input/TextInputField.tsx +52 -18
- package/src/components/layout/GridCell.tsx +118 -9
- package/src/components/layout/GridLayout.tsx +125 -24
- package/src/components/pages/FormPage.tsx +0 -1
- package/src/components/pages/Page.css +304 -332
- package/src/components/pages/Page.tsx +307 -255
- package/src/components/pages/index.ts +2 -2
- package/src/config/AppConfig.ts +133 -0
- package/src/config/AppConfigBuilder.ts +421 -0
- package/src/config/__tests__/AppConfig.test.ts +385 -0
- package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
- package/src/config/index.ts +24 -0
- package/src/config/types.ts +170 -0
- package/src/config.ts +25 -0
- package/src/contexts/PrintModeContext.tsx +332 -0
- package/src/contexts/QwickAppContext.tsx +2 -2
- package/src/contexts/ThemeContext.tsx +1 -2
- package/src/contexts/index.ts +2 -0
- package/src/hooks/index.ts +5 -1
- package/src/hooks/usePrintMode.ts +73 -0
- package/src/index.ts +3 -0
- package/src/schemas/CodeSchema.ts +3 -3
- package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
- package/src/schemas/ContentSchema.ts +2 -1
- package/src/schemas/GridCellSchema.ts +164 -0
- package/src/schemas/GridLayoutSchema.ts +133 -0
- package/src/schemas/HtmlSchema.ts +47 -0
- package/src/schemas/ImageSchema.ts +235 -0
- package/src/schemas/LogoSchema.ts +241 -0
- package/src/schemas/MarkdownSchema.ts +47 -0
- package/src/schemas/PageTemplateSchema.ts +186 -0
- package/src/schemas/PrintConfigSchema.ts +207 -0
- package/src/schemas/README.md +661 -0
- package/src/schemas/SectionSchema.ts +2 -1
- package/src/schemas/TextSchema.ts +329 -0
- package/src/schemas/ViewModelSchema.ts +115 -0
- package/src/schemas/index.ts +21 -2
- package/src/schemas/transformers/ComponentTransformer.ts +403 -0
- package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
- package/src/schemas/transformers/registry.ts +72 -0
- package/src/schemas/types/Serializable.ts +51 -0
- package/src/stories/AccessibilityProvider.stories.tsx +253 -253
- package/src/stories/Article.stories.tsx +433 -433
- package/src/stories/Button.stories.tsx +1 -1
- package/src/stories/CardListGrid.stories.tsx +451 -451
- package/src/stories/ChoiceInputField.stories.tsx +503 -503
- package/src/stories/Code.stories.tsx +1 -1
- package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
- package/src/stories/Content.stories.tsx +393 -393
- package/src/stories/CoverImageHeader.stories.tsx +701 -701
- package/src/stories/DataBinding.advanced.stories.tsx +432 -432
- package/src/stories/DataProvider.stories.tsx +1192 -1192
- package/src/stories/FeatureCard.stories.tsx +557 -557
- package/src/stories/FeatureGrid.stories.tsx +594 -594
- package/src/stories/Footer.stories.tsx +640 -640
- package/src/stories/FormBlock.stories.tsx +760 -760
- package/src/stories/FormComponents.stories.tsx +349 -541
- package/src/stories/GridCell.stories.tsx +417 -0
- package/src/stories/GridLayout.stories.tsx +353 -0
- package/src/stories/HeroBlock.stories.tsx +862 -373
- package/src/stories/HtmlInputField.stories.tsx +474 -474
- package/src/stories/Image.stories.tsx +819 -0
- package/src/stories/Introduction.stories.tsx +667 -667
- package/src/stories/LayoutBlocks.stories.tsx +324 -324
- package/src/stories/Logo.stories.tsx +165 -6
- package/src/stories/Markdown.stories.tsx +137 -137
- package/src/stories/ModelView.stories.tsx +477 -0
- package/src/stories/Page.stories.tsx +688 -688
- package/src/stories/PageBannerHeader.stories.tsx +864 -864
- package/src/stories/PaletteSwitcher.stories.tsx +119 -119
- package/src/stories/ProductCard.stories.tsx +424 -424
- package/src/stories/QwickApp.stories.tsx +368 -368
- package/src/stories/ResponsiveMenu.stories.tsx +249 -249
- package/src/stories/SafeSpan.stories.tsx +531 -531
- package/src/stories/Section.stories.tsx +90 -2
- package/src/stories/SelectInputField.stories.tsx +524 -524
- package/src/stories/Text.stories.tsx +560 -0
- package/src/stories/TextInputField.stories.tsx +443 -443
- package/src/stories/ThemeSwitcher.stories.tsx +123 -123
- package/src/utils/htmlTransform.tsx +74 -53
- package/src/utils/reactUtils.tsx +57 -6
- package/dist/index.bundled.css +0 -12
- /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
- /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/optional-logging.test.ts +0 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppConfigBuilder Tests
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive test suite for the AppConfigBuilder class.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { AppConfigBuilder } from '../AppConfigBuilder';
|
|
12
|
+
import { AppConfig } from '../AppConfig';
|
|
13
|
+
|
|
14
|
+
// Mock fs module for file system tests
|
|
15
|
+
jest.mock('fs');
|
|
16
|
+
const mockFs = fs as jest.Mocked<typeof fs>;
|
|
17
|
+
|
|
18
|
+
describe('AppConfigBuilder', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('Builder Pattern', () => {
|
|
24
|
+
it('should create a new builder instance', () => {
|
|
25
|
+
const builder = AppConfigBuilder.create();
|
|
26
|
+
expect(builder).toBeInstanceOf(AppConfigBuilder);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should support fluent API chaining', () => {
|
|
30
|
+
const builder = AppConfigBuilder.create()
|
|
31
|
+
.withName('Test App')
|
|
32
|
+
.withId('test-app')
|
|
33
|
+
.withPort(3000)
|
|
34
|
+
.withThemeColor('#ff0000');
|
|
35
|
+
|
|
36
|
+
expect(builder).toBeInstanceOf(AppConfigBuilder);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('Required Fields Validation', () => {
|
|
41
|
+
it('should throw error when app name is missing', () => {
|
|
42
|
+
expect(() => {
|
|
43
|
+
AppConfigBuilder.create()
|
|
44
|
+
.withId('test-app')
|
|
45
|
+
.build();
|
|
46
|
+
}).toThrow('AppConfig validation failed');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should throw error when app ID is missing', () => {
|
|
50
|
+
expect(() => {
|
|
51
|
+
AppConfigBuilder.create()
|
|
52
|
+
.withName('Test App')
|
|
53
|
+
.build();
|
|
54
|
+
}).toThrow('AppConfig validation failed');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should build successfully with required fields', () => {
|
|
58
|
+
const config = AppConfigBuilder.create()
|
|
59
|
+
.withName('Test App')
|
|
60
|
+
.withId('test-app')
|
|
61
|
+
.build();
|
|
62
|
+
|
|
63
|
+
expect(config).toBeInstanceOf(AppConfig);
|
|
64
|
+
expect(config.app.name).toBe('Test App');
|
|
65
|
+
expect(config.app.id).toBe('test-app');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('Default Values', () => {
|
|
70
|
+
it('should apply default values for optional fields', () => {
|
|
71
|
+
const config = AppConfigBuilder.create()
|
|
72
|
+
.withName('Test App')
|
|
73
|
+
.withId('test-app')
|
|
74
|
+
.build();
|
|
75
|
+
|
|
76
|
+
// App defaults
|
|
77
|
+
expect(config.app.shortName).toBe('Test App'); // defaults to name
|
|
78
|
+
expect(config.app.description).toBe('Test App'); // defaults to name
|
|
79
|
+
expect(config.app.version).toBe('1.0.0');
|
|
80
|
+
expect(config.app.logo).toBe('/favicon.ico');
|
|
81
|
+
|
|
82
|
+
// Build defaults
|
|
83
|
+
expect(config.build.port).toBe(3000);
|
|
84
|
+
expect(config.build.previewPort).toBe(4173);
|
|
85
|
+
expect(config.build.outputDir).toBe('dist');
|
|
86
|
+
expect(config.build.publicPath).toBe('/');
|
|
87
|
+
expect(config.build.base).toBe('/');
|
|
88
|
+
|
|
89
|
+
// PWA defaults
|
|
90
|
+
expect(config.pwa.themeColor).toBe('#000000');
|
|
91
|
+
expect(config.pwa.backgroundColor).toBe('#ffffff');
|
|
92
|
+
expect(config.pwa.startUrl).toBe('/');
|
|
93
|
+
expect(config.pwa.scope).toBe('/');
|
|
94
|
+
expect(config.pwa.display).toBe('standalone');
|
|
95
|
+
|
|
96
|
+
// UI defaults
|
|
97
|
+
expect(config.ui.defaultTheme).toBe('light');
|
|
98
|
+
expect(config.ui.defaultPalette).toBe('default');
|
|
99
|
+
expect(config.ui.enableScaffolding).toBe(true);
|
|
100
|
+
expect(config.ui.showThemeSwitcher).toBe(false);
|
|
101
|
+
expect(config.ui.showPaletteSwitcher).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should override defaults with provided values', () => {
|
|
105
|
+
const config = AppConfigBuilder.create()
|
|
106
|
+
.withName('Custom App')
|
|
107
|
+
.withId('custom-app')
|
|
108
|
+
.withShortName('Custom')
|
|
109
|
+
.withDescription('A custom application')
|
|
110
|
+
.withVersion('2.0.0')
|
|
111
|
+
.withLogo('./custom-logo.svg')
|
|
112
|
+
.withPort(4000)
|
|
113
|
+
.withPreviewPort(5000)
|
|
114
|
+
.withThemeColor('#ff5722')
|
|
115
|
+
.withDefaultTheme('dark')
|
|
116
|
+
.withScaffolding(false)
|
|
117
|
+
.build();
|
|
118
|
+
|
|
119
|
+
expect(config.app.shortName).toBe('Custom');
|
|
120
|
+
expect(config.app.description).toBe('A custom application');
|
|
121
|
+
expect(config.app.version).toBe('2.0.0');
|
|
122
|
+
expect(config.app.logo).toBe('./custom-logo.svg');
|
|
123
|
+
expect(config.build.port).toBe(4000);
|
|
124
|
+
expect(config.build.previewPort).toBe(5000);
|
|
125
|
+
expect(config.pwa.themeColor).toBe('#ff5722');
|
|
126
|
+
expect(config.ui.defaultTheme).toBe('dark');
|
|
127
|
+
expect(config.ui.enableScaffolding).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('Port Validation', () => {
|
|
132
|
+
it('should accept valid port numbers', () => {
|
|
133
|
+
const config = AppConfigBuilder.create()
|
|
134
|
+
.withName('Test App')
|
|
135
|
+
.withId('test-app')
|
|
136
|
+
.withPort(3000)
|
|
137
|
+
.withPreviewPort(4000)
|
|
138
|
+
.build();
|
|
139
|
+
|
|
140
|
+
expect(config.build.port).toBe(3000);
|
|
141
|
+
expect(config.build.previewPort).toBe(4000);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should throw error for invalid port numbers', () => {
|
|
145
|
+
expect(() => {
|
|
146
|
+
AppConfigBuilder.create()
|
|
147
|
+
.withName('Test App')
|
|
148
|
+
.withId('test-app')
|
|
149
|
+
.withPort(0)
|
|
150
|
+
.build();
|
|
151
|
+
}).toThrow('Port must be a valid integer between 1 and 65535');
|
|
152
|
+
|
|
153
|
+
expect(() => {
|
|
154
|
+
AppConfigBuilder.create()
|
|
155
|
+
.withName('Test App')
|
|
156
|
+
.withId('test-app')
|
|
157
|
+
.withPort(70000)
|
|
158
|
+
.build();
|
|
159
|
+
}).toThrow('Port must be a valid integer between 1 and 65535');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should throw error for non-integer ports', () => {
|
|
163
|
+
expect(() => {
|
|
164
|
+
AppConfigBuilder.create()
|
|
165
|
+
.withName('Test App')
|
|
166
|
+
.withId('test-app')
|
|
167
|
+
.withPort(3000.5 as any)
|
|
168
|
+
.build();
|
|
169
|
+
}).toThrow('Port must be a valid integer between 1 and 65535');
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('Logo File Validation', () => {
|
|
174
|
+
it.skip('should warn when logo file does not exist', () => {
|
|
175
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
176
|
+
mockFs.existsSync.mockReturnValue(false);
|
|
177
|
+
|
|
178
|
+
const config = AppConfigBuilder.create()
|
|
179
|
+
.withName('Test App')
|
|
180
|
+
.withId('test-app')
|
|
181
|
+
.withLogo('./missing-logo.svg')
|
|
182
|
+
.build();
|
|
183
|
+
|
|
184
|
+
expect(consoleWarn).toHaveBeenCalledWith(
|
|
185
|
+
'⚠️ AppConfig: Logo file not found: ./missing-logo.svg (will use default)'
|
|
186
|
+
);
|
|
187
|
+
expect(config.app.logo).toBe('./missing-logo.svg'); // Still uses provided path
|
|
188
|
+
|
|
189
|
+
consoleWarn.mockRestore();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('should not warn when logo file exists', () => {
|
|
193
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
194
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
195
|
+
|
|
196
|
+
const config = AppConfigBuilder.create()
|
|
197
|
+
.withName('Test App')
|
|
198
|
+
.withId('test-app')
|
|
199
|
+
.withLogo('./existing-logo.svg')
|
|
200
|
+
.build();
|
|
201
|
+
|
|
202
|
+
expect(consoleWarn).not.toHaveBeenCalled();
|
|
203
|
+
expect(config.app.logo).toBe('./existing-logo.svg');
|
|
204
|
+
|
|
205
|
+
consoleWarn.mockRestore();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should skip validation when skipValidation option is true', () => {
|
|
209
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
210
|
+
|
|
211
|
+
const config = AppConfigBuilder.create()
|
|
212
|
+
.withOptions({ skipValidation: true })
|
|
213
|
+
.withName('Test App')
|
|
214
|
+
.withId('test-app')
|
|
215
|
+
.withLogo('./missing-logo.svg')
|
|
216
|
+
.build();
|
|
217
|
+
|
|
218
|
+
expect(consoleWarn).not.toHaveBeenCalled();
|
|
219
|
+
expect(mockFs.existsSync).not.toHaveBeenCalled();
|
|
220
|
+
|
|
221
|
+
consoleWarn.mockRestore();
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('Color Validation', () => {
|
|
226
|
+
it('should accept valid hex colors', () => {
|
|
227
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
228
|
+
|
|
229
|
+
const config = AppConfigBuilder.create()
|
|
230
|
+
.withName('Test App')
|
|
231
|
+
.withId('test-app')
|
|
232
|
+
.withThemeColor('#ff5722')
|
|
233
|
+
.withBackgroundColor('#ffffff')
|
|
234
|
+
.build();
|
|
235
|
+
|
|
236
|
+
expect(consoleWarn).not.toHaveBeenCalled();
|
|
237
|
+
expect(config.pwa.themeColor).toBe('#ff5722');
|
|
238
|
+
expect(config.pwa.backgroundColor).toBe('#ffffff');
|
|
239
|
+
|
|
240
|
+
consoleWarn.mockRestore();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should accept named colors', () => {
|
|
244
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
245
|
+
|
|
246
|
+
const config = AppConfigBuilder.create()
|
|
247
|
+
.withName('Test App')
|
|
248
|
+
.withId('test-app')
|
|
249
|
+
.withThemeColor('red')
|
|
250
|
+
.withBackgroundColor('white')
|
|
251
|
+
.build();
|
|
252
|
+
|
|
253
|
+
expect(consoleWarn).not.toHaveBeenCalled();
|
|
254
|
+
|
|
255
|
+
consoleWarn.mockRestore();
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should warn for potentially invalid colors', () => {
|
|
259
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
260
|
+
|
|
261
|
+
const config = AppConfigBuilder.create()
|
|
262
|
+
.withName('Test App')
|
|
263
|
+
.withId('test-app')
|
|
264
|
+
.withThemeColor('invalid-color')
|
|
265
|
+
.build();
|
|
266
|
+
|
|
267
|
+
expect(consoleWarn).toHaveBeenCalledWith(
|
|
268
|
+
'⚠️ AppConfig: Theme color may not be valid: invalid-color'
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
consoleWarn.mockRestore();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe('Config File Loading', () => {
|
|
276
|
+
it.skip('should load configuration from JSON file', () => {
|
|
277
|
+
const configData = {
|
|
278
|
+
app: {
|
|
279
|
+
name: 'Config App',
|
|
280
|
+
id: 'config-app',
|
|
281
|
+
version: '1.5.0'
|
|
282
|
+
},
|
|
283
|
+
build: {
|
|
284
|
+
port: 3500
|
|
285
|
+
},
|
|
286
|
+
pwa: {
|
|
287
|
+
themeColor: '#2196f3'
|
|
288
|
+
},
|
|
289
|
+
ui: {
|
|
290
|
+
defaultTheme: 'dark'
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
mockFs.readFileSync.mockReturnValue(JSON.stringify(configData));
|
|
295
|
+
|
|
296
|
+
const config = AppConfigBuilder.create()
|
|
297
|
+
.withConfig('./app.config.json')
|
|
298
|
+
.build();
|
|
299
|
+
|
|
300
|
+
expect(config.app.name).toBe('Config App');
|
|
301
|
+
expect(config.app.id).toBe('config-app');
|
|
302
|
+
expect(config.app.version).toBe('1.5.0');
|
|
303
|
+
expect(config.build.port).toBe(3500);
|
|
304
|
+
expect(config.pwa.themeColor).toBe('#2196f3');
|
|
305
|
+
expect(config.ui.defaultTheme).toBe('dark');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it.skip('should override config file values with builder methods', () => {
|
|
309
|
+
const configData = {
|
|
310
|
+
app: {
|
|
311
|
+
name: 'Config App',
|
|
312
|
+
id: 'config-app'
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
mockFs.readFileSync.mockReturnValue(JSON.stringify(configData));
|
|
317
|
+
|
|
318
|
+
const config = AppConfigBuilder.create()
|
|
319
|
+
.withConfig('./app.config.json')
|
|
320
|
+
.withName('Override App') // Override the config file value
|
|
321
|
+
.build();
|
|
322
|
+
|
|
323
|
+
expect(config.app.name).toBe('Override App');
|
|
324
|
+
expect(config.app.id).toBe('config-app');
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it.skip('should warn when config file cannot be loaded', () => {
|
|
328
|
+
const consoleWarn = jest.spyOn(console, 'warn').mockImplementation();
|
|
329
|
+
mockFs.readFileSync.mockImplementation(() => {
|
|
330
|
+
throw new Error('File not found');
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const config = AppConfigBuilder.create()
|
|
334
|
+
.withConfig('./missing.json')
|
|
335
|
+
.withName('Test App')
|
|
336
|
+
.withId('test-app')
|
|
337
|
+
.build();
|
|
338
|
+
|
|
339
|
+
expect(consoleWarn).toHaveBeenCalledWith(
|
|
340
|
+
'Warning: Could not load config file: ./missing.json'
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
consoleWarn.mockRestore();
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
describe('Computed Properties', () => {
|
|
348
|
+
it('should generate vite configuration', () => {
|
|
349
|
+
const config = AppConfigBuilder.create()
|
|
350
|
+
.withName('Test App')
|
|
351
|
+
.withId('test-app')
|
|
352
|
+
.withPort(3001)
|
|
353
|
+
.withPreviewPort(4001)
|
|
354
|
+
.withOutputDir('build')
|
|
355
|
+
.withBase('/app/')
|
|
356
|
+
.build();
|
|
357
|
+
|
|
358
|
+
const viteConfig = config.viteConfig;
|
|
359
|
+
|
|
360
|
+
expect(viteConfig.server?.port).toBe(3001);
|
|
361
|
+
expect(viteConfig.preview?.port).toBe(4001);
|
|
362
|
+
expect(viteConfig.build?.outDir).toBe('build');
|
|
363
|
+
expect(viteConfig.base).toBe('/app/');
|
|
364
|
+
expect(viteConfig.define?.__APP_NAME__).toBe('"Test App"');
|
|
365
|
+
expect(viteConfig.define?.__APP_ID__).toBe('"test-app"');
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('should generate PWA manifest', () => {
|
|
369
|
+
const config = AppConfigBuilder.create()
|
|
370
|
+
.withName('PWA Test App')
|
|
371
|
+
.withId('pwa-test')
|
|
372
|
+
.withShortName('PWA Test')
|
|
373
|
+
.withDescription('A PWA test application')
|
|
374
|
+
.withThemeColor('#4caf50')
|
|
375
|
+
.withBackgroundColor('#fafafa')
|
|
376
|
+
.withDisplay('fullscreen')
|
|
377
|
+
.build();
|
|
378
|
+
|
|
379
|
+
const manifest = config.pwaManifest;
|
|
380
|
+
|
|
381
|
+
expect(manifest.name).toBe('PWA Test App');
|
|
382
|
+
expect(manifest.short_name).toBe('PWA Test');
|
|
383
|
+
expect(manifest.description).toBe('A PWA test application');
|
|
384
|
+
expect(manifest.theme_color).toBe('#4caf50');
|
|
385
|
+
expect(manifest.background_color).toBe('#fafafa');
|
|
386
|
+
expect(manifest.display).toBe('fullscreen');
|
|
387
|
+
expect(manifest.icons).toHaveLength(2);
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
describe('Error Handling', () => {
|
|
392
|
+
it('should collect multiple errors and throw once', () => {
|
|
393
|
+
expect(() => {
|
|
394
|
+
AppConfigBuilder.create()
|
|
395
|
+
.withPort(0) // Invalid port
|
|
396
|
+
.withPreviewPort(100000) // Invalid port
|
|
397
|
+
.build(); // Missing name and ID
|
|
398
|
+
}).toThrow(/AppConfig validation failed/);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('should show all errors in the error message', () => {
|
|
402
|
+
try {
|
|
403
|
+
AppConfigBuilder.create()
|
|
404
|
+
.withPort(0)
|
|
405
|
+
.build();
|
|
406
|
+
} catch (error: any) {
|
|
407
|
+
const message = error.message;
|
|
408
|
+
expect(message).toContain('App name is required');
|
|
409
|
+
expect(message).toContain('App ID is required');
|
|
410
|
+
expect(message).toContain('Port must be a valid integer');
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
describe('Immutability', () => {
|
|
416
|
+
it('should create immutable configuration objects', () => {
|
|
417
|
+
const config = AppConfigBuilder.create()
|
|
418
|
+
.withName('Test App')
|
|
419
|
+
.withId('test-app')
|
|
420
|
+
.build();
|
|
421
|
+
|
|
422
|
+
// Attempt to modify the configuration should not work
|
|
423
|
+
expect(() => {
|
|
424
|
+
(config.app as any).name = 'Modified Name';
|
|
425
|
+
}).toThrow();
|
|
426
|
+
|
|
427
|
+
expect(() => {
|
|
428
|
+
(config as any).app = { name: 'New App' };
|
|
429
|
+
}).toThrow();
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QwickApps Configuration Module
|
|
3
|
+
*
|
|
4
|
+
* Exports configuration types and utilities for QwickApp applications.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { AppConfig } from './AppConfig';
|
|
10
|
+
export { AppConfigBuilder } from './AppConfigBuilder';
|
|
11
|
+
export type {
|
|
12
|
+
AppConfig as IAppConfig,
|
|
13
|
+
AppIdentity,
|
|
14
|
+
BuildConfig,
|
|
15
|
+
PWAConfig,
|
|
16
|
+
UIConfig,
|
|
17
|
+
CopyrightConfig,
|
|
18
|
+
AppConfigOptions,
|
|
19
|
+
ValidationResult,
|
|
20
|
+
} from './types';
|
|
21
|
+
|
|
22
|
+
// Re-export for convenience
|
|
23
|
+
import { AppConfigBuilder } from './AppConfigBuilder';
|
|
24
|
+
export const createAppConfig = AppConfigBuilder.create;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QwickApps AppConfig Types
|
|
3
|
+
*
|
|
4
|
+
* Defines the configuration contract for QwickApp applications.
|
|
5
|
+
* Separates static app configuration from runtime settings.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { UserConfig as ViteUserConfig } from 'vite';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Static, immutable application configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface AppConfig {
|
|
16
|
+
/** Application identity and metadata */
|
|
17
|
+
readonly app: AppIdentity;
|
|
18
|
+
|
|
19
|
+
/** Build and development settings */
|
|
20
|
+
readonly build: BuildConfig;
|
|
21
|
+
|
|
22
|
+
/** Progressive Web App configuration */
|
|
23
|
+
readonly pwa: PWAConfig;
|
|
24
|
+
|
|
25
|
+
/** Default theme and UI settings */
|
|
26
|
+
readonly ui: UIConfig;
|
|
27
|
+
|
|
28
|
+
/** Copyright and legal information */
|
|
29
|
+
readonly copyright: CopyrightConfig;
|
|
30
|
+
|
|
31
|
+
/** Computed Vite configuration */
|
|
32
|
+
readonly viteConfig: ViteUserConfig;
|
|
33
|
+
|
|
34
|
+
/** Computed PWA manifest */
|
|
35
|
+
readonly pwaManifest: Record<string, any>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Application identity and basic metadata
|
|
40
|
+
*/
|
|
41
|
+
export interface AppIdentity {
|
|
42
|
+
/** Unique application identifier */
|
|
43
|
+
readonly id: string;
|
|
44
|
+
|
|
45
|
+
/** Full application name */
|
|
46
|
+
readonly name: string;
|
|
47
|
+
|
|
48
|
+
/** Short name for PWA and limited spaces */
|
|
49
|
+
readonly shortName: string;
|
|
50
|
+
|
|
51
|
+
/** Application description */
|
|
52
|
+
readonly description: string;
|
|
53
|
+
|
|
54
|
+
/** Application version */
|
|
55
|
+
readonly version: string;
|
|
56
|
+
|
|
57
|
+
/** Path to application logo/icon */
|
|
58
|
+
readonly logo: string;
|
|
59
|
+
|
|
60
|
+
/** Application author/organization */
|
|
61
|
+
readonly author?: string;
|
|
62
|
+
|
|
63
|
+
/** Application homepage URL */
|
|
64
|
+
readonly homepage?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Build and development configuration
|
|
69
|
+
*/
|
|
70
|
+
export interface BuildConfig {
|
|
71
|
+
/** Development server port */
|
|
72
|
+
readonly port: number;
|
|
73
|
+
|
|
74
|
+
/** Preview server port */
|
|
75
|
+
readonly previewPort: number;
|
|
76
|
+
|
|
77
|
+
/** Build output directory */
|
|
78
|
+
readonly outputDir: string;
|
|
79
|
+
|
|
80
|
+
/** Public path for assets */
|
|
81
|
+
readonly publicPath: string;
|
|
82
|
+
|
|
83
|
+
/** Base URL for the application */
|
|
84
|
+
readonly base: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Progressive Web App configuration
|
|
89
|
+
*/
|
|
90
|
+
export interface PWAConfig {
|
|
91
|
+
/** PWA theme color */
|
|
92
|
+
readonly themeColor: string;
|
|
93
|
+
|
|
94
|
+
/** PWA background color */
|
|
95
|
+
readonly backgroundColor: string;
|
|
96
|
+
|
|
97
|
+
/** PWA start URL */
|
|
98
|
+
readonly startUrl: string;
|
|
99
|
+
|
|
100
|
+
/** PWA scope */
|
|
101
|
+
readonly scope: string;
|
|
102
|
+
|
|
103
|
+
/** PWA display mode */
|
|
104
|
+
readonly display: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';
|
|
105
|
+
|
|
106
|
+
/** PWA orientation */
|
|
107
|
+
readonly orientation?: 'portrait' | 'landscape' | 'any';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Default UI and theme configuration
|
|
112
|
+
*/
|
|
113
|
+
export interface UIConfig {
|
|
114
|
+
/** Default theme mode */
|
|
115
|
+
readonly defaultTheme: 'light' | 'dark' | 'system';
|
|
116
|
+
|
|
117
|
+
/** Default color palette */
|
|
118
|
+
readonly defaultPalette: string;
|
|
119
|
+
|
|
120
|
+
/** Enable scaffolding (navigation, layout) */
|
|
121
|
+
readonly enableScaffolding: boolean;
|
|
122
|
+
|
|
123
|
+
/** Show theme switcher */
|
|
124
|
+
readonly showThemeSwitcher: boolean;
|
|
125
|
+
|
|
126
|
+
/** Show palette switcher */
|
|
127
|
+
readonly showPaletteSwitcher: boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Copyright and legal information
|
|
132
|
+
*/
|
|
133
|
+
export interface CopyrightConfig {
|
|
134
|
+
/** Copyright year ('auto' for current year or specific year) */
|
|
135
|
+
readonly year: 'auto' | number;
|
|
136
|
+
|
|
137
|
+
/** Copyright holder/owner */
|
|
138
|
+
readonly author: string;
|
|
139
|
+
|
|
140
|
+
/** Additional legal text */
|
|
141
|
+
readonly text?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Configuration builder options
|
|
146
|
+
*/
|
|
147
|
+
export interface AppConfigOptions {
|
|
148
|
+
/** Base directory for resolving relative paths */
|
|
149
|
+
baseDir?: string;
|
|
150
|
+
|
|
151
|
+
/** Environment (development, production, test) */
|
|
152
|
+
env?: string;
|
|
153
|
+
|
|
154
|
+
/** Skip file existence validation */
|
|
155
|
+
skipValidation?: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Validation result
|
|
160
|
+
*/
|
|
161
|
+
export interface ValidationResult {
|
|
162
|
+
/** Validation warnings */
|
|
163
|
+
warnings: string[];
|
|
164
|
+
|
|
165
|
+
/** Validation errors */
|
|
166
|
+
errors: string[];
|
|
167
|
+
|
|
168
|
+
/** Whether configuration is valid */
|
|
169
|
+
isValid: boolean;
|
|
170
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QwickApps Configuration Module Entry
|
|
3
|
+
*
|
|
4
|
+
* Lightweight export for config-only usage at build time.
|
|
5
|
+
* This file only exports configuration types and builders
|
|
6
|
+
* without pulling in React or MUI dependencies.
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { AppConfig } from './config/AppConfig';
|
|
12
|
+
export { AppConfigBuilder } from './config/AppConfigBuilder';
|
|
13
|
+
export type {
|
|
14
|
+
AppConfig as IAppConfig,
|
|
15
|
+
AppIdentity,
|
|
16
|
+
BuildConfig,
|
|
17
|
+
PWAConfig,
|
|
18
|
+
UIConfig,
|
|
19
|
+
AppConfigOptions,
|
|
20
|
+
ValidationResult,
|
|
21
|
+
} from './config/types';
|
|
22
|
+
|
|
23
|
+
// Re-export for convenience
|
|
24
|
+
import { AppConfigBuilder } from './config/AppConfigBuilder';
|
|
25
|
+
export const createAppConfig = AppConfigBuilder.create;
|