@akanjs/cli 0.0.142 → 0.0.144
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 +8 -0
- package/cjs/index.js +2437 -3204
- package/cjs/src/guidelines/___library/sharedUiStructureDescription.en.md +786 -0
- package/cjs/src/guidelines/___library/utilUiStructureDescription.en.md +395 -0
- package/cjs/src/guidelines/___lint/lintRuleDescription.en.md +64 -0
- package/cjs/src/guidelines/___module/moduleStructureDescription.en.md +80 -0
- package/cjs/src/guidelines/componentRule/componentRule.instruction.md +732 -0
- package/cjs/src/guidelines/databaseModule/databaseModule.instruction.md +691 -0
- package/cjs/src/guidelines/enumConstant/enumConstant.instruction.md +232 -0
- package/cjs/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +611 -0
- package/cjs/src/guidelines/framework/framework.instruction.md +1112 -0
- package/cjs/src/guidelines/modelConstant/modelConstant.instruction.md +958 -0
- package/cjs/src/guidelines/modelDictionary/modelDictionary.instruction.md +583 -0
- package/cjs/src/guidelines/modelDocument/modelDocument.instruction.md +683 -0
- package/cjs/src/guidelines/modelService/modelService.instruction.md +935 -0
- package/cjs/src/guidelines/modelSignal/modelSignal.instruction.md +588 -0
- package/cjs/src/guidelines/modelStore/modelStore.instruction.md +591 -0
- package/cjs/src/guidelines/modelTemplate/modelTemplate.instruction.md +577 -0
- package/cjs/src/guidelines/modelUnit/modelUnit.instruction.md +833 -0
- package/cjs/src/guidelines/modelUtil/modelUtil.instruction.md +752 -0
- package/cjs/src/guidelines/modelView/modelView.instruction.md +1005 -0
- package/cjs/src/guidelines/modelZone/modelZone.instruction.md +528 -0
- package/cjs/src/guidelines/scalarConstant/scalarConstant.instruction.md +489 -0
- package/cjs/src/guidelines/scalarDictionary/scalarDictionary.instruction.md +347 -0
- package/cjs/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +318 -0
- package/cjs/src/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
- package/cjs/src/templates/module/__model__.dictionary.js +4 -5
- package/esm/index.js +2524 -3286
- package/esm/src/guidelines/___library/sharedUiStructureDescription.en.md +786 -0
- package/esm/src/guidelines/___library/utilUiStructureDescription.en.md +395 -0
- package/esm/src/guidelines/___lint/lintRuleDescription.en.md +64 -0
- package/esm/src/guidelines/___module/moduleStructureDescription.en.md +80 -0
- package/esm/src/guidelines/componentRule/componentRule.instruction.md +732 -0
- package/esm/src/guidelines/databaseModule/databaseModule.instruction.md +691 -0
- package/esm/src/guidelines/enumConstant/enumConstant.instruction.md +232 -0
- package/esm/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +611 -0
- package/esm/src/guidelines/framework/framework.instruction.md +1112 -0
- package/esm/src/guidelines/modelConstant/modelConstant.instruction.md +958 -0
- package/esm/src/guidelines/modelDictionary/modelDictionary.instruction.md +583 -0
- package/esm/src/guidelines/modelDocument/modelDocument.instruction.md +683 -0
- package/esm/src/guidelines/modelService/modelService.instruction.md +935 -0
- package/esm/src/guidelines/modelSignal/modelSignal.instruction.md +588 -0
- package/esm/src/guidelines/modelStore/modelStore.instruction.md +591 -0
- package/esm/src/guidelines/modelTemplate/modelTemplate.instruction.md +577 -0
- package/esm/src/guidelines/modelUnit/modelUnit.instruction.md +833 -0
- package/esm/src/guidelines/modelUtil/modelUtil.instruction.md +752 -0
- package/esm/src/guidelines/modelView/modelView.instruction.md +1005 -0
- package/esm/src/guidelines/modelZone/modelZone.instruction.md +528 -0
- package/esm/src/guidelines/scalarConstant/scalarConstant.instruction.md +489 -0
- package/esm/src/guidelines/scalarDictionary/scalarDictionary.instruction.md +347 -0
- package/esm/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +318 -0
- package/esm/src/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
- package/esm/src/templates/module/__model__.dictionary.js +4 -5
- package/package.json +3 -1
- package/src/guideline/guideline.command.d.ts +7 -0
- package/src/guideline/guideline.prompt.d.ts +15 -0
- package/src/guideline/guideline.runner.d.ts +5 -0
- package/src/guideline/guideline.script.d.ts +6 -0
- package/src/guidelines/___library/sharedUiStructureDescription.en.md +786 -0
- package/src/guidelines/___library/utilUiStructureDescription.en.md +395 -0
- package/src/guidelines/___lint/lintRuleDescription.en.md +64 -0
- package/src/guidelines/___module/moduleStructureDescription.en.md +80 -0
- package/src/guidelines/componentRule/componentRule.instruction.md +732 -0
- package/src/guidelines/databaseModule/databaseModule.instruction.md +691 -0
- package/src/guidelines/enumConstant/enumConstant.instruction.md +232 -0
- package/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +611 -0
- package/src/guidelines/framework/framework.instruction.md +1112 -0
- package/src/guidelines/modelConstant/modelConstant.instruction.md +958 -0
- package/src/guidelines/modelDictionary/modelDictionary.instruction.md +583 -0
- package/src/guidelines/modelDocument/modelDocument.instruction.md +683 -0
- package/src/guidelines/modelService/modelService.instruction.md +935 -0
- package/src/guidelines/modelSignal/modelSignal.instruction.md +588 -0
- package/src/guidelines/modelStore/modelStore.instruction.md +591 -0
- package/src/guidelines/modelTemplate/modelTemplate.instruction.md +577 -0
- package/src/guidelines/modelUnit/modelUnit.instruction.md +833 -0
- package/src/guidelines/modelUtil/modelUtil.instruction.md +752 -0
- package/src/guidelines/modelView/modelView.instruction.md +1005 -0
- package/src/guidelines/modelZone/modelZone.instruction.md +528 -0
- package/src/guidelines/scalarConstant/scalarConstant.instruction.md +489 -0
- package/src/guidelines/scalarDictionary/scalarDictionary.instruction.md +347 -0
- package/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +318 -0
- package/src/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
- package/src/module/module.command.d.ts +6 -8
- package/src/module/module.prompt.d.ts +2 -15
- package/src/module/module.request.d.ts +22 -18
- package/src/module/module.runner.d.ts +4 -20
- package/src/module/module.script.d.ts +6 -7
- package/src/scalar/scalar.command.d.ts +7 -0
- package/src/scalar/scalar.prompt.d.ts +23 -0
- package/src/scalar/scalar.runner.d.ts +13 -0
- package/src/scalar/scalar.script.d.ts +6 -0
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/page.js +0 -47
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/page.js +0 -128
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/page.js +0 -42
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/signin/page.js +0 -50
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/page.js +0 -41
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.js +0 -51
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(user)/layout.js +0 -43
- package/cjs/src/templates/app/app/[lang]/(__appName__)/(user)/self/page.js +0 -60
- package/cjs/src/templates/app/app/[lang]/(__appName__)/layout.js +0 -54
- package/cjs/src/templates/app/app/[lang]/(__appName__)/styles.css.template +0 -19
- package/cjs/src/templates/app/app/[lang]/admin/layout.js +0 -54
- package/cjs/src/templates/app/app/[lang]/admin/page.js +0 -63
- package/cjs/src/templates/app/app/csr.js +0 -34
- package/cjs/src/templates/app/app/index.html.template +0 -13
- package/cjs/src/templates/app/app/layout.js +0 -38
- package/cjs/src/templates/app/capacitor.config.ts.template +0 -8
- package/cjs/src/templates/app/env/env.client.debug.ts.template +0 -7
- package/cjs/src/templates/app/env/env.client.develop.ts.template +0 -7
- package/cjs/src/templates/app/env/env.client.local.ts.template +0 -7
- package/cjs/src/templates/app/env/env.client.main.ts.template +0 -7
- package/cjs/src/templates/app/env/env.client.testing.ts.template +0 -7
- package/cjs/src/templates/app/env/env.server.debug.ts.template +0 -15
- package/cjs/src/templates/app/env/env.server.develop.ts.template +0 -15
- package/cjs/src/templates/app/env/env.server.local.ts.template +0 -15
- package/cjs/src/templates/app/env/env.server.main.ts.template +0 -15
- package/cjs/src/templates/app/env/env.server.testing.ts.template +0 -7
- package/cjs/src/templates/app/lib/setting/Setting.Template.js +0 -57
- package/cjs/src/templates/app/lib/setting/Setting.Unit.js +0 -38
- package/cjs/src/templates/app/lib/setting/Setting.Util.js +0 -34
- package/cjs/src/templates/app/lib/setting/Setting.View.js +0 -51
- package/cjs/src/templates/app/lib/setting/Setting.Zone.js +0 -80
- package/cjs/src/templates/app/lib/setting/index.js +0 -61
- package/cjs/src/templates/app/lib/summary/Summary.Template.js +0 -43
- package/cjs/src/templates/app/lib/summary/Summary.Unit.js +0 -38
- package/cjs/src/templates/app/lib/summary/Summary.Util.js +0 -33
- package/cjs/src/templates/app/lib/summary/Summary.View.js +0 -51
- package/cjs/src/templates/app/lib/summary/Summary.Zone.js +0 -62
- package/cjs/src/templates/app/lib/summary/index.js +0 -67
- package/cjs/src/templates/app/lib/user/User.Template.js +0 -65
- package/cjs/src/templates/app/lib/user/User.Unit.js +0 -38
- package/cjs/src/templates/app/lib/user/User.Util.js +0 -94
- package/cjs/src/templates/app/lib/user/User.View.js +0 -66
- package/cjs/src/templates/app/lib/user/User.Zone.js +0 -74
- package/cjs/src/templates/app/lib/user/index.js +0 -61
- package/cjs/src/templates/app/page.test.ts.template +0 -10
- package/cjs/src/templates/app/playwright.config.ts.template +0 -6
- package/cjs/src/templates/app/postcss.config.js.template +0 -10
- package/cjs/src/templates/app/public/manifest.json.template +0 -67
- package/cjs/src/templates/app/tsconfig.json.template +0 -22
- package/cjs/src/templates/app/tsconfig.spec.json.template +0 -7
- package/cjs/src/templates/app/ui/Footer.js +0 -67
- package/cjs/src/templates/app/ui/MainHeader.js +0 -131
- package/cjs/src/templates/crudPages/[__model__Id]/edit/page.js +0 -73
- package/cjs/src/templates/crudPages/[__model__Id]/page.js +0 -83
- package/cjs/src/templates/crudPages/new/page.js +0 -70
- package/cjs/src/templates/crudPages/page.js +0 -71
- package/cjs/src/templates/libRoot/.gitignore.template +0 -15
- package/cjs/src/templates/libRoot/env/env.server.example.ts.template +0 -7
- package/cjs/src/templates/libRoot/env/env.server.testing.ts.template +0 -7
- package/cjs/src/templates/libRoot/lib/setting/Setting.Template.js +0 -57
- package/cjs/src/templates/libRoot/lib/setting/Setting.Unit.js +0 -38
- package/cjs/src/templates/libRoot/lib/setting/Setting.Util.js +0 -34
- package/cjs/src/templates/libRoot/lib/setting/Setting.View.js +0 -51
- package/cjs/src/templates/libRoot/lib/setting/Setting.Zone.js +0 -80
- package/cjs/src/templates/libRoot/lib/setting/index.js +0 -61
- package/cjs/src/templates/libRoot/lib/summary/Summary.Template.js +0 -43
- package/cjs/src/templates/libRoot/lib/summary/Summary.Unit.js +0 -38
- package/cjs/src/templates/libRoot/lib/summary/Summary.Util.js +0 -33
- package/cjs/src/templates/libRoot/lib/summary/Summary.View.js +0 -51
- package/cjs/src/templates/libRoot/lib/summary/Summary.Zone.js +0 -62
- package/cjs/src/templates/libRoot/lib/summary/index.js +0 -67
- package/cjs/src/templates/libRoot/lib/user/User.Template.js +0 -65
- package/cjs/src/templates/libRoot/lib/user/User.Unit.js +0 -38
- package/cjs/src/templates/libRoot/lib/user/User.Util.js +0 -94
- package/cjs/src/templates/libRoot/lib/user/User.View.js +0 -66
- package/cjs/src/templates/libRoot/lib/user/User.Zone.js +0 -74
- package/cjs/src/templates/libRoot/lib/user/index.js +0 -61
- package/cjs/src/templates/libRoot/package.json.template +0 -4
- package/cjs/src/templates/libRoot/tsconfig.json.template +0 -13
- package/cjs/src/templates/libRoot/tsconfig.spec.json.template +0 -7
- package/cjs/src/templates/localDev/docker-compose.yaml.template +0 -36
- package/cjs/src/templates/module/__Model__.Template.js +0 -54
- package/cjs/src/templates/module/__Model__.Unit.js +0 -42
- package/cjs/src/templates/module/__Model__.Util.js +0 -70
- package/cjs/src/templates/module/__Model__.View.js +0 -48
- package/cjs/src/templates/module/__Model__.Zone.js +0 -83
- package/cjs/src/templates/module/index.js +0 -61
- package/cjs/src/templates/pkgRoot/tsconfig.json.template +0 -15
- package/cjs/src/templates/workspaceRoot/.env.template +0 -20
- package/cjs/src/templates/workspaceRoot/.gitignore.template +0 -118
- package/cjs/src/templates/workspaceRoot/.prettierignore.template +0 -10
- package/cjs/src/templates/workspaceRoot/.prettierrc.json.template +0 -6
- package/cjs/src/templates/workspaceRoot/.swcrc.template +0 -9
- package/cjs/src/templates/workspaceRoot/.vscode/settings.json.template +0 -13
- package/cjs/src/templates/workspaceRoot/README.md.template +0 -37
- package/cjs/src/templates/workspaceRoot/eslint.config.ts.template +0 -3
- package/cjs/src/templates/workspaceRoot/package.json.template +0 -43
- package/cjs/src/templates/workspaceRoot/tsconfig.json.template +0 -29
- package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/page.js +0 -27
- package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/page.js +0 -108
- package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/page.js +0 -22
- package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/signin/page.js +0 -30
- package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/page.js +0 -21
- package/esm/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.js +0 -31
- package/esm/src/templates/app/app/[lang]/(__appName__)/(user)/layout.js +0 -23
- package/esm/src/templates/app/app/[lang]/(__appName__)/(user)/self/page.js +0 -40
- package/esm/src/templates/app/app/[lang]/(__appName__)/layout.js +0 -34
- package/esm/src/templates/app/app/[lang]/(__appName__)/styles.css.template +0 -19
- package/esm/src/templates/app/app/[lang]/admin/layout.js +0 -34
- package/esm/src/templates/app/app/[lang]/admin/page.js +0 -43
- package/esm/src/templates/app/app/csr.js +0 -14
- package/esm/src/templates/app/app/index.html.template +0 -13
- package/esm/src/templates/app/app/layout.js +0 -18
- package/esm/src/templates/app/capacitor.config.ts.template +0 -8
- package/esm/src/templates/app/env/env.client.debug.ts.template +0 -7
- package/esm/src/templates/app/env/env.client.develop.ts.template +0 -7
- package/esm/src/templates/app/env/env.client.local.ts.template +0 -7
- package/esm/src/templates/app/env/env.client.main.ts.template +0 -7
- package/esm/src/templates/app/env/env.client.testing.ts.template +0 -7
- package/esm/src/templates/app/env/env.server.debug.ts.template +0 -15
- package/esm/src/templates/app/env/env.server.develop.ts.template +0 -15
- package/esm/src/templates/app/env/env.server.local.ts.template +0 -15
- package/esm/src/templates/app/env/env.server.main.ts.template +0 -15
- package/esm/src/templates/app/env/env.server.testing.ts.template +0 -7
- package/esm/src/templates/app/lib/setting/Setting.Template.js +0 -37
- package/esm/src/templates/app/lib/setting/Setting.Unit.js +0 -18
- package/esm/src/templates/app/lib/setting/Setting.Util.js +0 -14
- package/esm/src/templates/app/lib/setting/Setting.View.js +0 -31
- package/esm/src/templates/app/lib/setting/Setting.Zone.js +0 -60
- package/esm/src/templates/app/lib/setting/index.js +0 -41
- package/esm/src/templates/app/lib/summary/Summary.Template.js +0 -23
- package/esm/src/templates/app/lib/summary/Summary.Unit.js +0 -18
- package/esm/src/templates/app/lib/summary/Summary.Util.js +0 -13
- package/esm/src/templates/app/lib/summary/Summary.View.js +0 -31
- package/esm/src/templates/app/lib/summary/Summary.Zone.js +0 -42
- package/esm/src/templates/app/lib/summary/index.js +0 -47
- package/esm/src/templates/app/lib/user/User.Template.js +0 -45
- package/esm/src/templates/app/lib/user/User.Unit.js +0 -18
- package/esm/src/templates/app/lib/user/User.Util.js +0 -74
- package/esm/src/templates/app/lib/user/User.View.js +0 -46
- package/esm/src/templates/app/lib/user/User.Zone.js +0 -54
- package/esm/src/templates/app/lib/user/index.js +0 -41
- package/esm/src/templates/app/page.test.ts.template +0 -10
- package/esm/src/templates/app/playwright.config.ts.template +0 -6
- package/esm/src/templates/app/postcss.config.js.template +0 -10
- package/esm/src/templates/app/public/manifest.json.template +0 -67
- package/esm/src/templates/app/tsconfig.json.template +0 -22
- package/esm/src/templates/app/tsconfig.spec.json.template +0 -7
- package/esm/src/templates/app/ui/Footer.js +0 -47
- package/esm/src/templates/app/ui/MainHeader.js +0 -111
- package/esm/src/templates/crudPages/[__model__Id]/edit/page.js +0 -53
- package/esm/src/templates/crudPages/[__model__Id]/page.js +0 -63
- package/esm/src/templates/crudPages/new/page.js +0 -50
- package/esm/src/templates/crudPages/page.js +0 -51
- package/esm/src/templates/libRoot/.gitignore.template +0 -15
- package/esm/src/templates/libRoot/env/env.server.example.ts.template +0 -7
- package/esm/src/templates/libRoot/env/env.server.testing.ts.template +0 -7
- package/esm/src/templates/libRoot/lib/setting/Setting.Template.js +0 -37
- package/esm/src/templates/libRoot/lib/setting/Setting.Unit.js +0 -18
- package/esm/src/templates/libRoot/lib/setting/Setting.Util.js +0 -14
- package/esm/src/templates/libRoot/lib/setting/Setting.View.js +0 -31
- package/esm/src/templates/libRoot/lib/setting/Setting.Zone.js +0 -60
- package/esm/src/templates/libRoot/lib/setting/index.js +0 -41
- package/esm/src/templates/libRoot/lib/summary/Summary.Template.js +0 -23
- package/esm/src/templates/libRoot/lib/summary/Summary.Unit.js +0 -18
- package/esm/src/templates/libRoot/lib/summary/Summary.Util.js +0 -13
- package/esm/src/templates/libRoot/lib/summary/Summary.View.js +0 -31
- package/esm/src/templates/libRoot/lib/summary/Summary.Zone.js +0 -42
- package/esm/src/templates/libRoot/lib/summary/index.js +0 -47
- package/esm/src/templates/libRoot/lib/user/User.Template.js +0 -45
- package/esm/src/templates/libRoot/lib/user/User.Unit.js +0 -18
- package/esm/src/templates/libRoot/lib/user/User.Util.js +0 -74
- package/esm/src/templates/libRoot/lib/user/User.View.js +0 -46
- package/esm/src/templates/libRoot/lib/user/User.Zone.js +0 -54
- package/esm/src/templates/libRoot/lib/user/index.js +0 -41
- package/esm/src/templates/libRoot/package.json.template +0 -4
- package/esm/src/templates/libRoot/tsconfig.json.template +0 -13
- package/esm/src/templates/libRoot/tsconfig.spec.json.template +0 -7
- package/esm/src/templates/localDev/docker-compose.yaml.template +0 -36
- package/esm/src/templates/module/__Model__.Template.js +0 -34
- package/esm/src/templates/module/__Model__.Unit.js +0 -22
- package/esm/src/templates/module/__Model__.Util.js +0 -50
- package/esm/src/templates/module/__Model__.View.js +0 -28
- package/esm/src/templates/module/__Model__.Zone.js +0 -63
- package/esm/src/templates/module/index.js +0 -41
- package/esm/src/templates/pkgRoot/tsconfig.json.template +0 -15
- package/esm/src/templates/workspaceRoot/.env.template +0 -20
- package/esm/src/templates/workspaceRoot/.gitignore.template +0 -118
- package/esm/src/templates/workspaceRoot/.prettierignore.template +0 -10
- package/esm/src/templates/workspaceRoot/.prettierrc.json.template +0 -6
- package/esm/src/templates/workspaceRoot/.swcrc.template +0 -9
- package/esm/src/templates/workspaceRoot/.vscode/settings.json.template +0 -13
- package/esm/src/templates/workspaceRoot/README.md.template +0 -37
- package/esm/src/templates/workspaceRoot/eslint.config.ts.template +0 -3
- package/esm/src/templates/workspaceRoot/package.json.template +0 -43
- package/esm/src/templates/workspaceRoot/tsconfig.json.template +0 -29
- package/src/application/application.prompt.d.ts +0 -2
- package/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/page.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/(public)/page.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/page.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/(public)/signin/page.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/page.d.ts +0 -10
- package/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/(user)/layout.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/(user)/self/page.d.ts +0 -9
- package/src/templates/app/app/[lang]/(__appName__)/layout.d.ts +0 -9
- package/src/templates/app/app/[lang]/admin/layout.d.ts +0 -9
- package/src/templates/app/app/[lang]/admin/page.d.ts +0 -9
- package/src/templates/app/app/csr.d.ts +0 -9
- package/src/templates/app/app/layout.d.ts +0 -9
- package/src/templates/app/lib/setting/Setting.Template.d.ts +0 -9
- package/src/templates/app/lib/setting/Setting.Unit.d.ts +0 -9
- package/src/templates/app/lib/setting/Setting.Util.d.ts +0 -9
- package/src/templates/app/lib/setting/Setting.View.d.ts +0 -9
- package/src/templates/app/lib/setting/Setting.Zone.d.ts +0 -9
- package/src/templates/app/lib/setting/index.d.ts +0 -9
- package/src/templates/app/lib/summary/Summary.Template.d.ts +0 -9
- package/src/templates/app/lib/summary/Summary.Unit.d.ts +0 -9
- package/src/templates/app/lib/summary/Summary.Util.d.ts +0 -9
- package/src/templates/app/lib/summary/Summary.View.d.ts +0 -9
- package/src/templates/app/lib/summary/Summary.Zone.d.ts +0 -9
- package/src/templates/app/lib/summary/index.d.ts +0 -9
- package/src/templates/app/lib/user/User.Template.d.ts +0 -9
- package/src/templates/app/lib/user/User.Unit.d.ts +0 -9
- package/src/templates/app/lib/user/User.Util.d.ts +0 -9
- package/src/templates/app/lib/user/User.View.d.ts +0 -9
- package/src/templates/app/lib/user/User.Zone.d.ts +0 -9
- package/src/templates/app/lib/user/index.d.ts +0 -9
- package/src/templates/app/ui/Footer.d.ts +0 -9
- package/src/templates/app/ui/MainHeader.d.ts +0 -10
- package/src/templates/crudPages/[__model__Id]/edit/page.d.ts +0 -11
- package/src/templates/crudPages/[__model__Id]/page.d.ts +0 -11
- package/src/templates/crudPages/new/page.d.ts +0 -11
- package/src/templates/crudPages/page.d.ts +0 -11
- package/src/templates/libRoot/lib/setting/Setting.Template.d.ts +0 -9
- package/src/templates/libRoot/lib/setting/Setting.Unit.d.ts +0 -9
- package/src/templates/libRoot/lib/setting/Setting.Util.d.ts +0 -9
- package/src/templates/libRoot/lib/setting/Setting.View.d.ts +0 -9
- package/src/templates/libRoot/lib/setting/Setting.Zone.d.ts +0 -9
- package/src/templates/libRoot/lib/setting/index.d.ts +0 -9
- package/src/templates/libRoot/lib/summary/Summary.Template.d.ts +0 -9
- package/src/templates/libRoot/lib/summary/Summary.Unit.d.ts +0 -9
- package/src/templates/libRoot/lib/summary/Summary.Util.d.ts +0 -9
- package/src/templates/libRoot/lib/summary/Summary.View.d.ts +0 -9
- package/src/templates/libRoot/lib/summary/Summary.Zone.d.ts +0 -9
- package/src/templates/libRoot/lib/summary/index.d.ts +0 -9
- package/src/templates/libRoot/lib/user/User.Template.d.ts +0 -9
- package/src/templates/libRoot/lib/user/User.Unit.d.ts +0 -9
- package/src/templates/libRoot/lib/user/User.Util.d.ts +0 -9
- package/src/templates/libRoot/lib/user/User.View.d.ts +0 -9
- package/src/templates/libRoot/lib/user/User.Zone.d.ts +0 -9
- package/src/templates/libRoot/lib/user/index.d.ts +0 -9
- package/src/templates/module/__Model__.Template.d.ts +0 -11
- package/src/templates/module/__Model__.Unit.d.ts +0 -11
- package/src/templates/module/__Model__.Util.d.ts +0 -11
- package/src/templates/module/__Model__.View.d.ts +0 -11
- package/src/templates/module/__Model__.Zone.d.ts +0 -11
- package/src/templates/module/index.d.ts +0 -11
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
# Model Store Implementation Guide
|
|
2
|
+
|
|
3
|
+
## Purpose and Role of model.store.ts
|
|
4
|
+
|
|
5
|
+
The `model.store.ts` file is a crucial component in the Akan.js framework that serves as the state management layer connecting your UI components with GraphQL operations. Built on Zustand, model stores provide:
|
|
6
|
+
|
|
7
|
+
1. **Centralized State Management**: Single source of truth for model data
|
|
8
|
+
2. **GraphQL Integration**: Automatic CRUD operations with backend services
|
|
9
|
+
3. **Form Handling**: Comprehensive form state, validation, and submission
|
|
10
|
+
4. **Reactive UI Updates**: Optimized re-rendering through selectors
|
|
11
|
+
5. **Business Logic**: Centralized place for domain-specific operations
|
|
12
|
+
6. **Sliced Data Access**: Contextual data lists with pagination, filtering, and sorting
|
|
13
|
+
|
|
14
|
+
## Store Architecture Overview
|
|
15
|
+
|
|
16
|
+
Model stores follow a consistent architecture pattern:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
20
|
+
│ model.store.ts │ ←── │ fetch.ts │ ←─ │ model.signal.ts│
|
|
21
|
+
│ (Zustand) │ │ (GraphQL API) │ │ (Backend API) │
|
|
22
|
+
└────────┬────────┘ └─────────────────┘ └─────────────────┘
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
26
|
+
│ st.ts │ ──→ │ Components │
|
|
27
|
+
│ (Store Registry) │ │ (React/UI) │
|
|
28
|
+
└─────────────────┘ └─────────────────┘
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Basic Store Implementation
|
|
32
|
+
|
|
33
|
+
### Store Structure
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { stateOf, Store } from "@akanjs/store";
|
|
37
|
+
import { cnst } from "../cnst";
|
|
38
|
+
import { fetch } from "../fetch";
|
|
39
|
+
|
|
40
|
+
@Store(() => cnst.Product)
|
|
41
|
+
export class ProductStore extends stateOf(fetch.productGql, {
|
|
42
|
+
// Custom state properties
|
|
43
|
+
featuredProducts: [] as cnst.LightProduct[],
|
|
44
|
+
viewMode: "grid" as "grid" | "list",
|
|
45
|
+
}) {
|
|
46
|
+
// Custom actions
|
|
47
|
+
async featureProduct(id: string) {
|
|
48
|
+
const product = await fetch.featureProduct(id);
|
|
49
|
+
this.set({
|
|
50
|
+
featuredProducts: [...this.get().featuredProducts, product],
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Core Components
|
|
57
|
+
|
|
58
|
+
1. **`@Store` Decorator**: Registers the store class with metadata
|
|
59
|
+
2. **`stateOf` Function**: Creates the base store with generated state and actions
|
|
60
|
+
3. **Custom State**: Additional state properties specific to your model
|
|
61
|
+
4. **Custom Actions**: Business logic methods for model operations
|
|
62
|
+
|
|
63
|
+
## State Management
|
|
64
|
+
|
|
65
|
+
### Base State (Automatically Generated)
|
|
66
|
+
|
|
67
|
+
Each store automatically creates the following state properties:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Standard state properties
|
|
71
|
+
{
|
|
72
|
+
model: null, // Current active model instance
|
|
73
|
+
modelList: [], // Main list of models
|
|
74
|
+
modelForm: {}, // Form state for create/update
|
|
75
|
+
modelLoading: false, // Loading state for current model
|
|
76
|
+
modelListLoading: false, // Loading state for model list
|
|
77
|
+
modelFormLoading: false, // Loading state for form submission
|
|
78
|
+
modelTotal: 0, // Total count of models
|
|
79
|
+
modelPage: 1, // Current page number
|
|
80
|
+
modelLimit: 20, // Items per page
|
|
81
|
+
modelSort: "createdAt", // Current sort field
|
|
82
|
+
modelQuery: {}, // Query arguments for filtering
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Custom State
|
|
87
|
+
|
|
88
|
+
Add custom state properties in the second parameter of `stateOf`:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
extends stateOf(fetch.productGql, {
|
|
92
|
+
// UI state
|
|
93
|
+
productViewMode: "grid" as "grid" | "list",
|
|
94
|
+
selectedProductIds: [] as string[],
|
|
95
|
+
|
|
96
|
+
// Business state
|
|
97
|
+
featuredProducts: [] as cnst.LightProduct[],
|
|
98
|
+
productAnalytics: null as ProductAnalytics | null,
|
|
99
|
+
|
|
100
|
+
// Complex state
|
|
101
|
+
productCategoryMap: new Map<string, cnst.ProductCategory[]>(),
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Accessing State
|
|
106
|
+
|
|
107
|
+
In your store actions, use these methods to access state:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// Get the entire state
|
|
111
|
+
const state = this.get();
|
|
112
|
+
|
|
113
|
+
// Get specific properties
|
|
114
|
+
const { productList, selectedProductIds } = this.pick("productList", "selectedProductIds");
|
|
115
|
+
|
|
116
|
+
// Set state (triggers UI updates)
|
|
117
|
+
this.set({ productViewMode: "list" });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Store Actions
|
|
121
|
+
|
|
122
|
+
### Core Actions (Automatically Generated)
|
|
123
|
+
|
|
124
|
+
Each store comes with standard CRUD operations:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Core model actions
|
|
128
|
+
st.do.createModel(); // Create a new model
|
|
129
|
+
st.do.updateModel(); // Update an existing model
|
|
130
|
+
st.do.removeModel(); // Delete a model
|
|
131
|
+
st.do.getModel(); // Get a single model by ID
|
|
132
|
+
st.do.listModel(); // Get a list of models
|
|
133
|
+
|
|
134
|
+
// Initialization
|
|
135
|
+
st.do.initModel(); // Initialize the store
|
|
136
|
+
st.do.refreshModel(); // Refresh data
|
|
137
|
+
|
|
138
|
+
// Pagination/Sorting
|
|
139
|
+
st.do.setPageOfModel(); // Change page number
|
|
140
|
+
st.do.setLimitOfModel(); // Change items per page
|
|
141
|
+
st.do.setSortOfModel(); // Change sort field
|
|
142
|
+
st.do.setQueryArgsOfModel(); // Set filter query arguments
|
|
143
|
+
|
|
144
|
+
// Form management
|
|
145
|
+
st.do.setFieldOnModel(); // Set a form field
|
|
146
|
+
st.do.addFieldOnModel(); // Add to an array field
|
|
147
|
+
st.do.submitModel(); // Submit the form
|
|
148
|
+
st.do.checkModelSubmitable(); // Check form validity
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Custom Actions
|
|
152
|
+
|
|
153
|
+
Define custom business logic by adding methods to your store class:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Basic custom action
|
|
157
|
+
async archiveProduct(id: string) {
|
|
158
|
+
const product = await fetch.archiveProduct(id);
|
|
159
|
+
this.setProduct(product);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Action with loading state
|
|
163
|
+
async generateProductReport(id: string) {
|
|
164
|
+
this.set({ productReportLoading: true });
|
|
165
|
+
try {
|
|
166
|
+
const report = await fetch.generateProductReport(id);
|
|
167
|
+
this.set({ productReport: report });
|
|
168
|
+
} finally {
|
|
169
|
+
this.set({ productReportLoading: false });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Action with notification
|
|
174
|
+
@Toast({ root: "product" })
|
|
175
|
+
async bulkUpdatePrices(percentage: number) {
|
|
176
|
+
const { selectedProductIds } = this.pick("selectedProductIds");
|
|
177
|
+
await fetch.updatePrices(selectedProductIds, percentage);
|
|
178
|
+
this.refreshProductList();
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Using Slices for List Operations
|
|
183
|
+
|
|
184
|
+
Slices are specialized query operations for retrieving contextual lists of data.
|
|
185
|
+
|
|
186
|
+
### Slice Definition
|
|
187
|
+
|
|
188
|
+
Slices are defined in your GraphQL fetch operations:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
// In fetch.ts
|
|
192
|
+
export const productGql = {
|
|
193
|
+
// Basic operations
|
|
194
|
+
product: (id: string) => [id],
|
|
195
|
+
productList: () => [],
|
|
196
|
+
|
|
197
|
+
// Slice operations (contextual lists)
|
|
198
|
+
productListByCategory: (categoryId: string) => [categoryId],
|
|
199
|
+
productListByVendor: (vendorId: string) => [vendorId],
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Slice State
|
|
204
|
+
|
|
205
|
+
Each slice automatically creates these state properties:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
{
|
|
209
|
+
productListByCategory: [], // Slice data
|
|
210
|
+
productListByCategoryLoading: false, // Loading state
|
|
211
|
+
productListByCategoryTotal: 0, // Total count
|
|
212
|
+
productListByCategoryPage: 1, // Current page
|
|
213
|
+
productListByCategoryLimit: 20, // Items per page
|
|
214
|
+
productListByCategorySort: "createdAt", // Sort field
|
|
215
|
+
productListByCategoryQuery: {}, // Query args
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Using Slice State in Components
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const ProductCategoryPage = ({ categoryId }) => {
|
|
223
|
+
// Initialize slice when component mounts
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
st.do.initProductListByCategory(categoryId);
|
|
226
|
+
}, [categoryId]);
|
|
227
|
+
|
|
228
|
+
// Access slice state
|
|
229
|
+
const products = st.use.productListByCategory();
|
|
230
|
+
const loading = st.use.productListByCategoryLoading();
|
|
231
|
+
const total = st.use.productListByCategoryTotal();
|
|
232
|
+
|
|
233
|
+
// Pagination control
|
|
234
|
+
const handlePageChange = (page: number) => {
|
|
235
|
+
st.do.setPageOfProductListByCategory(page);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Rendering
|
|
239
|
+
return (
|
|
240
|
+
<div>
|
|
241
|
+
{loading ? (
|
|
242
|
+
<Spinner />
|
|
243
|
+
) : (
|
|
244
|
+
<ProductGrid products={products} />
|
|
245
|
+
)}
|
|
246
|
+
|
|
247
|
+
<Pagination
|
|
248
|
+
total={total}
|
|
249
|
+
onChange={handlePageChange}
|
|
250
|
+
/>
|
|
251
|
+
</div>
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Slice Actions
|
|
257
|
+
|
|
258
|
+
Each slice gets these automatically generated actions:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// Initialize slice
|
|
262
|
+
st.do.initProductListByCategory(categoryId);
|
|
263
|
+
|
|
264
|
+
// Refresh slice data
|
|
265
|
+
st.do.refreshProductListByCategory(categoryId);
|
|
266
|
+
|
|
267
|
+
// Pagination/Sorting
|
|
268
|
+
st.do.setPageOfProductListByCategory(2);
|
|
269
|
+
st.do.setLimitOfProductListByCategory(50);
|
|
270
|
+
st.do.setSortOfProductListByCategory("price");
|
|
271
|
+
|
|
272
|
+
// Filtering
|
|
273
|
+
st.do.setQueryArgsOfProductListByCategory({
|
|
274
|
+
minPrice: 100,
|
|
275
|
+
inStock: true,
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Form Management
|
|
280
|
+
|
|
281
|
+
Stores provide comprehensive form handling capabilities.
|
|
282
|
+
|
|
283
|
+
### Form State Handling
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
// Form initialization
|
|
287
|
+
useEffect(() => {
|
|
288
|
+
if (productId) {
|
|
289
|
+
st.do.getProduct(productId);
|
|
290
|
+
} else {
|
|
291
|
+
st.do.initProduct(); // Create empty form
|
|
292
|
+
}
|
|
293
|
+
}, [productId]);
|
|
294
|
+
|
|
295
|
+
// Access form state
|
|
296
|
+
const productForm = st.use.productForm();
|
|
297
|
+
const loading = st.use.productFormLoading();
|
|
298
|
+
const submitable = st.use.productSubmitable();
|
|
299
|
+
|
|
300
|
+
// Form component
|
|
301
|
+
return (
|
|
302
|
+
<Form onSubmit={st.do.submitProduct}>
|
|
303
|
+
<Input
|
|
304
|
+
value={productForm.name}
|
|
305
|
+
onChange={(value) => st.do.setNameOnProduct(value)}
|
|
306
|
+
/>
|
|
307
|
+
|
|
308
|
+
<Select
|
|
309
|
+
value={productForm.category}
|
|
310
|
+
onChange={(value) => st.do.setCategoryOnProduct(value)}
|
|
311
|
+
options={categories}
|
|
312
|
+
/>
|
|
313
|
+
|
|
314
|
+
<FileUpload
|
|
315
|
+
files={productForm.images || []}
|
|
316
|
+
onAdd={(files) => st.do.addImagesOnProduct(files)}
|
|
317
|
+
onRemove={(index) => st.do.removeImagesOnProduct(index)}
|
|
318
|
+
/>
|
|
319
|
+
|
|
320
|
+
<Button
|
|
321
|
+
type="submit"
|
|
322
|
+
disabled={!submitable || loading}
|
|
323
|
+
>
|
|
324
|
+
Save Product
|
|
325
|
+
</Button>
|
|
326
|
+
</Form>
|
|
327
|
+
);
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Form Submission
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// Basic submission
|
|
334
|
+
st.do.submitProduct();
|
|
335
|
+
|
|
336
|
+
// With callbacks
|
|
337
|
+
st.do.submitProduct({
|
|
338
|
+
onSuccess: (product) => {
|
|
339
|
+
router.push(`/products/${product.id}`);
|
|
340
|
+
},
|
|
341
|
+
onError: (error) => {
|
|
342
|
+
console.error("Failed to save product:", error);
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// With validation
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
st.do.checkProductSubmitable();
|
|
349
|
+
}, [st.sel((s) => s.productForm)]);
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Advanced Store Patterns
|
|
353
|
+
|
|
354
|
+
### Store Composition
|
|
355
|
+
|
|
356
|
+
For complex applications, compose multiple stores:
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
// In store.ts
|
|
360
|
+
export class RootStore extends MixStore(ProductStore, CategoryStore, VendorStore, CartStore) {}
|
|
361
|
+
|
|
362
|
+
export const store = rootStoreOf(RootStore);
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Cross-Store Operations
|
|
366
|
+
|
|
367
|
+
Access other stores from within a store:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
async addToCart(productId: string, quantity: number) {
|
|
371
|
+
const product = await fetch.getProduct(productId);
|
|
372
|
+
|
|
373
|
+
// Access another store
|
|
374
|
+
(this as unknown as RootStore).do.addItemToCart({
|
|
375
|
+
productId: product.id,
|
|
376
|
+
name: product.name,
|
|
377
|
+
price: product.price,
|
|
378
|
+
quantity
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Optimistic Updates
|
|
384
|
+
|
|
385
|
+
Update UI before API operations complete:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
async toggleProductFavorite(id: string) {
|
|
389
|
+
const { productList } = this.pick("productList");
|
|
390
|
+
|
|
391
|
+
// Find product in list
|
|
392
|
+
const index = productList.findIndex(p => p.id === id);
|
|
393
|
+
if (index === -1) return;
|
|
394
|
+
|
|
395
|
+
// Clone the list
|
|
396
|
+
const newList = [...productList];
|
|
397
|
+
|
|
398
|
+
// Optimistically update
|
|
399
|
+
newList[index] = {
|
|
400
|
+
...newList[index],
|
|
401
|
+
isFavorite: !newList[index].isFavorite
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// Update UI immediately
|
|
405
|
+
this.set({ productList: newList });
|
|
406
|
+
|
|
407
|
+
// Perform actual API call
|
|
408
|
+
try {
|
|
409
|
+
await fetch.toggleProductFavorite(id);
|
|
410
|
+
} catch (error) {
|
|
411
|
+
// Revert on error
|
|
412
|
+
this.refreshProductList();
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Real-time Updates
|
|
419
|
+
|
|
420
|
+
Connect stores with GraphQL subscriptions:
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
initProductChat(productId: string) {
|
|
424
|
+
this.set({ productChatLoading: true });
|
|
425
|
+
|
|
426
|
+
// Set up subscription
|
|
427
|
+
fetch.subscribeToProductChat(productId, (message) => {
|
|
428
|
+
const { productChatMessages } = this.pick("productChatMessages");
|
|
429
|
+
this.set({
|
|
430
|
+
productChatMessages: [...productChatMessages, message]
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
this.set({ productChatLoading: false });
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## Best Practices
|
|
439
|
+
|
|
440
|
+
1. **Naming Conventions**:
|
|
441
|
+
|
|
442
|
+
- Use `modelList{Context}` for slice names (e.g., `productListByCategory`)
|
|
443
|
+
- Use camelCase for state properties
|
|
444
|
+
- Use action verbs for method names
|
|
445
|
+
|
|
446
|
+
2. **State Management**:
|
|
447
|
+
|
|
448
|
+
- Keep UI state (loading, selected items) in the store
|
|
449
|
+
- Use `this.pick()` for accessing multiple properties
|
|
450
|
+
- Create new references for objects/arrays when updating
|
|
451
|
+
|
|
452
|
+
3. **Performance**:
|
|
453
|
+
|
|
454
|
+
- Use selective subscriptions in components:
|
|
455
|
+
```typescript
|
|
456
|
+
// Subscribe to specific state properties
|
|
457
|
+
const name = st.use.product((s) => s.name);
|
|
458
|
+
```
|
|
459
|
+
- Initialize slices only when needed
|
|
460
|
+
- Clean up subscriptions when components unmount
|
|
461
|
+
|
|
462
|
+
4. **Error Handling**:
|
|
463
|
+
|
|
464
|
+
- Use the `@Toast` decorator for user notifications
|
|
465
|
+
- Always reset loading states in finally blocks
|
|
466
|
+
- Implement retry logic for critical operations
|
|
467
|
+
|
|
468
|
+
5. **Testing**:
|
|
469
|
+
- Mock stores with initial state for unit tests
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
const testStore = makeStore(
|
|
473
|
+
{
|
|
474
|
+
productList: [mockProduct1, mockProduct2],
|
|
475
|
+
},
|
|
476
|
+
ProductStore
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
await testStore.do.submitProduct();
|
|
480
|
+
expect(testStore.get().product).toEqual(expectedProduct);
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Complete Example
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
import { stateOf, Store, Toast } from "@akanjs/store";
|
|
487
|
+
import { cnst } from "../cnst";
|
|
488
|
+
import { fetch } from "../fetch";
|
|
489
|
+
import { msg } from "../msg";
|
|
490
|
+
|
|
491
|
+
@Store(() => cnst.Product)
|
|
492
|
+
export class ProductStore extends stateOf(fetch.productGql, {
|
|
493
|
+
// UI State
|
|
494
|
+
productViewMode: "grid" as "grid" | "list",
|
|
495
|
+
selectedProductIds: [] as string[],
|
|
496
|
+
productFilterDrawerOpen: false,
|
|
497
|
+
|
|
498
|
+
// Business State
|
|
499
|
+
featuredProducts: [] as cnst.LightProduct[],
|
|
500
|
+
relatedProductMap: new Map<string, cnst.LightProduct[]>(),
|
|
501
|
+
|
|
502
|
+
// Reports
|
|
503
|
+
productAnalytics: null as ProductAnalytics | null,
|
|
504
|
+
productReportLoading: false,
|
|
505
|
+
}) {
|
|
506
|
+
// Selection Management
|
|
507
|
+
selectProduct(id: string) {
|
|
508
|
+
const { selectedProductIds } = this.pick("selectedProductIds");
|
|
509
|
+
this.set({
|
|
510
|
+
selectedProductIds: [...selectedProductIds, id],
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
deselectProduct(id: string) {
|
|
515
|
+
const { selectedProductIds } = this.pick("selectedProductIds");
|
|
516
|
+
this.set({
|
|
517
|
+
selectedProductIds: selectedProductIds.filter((pid) => pid !== id),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
clearSelectedProducts() {
|
|
522
|
+
this.set({ selectedProductIds: [] });
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Business Operations
|
|
526
|
+
@Toast({ root: "product" })
|
|
527
|
+
async featureProduct(id: string) {
|
|
528
|
+
const product = await fetch.featureProduct(id);
|
|
529
|
+
const { featuredProducts } = this.pick("featuredProducts");
|
|
530
|
+
|
|
531
|
+
this.set({
|
|
532
|
+
featuredProducts: [...featuredProducts, product],
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
@Toast({ root: "product" })
|
|
537
|
+
async bulkUpdatePrices(percentage: number) {
|
|
538
|
+
const { selectedProductIds } = this.pick("selectedProductIds");
|
|
539
|
+
|
|
540
|
+
if (selectedProductIds.length === 0) {
|
|
541
|
+
msg.error("product.noProductsSelectedError");
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
await fetch.updatePrices(selectedProductIds, percentage);
|
|
546
|
+
this.refreshProductList();
|
|
547
|
+
this.clearSelectedProducts();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Analytics
|
|
551
|
+
async loadProductAnalytics(id: string) {
|
|
552
|
+
this.set({ productReportLoading: true });
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
const analytics = await fetch.getProductAnalytics(id);
|
|
556
|
+
this.set({ productAnalytics: analytics });
|
|
557
|
+
} catch (error) {
|
|
558
|
+
msg.error("product.analyticsLoadError");
|
|
559
|
+
this.set({ productAnalytics: null });
|
|
560
|
+
} finally {
|
|
561
|
+
this.set({ productReportLoading: false });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Related Products
|
|
566
|
+
async loadRelatedProducts(id: string) {
|
|
567
|
+
const { relatedProductMap } = this.pick("relatedProductMap");
|
|
568
|
+
|
|
569
|
+
// Check cache
|
|
570
|
+
if (relatedProductMap.has(id)) return;
|
|
571
|
+
|
|
572
|
+
const relatedProducts = await fetch.getRelatedProducts(id);
|
|
573
|
+
|
|
574
|
+
// Update map immutably
|
|
575
|
+
const newMap = new Map(relatedProductMap);
|
|
576
|
+
newMap.set(id, relatedProducts);
|
|
577
|
+
|
|
578
|
+
this.set({ relatedProductMap: newMap });
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
## File Structure Convention
|
|
584
|
+
|
|
585
|
+
Store files should follow this pattern:
|
|
586
|
+
`{apps,libs}/*/lib/{feature}/{feature}.store.ts`
|
|
587
|
+
|
|
588
|
+
Examples:
|
|
589
|
+
|
|
590
|
+
- `apps/commerce/lib/products/product.store.ts`
|
|
591
|
+
- `libs/shared/lib/auth/auth.store.ts`
|