@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,691 @@
|
|
|
1
|
+
# Database Module in Akan.js
|
|
2
|
+
|
|
3
|
+
## Purpose of Database Modules
|
|
4
|
+
|
|
5
|
+
Database modules in Akan.js provide a structured approach to building domain-specific features with seamless integration between server and client:
|
|
6
|
+
|
|
7
|
+
1. **Domain Encapsulation**: Encapsulate all domain-specific logic (models, services, signals) in a consistent structure
|
|
8
|
+
2. **Full-Stack Integration**: Enable seamless integration between MongoDB, NestJS server, and React client
|
|
9
|
+
3. **Type Safety**: Ensure type safety across the entire stack with auto-generated GraphQL types
|
|
10
|
+
4. **Automated CRUD**: Provide automatic CRUD operations through standardized patterns
|
|
11
|
+
5. **Real-time Capabilities**: Support for websockets, GraphQL subscriptions, and background processing
|
|
12
|
+
6. **Security**: Implement role-based access control and validation at every level
|
|
13
|
+
|
|
14
|
+
## File Structure and Location Conventions
|
|
15
|
+
|
|
16
|
+
A complete database module follows this structure:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
libs/shared/lib/[module-name]/
|
|
20
|
+
├── [ModuleName].Template.tsx // Form components
|
|
21
|
+
├── [ModuleName].Unit.tsx // Card/list view components
|
|
22
|
+
├── [ModuleName].Util.tsx // Utility components (dashboard, insights)
|
|
23
|
+
├── [ModuleName].View.tsx // Single item view components
|
|
24
|
+
├── [ModuleName].Zone.tsx // Main zone layout and routing
|
|
25
|
+
├── _server.ts // Module registration
|
|
26
|
+
├── [module-name].constant.ts // Model definitions
|
|
27
|
+
├── [module-name].dictionary.ts // Translations
|
|
28
|
+
├── [module-name].document.ts // Database schema
|
|
29
|
+
├── [module-name].service.ts // Business logic
|
|
30
|
+
├── [module-name].signal.ts // API endpoints
|
|
31
|
+
├── [module-name].store.ts // Client state management
|
|
32
|
+
└── index.tsx // Module exports
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## How to Create Database Modules
|
|
36
|
+
|
|
37
|
+
### 1. Define Model Schema (`[module-name].constant.ts`)
|
|
38
|
+
|
|
39
|
+
Start by defining your data model schema using the decorator pattern:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { Dayjs, dayjs, enumOf, Int } from "@akanjs/base";
|
|
43
|
+
import { Field, Filter, Model, sortOf, via } from "@akanjs/constant";
|
|
44
|
+
import { validate } from "@util/common";
|
|
45
|
+
|
|
46
|
+
// Define enums
|
|
47
|
+
export const UserRole = enumOf(["user", "admin"] as const);
|
|
48
|
+
export type UserRole = enumOf<typeof UserRole>;
|
|
49
|
+
|
|
50
|
+
// Define input model (for create/update operations)
|
|
51
|
+
@Model.Input("UserInput")
|
|
52
|
+
export class UserInput {
|
|
53
|
+
@Field.Prop(() => String, { validate: validate.email, type: "email", example: "user@example.com" })
|
|
54
|
+
email: string;
|
|
55
|
+
|
|
56
|
+
@Field.Secret(() => String, { nullable: true, type: "password", example: "password123" })
|
|
57
|
+
password: string | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Define object model (full data model)
|
|
61
|
+
@Model.Object("UserObject")
|
|
62
|
+
export class UserObject extends via(UserInput) {
|
|
63
|
+
@Field.Prop(() => [String], [{ enum: UserRole, example: ["user"] }])
|
|
64
|
+
roles: (typeof UserRole.value)[];
|
|
65
|
+
|
|
66
|
+
@Field.Prop(() => Date, { default: () => dayjs(), example: dayjs() })
|
|
67
|
+
lastLoginAt: Dayjs;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Define light model (client-side model with essential fields)
|
|
71
|
+
@Model.Light("LightUser")
|
|
72
|
+
export class LightUser extends via(UserObject, ["email", "roles"] as const) {
|
|
73
|
+
hasAccess(role: UserRole) {
|
|
74
|
+
return this.roles.includes(role);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Define full model (server-side model with all fields)
|
|
79
|
+
@Model.Full("User")
|
|
80
|
+
export class User extends via(UserObject, LightUser) {}
|
|
81
|
+
|
|
82
|
+
// Define filter model (for queries)
|
|
83
|
+
@Model.Filter("UserFilter")
|
|
84
|
+
export class UserFilter extends sortOf(User, {}) {
|
|
85
|
+
@Filter.Mongo()
|
|
86
|
+
byEmail(@Filter.Arg("email", () => String) email: string) {
|
|
87
|
+
return { email };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2. Implement Database Schema (`[module-name].document.ts`)
|
|
93
|
+
|
|
94
|
+
Create the MongoDB schema with document methods and middleware:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { dayjs } from "@akanjs/base";
|
|
98
|
+
import { beyond, by, Database, into, Loader, type SchemaOf } from "@akanjs/document";
|
|
99
|
+
import { hashPassword } from "@shared/nest";
|
|
100
|
+
|
|
101
|
+
import { cnst } from "../cnst";
|
|
102
|
+
|
|
103
|
+
// Input model for database operations
|
|
104
|
+
@Database.Input(() => cnst.UserInput)
|
|
105
|
+
export class UserInput extends by(cnst.UserInput) {}
|
|
106
|
+
|
|
107
|
+
// Document model with methods
|
|
108
|
+
@Database.Document(() => cnst.User)
|
|
109
|
+
export class User extends by(cnst.User) {
|
|
110
|
+
addRole(role: cnst.UserRole) {
|
|
111
|
+
if (!this.roles.includes(role)) this.roles = [...this.roles, role];
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
updateLastLogin() {
|
|
116
|
+
this.lastLoginAt = dayjs();
|
|
117
|
+
return this;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Model with database operations
|
|
122
|
+
@Database.Model(() => cnst.User)
|
|
123
|
+
export class UserModel extends into(User, cnst.userCnst) {
|
|
124
|
+
@Loader.ByField("email") userEmailLoader: Loader<string, User>;
|
|
125
|
+
|
|
126
|
+
async findByEmail(email: string) {
|
|
127
|
+
return this.User.findOne({ email, removedAt: { $exists: false } });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async getUserSecret(email: string) {
|
|
131
|
+
return this.User.pickOne({ email, removedAt: { $exists: false } }, { roles: true, password: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Middleware for hooks and indexes
|
|
136
|
+
@Database.Middleware(() => cnst.User)
|
|
137
|
+
export class UserMiddleware extends beyond(UserModel, User) {
|
|
138
|
+
onSchema(schema: SchemaOf<UserModel, User>) {
|
|
139
|
+
// Hash password before saving
|
|
140
|
+
schema.pre<User>("save", async function (next) {
|
|
141
|
+
if (!this.isModified("password") || !this.password) {
|
|
142
|
+
next();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const encryptedPassword = await hashPassword(this.password);
|
|
146
|
+
this.password = encryptedPassword;
|
|
147
|
+
next();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Create indexes
|
|
151
|
+
schema.index({ email: 1 }, { unique: true });
|
|
152
|
+
schema.index({ email: "text" });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 3. Create Service (`[module-name].service.ts`)
|
|
158
|
+
|
|
159
|
+
Implement business logic in the service:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { DbService, Service, Srv, Use } from "@akanjs/service";
|
|
163
|
+
import { Account, type Me } from "@akanjs/signal";
|
|
164
|
+
import { isPasswordMatch } from "@shared/nest";
|
|
165
|
+
|
|
166
|
+
import { cnst } from "../cnst";
|
|
167
|
+
import * as db from "../db";
|
|
168
|
+
import type * as option from "../option";
|
|
169
|
+
import type * as srv from "../srv";
|
|
170
|
+
|
|
171
|
+
@Service("UserService")
|
|
172
|
+
export class UserService extends DbService(db.userDb) {
|
|
173
|
+
@Use() protected readonly config: option.SecurityConfig;
|
|
174
|
+
@Srv() protected readonly securityService: srv.util.SecurityService;
|
|
175
|
+
|
|
176
|
+
async signin(email: string, password: string, account?: Account) {
|
|
177
|
+
const userSecret = await this.userModel.getUserSecret(email);
|
|
178
|
+
if (!userSecret) throw new Error("User not found");
|
|
179
|
+
|
|
180
|
+
const matched = await isPasswordMatch(password, userSecret.password || "");
|
|
181
|
+
if (!matched) throw new Error("Invalid credentials");
|
|
182
|
+
|
|
183
|
+
const user = await this.userModel.getUser(userSecret.id);
|
|
184
|
+
await user.updateLastLogin().save();
|
|
185
|
+
|
|
186
|
+
return this.securityService.addJwt({ me: user }, account);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async addRole(userId: string, role: cnst.UserRole) {
|
|
190
|
+
const user = await this.userModel.getUser(userId);
|
|
191
|
+
return await user.addRole(role).save();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async createUser(data: db.UserInput) {
|
|
195
|
+
const existingUser = await this.userModel.findByEmail(data.email);
|
|
196
|
+
if (existingUser) throw new Error("User already exists");
|
|
197
|
+
|
|
198
|
+
const user = await this.userModel.createUser(data);
|
|
199
|
+
return await user.set({ roles: ["user"] }).save();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 4. Create Signal (`[module-name].signal.ts`)
|
|
205
|
+
|
|
206
|
+
Define GraphQL operations in the signal:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { ID } from "@akanjs/base";
|
|
210
|
+
import { Account, Arg, DbSignal, Me, Mutation, Query, resolve, Signal } from "@akanjs/signal";
|
|
211
|
+
|
|
212
|
+
import { cnst, Srvs } from "../cnst";
|
|
213
|
+
import type * as db from "../db";
|
|
214
|
+
|
|
215
|
+
@Signal(() => cnst.User)
|
|
216
|
+
export class UserSignal extends DbSignal(cnst.userCnst, Srvs, {
|
|
217
|
+
guards: { get: Query.Public, cru: Mutation.Admin },
|
|
218
|
+
}) {
|
|
219
|
+
@Mutation.Public(() => cnst.util.AccessToken)
|
|
220
|
+
async signin(
|
|
221
|
+
@Arg.Body("email", () => String, { example: "user@example.com" }) email: string,
|
|
222
|
+
@Arg.Body("password", () => String, { example: "password123" }) password: string,
|
|
223
|
+
@Account() account: Account
|
|
224
|
+
) {
|
|
225
|
+
const accessToken = await this.userService.signin(email, password, account);
|
|
226
|
+
return resolve<cnst.util.AccessToken>(accessToken);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@Query.User(() => cnst.User)
|
|
230
|
+
async me(@Me() me: Me) {
|
|
231
|
+
const user = await this.userService.getUser(me.id);
|
|
232
|
+
return resolve<cnst.User>(user);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@Mutation.Admin(() => cnst.User)
|
|
236
|
+
async createUser(@Arg.Body("data", () => cnst.UserInput) data: db.UserInput) {
|
|
237
|
+
const user = await this.userService.createUser(data);
|
|
238
|
+
return resolve<cnst.User>(user);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@Mutation.Admin(() => cnst.User)
|
|
242
|
+
async addUserRole(
|
|
243
|
+
@Arg.Param("userId", () => ID) userId: string,
|
|
244
|
+
@Arg.Body("role", () => String) role: cnst.UserRole
|
|
245
|
+
) {
|
|
246
|
+
const user = await this.userService.addRole(userId, role);
|
|
247
|
+
return resolve<cnst.User>(user);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 5. Create Store (`[module-name].store.ts`)
|
|
253
|
+
|
|
254
|
+
Implement client-side state management:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { StateCreator } from "zustand";
|
|
258
|
+
import { immer } from "zustand/middleware/immer";
|
|
259
|
+
|
|
260
|
+
import { cnst } from "../cnst";
|
|
261
|
+
import * as fetch from "../fetch";
|
|
262
|
+
|
|
263
|
+
export interface UserState {
|
|
264
|
+
users: cnst.User[];
|
|
265
|
+
selectedUser?: cnst.User;
|
|
266
|
+
userForm: cnst.UserInput;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface UserAction {
|
|
270
|
+
setUsers: (users: cnst.User[]) => void;
|
|
271
|
+
selectUser: (user?: cnst.User) => void;
|
|
272
|
+
setUserForm: (form: Partial<cnst.UserInput>) => void;
|
|
273
|
+
resetUserForm: () => void;
|
|
274
|
+
signin: () => Promise<void>;
|
|
275
|
+
createUser: () => Promise<void>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export type UserStore = UserState & UserAction;
|
|
279
|
+
|
|
280
|
+
export const createUserStore: StateCreator<UserStore, [["zustand/immer", never]], [], UserStore> = immer(
|
|
281
|
+
(set, get) => ({
|
|
282
|
+
users: [],
|
|
283
|
+
userForm: { email: "", password: null },
|
|
284
|
+
|
|
285
|
+
setUsers: (users) =>
|
|
286
|
+
set((state) => {
|
|
287
|
+
state.users = users;
|
|
288
|
+
}),
|
|
289
|
+
selectUser: (user) =>
|
|
290
|
+
set((state) => {
|
|
291
|
+
state.selectedUser = user;
|
|
292
|
+
}),
|
|
293
|
+
setUserForm: (form) =>
|
|
294
|
+
set((state) => {
|
|
295
|
+
state.userForm = { ...state.userForm, ...form };
|
|
296
|
+
}),
|
|
297
|
+
resetUserForm: () =>
|
|
298
|
+
set((state) => {
|
|
299
|
+
state.userForm = { email: "", password: null };
|
|
300
|
+
}),
|
|
301
|
+
|
|
302
|
+
signin: async () => {
|
|
303
|
+
const { email, password } = get().userForm;
|
|
304
|
+
if (!password) return;
|
|
305
|
+
await fetch.user.signin(email, password);
|
|
306
|
+
get().resetUserForm();
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
createUser: async () => {
|
|
310
|
+
const { userForm } = get();
|
|
311
|
+
const user = await fetch.user.createUser({ data: userForm });
|
|
312
|
+
set((state) => {
|
|
313
|
+
state.users = [...state.users, user];
|
|
314
|
+
state.userForm = { email: "", password: null };
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
})
|
|
318
|
+
);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### 6. Create Dictionary (`[module-name].dictionary.ts`)
|
|
322
|
+
|
|
323
|
+
Define internationalization strings:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
export const userDict = {
|
|
327
|
+
email: {
|
|
328
|
+
ko: "이메일",
|
|
329
|
+
en: "Email",
|
|
330
|
+
},
|
|
331
|
+
password: {
|
|
332
|
+
ko: "비밀번호",
|
|
333
|
+
en: "Password",
|
|
334
|
+
},
|
|
335
|
+
signin: {
|
|
336
|
+
ko: "로그인",
|
|
337
|
+
en: "Sign In",
|
|
338
|
+
},
|
|
339
|
+
user_list: {
|
|
340
|
+
ko: "사용자 목록",
|
|
341
|
+
en: "User List",
|
|
342
|
+
},
|
|
343
|
+
add_user: {
|
|
344
|
+
ko: "사용자 추가",
|
|
345
|
+
en: "Add User",
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 7. Register Module (`_server.ts`)
|
|
351
|
+
|
|
352
|
+
Create module registration for the server:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { databaseModuleOf } from "@akanjs/server";
|
|
356
|
+
|
|
357
|
+
import { cnst } from "../cnst";
|
|
358
|
+
import * as db from "../db";
|
|
359
|
+
import type { ModulesOptions } from "../option";
|
|
360
|
+
import { allSrvs } from "../srv";
|
|
361
|
+
import { UserService } from "./user.service";
|
|
362
|
+
import { UserSignal } from "./user.signal";
|
|
363
|
+
|
|
364
|
+
export const registerUserModule = (option: ModulesOptions) =>
|
|
365
|
+
databaseModuleOf(
|
|
366
|
+
{
|
|
367
|
+
constant: cnst.userCnst,
|
|
368
|
+
database: db.userDb,
|
|
369
|
+
signal: UserSignal,
|
|
370
|
+
service: UserService,
|
|
371
|
+
uses: { securityConfig: option.securityConfig },
|
|
372
|
+
},
|
|
373
|
+
allSrvs
|
|
374
|
+
);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 8. Create UI Components
|
|
378
|
+
|
|
379
|
+
#### Template Component (`[ModuleName].Template.tsx`)
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
import { Button, Form } from "@util/ui";
|
|
383
|
+
|
|
384
|
+
import { dict } from "../dict";
|
|
385
|
+
import { st } from "../st";
|
|
386
|
+
|
|
387
|
+
export const General = () => {
|
|
388
|
+
const { userForm } = st.use.user();
|
|
389
|
+
const { signin, setUserForm } = st.do.user();
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<Form onSubmit={signin}>
|
|
393
|
+
<Form.Item label={dict.user.email}>
|
|
394
|
+
<Form.Input type="email" value={userForm.email} onChange={(e) => setUserForm({ email: e.target.value })} />
|
|
395
|
+
</Form.Item>
|
|
396
|
+
<Form.Item label={dict.user.password}>
|
|
397
|
+
<Form.Input
|
|
398
|
+
type="password"
|
|
399
|
+
value={userForm.password || ""}
|
|
400
|
+
onChange={(e) => setUserForm({ password: e.target.value })}
|
|
401
|
+
/>
|
|
402
|
+
</Form.Item>
|
|
403
|
+
<Button type="submit">{dict.user.signin}</Button>
|
|
404
|
+
</Form>
|
|
405
|
+
);
|
|
406
|
+
};
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### Unit Component (`[ModuleName].Unit.tsx`)
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
import { Card, ModelProps } from "@util/ui";
|
|
413
|
+
|
|
414
|
+
export const UserCard = ({ user }: ModelProps<"user">) => (
|
|
415
|
+
<Card>
|
|
416
|
+
<Card.Title>{user.email}</Card.Title>
|
|
417
|
+
<Card.Content>
|
|
418
|
+
<div>Roles: {user.roles.join(", ")}</div>
|
|
419
|
+
</Card.Content>
|
|
420
|
+
</Card>
|
|
421
|
+
);
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### View Component (`[ModuleName].View.tsx`)
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { useEffect } from "react";
|
|
428
|
+
import { Container, ListContainer } from "@util/ui";
|
|
429
|
+
|
|
430
|
+
import * as Unit from "./User.Unit";
|
|
431
|
+
import * as Template from "./User.Template";
|
|
432
|
+
import { st } from "../st";
|
|
433
|
+
import { sig } from "../sig";
|
|
434
|
+
|
|
435
|
+
export const List = () => {
|
|
436
|
+
const { users } = st.use.user();
|
|
437
|
+
|
|
438
|
+
useEffect(() => {
|
|
439
|
+
void sig.user.getUsers().then((data) => {
|
|
440
|
+
st.do.user().setUsers(data.users);
|
|
441
|
+
});
|
|
442
|
+
}, []);
|
|
443
|
+
|
|
444
|
+
return (
|
|
445
|
+
<Container>
|
|
446
|
+
<ListContainer items={users} renderItem={(user) => <Unit.UserCard user={user} />} emptyText="No users found" />
|
|
447
|
+
</Container>
|
|
448
|
+
);
|
|
449
|
+
};
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### Zone Component (`[ModuleName].Zone.tsx`)
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
import { Zone } from "@util/ui";
|
|
456
|
+
|
|
457
|
+
import * as View from "./User.View";
|
|
458
|
+
import * as Template from "./User.Template";
|
|
459
|
+
import { dict } from "../dict";
|
|
460
|
+
|
|
461
|
+
export const User = () => (
|
|
462
|
+
<Zone title={dict.user.user_list}>
|
|
463
|
+
<Zone.Section title={dict.user.add_user}>
|
|
464
|
+
<Template.General />
|
|
465
|
+
</Zone.Section>
|
|
466
|
+
<Zone.Section>
|
|
467
|
+
<View.List />
|
|
468
|
+
</Zone.Section>
|
|
469
|
+
</Zone>
|
|
470
|
+
);
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### Client Exports (`index.tsx`)
|
|
474
|
+
|
|
475
|
+
```tsx
|
|
476
|
+
import { Signal } from "@util/ui";
|
|
477
|
+
import { FaUser } from "react-icons/fa";
|
|
478
|
+
|
|
479
|
+
import * as Template from "./User.Template";
|
|
480
|
+
import * as Unit from "./User.Unit";
|
|
481
|
+
import * as Util from "./User.Util";
|
|
482
|
+
import * as View from "./User.View";
|
|
483
|
+
import * as Zone from "./User.Zone";
|
|
484
|
+
|
|
485
|
+
export const User = {
|
|
486
|
+
Menu: {
|
|
487
|
+
User: {
|
|
488
|
+
key: "user",
|
|
489
|
+
label: "Users",
|
|
490
|
+
icon: <FaUser />,
|
|
491
|
+
render: () => <Zone.User />,
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
Template,
|
|
495
|
+
Unit,
|
|
496
|
+
Util,
|
|
497
|
+
View,
|
|
498
|
+
Zone,
|
|
499
|
+
};
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## How to Use Database Modules in Nest.js Server
|
|
503
|
+
|
|
504
|
+
### 1. Register Module in Server Bootstrap
|
|
505
|
+
|
|
506
|
+
In your server bootstrap file:
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
import { createNestApp } from "@akanjs/server";
|
|
510
|
+
import { registerUserModule } from "./user/_server";
|
|
511
|
+
import { registerAdminModule } from "./admin/_server";
|
|
512
|
+
|
|
513
|
+
const startServer = async () => {
|
|
514
|
+
const app = await createNestApp({
|
|
515
|
+
env: serverEnv,
|
|
516
|
+
registerModules: (options) => [
|
|
517
|
+
registerUserModule(options),
|
|
518
|
+
registerAdminModule(options),
|
|
519
|
+
// Register other modules...
|
|
520
|
+
],
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
return app;
|
|
524
|
+
};
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### 2. Using Services in Controllers or Other Services
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
import { Controller, Get } from "@nestjs/common";
|
|
531
|
+
import { UserService } from "./user/user.service";
|
|
532
|
+
|
|
533
|
+
@Controller("auth")
|
|
534
|
+
export class AuthController {
|
|
535
|
+
constructor(private readonly userService: UserService) {}
|
|
536
|
+
|
|
537
|
+
@Get("users")
|
|
538
|
+
async getUsers() {
|
|
539
|
+
return this.userService.getUsers({});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
## How to Use Components, Stores, and Signals in Client Side
|
|
545
|
+
|
|
546
|
+
### 1. Using Components in Pages
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
import { User } from "@shared/lib/user";
|
|
550
|
+
|
|
551
|
+
export default function UserPage() {
|
|
552
|
+
return (
|
|
553
|
+
<main>
|
|
554
|
+
<User.Zone.User />
|
|
555
|
+
</main>
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### 2. Using Stores for State Management
|
|
561
|
+
|
|
562
|
+
```tsx
|
|
563
|
+
import { st } from "@shared/client";
|
|
564
|
+
|
|
565
|
+
const UserComponent = () => {
|
|
566
|
+
const { users, selectedUser } = st.use.user();
|
|
567
|
+
const { selectUser, setUsers } = st.do.user();
|
|
568
|
+
|
|
569
|
+
// Use the store state and actions
|
|
570
|
+
return (
|
|
571
|
+
<div>
|
|
572
|
+
{users.map((user) => (
|
|
573
|
+
<div key={user.id} onClick={() => selectUser(user)} className={selectedUser?.id === user.id ? "selected" : ""}>
|
|
574
|
+
{user.email}
|
|
575
|
+
</div>
|
|
576
|
+
))}
|
|
577
|
+
</div>
|
|
578
|
+
);
|
|
579
|
+
};
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### 3. Using Signals for API Calls
|
|
583
|
+
|
|
584
|
+
```tsx
|
|
585
|
+
import { useEffect, useState } from "react";
|
|
586
|
+
import { sig } from "@shared/client";
|
|
587
|
+
|
|
588
|
+
const UserData = () => {
|
|
589
|
+
const [loading, setLoading] = useState(true);
|
|
590
|
+
const [error, setError] = useState<string | null>(null);
|
|
591
|
+
|
|
592
|
+
useEffect(() => {
|
|
593
|
+
setLoading(true);
|
|
594
|
+
sig.user
|
|
595
|
+
.getUsers()
|
|
596
|
+
.then((data) => {
|
|
597
|
+
st.do.user().setUsers(data.users);
|
|
598
|
+
setLoading(false);
|
|
599
|
+
})
|
|
600
|
+
.catch((err) => {
|
|
601
|
+
setError(err.message);
|
|
602
|
+
setLoading(false);
|
|
603
|
+
});
|
|
604
|
+
}, []);
|
|
605
|
+
|
|
606
|
+
if (loading) return <div>Loading...</div>;
|
|
607
|
+
if (error) return <div>Error: {error}</div>;
|
|
608
|
+
|
|
609
|
+
return <User.View.List />;
|
|
610
|
+
};
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### 4. Integrating with Menu System
|
|
614
|
+
|
|
615
|
+
```tsx
|
|
616
|
+
import { AppLayout } from "@util/ui";
|
|
617
|
+
import { User } from "@shared/lib/user";
|
|
618
|
+
import { Admin } from "@shared/lib/admin";
|
|
619
|
+
|
|
620
|
+
export const Layout = () => (
|
|
621
|
+
<AppLayout
|
|
622
|
+
pageMenus={[
|
|
623
|
+
{
|
|
624
|
+
key: "users",
|
|
625
|
+
title: "User Management",
|
|
626
|
+
menus: User.Menu,
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
key: "admin",
|
|
630
|
+
title: "Administration",
|
|
631
|
+
menus: Admin.Menu,
|
|
632
|
+
},
|
|
633
|
+
]}
|
|
634
|
+
/>
|
|
635
|
+
);
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
## Best Practices
|
|
639
|
+
|
|
640
|
+
1. **Naming Conventions**
|
|
641
|
+
|
|
642
|
+
- Use PascalCase for classes and components (e.g., `UserService`, `User.Unit.tsx`)
|
|
643
|
+
- Use camelCase for files (e.g., `user.service.ts`, `user.document.ts`)
|
|
644
|
+
|
|
645
|
+
2. **Security**
|
|
646
|
+
|
|
647
|
+
- Use `@Field.Secret` for sensitive data like passwords
|
|
648
|
+
- Apply proper permission guards to queries and mutations (`@Query.Admin`, `@Mutation.Public`)
|
|
649
|
+
- Validate input data using the `validate` option in `@Field.Prop`
|
|
650
|
+
|
|
651
|
+
3. **Code Organization**
|
|
652
|
+
|
|
653
|
+
- Keep business logic in service files
|
|
654
|
+
- Use signals for API calls only, not for business logic
|
|
655
|
+
- Define reusable utility methods in document models
|
|
656
|
+
|
|
657
|
+
4. **Performance**
|
|
658
|
+
|
|
659
|
+
- Use dataloader pattern (`@Loader.ByField`) for efficient database access
|
|
660
|
+
- Create proper indexes in the middleware
|
|
661
|
+
- Use projections to limit returned fields when appropriate
|
|
662
|
+
|
|
663
|
+
5. **Testing**
|
|
664
|
+
|
|
665
|
+
- Create signal tests for each API endpoint
|
|
666
|
+
- Mock services for unit testing signals
|
|
667
|
+
- Use integration tests for testing complex workflows
|
|
668
|
+
|
|
669
|
+
6. **UI Components**
|
|
670
|
+
|
|
671
|
+
- Follow the separation between Template, Unit, View, and Zone components
|
|
672
|
+
- Make components reusable across different parts of the application
|
|
673
|
+
- Use dictionary files for all UI text to support internationalization
|
|
674
|
+
|
|
675
|
+
7. **Real-time Features**
|
|
676
|
+
- Use GraphQL subscriptions for real-time updates
|
|
677
|
+
- Use WebSockets for bidirectional communication
|
|
678
|
+
- Use Bull queues for background processing
|
|
679
|
+
|
|
680
|
+
## Data Flow in Database Modules
|
|
681
|
+
|
|
682
|
+
1. **User Interaction** → User interacts with a component (e.g., submits a form)
|
|
683
|
+
2. **Store Action** → Action in store is triggered (e.g., `st.do.user().signin()`)
|
|
684
|
+
3. **Signal Call** → Signal method is called (e.g., `sig.user.signin()`)
|
|
685
|
+
4. **GraphQL Request** → GraphQL request is sent to the server
|
|
686
|
+
5. **Resolver** → NestJS resolver (generated from Signal) handles the request
|
|
687
|
+
6. **Service** → Service method processes the business logic
|
|
688
|
+
7. **Database** → Database operations are performed
|
|
689
|
+
8. **Response** → Result is returned through the GraphQL API
|
|
690
|
+
9. **Store Update** → Client state is updated based on the response
|
|
691
|
+
10. **UI Update** → Components re-render with the updated state
|