shutro-erp 0.2.1 → 0.3.1
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 +74 -67
- package/dist/account_portal/.kosh/bindings.d.ts +22 -0
- package/dist/account_portal/.kosh/bindings.js +15 -0
- package/dist/account_portal/.kosh/schema.d.ts +1380 -0
- package/dist/account_portal/index.d.ts +3 -0
- package/dist/account_portal/index.js +73 -0
- package/dist/account_portal/module.d.ts +5983 -0
- package/dist/account_portal/module.js +18 -0
- package/dist/accounting/.kosh/bindings.js +1 -1
- package/dist/accounting/.kosh/schema.d.ts +172 -9
- package/dist/accounting/chart.d.ts +40 -8
- package/dist/accounting/chart.js +124 -30
- package/dist/accounting/closing.d.ts +6 -1
- package/dist/accounting/closing.js +5 -1
- package/dist/accounting/demo.js +6 -5
- package/dist/accounting/index.d.ts +3 -3
- package/dist/accounting/index.js +200 -23
- package/dist/accounting/module.d.ts +3326 -1086
- package/dist/accounting/module.js +408 -66
- package/dist/accounting/payments.d.ts +25 -0
- package/dist/accounting/payments.js +96 -4
- package/dist/accounting/web/RegisterPayment.d.ts +3 -2
- package/dist/accounting/web/RegisterPayment.js +39 -6
- package/dist/accounting/web/SettingsPage.js +5 -1
- package/dist/accounting/web/messages.js +10 -0
- package/dist/assistant/routes.js +1 -1
- package/dist/automation/engine.js +1 -1
- package/dist/automation/web/messages.js +2 -2
- package/dist/cli/apps.d.ts +1 -1
- package/dist/cli/apps.js +14 -14
- package/dist/cli/bin.js +3 -0
- package/dist/cli/index.js +11 -11
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +224 -78
- package/dist/cli/launch.d.ts +16 -0
- package/dist/cli/launch.js +138 -0
- package/dist/cli/project.d.ts +7 -7
- package/dist/cli/project.js +25 -25
- package/dist/cli/prompt.d.ts +35 -0
- package/dist/cli/prompt.js +48 -2
- package/dist/cli/templates.d.ts +14 -6
- package/dist/cli/templates.js +61 -34
- package/dist/cli/tui.d.ts +7 -0
- package/dist/cli/tui.js +254 -0
- package/dist/cli/ui.d.ts +21 -8
- package/dist/cli/ui.js +65 -19
- package/dist/contacts/.kosh/bindings.js +1 -1
- package/dist/contacts/.kosh/schema.d.ts +33 -1
- package/dist/contacts/index.js +24 -1
- package/dist/contacts/module.d.ts +42 -0
- package/dist/contacts/module.js +3 -1
- package/dist/import/convert.d.ts +55 -0
- package/dist/import/convert.js +224 -0
- package/dist/import/csv.d.ts +28 -0
- package/dist/import/csv.js +115 -0
- package/dist/import/index.d.ts +33 -0
- package/dist/import/index.js +60 -0
- package/dist/import/mapping.d.ts +15 -0
- package/dist/import/mapping.js +33 -0
- package/dist/import/match.d.ts +24 -0
- package/dist/import/match.js +60 -0
- package/dist/import/models.d.ts +2 -0
- package/dist/import/models.js +102 -0
- package/dist/import/routes.d.ts +13 -0
- package/dist/import/routes.js +392 -0
- package/dist/import/run.d.ts +131 -0
- package/dist/import/run.js +568 -0
- package/dist/import/service.d.ts +153 -0
- package/dist/import/service.js +367 -0
- package/dist/import/web/ImportButton.d.ts +7 -0
- package/dist/import/web/ImportButton.js +31 -0
- package/dist/import/web/ImportWizard.d.ts +75 -0
- package/dist/import/web/ImportWizard.js +217 -0
- package/dist/import/web/index.d.ts +13 -0
- package/dist/import/web/index.js +18 -0
- package/dist/import/web/messages.d.ts +2 -0
- package/dist/import/web/messages.js +139 -0
- package/dist/import/worker.d.ts +3 -0
- package/dist/import/worker.js +52 -0
- package/dist/import/xlsx.d.ts +20 -0
- package/dist/import/xlsx.js +192 -0
- package/dist/l10n_bd/.kosh/bindings.d.ts +22 -0
- package/dist/l10n_bd/.kosh/bindings.js +15 -0
- package/dist/l10n_bd/.kosh/schema.d.ts +1311 -0
- package/dist/l10n_bd/documents.d.ts +8 -0
- package/dist/l10n_bd/documents.js +183 -0
- package/dist/l10n_bd/index.d.ts +8 -0
- package/dist/l10n_bd/index.js +156 -0
- package/dist/l10n_bd/module.d.ts +5705 -0
- package/dist/l10n_bd/module.js +163 -0
- package/dist/l10n_bd/mushak.d.ts +67 -0
- package/dist/l10n_bd/mushak.js +139 -0
- package/dist/l10n_bd/routes.d.ts +3 -0
- package/dist/l10n_bd/routes.js +205 -0
- package/dist/l10n_bd/web/MushakPage.d.ts +7 -0
- package/dist/l10n_bd/web/MushakPage.js +53 -0
- package/dist/l10n_bd/web/index.d.ts +13 -0
- package/dist/l10n_bd/web/index.js +18 -0
- package/dist/l10n_bd/web/messages.d.ts +2 -0
- package/dist/l10n_bd/web/messages.js +101 -0
- package/dist/l10n_in/.kosh/bindings.d.ts +22 -0
- package/dist/l10n_in/.kosh/bindings.js +15 -0
- package/dist/l10n_in/.kosh/schema.d.ts +1373 -0
- package/dist/l10n_in/documents.d.ts +8 -0
- package/dist/l10n_in/documents.js +114 -0
- package/dist/l10n_in/einvoice.d.ts +253 -0
- package/dist/l10n_in/einvoice.js +485 -0
- package/dist/l10n_in/gstr.d.ts +109 -0
- package/dist/l10n_in/gstr.js +430 -0
- package/dist/l10n_in/index.d.ts +20 -0
- package/dist/l10n_in/index.js +232 -0
- package/dist/l10n_in/module.d.ts +7823 -0
- package/dist/l10n_in/module.js +427 -0
- package/dist/l10n_in/routes-einvoice.d.ts +15 -0
- package/dist/l10n_in/routes-einvoice.js +124 -0
- package/dist/l10n_in/routes.d.ts +17 -0
- package/dist/l10n_in/routes.js +282 -0
- package/dist/l10n_in/web/EInvoicePanel.d.ts +8 -0
- package/dist/l10n_in/web/EInvoicePanel.js +63 -0
- package/dist/l10n_in/web/GstPage.d.ts +7 -0
- package/dist/l10n_in/web/GstPage.js +57 -0
- package/dist/l10n_in/web/GstSettings.d.ts +10 -0
- package/dist/l10n_in/web/GstSettings.js +36 -0
- package/dist/l10n_in/web/index.d.ts +15 -0
- package/dist/l10n_in/web/index.js +22 -0
- package/dist/l10n_in/web/messages.d.ts +2 -0
- package/dist/l10n_in/web/messages.js +166 -0
- package/dist/mail/index.js +2 -2
- package/dist/modules-sdk/demo.d.ts +2 -0
- package/dist/modules-sdk/demo.js +7 -3
- package/dist/modules-sdk/index.d.ts +2 -2
- package/dist/modules-sdk/index.js +1 -1
- package/dist/modules-sdk/loader.js +2 -2
- package/dist/modules-sdk/manifest.d.ts +132 -0
- package/dist/modules-sdk/manifest.js +22 -0
- package/dist/notify/inbox.js +21 -0
- package/dist/notify/messages.js +7 -3
- package/dist/notify/models.d.ts +1 -1
- package/dist/notify/models.js +2 -0
- package/dist/notify/routes.js +1 -1
- package/dist/notify/web/messages.js +5 -1
- package/dist/portal/.kosh/bindings.d.ts +22 -0
- package/dist/portal/.kosh/bindings.js +15 -0
- package/dist/portal/.kosh/schema.d.ts +376 -0
- package/dist/portal/announce.d.ts +16 -0
- package/dist/portal/announce.js +117 -0
- package/dist/portal/documents.d.ts +17 -0
- package/dist/portal/documents.js +61 -0
- package/dist/portal/index.d.ts +20 -0
- package/dist/portal/index.js +65 -0
- package/dist/portal/module.d.ts +1405 -0
- package/dist/portal/module.js +84 -0
- package/dist/portal/routes-documents.d.ts +2 -0
- package/dist/portal/routes-documents.js +391 -0
- package/dist/portal/routes.d.ts +13 -0
- package/dist/portal/routes.js +313 -0
- package/dist/portal/rules.d.ts +11 -0
- package/dist/portal/rules.js +25 -0
- package/dist/portal/web/PortalAccess.d.ts +8 -0
- package/dist/portal/web/PortalAccess.js +66 -0
- package/dist/portal/web/index.d.ts +12 -0
- package/dist/portal/web/index.js +17 -0
- package/dist/portal/web/messages.d.ts +2 -0
- package/dist/portal/web/messages.js +33 -0
- package/dist/product/.kosh/bindings.js +1 -1
- package/dist/product/.kosh/schema.d.ts +42 -3
- package/dist/product/demo.js +6 -5
- package/dist/product/index.d.ts +1 -0
- package/dist/product/index.js +17 -4
- package/dist/product/module.d.ts +346 -14
- package/dist/product/module.js +48 -18
- package/dist/product/taxes.d.ts +59 -0
- package/dist/product/taxes.js +61 -0
- package/dist/project/.kosh/bindings.js +1 -1
- package/dist/project/.kosh/schema.d.ts +33 -1
- package/dist/project/module.d.ts +20 -0
- package/dist/project_portal/.kosh/bindings.d.ts +22 -0
- package/dist/project_portal/.kosh/bindings.js +15 -0
- package/dist/project_portal/.kosh/schema.d.ts +701 -0
- package/dist/project_portal/index.d.ts +9 -0
- package/dist/project_portal/index.js +42 -0
- package/dist/project_portal/module.d.ts +2142 -0
- package/dist/project_portal/module.js +22 -0
- package/dist/purchase/.kosh/bindings.js +1 -1
- package/dist/purchase/.kosh/schema.d.ts +45 -4
- package/dist/purchase/demo.js +3 -3
- package/dist/purchase/index.js +1 -1
- package/dist/purchase/module.d.ts +232 -8
- package/dist/purchase/module.js +51 -9
- package/dist/purchase_account/.kosh/bindings.js +1 -1
- package/dist/purchase_account/.kosh/schema.d.ts +174 -10
- package/dist/purchase_account/module.d.ts +2008 -641
- package/dist/purchase_account/module.js +2 -2
- package/dist/purchase_portal/.kosh/bindings.d.ts +22 -0
- package/dist/purchase_portal/.kosh/bindings.js +15 -0
- package/dist/purchase_portal/.kosh/schema.d.ts +852 -0
- package/dist/purchase_portal/index.d.ts +9 -0
- package/dist/purchase_portal/index.js +53 -0
- package/dist/purchase_portal/module.d.ts +2758 -0
- package/dist/purchase_portal/module.js +18 -0
- package/dist/reporting/documents.js +20 -3
- package/dist/reporting/index.d.ts +1 -0
- package/dist/reporting/index.js +1 -0
- package/dist/reporting/routes-documents.js +9 -2
- package/dist/reporting/words.d.ts +11 -0
- package/dist/reporting/words.js +229 -0
- package/dist/sale_account/.kosh/bindings.js +1 -1
- package/dist/sale_account/.kosh/schema.d.ts +174 -10
- package/dist/sale_account/module.d.ts +2008 -641
- package/dist/sale_account/module.js +3 -3
- package/dist/sale_portal/.kosh/bindings.d.ts +22 -0
- package/dist/sale_portal/.kosh/bindings.js +15 -0
- package/dist/sale_portal/.kosh/schema.d.ts +766 -0
- package/dist/sale_portal/index.d.ts +9 -0
- package/dist/sale_portal/index.js +71 -0
- package/dist/sale_portal/module.d.ts +2718 -0
- package/dist/sale_portal/module.js +19 -0
- package/dist/sale_project/.kosh/bindings.js +1 -1
- package/dist/sale_project/.kosh/schema.d.ts +45 -4
- package/dist/sale_project/module.d.ts +390 -10
- package/dist/sales/.kosh/bindings.js +1 -1
- package/dist/sales/.kosh/schema.d.ts +45 -4
- package/dist/sales/demo.js +3 -3
- package/dist/sales/index.js +67 -1
- package/dist/sales/module.d.ts +232 -8
- package/dist/sales/module.js +51 -12
- package/dist/server/api/client.js +1 -1
- package/dist/server/api/openapi.js +17 -1
- package/dist/server/apps.js +5 -5
- package/dist/server/auth/api-keys.d.ts +13 -0
- package/dist/server/auth/api-keys.js +65 -0
- package/dist/server/auth/base.js +26 -0
- package/dist/server/auth/crypto.js +1 -1
- package/dist/server/auth/scopes.d.ts +12 -0
- package/dist/server/auth/scopes.js +51 -0
- package/dist/server/auth/service.d.ts +59 -1
- package/dist/server/auth/service.js +236 -6
- package/dist/server/demo.d.ts +1 -1
- package/dist/server/demo.js +1 -1
- package/dist/server/env-names.d.ts +2 -0
- package/dist/server/env-names.js +16 -0
- package/dist/server/host.js +5 -1
- package/dist/server/identity.d.ts +7 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -1
- package/dist/server/registry.js +1 -1
- package/dist/server/server.d.ts +5 -0
- package/dist/server/server.js +71 -6
- package/dist/settings/routes.js +1 -1
- package/dist/settings/web/ApiKeysPage.d.ts +8 -0
- package/dist/settings/web/ApiKeysPage.js +70 -0
- package/dist/settings/web/index.d.ts +1 -0
- package/dist/settings/web/index.js +4 -0
- package/dist/settings/web/messages.js +62 -0
- package/dist/storage/routes.js +1 -1
- package/dist/studio/build.js +1 -1
- package/dist/studio/generate.js +4 -4
- package/dist/studio/module.js +5 -5
- package/dist/studio/web/messages.js +2 -2
- package/dist/ui/api.d.ts +2 -0
- package/dist/ui/app.js +27 -4
- package/dist/ui/context.d.ts +3 -1
- package/dist/ui/context.js +2 -2
- package/dist/ui/i18n/messages.js +2 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/lib/format.d.ts +2 -0
- package/dist/ui/lib/format.js +3 -1
- package/dist/ui/pwa/worker.js +2 -2
- package/dist/ui/registry.d.ts +15 -0
- package/dist/ui/registry.js +20 -0
- package/dist/ui/views/FormView.js +19 -6
- package/package.json +52 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# shutro-erp
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Shutro ERP** is an ERP framework for Node.js, TypeScript and PostgreSQL, built on the
|
|
4
4
|
[Shutro](https://www.npmjs.com/package/shutro) ORM. Define a model once and get a REST API with OpenAPI, a typed
|
|
5
5
|
client, list / form / kanban / pivot / graph / calendar / gantt / map / dashboard views, exports, PDF documents and a
|
|
6
6
|
chatter on every record. Permissions are checked on the server on every route.
|
|
@@ -20,13 +20,13 @@ chatter on every record. Permissions are checked on the server on every route.
|
|
|
20
20
|
## Requirements
|
|
21
21
|
|
|
22
22
|
- **Node.js 24** or later (`node --version`)
|
|
23
|
-
- **PostgreSQL 16** or later, or **Docker** (
|
|
23
|
+
- **PostgreSQL 16** or later, or **Docker** (Shutro ERP can start PostgreSQL for you)
|
|
24
24
|
- An authenticator app for the administrator's second factor (Google Authenticator, Microsoft Authenticator,
|
|
25
25
|
1Password, …)
|
|
26
26
|
|
|
27
27
|
## Install with the terminal
|
|
28
28
|
|
|
29
|
-
One command creates the project, installs
|
|
29
|
+
One command creates the project, installs Shutro ERP and asks for everything it needs:
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
32
|
npx shutro-erp@latest init my-erp # the project my-erp
|
|
@@ -37,54 +37,61 @@ npx shutro-erp@latest init # asks for the project name first
|
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
39
|
npm install shutro-erp # Shutro, the ORM, comes with it
|
|
40
|
-
npx
|
|
40
|
+
npx shutro-erp init
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
The setup asks for what the installation needs
|
|
43
|
+
The setup asks for what the installation needs, one question at a time: type an answer or press **Enter** for
|
|
44
|
+
the default shown, pick from lists with **↑ ↓** and **Enter**, tick apps with **Space**, stop with **Ctrl+C**
|
|
45
|
+
(piped or scripted, the same questions are asked line by line):
|
|
44
46
|
|
|
45
47
|
| Question | Example | Notes |
|
|
46
48
|
|---|---|---|
|
|
47
|
-
| PostgreSQL |
|
|
49
|
+
| PostgreSQL | your server, or start one in Docker | Docker needs Docker Desktop running; it writes `compose.yaml` and starts the `db` service |
|
|
48
50
|
| Username, password, port, host, database name | `postgres`, (hidden), `5432`, `localhost`, `my_erp` | for `1`; a missing database is created after you confirm; if nothing answers, it offers Docker instead |
|
|
49
|
-
| Company name, currency | `Padma Traders`, `BDT
|
|
51
|
+
| Company name, currency, country | `Padma Traders`, `BDT`, Bangladesh | the first company; a country with a localization gets its taxes, chart and returns |
|
|
50
52
|
| Language, time zone | `bn`, `Asia/Dhaka` | the administrator's |
|
|
51
53
|
| Administrator login, name, email, password | `admin`, …, 12+ characters | the password is typed hidden and stored only as a hash |
|
|
52
|
-
| Apps |
|
|
53
|
-
| File storage |
|
|
54
|
+
| Apps | all ticked; untick what you do not need | roles and approvals, reports, chatter, the business apps |
|
|
55
|
+
| File storage | a folder, or S3-compatible | S3, SeaweedFS, MinIO; the bucket is created |
|
|
54
56
|
| Valkey/Redis URL | empty | optional: rate limits and caches shared by several servers |
|
|
55
|
-
| API port | `3000` | |
|
|
57
|
+
| API port, back-office (web) port | `3000`, `5173` | the next free ones are proposed |
|
|
56
58
|
| Authenticator code | `123456` | scan the printed secret, type a code; **keep the recovery codes** it prints |
|
|
57
59
|
|
|
58
60
|
Then it writes the project, creates the database tables (`migrations/0001_init.sql`), the company and the
|
|
59
|
-
administrator, and loads the apps' default data.
|
|
61
|
+
administrator, and loads the apps' default data. **Then it starts Shutro ERP for you**: it installs the project's
|
|
62
|
+
dependencies (with the package manager you ran it with: npm, pnpm, yarn or bun), starts the API and the
|
|
63
|
+
back-office, waits until both answer, and opens the back-office in your browser on the web port. Both keep
|
|
64
|
+
running in that terminal; **Ctrl+C** stops them. Sign in with the administrator's login, password and a code from
|
|
65
|
+
the authenticator app.
|
|
66
|
+
|
|
67
|
+
To start it again later (or after `--no-start`, which only sets up):
|
|
60
68
|
|
|
61
69
|
```sh
|
|
70
|
+
cd my-erp
|
|
62
71
|
npm start # the API on http://localhost:3000
|
|
63
72
|
npm run web # the back-office on http://localhost:5173, in a second terminal
|
|
64
73
|
```
|
|
65
74
|
|
|
66
|
-
Sign in with the administrator's login, password and a code from the authenticator app.
|
|
67
|
-
|
|
68
75
|
**Without questions** (scripts, CI): pass the answers as flags.
|
|
69
76
|
|
|
70
77
|
```sh
|
|
71
78
|
npx shutro-erp@latest init my-erp --yes --docker-db --admin-password "a long passphrase here"
|
|
72
79
|
|
|
73
|
-
npx
|
|
80
|
+
npx shutro-erp init --yes \
|
|
74
81
|
--database-url postgres://postgres:postgres@localhost:5432/my_erp --create-database \
|
|
75
82
|
--company "Padma Traders" --currency BDT --lang bn --tz Asia/Dhaka \
|
|
76
83
|
--admin-login admin --admin-password "a long passphrase here" \
|
|
77
|
-
--apps permissions,reporting,messaging --storage-dir ./var/attachments --port 3000
|
|
84
|
+
--apps permissions,reporting,messaging --storage-dir ./var/attachments --port 3000 --web-port 5173
|
|
78
85
|
```
|
|
79
86
|
|
|
80
|
-
With `--yes` nothing is asked, so the authenticator is not enrolled: run `npx
|
|
81
|
-
enrol it (administrator rights wait for it). `npx
|
|
87
|
+
With `--yes` nothing is asked, so the authenticator is not enrolled: run `npx shutro-erp init` again in a terminal to
|
|
88
|
+
enrol it (administrator rights wait for it). `npx shutro-erp init --help` lists every flag. Replies by email: set `MAIL_INBOUND_DOMAIN` in `.env` (the secrets are generated) and point your email provider's inbound webhook at `/api/v1/mail/inbound` with the `MAIL_INBOUND_WEBHOOK_SECRET`. `--demo` (or a yes to the
|
|
82
89
|
question after the apps) loads a sample company with contacts, products, orders, invoices and projects, made by
|
|
83
90
|
the demo users `dina`, `rahim`, `karim` and `sumi` (one shared password, printed at the end); not for production.
|
|
84
91
|
|
|
85
92
|
## Install with Docker
|
|
86
93
|
|
|
87
|
-
`
|
|
94
|
+
`shutro-erp init` writes `Dockerfile`, `compose.yaml`, `nginx.conf` and `.dockerignore` into every project.
|
|
88
95
|
|
|
89
96
|
**PostgreSQL in Docker, the app on your machine** (development):
|
|
90
97
|
|
|
@@ -110,21 +117,21 @@ docker compose up -d --build # db + api + web; the back-office on http://
|
|
|
110
117
|
| Service | What | Port |
|
|
111
118
|
|---|---|---|
|
|
112
119
|
| `db` | PostgreSQL 18, data in the `db` volume | `127.0.0.1:5432` (`POSTGRES_PORT`) |
|
|
113
|
-
| `api` | the
|
|
120
|
+
| `api` | the Shutro ERP API; runs `shutro-erp migrate` on every start, then serves | inside the network (`api:3000`) |
|
|
114
121
|
| `web` | nginx with the built back-office, `/api` proxied to `api` | `8080` (`WEB_PORT`) |
|
|
115
122
|
|
|
116
123
|
Useful commands:
|
|
117
124
|
|
|
118
125
|
```sh
|
|
119
126
|
docker compose logs -f api # the API's log
|
|
120
|
-
docker compose exec api npx
|
|
121
|
-
docker compose exec api npx
|
|
127
|
+
docker compose exec api npx shutro-erp migrate status # any shutro-erp command inside the container
|
|
128
|
+
docker compose exec api npx shutro-erp seed
|
|
122
129
|
docker compose up -d --build api # after changing modules: rebuild and migrate
|
|
123
130
|
docker compose down # stop (volumes keep the data)
|
|
124
|
-
docker compose exec db pg_dump -U
|
|
131
|
+
docker compose exec db pg_dump -U shutro my_erp > backup.sql # a backup
|
|
125
132
|
```
|
|
126
133
|
|
|
127
|
-
Behind HTTPS, set `
|
|
134
|
+
Behind HTTPS, set `SHUTRO_ERP_SECURE_COOKIES: "true"` in `compose.yaml`. To use a PostgreSQL server outside Docker, set
|
|
128
135
|
`DOCKER_DATABASE_URL` in `.env` (an address the container can reach, not `localhost`).
|
|
129
136
|
|
|
130
137
|
## Project structure
|
|
@@ -137,7 +144,7 @@ my-erp/
|
|
|
137
144
|
├── src/
|
|
138
145
|
│ ├── modules.ts the installed modules: base, the apps, your modules
|
|
139
146
|
│ ├── server.ts the API server (npm start)
|
|
140
|
-
│ ├── modules/ your modules (
|
|
147
|
+
│ ├── modules/ your modules (shutro-erp module create <name>)
|
|
141
148
|
│ │ └── library/
|
|
142
149
|
│ │ ├── index.ts the module: groups, access levels, app, menus, actions, views
|
|
143
150
|
│ │ ├── models.ts its models (fields, access per group, record rules)
|
|
@@ -145,7 +152,7 @@ my-erp/
|
|
|
145
152
|
│ │ └── migrations.ts its data migrations
|
|
146
153
|
│ └── web/
|
|
147
154
|
│ ├── main.tsx the back-office (React): renderers of each installed app
|
|
148
|
-
│ └── index.css Tailwind +
|
|
155
|
+
│ └── index.css Tailwind + Shutro ERP's design tokens
|
|
149
156
|
├── index.html, vite.config.ts the back-office build (npm run web / build:web)
|
|
150
157
|
├── Dockerfile, compose.yaml, nginx.conf, .dockerignore
|
|
151
158
|
└── var/attachments/ uploaded files (with folder storage)
|
|
@@ -156,8 +163,8 @@ my-erp/
|
|
|
156
163
|
A module is a folder with its models and a manifest. Create one:
|
|
157
164
|
|
|
158
165
|
```sh
|
|
159
|
-
npx
|
|
160
|
-
npx
|
|
166
|
+
npx shutro-erp module create library
|
|
167
|
+
npx shutro-erp migrate # creates its tables, records it, loads its seed data
|
|
161
168
|
```
|
|
162
169
|
|
|
163
170
|
It writes `src/modules/library/` and adds `library` to `src/modules.ts`. After `npm start` and a reload of the
|
|
@@ -191,7 +198,7 @@ export const Book = defineModel('library.book', {
|
|
|
191
198
|
```
|
|
192
199
|
|
|
193
200
|
**`index.ts`**: the module: its Shutro part (name, version, groups, models, seed data, data migrations) and its
|
|
194
|
-
|
|
201
|
+
Shutro ERP part (access levels, app, menus, actions, views):
|
|
195
202
|
|
|
196
203
|
```ts
|
|
197
204
|
import { base, baseShutro } from 'shutro-erp';
|
|
@@ -252,29 +259,29 @@ export const modules = [base, messaging, library];
|
|
|
252
259
|
```
|
|
253
260
|
|
|
254
261
|
```sh
|
|
255
|
-
npx
|
|
262
|
+
npx shutro-erp migrate # tables, the module's version (shutro_module), its seed data
|
|
256
263
|
```
|
|
257
264
|
|
|
258
265
|
A module published on npm installs the same way: `npm install <package>`, import it in `src/modules.ts`, then
|
|
259
|
-
`npx
|
|
266
|
+
`npx shutro-erp migrate`. Installing does not give anyone access: grant its roles to users ([Users and roles](#users-and-roles)).
|
|
260
267
|
|
|
261
|
-
**Remove a module**: take it out of `src/modules.ts`; `npx
|
|
262
|
-
destructive: it stops for review, and `npx
|
|
268
|
+
**Remove a module**: take it out of `src/modules.ts`; `npx shutro-erp migrate` then plans dropping its tables, which is
|
|
269
|
+
destructive: it stops for review, and `npx shutro-erp migrate --allow-destructive` applies it. Back up first.
|
|
263
270
|
|
|
264
271
|
## Migrations
|
|
265
272
|
|
|
266
273
|
```sh
|
|
267
|
-
npx
|
|
268
|
-
npx
|
|
269
|
-
npx
|
|
270
|
-
npx
|
|
271
|
-
npx
|
|
274
|
+
npx shutro-erp migrate # plan + apply + seed
|
|
275
|
+
npx shutro-erp migrate --plan # only write the plan, to review it
|
|
276
|
+
npx shutro-erp migrate --name add_isbn # name the new file (migrations/0002_add_isbn.sql)
|
|
277
|
+
npx shutro-erp migrate status # applied and pending files
|
|
278
|
+
npx shutro-erp migrate --allow-destructive
|
|
272
279
|
```
|
|
273
280
|
|
|
274
|
-
- **Schema migrations** are SQL files in `migrations/`. `
|
|
281
|
+
- **Schema migrations** are SQL files in `migrations/`. `shutro-erp migrate` compares your modules with the live database
|
|
275
282
|
and writes the differences as the next file (`0002_update.sql`), applies every pending file in order (each in its
|
|
276
283
|
own transaction, recorded in `shutro_migration`), then loads the seed data. Commit the files: a deployment runs the
|
|
277
|
-
same ones (the Docker `api` service runs `
|
|
284
|
+
same ones (the Docker `api` service runs `shutro-erp migrate` on start).
|
|
278
285
|
- **Destructive changes** (dropping a column or a table, narrowing a type) are written but not applied without
|
|
279
286
|
`--allow-destructive`. A file written earlier and not applied yet is applied first.
|
|
280
287
|
- **Per-module data migrations** change existing data when a module is upgraded. Declare them in the module's
|
|
@@ -298,7 +305,7 @@ export const migrations: DataMigration[] = [
|
|
|
298
305
|
|
|
299
306
|
```sh
|
|
300
307
|
# index.ts: version: '0.2.0'
|
|
301
|
-
npx
|
|
308
|
+
npx shutro-erp migrate # … module library: 0.1.0 → 0.2.0, data migration library@0.2.0
|
|
302
309
|
```
|
|
303
310
|
|
|
304
311
|
## Seed data
|
|
@@ -322,18 +329,18 @@ export const data = [
|
|
|
322
329
|
```
|
|
323
330
|
|
|
324
331
|
```sh
|
|
325
|
-
npx
|
|
326
|
-
npx
|
|
332
|
+
npx shutro-erp seed # every module's seed data, and the apps' defaults
|
|
333
|
+
npx shutro-erp seed library # one module (or several: shutro-erp seed library inventory)
|
|
327
334
|
```
|
|
328
335
|
|
|
329
|
-
`
|
|
336
|
+
`shutro-erp migrate` seeds too (skip with `--no-seed`). The apps' defaults are also seeded: approval policies
|
|
330
337
|
(permissions), document templates (reporting), activity types (messaging); users may edit them afterwards.
|
|
331
338
|
|
|
332
339
|
## Users and roles
|
|
333
340
|
|
|
334
341
|
```sh
|
|
335
|
-
npx
|
|
336
|
-
npx
|
|
342
|
+
npx shutro-erp user create rahim --name "Rahim Uddin" --email rahim@example.com --roles library.user,messaging.user
|
|
343
|
+
npx shutro-erp user password rahim # a new password (asked, hidden)
|
|
337
344
|
```
|
|
338
345
|
|
|
339
346
|
Roles are the groups of the installed modules' access levels (`library.user`, `library.manager`,
|
|
@@ -347,31 +354,31 @@ their roles grants it. Administrators manage roles, field security and grants in
|
|
|
347
354
|
|---|---|
|
|
348
355
|
| `DATABASE_URL` | PostgreSQL: `postgres://user:password@host:5432/database` |
|
|
349
356
|
| `PORT`, `HOST` | the API's port (3000) and address (127.0.0.1; 0.0.0.0 in Docker) |
|
|
350
|
-
| `
|
|
357
|
+
| `SHUTRO_ERP_STORAGE_DIR` | attachments in this folder, or: |
|
|
351
358
|
| `S3_ENDPOINT`, `S3_BUCKET`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_REGION` | S3-compatible storage |
|
|
352
|
-
| `
|
|
359
|
+
| `SHUTRO_ERP_ATTACHMENT_MAX_BYTES` | upload limit (25 MB) |
|
|
353
360
|
| `VALKEY_URL` | optional Valkey/Redis: rate limits and caches across servers |
|
|
354
|
-
| `
|
|
355
|
-
| `
|
|
361
|
+
| `SHUTRO_ERP_SECURE_COOKIES` | `true` behind HTTPS (default in production), `false` for plain HTTP |
|
|
362
|
+
| `SHUTRO_ERP_SCHEDULES` | `off` stops the scheduled-report ticker on this server |
|
|
356
363
|
| `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB`, `POSTGRES_PORT` | the Docker `db` service |
|
|
357
364
|
| `DOCKER_DATABASE_URL`, `WEB_PORT` | Docker: another database for `api`; the back-office's port (8080) |
|
|
358
365
|
|
|
359
366
|
## Command reference
|
|
360
367
|
|
|
361
|
-
Run them in the project folder (`npx
|
|
368
|
+
Run them in the project folder (`npx shutro-erp …`, or `npm run migrate` / `npm run seed`). They read `.env` and
|
|
362
369
|
`src/modules.ts` (`--modules <file>` for another list).
|
|
363
370
|
|
|
364
371
|
| Command | What |
|
|
365
372
|
|---|---|
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
| `
|
|
374
|
-
| `
|
|
373
|
+
| `shutro-erp init [folder]` | set up an installation (questions, or flags with `--yes`); again later to enrol 2FA |
|
|
374
|
+
| `shutro-erp migrate` | apply pending files, plan what is missing into a new file and apply it, run data migrations, seed |
|
|
375
|
+
| `shutro-erp migrate --plan` · `--name <n>` · `--allow-destructive` · `--no-seed` | review only · file name · drops · no seeding |
|
|
376
|
+
| `shutro-erp migrate status` | applied and pending migration files |
|
|
377
|
+
| `shutro-erp seed [module …]` | seed data of all modules, or of those named |
|
|
378
|
+
| `shutro-erp module create <name>` | a new module in `src/modules/<name>/`, listed in `src/modules.ts` |
|
|
379
|
+
| `shutro-erp user create <login>` | a user: `--name`, `--email`, `--roles`, `--password` (asked when missing) |
|
|
380
|
+
| `shutro-erp user password <login>` | a new password |
|
|
381
|
+
| `shutro-erp generate client` | a typed API client for your front-end (`--out src/api/shutro-erp.gen.ts`) |
|
|
375
382
|
| `npm start` · `npm run web` · `npm run build:web` | the API · the back-office (dev) · the back-office build (`dist/`) |
|
|
376
383
|
| `npm run docker:up` | `docker compose up -d --build` |
|
|
377
384
|
|
|
@@ -380,26 +387,26 @@ Run them in the project folder (`npx kosh …`, or `npm run migrate` / `npm run
|
|
|
380
387
|
| Import | What |
|
|
381
388
|
|---|---|
|
|
382
389
|
| `shutro-erp` | the server: `createServer`, `startServer`, `base`, REST + OpenAPI, sessions and 2FA |
|
|
383
|
-
| `shutro-erp/orm` | Shutro (models, fields, groups, records, migrations) as
|
|
390
|
+
| `shutro-erp/orm` | Shutro (models, fields, groups, records, migrations) as Shutro ERP uses it |
|
|
384
391
|
| `shutro-erp/modules-sdk` | `defineModule`: manifests, access levels, menus, actions |
|
|
385
392
|
| `shutro-erp/views`, `shutro-erp/search` | view definitions (`list`, `form`, `kanban`, `pivot`, …) and the search layer |
|
|
386
393
|
| `shutro-erp/permissions` | roles, field security, approvals (`/web`: the approval panel) |
|
|
387
394
|
| `shutro-erp/reporting` | pivots, exports, documents, scheduled reports (`/web`: the report views) |
|
|
388
395
|
| `shutro-erp/messaging`, `shutro-erp/storage` | the chatter, activities, attachments (`/web`: the chatter) |
|
|
389
396
|
| `shutro-erp/ui` | the React app shell, design system and renderers; `shutro-erp/ui/styles.css` the tokens |
|
|
390
|
-
| `shutro-erp/cli` | the `
|
|
397
|
+
| `shutro-erp/cli` | the `shutro-erp` command's functions |
|
|
391
398
|
|
|
392
399
|
## Troubleshooting
|
|
393
400
|
|
|
394
401
|
- **"PostgreSQL did not answer"**: nothing listens at that host and port. Start your PostgreSQL service, or
|
|
395
402
|
answer `2` (Docker) to the first question; Docker Desktop must be running.
|
|
396
403
|
- **"password authentication failed"**: the user or password in `DATABASE_URL` is wrong.
|
|
397
|
-
- **Signed in but no apps**: the user has no role granting them (`
|
|
398
|
-
their authenticator enrolled (`npx
|
|
399
|
-
- **Sign-in works on the API but not in the browser over plain HTTP**: `
|
|
400
|
-
- **Lost the phone**: sign in with one of the recovery codes `
|
|
401
|
-
- **"It drops or changes existing data"**: `
|
|
402
|
-
`migrations/`, back up, then `npx
|
|
404
|
+
- **Signed in but no apps**: the user has no role granting them (`shutro-erp user create … --roles`); administrators need
|
|
405
|
+
their authenticator enrolled (`npx shutro-erp init` again).
|
|
406
|
+
- **Sign-in works on the API but not in the browser over plain HTTP**: `SHUTRO_ERP_SECURE_COOKIES=false`.
|
|
407
|
+
- **Lost the phone**: sign in with one of the recovery codes `shutro-erp init` printed.
|
|
408
|
+
- **"It drops or changes existing data"**: `shutro-erp migrate` found a destructive change; read the new file in
|
|
409
|
+
`migrations/`, back up, then `npx shutro-erp migrate --allow-destructive`.
|
|
403
410
|
|
|
404
411
|
Documentation, design notes and the source: https://github.com/isahaq1/kosh
|
|
405
412
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
2
|
+
import { type DefinitionHelpers } from '../../server/orm.js';
|
|
3
|
+
import type { DefaultLoaded, Env as CoreEnv, RecordSet as CoreRecordSet, Shutro as CoreShutro } from '../../server/orm.js';
|
|
4
|
+
import type { SchemaView } from './schema.js';
|
|
5
|
+
export type { SchemaView };
|
|
6
|
+
/** Every model visible in this view. */
|
|
7
|
+
export type ModelName = keyof SchemaView & string;
|
|
8
|
+
/** `Env` typed to this view. */
|
|
9
|
+
export type Env = CoreEnv<SchemaView>;
|
|
10
|
+
/** `Shutro` typed to this view. */
|
|
11
|
+
export type Shutro = CoreShutro<SchemaView>;
|
|
12
|
+
/** A recordset of `M`, with the default loaded shape unless `L` is given. */
|
|
13
|
+
export type Records<M extends ModelName, L = DefaultLoaded<SchemaView, M>> = CoreRecordSet<SchemaView, M, L>;
|
|
14
|
+
export declare const compute: DefinitionHelpers<SchemaView>['compute'];
|
|
15
|
+
export declare const check: DefinitionHelpers<SchemaView>['check'];
|
|
16
|
+
export declare const onchange: DefinitionHelpers<SchemaView>['onchange'];
|
|
17
|
+
export declare const records: DefinitionHelpers<SchemaView>['records'];
|
|
18
|
+
export declare const method: DefinitionHelpers<SchemaView>['method'];
|
|
19
|
+
/** Module data (RFC 0017): records, overrides of dependencies' records, and references, typed like creates. */
|
|
20
|
+
export declare const record: DefinitionHelpers<SchemaView>['record'];
|
|
21
|
+
export declare const override: DefinitionHelpers<SchemaView>['override'];
|
|
22
|
+
export declare const ref: DefinitionHelpers<SchemaView>['ref'];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 0ea5d21ac5b24166
|
|
2
|
+
// Bindings of module `account_portal`: import the definition API from here to get types scoped to what it can see.
|
|
3
|
+
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
|
+
import { definitions } from '../../server/orm.js';
|
|
5
|
+
/** Definition callbacks typed against this module's view: no casts in computes, checks, onchange, methods. */
|
|
6
|
+
const helpers = definitions();
|
|
7
|
+
export const compute = helpers.compute;
|
|
8
|
+
export const check = helpers.check;
|
|
9
|
+
export const onchange = helpers.onchange;
|
|
10
|
+
export const records = helpers.records;
|
|
11
|
+
export const method = helpers.method;
|
|
12
|
+
/** Module data (RFC 0017): records, overrides of dependencies' records, and references, typed like creates. */
|
|
13
|
+
export const record = helpers.record;
|
|
14
|
+
export const override = helpers.override;
|
|
15
|
+
export const ref = helpers.ref;
|