@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,1112 @@
|
|
|
1
|
+
# Akan.js Framework Guide
|
|
2
|
+
|
|
3
|
+
## Introduction to Akan.js Framework
|
|
4
|
+
|
|
5
|
+
Akan.js is a comprehensive full-stack TypeScript framework designed to streamline application development across all layers of the technology stack. It enables developers to:
|
|
6
|
+
|
|
7
|
+
- Build complete, type-safe applications with minimal code
|
|
8
|
+
- Deploy simultaneously to web, mobile, server, database, and infrastructure
|
|
9
|
+
- Maintain consistent patterns and high performance throughout the application
|
|
10
|
+
|
|
11
|
+
Akan.js reduces development complexity by providing a unified interface for all development concerns, from database schema to UI components, with built-in best practices for architecture, security, and scalability.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Key Features and Benefits
|
|
16
|
+
|
|
17
|
+
### Unified Development Experience
|
|
18
|
+
|
|
19
|
+
- **Integral Interface**: Single cohesive system for schema design, service logic, API endpoints, state management, and UI components
|
|
20
|
+
- **Reduced Boilerplate**: Write once, deploy everywhere with automated code generation
|
|
21
|
+
- **Full Type Safety**: End-to-end TypeScript with automatic type inference between layers
|
|
22
|
+
- **Automated Synchronization**: Changes to models automatically propagate across the stack
|
|
23
|
+
|
|
24
|
+
### Built-in Capabilities
|
|
25
|
+
|
|
26
|
+
- **Type-Safe API Layer**: Automatic API generation with proper typing
|
|
27
|
+
- **Internationalization**: Built-in i18n system with dictionary-based translations
|
|
28
|
+
- **Security**: Standardized authentication, authorization, and security practices
|
|
29
|
+
- **File Management**: Integrated system for uploads, storage, and delivery
|
|
30
|
+
- **Text Search**: Optimized search capabilities out of the box
|
|
31
|
+
- **Documentation**: Automatic API and model documentation
|
|
32
|
+
- **Admin Interface**: Generated admin panels for data management
|
|
33
|
+
|
|
34
|
+
### Platform Support
|
|
35
|
+
|
|
36
|
+
- **Web**: Next.js-based SSR and CSR support
|
|
37
|
+
- **Mobile**: Native iOS and Android apps via Capacitor
|
|
38
|
+
- **Server**: NestJS-based backend with GraphQL and REST
|
|
39
|
+
- **Database**: MongoDB integration with Mongoose
|
|
40
|
+
- **Infrastructure**: Automated deployment to Akan Cloud
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Architecture Overview
|
|
45
|
+
|
|
46
|
+
### Modular Architecture
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
├── apps/ # Application code
|
|
50
|
+
│ ├── app1/ # Individual application
|
|
51
|
+
│ │ ├── akan.config.ts # Application configuration
|
|
52
|
+
│ │ ├── app/ # Next.js app router
|
|
53
|
+
│ │ ├── lib/ # Domain modules
|
|
54
|
+
│ │ │ ├── moduleA/ # Feature module
|
|
55
|
+
│ │ │ │ ├── moduleA.constant.ts # Types and schemas
|
|
56
|
+
│ │ │ │ ├── moduleA.service.ts # Business logic
|
|
57
|
+
│ │ │ │ ├── moduleA.signal.ts # API endpoints
|
|
58
|
+
│ │ │ │ ├── moduleA.store.ts # State management
|
|
59
|
+
│ │ │ │ ├── moduleA.dictionary.ts # Translations
|
|
60
|
+
│ │ │ │ ├── moduleA.View.tsx # Page view component
|
|
61
|
+
│ │ │ │ ├── moduleA.Unit.tsx # List/card item component
|
|
62
|
+
│ │ │ │ └── moduleA.Template.tsx # Form template component
|
|
63
|
+
│ │ ├── env/ # Environment configurations
|
|
64
|
+
│ │ ├── main.ts # Application entry point
|
|
65
|
+
│ │ ├── client.ts # Client-side entry point
|
|
66
|
+
│ │ └── server.ts # Server-side entry point
|
|
67
|
+
├── libs/ # Shared libraries
|
|
68
|
+
│ ├── shared/ # Core shared library
|
|
69
|
+
│ ├── util/ # Utility library
|
|
70
|
+
│ └── [other libs]/ # Domain-specific libraries
|
|
71
|
+
└── pkgs/ # Framework packages
|
|
72
|
+
└── @akanjs/ # Core framework components
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Data Flow
|
|
76
|
+
|
|
77
|
+
1. **Model Definition**: `model.constant.ts` defines types, schemas, and validations
|
|
78
|
+
2. **Service Layer**: `model.service.ts` implements business logic and database operations
|
|
79
|
+
3. **API Layer**: `model.signal.ts` exposes endpoints and handles client-server communication
|
|
80
|
+
4. **State Management**: `model.store.ts` manages client-side state with Zustand
|
|
81
|
+
5. **UI Components**: `.View.tsx`, `.Unit.tsx`, `.Template.tsx` render the UI
|
|
82
|
+
|
|
83
|
+
### Multi-Environment Support
|
|
84
|
+
|
|
85
|
+
Configure and deploy to different environments with environment-specific settings:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
apps/yourapp/env/
|
|
89
|
+
├── env.client.debug.ts # Debug client environment
|
|
90
|
+
├── env.client.develop.ts # Development client environment
|
|
91
|
+
├── env.client.main.ts # Production client environment
|
|
92
|
+
├── env.server.debug.ts # Debug server environment
|
|
93
|
+
├── env.server.develop.ts # Development server environment
|
|
94
|
+
└── env.server.main.ts # Production server environment
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Domain-Driven Development Pattern
|
|
100
|
+
|
|
101
|
+
Akan.js embraces domain-driven design principles, organizing code around business domains rather than technical concerns.
|
|
102
|
+
|
|
103
|
+
### Module Pattern
|
|
104
|
+
|
|
105
|
+
Each domain feature follows a consistent module pattern:
|
|
106
|
+
|
|
107
|
+
1. **Constants**: Define types, interfaces, and schemas
|
|
108
|
+
2. **Service**: Implement business logic and database interactions
|
|
109
|
+
3. **Signal**: Create API endpoints and client-server communication
|
|
110
|
+
4. **Store**: Manage client-side state for the module
|
|
111
|
+
5. **Dictionary**: Provide translations for the module
|
|
112
|
+
6. **UI Components**: Create specialized components for the module
|
|
113
|
+
|
|
114
|
+
### Module Composition
|
|
115
|
+
|
|
116
|
+
Modules can interact and compose:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Importing from another module
|
|
120
|
+
import { userService } from "../user/user.service";
|
|
121
|
+
import { projectStore } from "../project/project.store";
|
|
122
|
+
|
|
123
|
+
// Using in your service
|
|
124
|
+
export const taskService = {
|
|
125
|
+
async assignTask(taskId: string, userId: string) {
|
|
126
|
+
// Validate user exists
|
|
127
|
+
const user = await userService.getUser(userId);
|
|
128
|
+
if (!user) throw new Error("User not found");
|
|
129
|
+
|
|
130
|
+
// Update task
|
|
131
|
+
const task = await Task.findByIdAndUpdate(taskId, {
|
|
132
|
+
assignedTo: userId,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Update client state
|
|
136
|
+
projectStore.getState().refreshTasks();
|
|
137
|
+
|
|
138
|
+
return task;
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Full-Stack Development Workflow
|
|
146
|
+
|
|
147
|
+
### Create a New Model
|
|
148
|
+
|
|
149
|
+
1. Define the model in `model.constant.ts`:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { Field, Model } from "@akanjs/constant";
|
|
153
|
+
|
|
154
|
+
@Model()
|
|
155
|
+
export class Project {
|
|
156
|
+
@Field()
|
|
157
|
+
id: string;
|
|
158
|
+
|
|
159
|
+
@Field()
|
|
160
|
+
title: string;
|
|
161
|
+
|
|
162
|
+
@Field()
|
|
163
|
+
description: string;
|
|
164
|
+
|
|
165
|
+
@Field()
|
|
166
|
+
status: "active" | "completed" | "archived";
|
|
167
|
+
|
|
168
|
+
@Field()
|
|
169
|
+
createdAt: Date;
|
|
170
|
+
|
|
171
|
+
@Field()
|
|
172
|
+
updatedAt: Date;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
2. Generate service, signal, and store files:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
akan generate:module project
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
3. Implement business logic in `project.service.ts`:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { Project } from "./project.constant";
|
|
186
|
+
|
|
187
|
+
export const projectService = {
|
|
188
|
+
async getProjects() {
|
|
189
|
+
return Project.find().sort({ updatedAt: -1 });
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
async createProject(data: Partial<Project>) {
|
|
193
|
+
return Project.create(data);
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
4. Define API endpoints in `project.signal.ts`:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { Signal } from "@akanjs/signal";
|
|
202
|
+
import { Project } from "./project.constant";
|
|
203
|
+
import { projectService } from "./project.service";
|
|
204
|
+
|
|
205
|
+
export class ProjectSignal {
|
|
206
|
+
@Signal()
|
|
207
|
+
async projectList() {
|
|
208
|
+
return projectService.getProjects();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@Signal()
|
|
212
|
+
async createProject(data: Partial<Project>) {
|
|
213
|
+
return projectService.createProject(data);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
5. Create UI components for your model:
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
// project.View.tsx
|
|
222
|
+
import { usePage } from "@akanjs/client";
|
|
223
|
+
import { projectSignal } from "./project.signal";
|
|
224
|
+
|
|
225
|
+
export const ProjectView = () => {
|
|
226
|
+
const { data } = projectSignal.useProjectList();
|
|
227
|
+
const { l } = usePage();
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<div>
|
|
231
|
+
<h1>{l("project.modelName")}</h1>
|
|
232
|
+
<div className="grid gap-4">{data?.map((project) => <ProjectUnit key={project.id} project={project} />)}</div>
|
|
233
|
+
</div>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Model Architecture
|
|
241
|
+
|
|
242
|
+
### Model Constants (`model.constant.ts`)
|
|
243
|
+
|
|
244
|
+
Defines the data structure, validation rules, and relationships:
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import { Field, Model, FilterArg, Query } from "@akanjs/constant";
|
|
248
|
+
|
|
249
|
+
@Model()
|
|
250
|
+
export class Task {
|
|
251
|
+
@Field()
|
|
252
|
+
id: string;
|
|
253
|
+
|
|
254
|
+
@Field()
|
|
255
|
+
title: string;
|
|
256
|
+
|
|
257
|
+
@Field({ required: false })
|
|
258
|
+
description?: string;
|
|
259
|
+
|
|
260
|
+
@Field()
|
|
261
|
+
status: "todo" | "in-progress" | "done";
|
|
262
|
+
|
|
263
|
+
@Field()
|
|
264
|
+
projectId: string;
|
|
265
|
+
|
|
266
|
+
@Field({ ref: () => User })
|
|
267
|
+
assignedTo: string;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export class TaskFilter {
|
|
271
|
+
@FilterArg()
|
|
272
|
+
statuses?: string[];
|
|
273
|
+
|
|
274
|
+
@Query("byProject")
|
|
275
|
+
byProject(projectId: string) {
|
|
276
|
+
return { projectId };
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Model Service (`model.service.ts`)
|
|
282
|
+
|
|
283
|
+
Implements business logic and database operations:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { Task } from "./task.constant";
|
|
287
|
+
import { userService } from "../user/user.service";
|
|
288
|
+
|
|
289
|
+
export const taskService = {
|
|
290
|
+
async getTasks(query = {}) {
|
|
291
|
+
return Task.find(query).sort({ updatedAt: -1 });
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
async createTask(data: Partial<Task>) {
|
|
295
|
+
// Business logic validation
|
|
296
|
+
if (data.assignedTo) {
|
|
297
|
+
const userExists = await userService.userExists(data.assignedTo);
|
|
298
|
+
if (!userExists) {
|
|
299
|
+
throw new Error("Assigned user not found");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return Task.create({
|
|
304
|
+
...data,
|
|
305
|
+
status: data.status || "todo",
|
|
306
|
+
});
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
async updateTaskStatus(taskId: string, status: Task["status"]) {
|
|
310
|
+
return Task.findByIdAndUpdate(taskId, { status });
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Model Signal (`model.signal.ts`)
|
|
316
|
+
|
|
317
|
+
Exposes API endpoints for client-server communication:
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { Signal } from "@akanjs/signal";
|
|
321
|
+
import { Task, TaskFilter } from "./task.constant";
|
|
322
|
+
import { taskService } from "./task.service";
|
|
323
|
+
|
|
324
|
+
export class TaskSignal {
|
|
325
|
+
@Signal()
|
|
326
|
+
async taskList(query: TaskFilter, skip = 0, limit = 20) {
|
|
327
|
+
return taskService.getTasks(query);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@Signal()
|
|
331
|
+
async task(taskId: string) {
|
|
332
|
+
return taskService.getTask(taskId);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@Signal()
|
|
336
|
+
async createTask(data: Partial<Task>) {
|
|
337
|
+
return taskService.createTask(data);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
@Signal()
|
|
341
|
+
async updateTaskStatus(taskId: string, status: Task["status"]) {
|
|
342
|
+
return taskService.updateTaskStatus(taskId, status);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Model Store (`model.store.ts`)
|
|
348
|
+
|
|
349
|
+
Manages client-side state:
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import { create } from "zustand";
|
|
353
|
+
import { Task } from "./task.constant";
|
|
354
|
+
import { taskSignal } from "./task.signal";
|
|
355
|
+
|
|
356
|
+
interface TaskStore {
|
|
357
|
+
tasks: Task[];
|
|
358
|
+
loading: boolean;
|
|
359
|
+
error: string | null;
|
|
360
|
+
fetchTasks: (projectId?: string) => Promise<void>;
|
|
361
|
+
addTask: (task: Task) => void;
|
|
362
|
+
updateTask: (taskId: string, data: Partial<Task>) => void;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export const taskStore = create<TaskStore>((set, get) => ({
|
|
366
|
+
tasks: [],
|
|
367
|
+
loading: false,
|
|
368
|
+
error: null,
|
|
369
|
+
|
|
370
|
+
fetchTasks: async (projectId) => {
|
|
371
|
+
set({ loading: true, error: null });
|
|
372
|
+
try {
|
|
373
|
+
const query = projectId ? { byProject: projectId } : {};
|
|
374
|
+
const tasks = await taskSignal.taskList(query);
|
|
375
|
+
set({ tasks, loading: false });
|
|
376
|
+
} catch (err) {
|
|
377
|
+
set({ error: err.message, loading: false });
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
|
|
381
|
+
addTask: (task) => {
|
|
382
|
+
set({ tasks: [...get().tasks, task] });
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
updateTask: (taskId, data) => {
|
|
386
|
+
set({
|
|
387
|
+
tasks: get().tasks.map((task) => (task.id === taskId ? { ...task, ...data } : task)),
|
|
388
|
+
});
|
|
389
|
+
},
|
|
390
|
+
}));
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Component Architecture
|
|
396
|
+
|
|
397
|
+
Akan.js uses a specialized component pattern to ensure consistency and separation of concerns.
|
|
398
|
+
|
|
399
|
+
### View Components (`model.View.tsx`)
|
|
400
|
+
|
|
401
|
+
Page-level components that display a full page or section:
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
import { usePage } from "@akanjs/client";
|
|
405
|
+
import { taskStore } from "./task.store";
|
|
406
|
+
import { TaskUnit } from "./task.Unit";
|
|
407
|
+
import { TaskTemplate } from "./task.Template";
|
|
408
|
+
|
|
409
|
+
export const TaskView = () => {
|
|
410
|
+
const { l } = usePage();
|
|
411
|
+
const { tasks, loading, fetchTasks } = taskStore();
|
|
412
|
+
|
|
413
|
+
useEffect(() => {
|
|
414
|
+
fetchTasks();
|
|
415
|
+
}, [fetchTasks]);
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<div className="p-4">
|
|
419
|
+
<h1 className="mb-4 text-2xl font-bold">{l("task.modelName")}</h1>
|
|
420
|
+
|
|
421
|
+
<TaskTemplate className="mb-6" />
|
|
422
|
+
|
|
423
|
+
{loading ? (
|
|
424
|
+
<div>Loading tasks...</div>
|
|
425
|
+
) : (
|
|
426
|
+
<div className="grid gap-4">
|
|
427
|
+
{tasks.map((task) => (
|
|
428
|
+
<TaskUnit key={task.id} task={task} />
|
|
429
|
+
))}
|
|
430
|
+
</div>
|
|
431
|
+
)}
|
|
432
|
+
</div>
|
|
433
|
+
);
|
|
434
|
+
};
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Unit Components (`model.Unit.tsx`)
|
|
438
|
+
|
|
439
|
+
Card or list item components that display a single instance of a model:
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
import { usePage } from "@akanjs/client";
|
|
443
|
+
import { Task } from "./task.constant";
|
|
444
|
+
import { taskSignal } from "./task.signal";
|
|
445
|
+
|
|
446
|
+
interface TaskUnitProps {
|
|
447
|
+
task: Task;
|
|
448
|
+
onStatusChange?: () => void;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export const TaskUnit = ({ task, onStatusChange }: TaskUnitProps) => {
|
|
452
|
+
const { l } = usePage();
|
|
453
|
+
const { mutate: updateStatus } = taskSignal.useUpdateTaskStatus();
|
|
454
|
+
|
|
455
|
+
const handleStatusChange = (status: Task["status"]) => {
|
|
456
|
+
updateStatus(task.id, status).then(() => {
|
|
457
|
+
onStatusChange?.();
|
|
458
|
+
});
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
return (
|
|
462
|
+
<div className="rounded border p-4">
|
|
463
|
+
<h3 className="font-bold">{task.title}</h3>
|
|
464
|
+
<p className="text-gray-700">{task.description}</p>
|
|
465
|
+
<div className="mt-2 flex justify-between">
|
|
466
|
+
<span className={`badge ${task.status}`}>{l(`enum-status-${task.status}`)}</span>
|
|
467
|
+
<select value={task.status} onChange={(e) => handleStatusChange(e.target.value as Task["status"])}>
|
|
468
|
+
<option value="todo">{l("enum-status-todo")}</option>
|
|
469
|
+
<option value="in-progress">{l("enum-status-in-progress")}</option>
|
|
470
|
+
<option value="done">{l("enum-status-done")}</option>
|
|
471
|
+
</select>
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
);
|
|
475
|
+
};
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Template Components (`model.Template.tsx`)
|
|
479
|
+
|
|
480
|
+
Form components for creating or editing a model:
|
|
481
|
+
|
|
482
|
+
```tsx
|
|
483
|
+
import { useState } from "react";
|
|
484
|
+
import { usePage } from "@akanjs/client";
|
|
485
|
+
import { Task } from "./task.constant";
|
|
486
|
+
import { taskSignal } from "./task.signal";
|
|
487
|
+
import { taskStore } from "./task.store";
|
|
488
|
+
|
|
489
|
+
interface TaskTemplateProps {
|
|
490
|
+
initialData?: Partial<Task>;
|
|
491
|
+
className?: string;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export const TaskTemplate = ({ initialData = {}, className }: TaskTemplateProps) => {
|
|
495
|
+
const { l } = usePage();
|
|
496
|
+
const { mutate: createTask, isLoading } = taskSignal.useCreateTask();
|
|
497
|
+
const addTask = taskStore((state) => state.addTask);
|
|
498
|
+
|
|
499
|
+
const [formData, setFormData] = useState({
|
|
500
|
+
title: initialData.title || "",
|
|
501
|
+
description: initialData.description || "",
|
|
502
|
+
status: initialData.status || "todo",
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
506
|
+
e.preventDefault();
|
|
507
|
+
createTask(formData).then((newTask) => {
|
|
508
|
+
addTask(newTask);
|
|
509
|
+
setFormData({ title: "", description: "", status: "todo" });
|
|
510
|
+
});
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
return (
|
|
514
|
+
<form className={`rounded border p-4 ${className}`} onSubmit={handleSubmit}>
|
|
515
|
+
<h2 className="mb-4 text-xl font-bold">{l("task.createTask")}</h2>
|
|
516
|
+
|
|
517
|
+
<div className="mb-4">
|
|
518
|
+
<label className="mb-1 block">{l("task.title")}</label>
|
|
519
|
+
<input
|
|
520
|
+
type="text"
|
|
521
|
+
className="w-full rounded border px-2 py-1"
|
|
522
|
+
value={formData.title}
|
|
523
|
+
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
|
|
524
|
+
required
|
|
525
|
+
/>
|
|
526
|
+
</div>
|
|
527
|
+
|
|
528
|
+
<div className="mb-4">
|
|
529
|
+
<label className="mb-1 block">{l("task.description")}</label>
|
|
530
|
+
<textarea
|
|
531
|
+
className="w-full rounded border px-2 py-1"
|
|
532
|
+
value={formData.description}
|
|
533
|
+
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
|
534
|
+
/>
|
|
535
|
+
</div>
|
|
536
|
+
|
|
537
|
+
<button type="submit" className="rounded bg-blue-500 px-4 py-2 text-white" disabled={isLoading}>
|
|
538
|
+
{isLoading ? l("loading") : l("submit")}
|
|
539
|
+
</button>
|
|
540
|
+
</form>
|
|
541
|
+
);
|
|
542
|
+
};
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Zone Components (`model.Zone.tsx`)
|
|
546
|
+
|
|
547
|
+
Layout containers that organize multiple components:
|
|
548
|
+
|
|
549
|
+
```tsx
|
|
550
|
+
import { ReactNode } from "react";
|
|
551
|
+
import { usePage } from "@akanjs/client";
|
|
552
|
+
|
|
553
|
+
interface TaskZoneProps {
|
|
554
|
+
title?: string;
|
|
555
|
+
children: ReactNode;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export const TaskZone = ({ title, children }: TaskZoneProps) => {
|
|
559
|
+
const { l } = usePage();
|
|
560
|
+
|
|
561
|
+
return (
|
|
562
|
+
<div className="rounded-lg border bg-gray-50 p-6">
|
|
563
|
+
{title && <h2 className="mb-4 text-xl font-bold">{title || l("task.tasks")}</h2>}
|
|
564
|
+
<div className="space-y-4">{children}</div>
|
|
565
|
+
</div>
|
|
566
|
+
);
|
|
567
|
+
};
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## API Integration Pattern
|
|
573
|
+
|
|
574
|
+
### Defining API Endpoints
|
|
575
|
+
|
|
576
|
+
In your signal file:
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
import { Signal } from "@akanjs/signal";
|
|
580
|
+
import { Product, ProductFilter } from "./product.constant";
|
|
581
|
+
import { productService } from "./product.service";
|
|
582
|
+
|
|
583
|
+
export class ProductSignal {
|
|
584
|
+
@Signal()
|
|
585
|
+
async productList(query: ProductFilter, skip = 0, limit = 20) {
|
|
586
|
+
return productService.getProducts(query, skip, limit);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
@Signal()
|
|
590
|
+
async product(productId: string) {
|
|
591
|
+
return productService.getProduct(productId);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
@Signal()
|
|
595
|
+
async createProduct(data: Partial<Product>) {
|
|
596
|
+
return productService.createProduct(data);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
@Signal()
|
|
600
|
+
async updateProduct(productId: string, data: Partial<Product>) {
|
|
601
|
+
return productService.updateProduct(productId, data);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### Using API Endpoints in Components
|
|
607
|
+
|
|
608
|
+
With auto-generated React hooks:
|
|
609
|
+
|
|
610
|
+
```tsx
|
|
611
|
+
import { productSignal } from "./product.signal";
|
|
612
|
+
|
|
613
|
+
export const ProductList = () => {
|
|
614
|
+
// Query hook with automatic caching and refetching
|
|
615
|
+
const { data: products, isLoading, error } = productSignal.useProductList();
|
|
616
|
+
|
|
617
|
+
// Mutation hook with automatic cache updating
|
|
618
|
+
const { mutate: createProduct, isLoading: isCreating } = productSignal.useCreateProduct();
|
|
619
|
+
|
|
620
|
+
// Access both data and mutation functions
|
|
621
|
+
return (
|
|
622
|
+
<div>
|
|
623
|
+
{isLoading ? (
|
|
624
|
+
<div>Loading...</div>
|
|
625
|
+
) : error ? (
|
|
626
|
+
<div>Error: {error.message}</div>
|
|
627
|
+
) : (
|
|
628
|
+
<ul>{products?.map((product) => <li key={product.id}>{product.name}</li>)}</ul>
|
|
629
|
+
)}
|
|
630
|
+
|
|
631
|
+
<button onClick={() => createProduct({ name: "New Product" })} disabled={isCreating}>
|
|
632
|
+
Add Product
|
|
633
|
+
</button>
|
|
634
|
+
</div>
|
|
635
|
+
);
|
|
636
|
+
};
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## State Management Pattern
|
|
642
|
+
|
|
643
|
+
Akan.js uses Zustand for state management, providing a simple but powerful store pattern:
|
|
644
|
+
|
|
645
|
+
### Creating a Store
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
import { create } from "zustand";
|
|
649
|
+
import { Order } from "./order.constant";
|
|
650
|
+
import { orderSignal } from "./order.signal";
|
|
651
|
+
|
|
652
|
+
interface OrderStore {
|
|
653
|
+
// State
|
|
654
|
+
orders: Order[];
|
|
655
|
+
selectedOrderId: string | null;
|
|
656
|
+
loading: boolean;
|
|
657
|
+
error: string | null;
|
|
658
|
+
|
|
659
|
+
// Actions
|
|
660
|
+
fetchOrders: () => Promise<void>;
|
|
661
|
+
selectOrder: (orderId: string) => void;
|
|
662
|
+
addOrder: (order: Order) => void;
|
|
663
|
+
updateOrder: (orderId: string, data: Partial<Order>) => void;
|
|
664
|
+
deleteOrder: (orderId: string) => Promise<void>;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
export const orderStore = create<OrderStore>((set, get) => ({
|
|
668
|
+
// Initial state
|
|
669
|
+
orders: [],
|
|
670
|
+
selectedOrderId: null,
|
|
671
|
+
loading: false,
|
|
672
|
+
error: null,
|
|
673
|
+
|
|
674
|
+
// Actions
|
|
675
|
+
fetchOrders: async () => {
|
|
676
|
+
set({ loading: true, error: null });
|
|
677
|
+
try {
|
|
678
|
+
const orders = await orderSignal.orderList();
|
|
679
|
+
set({ orders, loading: false });
|
|
680
|
+
} catch (err) {
|
|
681
|
+
set({ error: err.message, loading: false });
|
|
682
|
+
}
|
|
683
|
+
},
|
|
684
|
+
|
|
685
|
+
selectOrder: (orderId) => {
|
|
686
|
+
set({ selectedOrderId: orderId });
|
|
687
|
+
},
|
|
688
|
+
|
|
689
|
+
addOrder: (order) => {
|
|
690
|
+
set({ orders: [...get().orders, order] });
|
|
691
|
+
},
|
|
692
|
+
|
|
693
|
+
updateOrder: (orderId, data) => {
|
|
694
|
+
set({
|
|
695
|
+
orders: get().orders.map((order) => (order.id === orderId ? { ...order, ...data } : order)),
|
|
696
|
+
});
|
|
697
|
+
},
|
|
698
|
+
|
|
699
|
+
deleteOrder: async (orderId) => {
|
|
700
|
+
set({ loading: true, error: null });
|
|
701
|
+
try {
|
|
702
|
+
await orderSignal.removeOrder(orderId);
|
|
703
|
+
set({
|
|
704
|
+
orders: get().orders.filter((order) => order.id !== orderId),
|
|
705
|
+
loading: false,
|
|
706
|
+
});
|
|
707
|
+
} catch (err) {
|
|
708
|
+
set({ error: err.message, loading: false });
|
|
709
|
+
}
|
|
710
|
+
},
|
|
711
|
+
}));
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
### Using the Store in Components
|
|
715
|
+
|
|
716
|
+
```tsx
|
|
717
|
+
import { orderStore } from "./order.store";
|
|
718
|
+
import { orderSignal } from "./order.signal";
|
|
719
|
+
|
|
720
|
+
export const OrderManager = () => {
|
|
721
|
+
// Access store state and actions
|
|
722
|
+
const { orders, selectedOrderId, loading, fetchOrders, selectOrder } = orderStore();
|
|
723
|
+
|
|
724
|
+
// Lifecycle hooks
|
|
725
|
+
useEffect(() => {
|
|
726
|
+
fetchOrders();
|
|
727
|
+
}, [fetchOrders]);
|
|
728
|
+
|
|
729
|
+
// Render UI based on state
|
|
730
|
+
return (
|
|
731
|
+
<div className="grid grid-cols-2 gap-4">
|
|
732
|
+
<div>
|
|
733
|
+
<h2>Orders</h2>
|
|
734
|
+
{loading ? (
|
|
735
|
+
<div>Loading...</div>
|
|
736
|
+
) : (
|
|
737
|
+
<ul>
|
|
738
|
+
{orders.map((order) => (
|
|
739
|
+
<li
|
|
740
|
+
key={order.id}
|
|
741
|
+
className={order.id === selectedOrderId ? "selected" : ""}
|
|
742
|
+
onClick={() => selectOrder(order.id)}
|
|
743
|
+
>
|
|
744
|
+
{order.number} - {order.customerName}
|
|
745
|
+
</li>
|
|
746
|
+
))}
|
|
747
|
+
</ul>
|
|
748
|
+
)}
|
|
749
|
+
</div>
|
|
750
|
+
|
|
751
|
+
<div>
|
|
752
|
+
<h2>Details</h2>
|
|
753
|
+
{selectedOrderId && <OrderDetails orderId={selectedOrderId} />}
|
|
754
|
+
</div>
|
|
755
|
+
</div>
|
|
756
|
+
);
|
|
757
|
+
};
|
|
758
|
+
|
|
759
|
+
// Another component using the same store
|
|
760
|
+
const OrderDetails = ({ orderId }) => {
|
|
761
|
+
// Selective state access
|
|
762
|
+
const order = orderStore((state) => state.orders.find((o) => o.id === orderId));
|
|
763
|
+
|
|
764
|
+
// API integration
|
|
765
|
+
const { mutate: updateOrder } = orderSignal.useUpdateOrder();
|
|
766
|
+
|
|
767
|
+
// UI based on store state
|
|
768
|
+
return order ? (
|
|
769
|
+
<div>
|
|
770
|
+
<h3>{order.number}</h3>
|
|
771
|
+
<p>Customer: {order.customerName}</p>
|
|
772
|
+
<p>Status: {order.status}</p>
|
|
773
|
+
|
|
774
|
+
<select value={order.status} onChange={(e) => updateOrder(order.id, { status: e.target.value })}>
|
|
775
|
+
<option value="pending">Pending</option>
|
|
776
|
+
<option value="processing">Processing</option>
|
|
777
|
+
<option value="shipped">Shipped</option>
|
|
778
|
+
<option value="delivered">Delivered</option>
|
|
779
|
+
</select>
|
|
780
|
+
</div>
|
|
781
|
+
) : null;
|
|
782
|
+
};
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
---
|
|
786
|
+
|
|
787
|
+
## Multi-Platform Support
|
|
788
|
+
|
|
789
|
+
Akan.js provides seamless support for various platforms:
|
|
790
|
+
|
|
791
|
+
### Web Applications
|
|
792
|
+
|
|
793
|
+
SSR with Next.js:
|
|
794
|
+
|
|
795
|
+
```tsx
|
|
796
|
+
// app/[lang]/projects/page.tsx
|
|
797
|
+
import { ProjectView } from "../../../lib/project/project.View";
|
|
798
|
+
|
|
799
|
+
export default function ProjectsPage() {
|
|
800
|
+
return <ProjectView />;
|
|
801
|
+
}
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
### Mobile Applications
|
|
805
|
+
|
|
806
|
+
Using Capacitor for iOS and Android:
|
|
807
|
+
|
|
808
|
+
```typescript
|
|
809
|
+
// capacitor.config.ts
|
|
810
|
+
import { CapacitorConfig } from "@capacitor/cli";
|
|
811
|
+
|
|
812
|
+
const config: CapacitorConfig = {
|
|
813
|
+
appId: "com.example.myapp",
|
|
814
|
+
appName: "My App",
|
|
815
|
+
webDir: "dist",
|
|
816
|
+
bundledWebRuntime: false,
|
|
817
|
+
plugins: {
|
|
818
|
+
SplashScreen: {
|
|
819
|
+
launchShowDuration: 2000,
|
|
820
|
+
},
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
export default config;
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
Then build and run:
|
|
828
|
+
|
|
829
|
+
```bash
|
|
830
|
+
akan build
|
|
831
|
+
npx cap add ios
|
|
832
|
+
npx cap add android
|
|
833
|
+
npx cap copy
|
|
834
|
+
npx cap open ios # Open in Xcode
|
|
835
|
+
npx cap open android # Open in Android Studio
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
## Type Safety and Code Generation
|
|
841
|
+
|
|
842
|
+
Akan.js provides end-to-end type safety:
|
|
843
|
+
|
|
844
|
+
### Type-Safe Database Schema
|
|
845
|
+
|
|
846
|
+
```typescript
|
|
847
|
+
import { Field, Model } from "@akanjs/constant";
|
|
848
|
+
|
|
849
|
+
@Model()
|
|
850
|
+
export class Customer {
|
|
851
|
+
@Field()
|
|
852
|
+
id: string;
|
|
853
|
+
|
|
854
|
+
@Field({ required: true, maxLength: 100 })
|
|
855
|
+
name: string;
|
|
856
|
+
|
|
857
|
+
@Field({ required: true, isEmail: true })
|
|
858
|
+
email: string;
|
|
859
|
+
|
|
860
|
+
@Field({ required: false, minLength: 6 })
|
|
861
|
+
phone?: string;
|
|
862
|
+
|
|
863
|
+
@Field()
|
|
864
|
+
createdAt: Date;
|
|
865
|
+
}
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
### Type-Safe API Calls
|
|
869
|
+
|
|
870
|
+
```typescript
|
|
871
|
+
// Generated types for API responses
|
|
872
|
+
const { data, isLoading, error } = customerSignal.useCustomerList();
|
|
873
|
+
if (data) {
|
|
874
|
+
// data is typed as Customer[]
|
|
875
|
+
data.forEach((customer) => {
|
|
876
|
+
// Type-safe access to customer properties
|
|
877
|
+
console.log(customer.name, customer.email);
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
### Type-Safe Form Handling
|
|
883
|
+
|
|
884
|
+
```tsx
|
|
885
|
+
// Form with type checking
|
|
886
|
+
const { mutate: updateCustomer } = customerSignal.useUpdateCustomer();
|
|
887
|
+
|
|
888
|
+
// This will give a type error if fields don't match Customer model
|
|
889
|
+
updateCustomer(customerId, {
|
|
890
|
+
name: "John Doe",
|
|
891
|
+
email: "john@example.com",
|
|
892
|
+
invalidField: "value", // TypeScript error: Property 'invalidField' does not exist on type 'Customer'
|
|
893
|
+
});
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
---
|
|
897
|
+
|
|
898
|
+
## Internationalization (i18n) System
|
|
899
|
+
|
|
900
|
+
Akan.js provides a robust i18n system:
|
|
901
|
+
|
|
902
|
+
### Translation Dictionaries
|
|
903
|
+
|
|
904
|
+
```typescript
|
|
905
|
+
// customer.dictionary.ts
|
|
906
|
+
import { ModelDictionary, baseTrans } from "@akanjs/dictionary";
|
|
907
|
+
import { Customer, CustomerFilter } from "./customer.constant";
|
|
908
|
+
|
|
909
|
+
const modelDictionary = {
|
|
910
|
+
...baseTrans,
|
|
911
|
+
modelName: ["Customer", "고객"],
|
|
912
|
+
modelDesc: ["Customer account information", "고객 계정 정보"],
|
|
913
|
+
|
|
914
|
+
// * ==================== Model ==================== * //
|
|
915
|
+
name: ["Name", "이름"],
|
|
916
|
+
"desc-name": ["Customer's full name", "고객의 전체 이름"],
|
|
917
|
+
|
|
918
|
+
email: ["Email", "이메일"],
|
|
919
|
+
"desc-email": ["Primary contact email", "주요 연락 이메일"],
|
|
920
|
+
|
|
921
|
+
phone: ["Phone", "전화번호"],
|
|
922
|
+
"desc-phone": ["Contact phone number", "연락처 전화번호"],
|
|
923
|
+
// * ==================== Model ==================== * //
|
|
924
|
+
|
|
925
|
+
// * ==================== Filter ==================== * //
|
|
926
|
+
"qry-byEmail": ["By Email", "이메일로 검색"],
|
|
927
|
+
"qrydesc-byEmail": ["Search customers by email", "이메일로 고객 검색"],
|
|
928
|
+
"qarg-byEmail-email": ["Email", "이메일"],
|
|
929
|
+
"qargdesc-byEmail-email": ["Email address to search", "검색할 이메일 주소"],
|
|
930
|
+
// * ==================== Filter ==================== * //
|
|
931
|
+
|
|
932
|
+
// * ==================== Etc ==================== * //
|
|
933
|
+
"enum-status-active": ["Active", "활성"],
|
|
934
|
+
"enumdesc-status-active": ["Active customer", "활성 고객"],
|
|
935
|
+
|
|
936
|
+
"enum-status-inactive": ["Inactive", "비활성"],
|
|
937
|
+
"enumdesc-status-inactive": ["Inactive customer", "비활성 고객"],
|
|
938
|
+
// * ==================== Etc ==================== * //
|
|
939
|
+
} satisfies ModelDictionary<Customer, any, CustomerFilter>;
|
|
940
|
+
|
|
941
|
+
export const customerDictionary = modelDictionary;
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
### Using Translations
|
|
945
|
+
|
|
946
|
+
```tsx
|
|
947
|
+
import { usePage } from "@akanjs/client";
|
|
948
|
+
|
|
949
|
+
export const CustomerForm = () => {
|
|
950
|
+
const { l, locale } = usePage();
|
|
951
|
+
|
|
952
|
+
return (
|
|
953
|
+
<form>
|
|
954
|
+
<h2>{l("customer.modelName")}</h2>
|
|
955
|
+
|
|
956
|
+
<div>
|
|
957
|
+
<label>{l("customer.name")}</label>
|
|
958
|
+
<input type="text" placeholder={l("customer.desc-name")} />
|
|
959
|
+
</div>
|
|
960
|
+
|
|
961
|
+
<div>
|
|
962
|
+
<label>{l("customer.email")}</label>
|
|
963
|
+
<input type="email" placeholder={l("customer.desc-email")} />
|
|
964
|
+
</div>
|
|
965
|
+
|
|
966
|
+
<div>
|
|
967
|
+
<label>{l("customer.phone")}</label>
|
|
968
|
+
<input type="tel" placeholder={l("customer.desc-phone")} />
|
|
969
|
+
</div>
|
|
970
|
+
|
|
971
|
+
<button type="submit">{l("submit")}</button>
|
|
972
|
+
</form>
|
|
973
|
+
);
|
|
974
|
+
};
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
---
|
|
978
|
+
|
|
979
|
+
## Development Tools and Commands
|
|
980
|
+
|
|
981
|
+
Akan.js provides powerful CLI tools for development:
|
|
982
|
+
|
|
983
|
+
### Starting Applications
|
|
984
|
+
|
|
985
|
+
```bash
|
|
986
|
+
# Start frontend and backend
|
|
987
|
+
akan start my-app
|
|
988
|
+
|
|
989
|
+
# Start only the frontend
|
|
990
|
+
akan start-frontend my-app
|
|
991
|
+
|
|
992
|
+
# Start only the backend
|
|
993
|
+
akan start-backend my-app
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
### Code Generation
|
|
997
|
+
|
|
998
|
+
```bash
|
|
999
|
+
# Generate a new module
|
|
1000
|
+
akan generate:module customer
|
|
1001
|
+
|
|
1002
|
+
# Generate a new component
|
|
1003
|
+
akan generate:component customer CustomerDetails
|
|
1004
|
+
|
|
1005
|
+
# Generate service from a model
|
|
1006
|
+
akan generate:service customer
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
### Building and Deployment
|
|
1010
|
+
|
|
1011
|
+
```bash
|
|
1012
|
+
# Build for production
|
|
1013
|
+
akan build my-app
|
|
1014
|
+
|
|
1015
|
+
# Deploy to Akan Cloud
|
|
1016
|
+
akan deploy my-app
|
|
1017
|
+
```
|
|
1018
|
+
|
|
1019
|
+
### Testing
|
|
1020
|
+
|
|
1021
|
+
```bash
|
|
1022
|
+
# Run unit tests
|
|
1023
|
+
akan test my-app
|
|
1024
|
+
|
|
1025
|
+
# Run end-to-end tests
|
|
1026
|
+
akan test:e2e my-app
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
---
|
|
1030
|
+
|
|
1031
|
+
## Best Practices and Common Patterns
|
|
1032
|
+
|
|
1033
|
+
### File Naming Conventions
|
|
1034
|
+
|
|
1035
|
+
- **Model Files**: `moduleName.constant.ts`, `moduleName.service.ts`, etc.
|
|
1036
|
+
- **Component Files**: `ModuleName.View.tsx`, `ModuleName.Unit.tsx`, etc.
|
|
1037
|
+
- **Utility Files**: `moduleName.util.ts`
|
|
1038
|
+
|
|
1039
|
+
### Code Organization
|
|
1040
|
+
|
|
1041
|
+
- Group files by domain/module, not by technical function
|
|
1042
|
+
- Keep related code together in the same directory
|
|
1043
|
+
- Use absolute imports for cross-module dependencies
|
|
1044
|
+
|
|
1045
|
+
### State Management
|
|
1046
|
+
|
|
1047
|
+
- Use stores for global state that needs to be shared between components
|
|
1048
|
+
- Use React's local state for component-specific state
|
|
1049
|
+
- Keep API data fetching in signal hooks
|
|
1050
|
+
|
|
1051
|
+
### Error Handling
|
|
1052
|
+
|
|
1053
|
+
- Use the `Revert` class for business logic errors
|
|
1054
|
+
- Include proper error messages in dictionaries
|
|
1055
|
+
- Handle errors at the UI level for better user experience
|
|
1056
|
+
|
|
1057
|
+
### Performance Optimization
|
|
1058
|
+
|
|
1059
|
+
- Use SSR for initial page loads
|
|
1060
|
+
- Implement code splitting for large applications
|
|
1061
|
+
- Optimize images and assets for faster loading
|
|
1062
|
+
- Use memoization for expensive calculations
|
|
1063
|
+
|
|
1064
|
+
---
|
|
1065
|
+
|
|
1066
|
+
## Troubleshooting and Common Issues
|
|
1067
|
+
|
|
1068
|
+
### API Connection Issues
|
|
1069
|
+
|
|
1070
|
+
If you encounter API connection problems:
|
|
1071
|
+
|
|
1072
|
+
1. Check that your backend is running (`akan start-backend`)
|
|
1073
|
+
2. Verify environment variables in env files
|
|
1074
|
+
3. Check network request in browser developer tools
|
|
1075
|
+
4. Ensure signal files are properly imported
|
|
1076
|
+
|
|
1077
|
+
### Type Errors
|
|
1078
|
+
|
|
1079
|
+
For TypeScript errors:
|
|
1080
|
+
|
|
1081
|
+
1. Run `akan typecheck` to identify issues
|
|
1082
|
+
2. Ensure models are properly defined in constant files
|
|
1083
|
+
3. Check import paths for correctness
|
|
1084
|
+
4. Update generated types if necessary: `akan generate:types`
|
|
1085
|
+
|
|
1086
|
+
### Build Failures
|
|
1087
|
+
|
|
1088
|
+
If builds are failing:
|
|
1089
|
+
|
|
1090
|
+
1. Check console errors for specific issues
|
|
1091
|
+
2. Verify dependencies in package.json
|
|
1092
|
+
3. Run `akan lint` to identify code issues
|
|
1093
|
+
4. Clear cache with `akan clear-cache`
|
|
1094
|
+
|
|
1095
|
+
### Component Rendering Issues
|
|
1096
|
+
|
|
1097
|
+
For UI rendering problems:
|
|
1098
|
+
|
|
1099
|
+
1. Check component props and types
|
|
1100
|
+
2. Verify data is being loaded correctly
|
|
1101
|
+
3. Inspect component hierarchy with React DevTools
|
|
1102
|
+
4. Check for conditional rendering issues
|
|
1103
|
+
|
|
1104
|
+
---
|
|
1105
|
+
|
|
1106
|
+
## Further Resources
|
|
1107
|
+
|
|
1108
|
+
- [Official Documentation](https://docs.akanjs.com)
|
|
1109
|
+
- [API Reference](https://docs.akanjs.com/api)
|
|
1110
|
+
- [Example Projects](https://github.com/akanjs/examples)
|
|
1111
|
+
- [Community Forum](https://community.akanjs.com)
|
|
1112
|
+
- [Video Tutorials](https://youtube.com/akanjs)
|