shutro-erp 0.3.0 → 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 +58 -58
- package/dist/account_portal/.kosh/bindings.js +1 -1
- package/dist/account_portal/.kosh/schema.d.ts +31 -1
- package/dist/accounting/.kosh/bindings.js +1 -1
- package/dist/accounting/.kosh/schema.d.ts +31 -1
- 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 +58 -36
- package/dist/cli/launch.js +2 -2
- package/dist/cli/project.d.ts +7 -7
- package/dist/cli/project.js +25 -25
- package/dist/cli/prompt.js +2 -2
- package/dist/cli/templates.d.ts +3 -3
- package/dist/cli/templates.js +29 -27
- package/dist/cli/ui.d.ts +1 -8
- package/dist/cli/ui.js +17 -11
- package/dist/contacts/.kosh/bindings.js +1 -1
- package/dist/contacts/.kosh/schema.d.ts +31 -1
- package/dist/l10n_bd/.kosh/bindings.js +1 -1
- package/dist/l10n_bd/.kosh/schema.d.ts +31 -1
- package/dist/l10n_in/.kosh/bindings.js +1 -1
- package/dist/l10n_in/.kosh/schema.d.ts +31 -1
- package/dist/l10n_in/einvoice.js +1 -1
- package/dist/l10n_in/web/messages.js +2 -2
- package/dist/mail/index.js +2 -2
- package/dist/modules-sdk/loader.js +2 -2
- package/dist/notify/messages.js +3 -3
- package/dist/notify/routes.js +1 -1
- package/dist/notify/web/messages.js +1 -1
- package/dist/portal/.kosh/bindings.js +1 -1
- package/dist/portal/.kosh/schema.d.ts +31 -1
- package/dist/product/.kosh/bindings.js +1 -1
- package/dist/product/.kosh/schema.d.ts +31 -1
- package/dist/project/.kosh/bindings.js +1 -1
- package/dist/project/.kosh/schema.d.ts +31 -1
- package/dist/project_portal/.kosh/bindings.js +1 -1
- package/dist/project_portal/.kosh/schema.d.ts +31 -1
- package/dist/purchase/.kosh/bindings.js +1 -1
- package/dist/purchase/.kosh/schema.d.ts +31 -1
- package/dist/purchase_account/.kosh/bindings.js +1 -1
- package/dist/purchase_account/.kosh/schema.d.ts +31 -1
- package/dist/purchase_portal/.kosh/bindings.js +1 -1
- package/dist/purchase_portal/.kosh/schema.d.ts +31 -1
- package/dist/sale_account/.kosh/bindings.js +1 -1
- package/dist/sale_account/.kosh/schema.d.ts +31 -1
- package/dist/sale_portal/.kosh/bindings.js +1 -1
- package/dist/sale_portal/.kosh/schema.d.ts +31 -1
- package/dist/sale_project/.kosh/bindings.js +1 -1
- package/dist/sale_project/.kosh/schema.d.ts +31 -1
- package/dist/sales/.kosh/bindings.js +1 -1
- package/dist/sales/.kosh/schema.d.ts +31 -1
- 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 +24 -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 +57 -1
- package/dist/server/auth/service.js +229 -5
- 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 +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/registry.js +1 -1
- package/dist/server/server.d.ts +5 -0
- package/dist/server/server.js +45 -5
- 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/app.js +26 -3
- package/dist/ui/i18n/messages.js +2 -2
- package/dist/ui/pwa/worker.js +2 -2
- package/dist/ui/registry.d.ts +15 -0
- package/dist/ui/registry.js +20 -0
- package/package.json +3 -3
package/dist/cli/templates.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The starter project `
|
|
2
|
+
* The starter project `shutro-erp init` writes: an API server and the back-office app, both importing `shutro-erp`.
|
|
3
3
|
* Server files run on Node.js directly (type stripping); the back-office is a Vite app proxying `/api` to the server.
|
|
4
4
|
*/
|
|
5
|
-
/** The apps `
|
|
5
|
+
/** The apps `shutro-erp init` can install (base and Settings are always there), in the order the installer lists them. */
|
|
6
6
|
export const APPS = {
|
|
7
7
|
permissions: {
|
|
8
8
|
label: 'Roles, field security and approvals',
|
|
@@ -105,8 +105,8 @@ export function packageJson(options, existing) {
|
|
|
105
105
|
start: 'node --env-file=.env src/server.ts',
|
|
106
106
|
web: 'vite',
|
|
107
107
|
'build:web': 'vite build',
|
|
108
|
-
migrate: '
|
|
109
|
-
seed: '
|
|
108
|
+
migrate: 'shutro-erp migrate',
|
|
109
|
+
seed: 'shutro-erp seed',
|
|
110
110
|
'docker:up': 'docker compose up -d --build',
|
|
111
111
|
}),
|
|
112
112
|
engines: { node: '>=24', ...(base['engines'] ?? {}) },
|
|
@@ -130,7 +130,7 @@ export function modulesTs(_options) {
|
|
|
130
130
|
const imports = apps.map((a) => `import { ${APPS[a].server} } from 'shutro-erp/${a}';`);
|
|
131
131
|
return `/**
|
|
132
132
|
* The apps this installation can install (the catalogue). The database records which are installed: Settings → Apps
|
|
133
|
-
* in the back-office, or \`npx
|
|
133
|
+
* in the back-office, or \`npx shutro-erp apps\`, installs, disables and enables them. \`base\` (users, companies, sign-in)
|
|
134
134
|
* and Settings are always installed. Add your own modules here (\`defineModule\` from \`shutro-erp/modules-sdk\`),
|
|
135
135
|
* then install them from Settings → Apps.
|
|
136
136
|
*/
|
|
@@ -150,7 +150,7 @@ export const modules = [base, settings, realtime, notify, mail, automation, stud
|
|
|
150
150
|
}
|
|
151
151
|
export function serverTs() {
|
|
152
152
|
return `/**
|
|
153
|
-
* The
|
|
153
|
+
* The Shutro ERP API server: \`npm start\` (reads .env). It serves the installed apps of src/modules.ts, and switches to
|
|
154
154
|
* the new set without a restart when apps are installed or disabled (here or on another server).
|
|
155
155
|
*/
|
|
156
156
|
import { createAppHost, startAppHost } from 'shutro-erp';
|
|
@@ -162,11 +162,11 @@ const host = await createAppHost({
|
|
|
162
162
|
catalogue: modules,
|
|
163
163
|
migrationsDir: 'migrations',
|
|
164
164
|
...(env['VALKEY_URL'] ? { valkeyUrl: env['VALKEY_URL'] } : {}),
|
|
165
|
-
// Secure cookies need HTTPS: on by default in production (
|
|
166
|
-
auth: { secureCookies: (env['KOSH_SECURE_COOKIES'] ?? String(env['NODE_ENV'] === 'production')) === 'true' },
|
|
165
|
+
// Secure cookies need HTTPS: on by default in production (SHUTRO_ERP_SECURE_COOKIES=false for plain HTTP).
|
|
166
|
+
auth: { secureCookies: (env['SHUTRO_ERP_SECURE_COOKIES'] ?? env['KOSH_SECURE_COOKIES'] ?? String(env['NODE_ENV'] === 'production')) === 'true' },
|
|
167
167
|
});
|
|
168
168
|
const address = await startAppHost(host, { port: Number(env['PORT'] ?? 3000), host: env['HOST'] ?? '127.0.0.1' });
|
|
169
|
-
process.stdout.write(\`
|
|
169
|
+
process.stdout.write(\`Shutro ERP API on \${address}\\n\`);
|
|
170
170
|
`;
|
|
171
171
|
}
|
|
172
172
|
export function viteConfig(options) {
|
|
@@ -176,7 +176,7 @@ import react from '@vitejs/plugin-react';
|
|
|
176
176
|
import { koshPwa } from 'shutro-erp/ui/vite';
|
|
177
177
|
import { defineConfig } from 'vite';
|
|
178
178
|
|
|
179
|
-
const api = process.env['KOSH_API'] ?? 'http://localhost:${options.port}';
|
|
179
|
+
const api = process.env['SHUTRO_ERP_API'] ?? process.env['KOSH_API'] ?? 'http://localhost:${options.port}';
|
|
180
180
|
|
|
181
181
|
export default defineConfig({
|
|
182
182
|
// koshPwa: the service worker (the app opens offline and gets web push)
|
|
@@ -263,7 +263,7 @@ export function manifest(options) {
|
|
|
263
263
|
}
|
|
264
264
|
/** The app icon (replace it with the company's). */
|
|
265
265
|
export function icon() {
|
|
266
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="
|
|
266
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="Shutro ERP">
|
|
267
267
|
<rect width="512" height="512" rx="112" fill="#1d4ed8"/>
|
|
268
268
|
<path d="M156 128h56v112l108-112h72L270 258l128 126h-74L220 282v102h-64z" fill="#fff"/>
|
|
269
269
|
</svg>
|
|
@@ -273,7 +273,7 @@ export function indexCss() {
|
|
|
273
273
|
return `@import "tailwindcss";
|
|
274
274
|
@import "shutro-erp/ui/styles.css";
|
|
275
275
|
|
|
276
|
-
/* Tailwind scans
|
|
276
|
+
/* Tailwind scans Shutro ERP's components for the classes they use. */
|
|
277
277
|
@source "../../node_modules/shutro-erp/dist";
|
|
278
278
|
`;
|
|
279
279
|
}
|
|
@@ -286,7 +286,7 @@ var/
|
|
|
286
286
|
}
|
|
287
287
|
/** Three images from one build: the API (migrates, then serves) and nginx with the back-office. */
|
|
288
288
|
export function dockerfile() {
|
|
289
|
-
return `#
|
|
289
|
+
return `# Shutro ERP images (shutro-erp init). Built by compose.yaml: docker compose up -d --build
|
|
290
290
|
FROM node:24-alpine AS build
|
|
291
291
|
WORKDIR /app
|
|
292
292
|
COPY package.json package-lock.json* ./
|
|
@@ -306,7 +306,7 @@ COPY --from=build /app/migrations ./migrations
|
|
|
306
306
|
RUN mkdir -p /app/var/attachments && chown -R node:node /app/var
|
|
307
307
|
USER node
|
|
308
308
|
EXPOSE 3000
|
|
309
|
-
CMD ["sh", "-c", "npx
|
|
309
|
+
CMD ["sh", "-c", "npx shutro-erp migrate && node src/server.ts"]
|
|
310
310
|
|
|
311
311
|
# The back-office: static files, /api proxied to the API.
|
|
312
312
|
FROM nginx:1.27-alpine AS web
|
|
@@ -315,7 +315,7 @@ COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
|
315
315
|
`;
|
|
316
316
|
}
|
|
317
317
|
export function nginxConf() {
|
|
318
|
-
return `# The back-office (
|
|
318
|
+
return `# The back-office (shutro-erp init): the built app, /api proxied to the API service.
|
|
319
319
|
server {
|
|
320
320
|
listen 80;
|
|
321
321
|
root /usr/share/nginx/html;
|
|
@@ -346,9 +346,9 @@ export function composeYaml(options) {
|
|
|
346
346
|
const db = options.dockerDb ?? options.name.replace(/-/g, '_');
|
|
347
347
|
/** A compose variable: `${NAME}` or `${NAME:-default}` (plain strings: nothing to escape). */
|
|
348
348
|
const v = (name, fallback) => ['$', '{', name, fallback === undefined ? '' : fallback, '}'].join('');
|
|
349
|
-
const user = v('POSTGRES_USER', ':-
|
|
349
|
+
const user = v('POSTGRES_USER', ':-shutro');
|
|
350
350
|
const lines = [
|
|
351
|
-
'#
|
|
351
|
+
'# Shutro ERP in Docker (shutro-erp init).',
|
|
352
352
|
'# docker compose up -d db only PostgreSQL (the API runs with npm start)',
|
|
353
353
|
'# docker compose up -d --build everything: the back-office on http://localhost:8080',
|
|
354
354
|
`name: ${options.name}`,
|
|
@@ -367,7 +367,7 @@ export function composeYaml(options) {
|
|
|
367
367
|
' - db:/var/lib/postgresql',
|
|
368
368
|
' healthcheck:',
|
|
369
369
|
// $$ is a literal $ for compose: the shell in the container expands the variable.
|
|
370
|
-
` test: ["CMD-SHELL", "pg_isready -U $${v('POSTGRES_USER', ':-
|
|
370
|
+
` test: ["CMD-SHELL", "pg_isready -U $${v('POSTGRES_USER', ':-shutro')}"]`,
|
|
371
371
|
' interval: 5s',
|
|
372
372
|
' retries: 30',
|
|
373
373
|
'',
|
|
@@ -379,9 +379,11 @@ export function composeYaml(options) {
|
|
|
379
379
|
' env_file: .env',
|
|
380
380
|
' environment:',
|
|
381
381
|
` DATABASE_URL: ${v('DOCKER_DATABASE_URL', `:-postgres://${user}:${v('POSTGRES_PASSWORD')}@db:5432/${v('POSTGRES_DB', `:-${db}`)}`)}`,
|
|
382
|
-
...(options.fileStorage === false
|
|
382
|
+
...(options.fileStorage === false
|
|
383
|
+
? []
|
|
384
|
+
: [' SHUTRO_ERP_STORAGE_DIR: /app/var/attachments']),
|
|
383
385
|
' # Plain HTTP on localhost; set "true" when the site is served over HTTPS.',
|
|
384
|
-
'
|
|
386
|
+
' SHUTRO_ERP_SECURE_COOKIES: "false"',
|
|
385
387
|
' depends_on:',
|
|
386
388
|
' db:',
|
|
387
389
|
' condition: service_healthy',
|
|
@@ -431,19 +433,19 @@ export function tsconfig() {
|
|
|
431
433
|
export function readme(options) {
|
|
432
434
|
return `# ${options.name}
|
|
433
435
|
|
|
434
|
-
A [
|
|
436
|
+
A [Shutro ERP](https://www.npmjs.com/package/shutro-erp) installation, created with \`shutro-erp init\`.
|
|
435
437
|
|
|
436
438
|
\`\`\`sh
|
|
437
439
|
npm install
|
|
438
440
|
npm start # the API on http://localhost:${options.port}
|
|
439
441
|
npm run web # the back-office on http://localhost:${options.webPort ?? 5173} (sign in as the administrator)
|
|
440
|
-
npx
|
|
441
|
-
npx
|
|
442
|
+
npx shutro-erp migrate # after changing modules: plan and apply database migrations, load seed data
|
|
443
|
+
npx shutro-erp seed # load seed data again
|
|
442
444
|
# Settings → Apps in the back-office installs, enables and disables apps (or, in the terminal:)
|
|
443
|
-
npx
|
|
444
|
-
npx
|
|
445
|
-
npx
|
|
446
|
-
npx
|
|
445
|
+
npx shutro-erp apps # the apps: installed, disabled, available
|
|
446
|
+
npx shutro-erp apps install <name> # install an app (and what it needs) in one transaction
|
|
447
|
+
npx shutro-erp apps disable <name> # switch an app off; its data stays (npx shutro-erp apps enable <name>)
|
|
448
|
+
npx shutro-erp module create <name> # a new module in src/modules/<name>/
|
|
447
449
|
docker compose up -d --build # everything in Docker: http://localhost:8080
|
|
448
450
|
\`\`\`
|
|
449
451
|
|
package/dist/cli/ui.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The installer's look in the terminal, without dependencies: a logo, numbered steps, spinners for long work,
|
|
3
|
-
* status lines (✔ ▲ ✖) and a summary card. On a Unicode terminal everything hangs on one rail down the left (│),
|
|
4
|
-
* the questions of the interactive prompter included (`tui.ts`). Colour, Unicode and animation are detected from
|
|
5
|
-
* the terminal (NO_COLOR, FORCE_COLOR, KOSH_ASCII=1, TERM=dumb, Windows consoles without Unicode); output that is not
|
|
6
|
-
* a terminal (tests, logs, CI) gets plain lines with the same words and no escape codes.
|
|
7
|
-
*/
|
|
8
1
|
/** What the terminal can show. */
|
|
9
2
|
export interface Terminal {
|
|
10
3
|
readonly color: boolean;
|
|
@@ -23,7 +16,7 @@ type Env = Readonly<Record<string, string | undefined>>;
|
|
|
23
16
|
export declare function detectTerminal(stream: {
|
|
24
17
|
readonly isTTY?: boolean;
|
|
25
18
|
readonly columns?: number;
|
|
26
|
-
}, env?: Env, platform?: string): Terminal;
|
|
19
|
+
}, env?: Env, platform?: string, release?: string): Terminal;
|
|
27
20
|
export declare const ESC = "\u001B[";
|
|
28
21
|
/** The colours and weights the installer uses. */
|
|
29
22
|
export type Style = 'bold' | 'dim' | 'inverse' | 'underline' | 'green' | 'yellow' | 'red' | 'cyan' | 'magenta' | 'gray';
|
package/dist/cli/ui.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* The installer's look in the terminal, without dependencies: a logo, numbered steps, spinners for long work,
|
|
3
3
|
* status lines (✔ ▲ ✖) and a summary card. On a Unicode terminal everything hangs on one rail down the left (│),
|
|
4
4
|
* the questions of the interactive prompter included (`tui.ts`). Colour, Unicode and animation are detected from
|
|
5
|
-
* the terminal (NO_COLOR, FORCE_COLOR,
|
|
5
|
+
* the terminal (NO_COLOR, FORCE_COLOR, SHUTRO_ERP_ASCII=1, TERM=dumb, Windows consoles without Unicode); output that is not
|
|
6
6
|
* a terminal (tests, logs, CI) gets plain lines with the same words and no escape codes.
|
|
7
7
|
*/
|
|
8
|
+
import { release as osRelease } from 'node:os';
|
|
8
9
|
/** Plain output: logs, tests, pipes. */
|
|
9
10
|
export const PLAIN_TERMINAL = Object.freeze({
|
|
10
11
|
color: false,
|
|
@@ -14,7 +15,7 @@ export const PLAIN_TERMINAL = Object.freeze({
|
|
|
14
15
|
columns: 80,
|
|
15
16
|
});
|
|
16
17
|
/** Detects what `stream` (process.stdout) can show. */
|
|
17
|
-
export function detectTerminal(stream, env = process.env, platform = process.platform) {
|
|
18
|
+
export function detectTerminal(stream, env = process.env, platform = process.platform, release = osRelease()) {
|
|
18
19
|
const tty = stream.isTTY === true && env['TERM'] !== 'dumb' && env['CI'] === undefined;
|
|
19
20
|
const forced = env['FORCE_COLOR'] !== undefined && env['FORCE_COLOR'] !== '0';
|
|
20
21
|
const color = env['NO_COLOR'] === undefined && (forced || tty);
|
|
@@ -24,11 +25,16 @@ export function detectTerminal(stream, env = process.env, platform = process.pla
|
|
|
24
25
|
env['ConEmuTask'] === '{cmd::Cmder}' ||
|
|
25
26
|
env['TERM'] === 'xterm-256color' ||
|
|
26
27
|
env['TERM'] === 'alacritty';
|
|
27
|
-
|
|
28
|
+
// Windows 10 and later: the console host shows box drawing and colours too (UTF-8, virtual terminal); pictographs
|
|
29
|
+
// only in the modern terminals. Older Windows keeps ASCII.
|
|
30
|
+
const windows10 = Number(release.split('.')[0]) >= 10;
|
|
31
|
+
const unicode = env['KOSH_ASCII'] !== '1' &&
|
|
32
|
+
env['SHUTRO_ERP_ASCII'] !== '1' &&
|
|
33
|
+
(platform === 'win32' ? modernWindows || windows10 : env['TERM'] !== 'linux');
|
|
28
34
|
return {
|
|
29
35
|
color,
|
|
30
36
|
unicode,
|
|
31
|
-
emoji: unicode && tty,
|
|
37
|
+
emoji: unicode && tty && (platform !== 'win32' || modernWindows),
|
|
32
38
|
animate: tty,
|
|
33
39
|
columns: Math.max(40, Math.min(stream.columns ?? 80, 120)),
|
|
34
40
|
};
|
|
@@ -92,12 +98,12 @@ export const ICONS = {
|
|
|
92
98
|
rocket: ['🚀', '◆'],
|
|
93
99
|
};
|
|
94
100
|
const LOGO = [
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
'
|
|
98
|
-
'
|
|
99
|
-
'██║
|
|
100
|
-
'
|
|
101
|
+
'███████╗██╗ ██╗██╗ ██╗████████╗██████╗ ██████╗',
|
|
102
|
+
'██╔════╝██║ ██║██║ ██║╚══██╔══╝██╔══██╗██╔═══██╗',
|
|
103
|
+
'███████╗███████║██║ ██║ ██║ ██████╔╝██║ ██║',
|
|
104
|
+
'╚════██║██╔══██║██║ ██║ ██║ ██╔══██╗██║ ██║',
|
|
105
|
+
'███████║██║ ██║╚██████╔╝ ██║ ██║ ██║╚██████╔╝',
|
|
106
|
+
'╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝',
|
|
101
107
|
];
|
|
102
108
|
/** Cyan to violet, one 256-colour step per logo line. */
|
|
103
109
|
const GRADIENT = [51, 45, 39, 33, 63, 99];
|
|
@@ -141,7 +147,7 @@ export function createUi(out, terminal = PLAIN_TERMINAL, options = {}) {
|
|
|
141
147
|
icon,
|
|
142
148
|
async banner(subtitle) {
|
|
143
149
|
if (!terminal.unicode) {
|
|
144
|
-
write(`\n ${s('bold', '
|
|
150
|
+
write(`\n ${s('bold', 'S H U T R O E R P')} ${subtitle}\n`);
|
|
145
151
|
return;
|
|
146
152
|
}
|
|
147
153
|
write('\n');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 2271aaa68e1a18a5
|
|
2
2
|
// Bindings of module `contacts`: import the definition API from here to get types scoped to what it can see.
|
|
3
3
|
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
4
|
import { definitions } from '../../server/orm.js';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 2271aaa68e1a18a5
|
|
2
2
|
// Schema view of module `contacts` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
|
|
3
3
|
import type { F } from '../../server/orm.js';
|
|
4
4
|
|
|
5
5
|
/** Model name → model type (RFC 0002 §7.7). */
|
|
6
6
|
export interface SchemaView {
|
|
7
7
|
readonly 'audit.event': AuditEvent;
|
|
8
|
+
readonly 'auth.api_key': AuthApiKey;
|
|
8
9
|
readonly 'auth.credential': AuthCredential;
|
|
9
10
|
readonly 'auth.session': AuthSession;
|
|
10
11
|
readonly 'auth.user_grant': AuthUserGrant;
|
|
@@ -42,6 +43,34 @@ export interface AuditEvent {
|
|
|
42
43
|
export interface AuditEventMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'audit.event'> {
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
/** `auth.api_key` (owner: base). */
|
|
47
|
+
export interface AuthApiKey {
|
|
48
|
+
readonly name: 'auth.api_key';
|
|
49
|
+
readonly fields: {
|
|
50
|
+
readonly id: F.Id<'auth.api_key'>;
|
|
51
|
+
readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
52
|
+
readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
53
|
+
readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
54
|
+
readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
55
|
+
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
56
|
+
readonly name: F.Char<{ readonly required: true }>;
|
|
57
|
+
readonly user: F.Many2one<'res.users', { readonly required: true }>;
|
|
58
|
+
readonly tokenHash: F.Char<{ readonly required: true }>;
|
|
59
|
+
readonly prefix: F.Char<{ readonly required: true }>;
|
|
60
|
+
readonly scopes: F.Text<{ readonly required: true }>;
|
|
61
|
+
readonly expiresAt: F.Datetime<{ readonly required: true }>;
|
|
62
|
+
readonly lastUsedAt: F.Datetime;
|
|
63
|
+
readonly lastUsedIp: F.Char;
|
|
64
|
+
readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
65
|
+
readonly issuedBy: F.Many2one<'res.users'>;
|
|
66
|
+
};
|
|
67
|
+
readonly methods: AuthApiKeyMethods;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Methods of `auth.api_key`: declared ones and transitions. */
|
|
71
|
+
export interface AuthApiKeyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.api_key'> {
|
|
72
|
+
}
|
|
73
|
+
|
|
45
74
|
/** `auth.credential` (owner: base). */
|
|
46
75
|
export interface AuthCredential {
|
|
47
76
|
readonly name: 'auth.credential';
|
|
@@ -260,6 +289,7 @@ export interface ResUsers {
|
|
|
260
289
|
readonly companies: F.Many2many<'res.company', { readonly required: true }>;
|
|
261
290
|
readonly lang: F.Char<{ readonly default: true }>;
|
|
262
291
|
readonly tz: F.Char<{ readonly default: true }>;
|
|
292
|
+
readonly isService: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
263
293
|
};
|
|
264
294
|
readonly methods: ResUsersMethods;
|
|
265
295
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 52fb4c0464f10e60
|
|
2
2
|
// Bindings of module `l10n_bd`: import the definition API from here to get types scoped to what it can see.
|
|
3
3
|
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
4
|
import { definitions } from '../../server/orm.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 52fb4c0464f10e60
|
|
2
2
|
// Schema view of module `l10n_bd` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
|
|
3
3
|
import type { F } from '../../server/orm.js';
|
|
4
4
|
|
|
@@ -22,6 +22,7 @@ export interface SchemaView {
|
|
|
22
22
|
readonly 'approval.policy': ApprovalPolicy;
|
|
23
23
|
readonly 'approval.request': ApprovalRequest;
|
|
24
24
|
readonly 'audit.event': AuditEvent;
|
|
25
|
+
readonly 'auth.api_key': AuthApiKey;
|
|
25
26
|
readonly 'auth.credential': AuthCredential;
|
|
26
27
|
readonly 'auth.session': AuthSession;
|
|
27
28
|
readonly 'auth.user_grant': AuthUserGrant;
|
|
@@ -583,6 +584,34 @@ export interface AuditEvent {
|
|
|
583
584
|
export interface AuditEventMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'audit.event'> {
|
|
584
585
|
}
|
|
585
586
|
|
|
587
|
+
/** `auth.api_key` (owner: base). */
|
|
588
|
+
export interface AuthApiKey {
|
|
589
|
+
readonly name: 'auth.api_key';
|
|
590
|
+
readonly fields: {
|
|
591
|
+
readonly id: F.Id<'auth.api_key'>;
|
|
592
|
+
readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
593
|
+
readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
594
|
+
readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
595
|
+
readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
596
|
+
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
597
|
+
readonly name: F.Char<{ readonly required: true }>;
|
|
598
|
+
readonly user: F.Many2one<'res.users', { readonly required: true }>;
|
|
599
|
+
readonly tokenHash: F.Char<{ readonly required: true }>;
|
|
600
|
+
readonly prefix: F.Char<{ readonly required: true }>;
|
|
601
|
+
readonly scopes: F.Text<{ readonly required: true }>;
|
|
602
|
+
readonly expiresAt: F.Datetime<{ readonly required: true }>;
|
|
603
|
+
readonly lastUsedAt: F.Datetime;
|
|
604
|
+
readonly lastUsedIp: F.Char;
|
|
605
|
+
readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
606
|
+
readonly issuedBy: F.Many2one<'res.users'>;
|
|
607
|
+
};
|
|
608
|
+
readonly methods: AuthApiKeyMethods;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/** Methods of `auth.api_key`: declared ones and transitions. */
|
|
612
|
+
export interface AuthApiKeyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.api_key'> {
|
|
613
|
+
}
|
|
614
|
+
|
|
586
615
|
/** `auth.credential` (owner: base). */
|
|
587
616
|
export interface AuthCredential {
|
|
588
617
|
readonly name: 'auth.credential';
|
|
@@ -1224,6 +1253,7 @@ export interface ResUsers {
|
|
|
1224
1253
|
readonly companies: F.Many2many<'res.company', { readonly required: true }>;
|
|
1225
1254
|
readonly lang: F.Char<{ readonly default: true }>;
|
|
1226
1255
|
readonly tz: F.Char<{ readonly default: true }>;
|
|
1256
|
+
readonly isService: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
1227
1257
|
};
|
|
1228
1258
|
readonly methods: ResUsersMethods;
|
|
1229
1259
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 3a48057268d9c891
|
|
2
2
|
// Bindings of module `l10n_in`: import the definition API from here to get types scoped to what it can see.
|
|
3
3
|
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
4
|
import { definitions } from '../../server/orm.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 3a48057268d9c891
|
|
2
2
|
// Schema view of module `l10n_in` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
|
|
3
3
|
import type { F } from '../../server/orm.js';
|
|
4
4
|
|
|
@@ -22,6 +22,7 @@ export interface SchemaView {
|
|
|
22
22
|
readonly 'approval.policy': ApprovalPolicy;
|
|
23
23
|
readonly 'approval.request': ApprovalRequest;
|
|
24
24
|
readonly 'audit.event': AuditEvent;
|
|
25
|
+
readonly 'auth.api_key': AuthApiKey;
|
|
25
26
|
readonly 'auth.credential': AuthCredential;
|
|
26
27
|
readonly 'auth.session': AuthSession;
|
|
27
28
|
readonly 'auth.user_grant': AuthUserGrant;
|
|
@@ -605,6 +606,34 @@ export interface AuditEvent {
|
|
|
605
606
|
export interface AuditEventMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'audit.event'> {
|
|
606
607
|
}
|
|
607
608
|
|
|
609
|
+
/** `auth.api_key` (owner: base). */
|
|
610
|
+
export interface AuthApiKey {
|
|
611
|
+
readonly name: 'auth.api_key';
|
|
612
|
+
readonly fields: {
|
|
613
|
+
readonly id: F.Id<'auth.api_key'>;
|
|
614
|
+
readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
615
|
+
readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
616
|
+
readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
617
|
+
readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
618
|
+
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
619
|
+
readonly name: F.Char<{ readonly required: true }>;
|
|
620
|
+
readonly user: F.Many2one<'res.users', { readonly required: true }>;
|
|
621
|
+
readonly tokenHash: F.Char<{ readonly required: true }>;
|
|
622
|
+
readonly prefix: F.Char<{ readonly required: true }>;
|
|
623
|
+
readonly scopes: F.Text<{ readonly required: true }>;
|
|
624
|
+
readonly expiresAt: F.Datetime<{ readonly required: true }>;
|
|
625
|
+
readonly lastUsedAt: F.Datetime;
|
|
626
|
+
readonly lastUsedIp: F.Char;
|
|
627
|
+
readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
628
|
+
readonly issuedBy: F.Many2one<'res.users'>;
|
|
629
|
+
};
|
|
630
|
+
readonly methods: AuthApiKeyMethods;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/** Methods of `auth.api_key`: declared ones and transitions. */
|
|
634
|
+
export interface AuthApiKeyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.api_key'> {
|
|
635
|
+
}
|
|
636
|
+
|
|
608
637
|
/** `auth.credential` (owner: base). */
|
|
609
638
|
export interface AuthCredential {
|
|
610
639
|
readonly name: 'auth.credential';
|
|
@@ -1286,6 +1315,7 @@ export interface ResUsers {
|
|
|
1286
1315
|
readonly companies: F.Many2many<'res.company', { readonly required: true }>;
|
|
1287
1316
|
readonly lang: F.Char<{ readonly default: true }>;
|
|
1288
1317
|
readonly tz: F.Char<{ readonly default: true }>;
|
|
1318
|
+
readonly isService: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
1289
1319
|
};
|
|
1290
1320
|
readonly methods: ResUsersMethods;
|
|
1291
1321
|
}
|
package/dist/l10n_in/einvoice.js
CHANGED
|
@@ -280,7 +280,7 @@ export async function einvoiceState(env, id) {
|
|
|
280
280
|
},
|
|
281
281
|
};
|
|
282
282
|
}
|
|
283
|
-
const unavailable = () => new HttpProblem(409, 'no-gst-provider', 'E-invoicing is not set up', 'No IRP / e-way bill provider is configured for this installation (
|
|
283
|
+
const unavailable = () => new HttpProblem(409, 'no-gst-provider', 'E-invoicing is not set up', 'No IRP / e-way bill provider is configured for this installation (SHUTRO_ERP_GST_PROVIDER).');
|
|
284
284
|
/**
|
|
285
285
|
* Registers a document with the IRP. The document must be readable and the user may post (the right to e-invoice
|
|
286
286
|
* goes with it). A refusal, here or by the IRP, is kept on the document and answered with 422.
|
|
@@ -43,7 +43,7 @@ export const messages = {
|
|
|
43
43
|
save: 'Save',
|
|
44
44
|
saved: 'Saved.',
|
|
45
45
|
provider: 'IRP provider: {{provider}}',
|
|
46
|
-
noProvider: 'No IRP provider is set up (
|
|
46
|
+
noProvider: 'No IRP provider is set up (SHUTRO_ERP_GST_PROVIDER): e-invoicing is unavailable.',
|
|
47
47
|
},
|
|
48
48
|
gst: {
|
|
49
49
|
title: 'GST returns',
|
|
@@ -122,7 +122,7 @@ export const messages = {
|
|
|
122
122
|
save: 'সংরক্ষণ',
|
|
123
123
|
saved: 'সংরক্ষিত।',
|
|
124
124
|
provider: 'IRP প্রদানকারী: {{provider}}',
|
|
125
|
-
noProvider: 'কোনো IRP প্রদানকারী নেই (
|
|
125
|
+
noProvider: 'কোনো IRP প্রদানকারী নেই (SHUTRO_ERP_GST_PROVIDER): ই-চালান অনুপলব্ধ।',
|
|
126
126
|
},
|
|
127
127
|
gst: {
|
|
128
128
|
title: 'জিএসটি রিটার্ন',
|
package/dist/mail/index.js
CHANGED
|
@@ -40,14 +40,14 @@ export function mailerFromEnv(env = process.env) {
|
|
|
40
40
|
const url = env['SMTP_URL'];
|
|
41
41
|
if (url === undefined || url === '')
|
|
42
42
|
return undefined;
|
|
43
|
-
return createSmtpMailer({ url, from: env['MAIL_FROM'] ?? '
|
|
43
|
+
return createSmtpMailer({ url, from: env['MAIL_FROM'] ?? 'Shutro ERP <shutro-erp@localhost>' });
|
|
44
44
|
}
|
|
45
45
|
/** A mailer that keeps what it is given (tests, dry runs). */
|
|
46
46
|
export function createMemoryMailer() {
|
|
47
47
|
const sent = [];
|
|
48
48
|
return {
|
|
49
49
|
name: 'memory',
|
|
50
|
-
from: '
|
|
50
|
+
from: 'Shutro ERP <shutro-erp@localhost>',
|
|
51
51
|
sent,
|
|
52
52
|
async send(mail) {
|
|
53
53
|
sent.push(mail);
|
|
@@ -63,11 +63,11 @@ export function loadModules(roots, options) {
|
|
|
63
63
|
const actions = new Map();
|
|
64
64
|
for (const m of modules) {
|
|
65
65
|
if (!satisfies(options.koshVersion, m.kosh))
|
|
66
|
-
fail(`Module '${m.name}' needs
|
|
66
|
+
fail(`Module '${m.name}' needs Shutro ERP ${m.kosh}; this is Shutro ERP ${options.koshVersion}.`, 'Upgrade the module or the framework.');
|
|
67
67
|
const deps = closure(m);
|
|
68
68
|
for (const sd of m.shutro.depends)
|
|
69
69
|
if (!deps.has(sd.name))
|
|
70
|
-
fail(`Module '${m.name}' uses the Shutro module '${sd.name}' but no
|
|
70
|
+
fail(`Module '${m.name}' uses the Shutro module '${sd.name}' but no Shutro ERP module it depends on provides it.`, `Add the Shutro ERP module '${sd.name}' to depends.`);
|
|
71
71
|
// Groups an access level may grant: this module's and its dependencies'.
|
|
72
72
|
const groups = new Set(m.shutro.groups.map((g) => g.code));
|
|
73
73
|
for (const d of deps)
|
package/dist/notify/messages.js
CHANGED
|
@@ -13,9 +13,9 @@ export const TEXTS = {
|
|
|
13
13
|
},
|
|
14
14
|
states: { approved: 'approved', rejected: 'rejected' },
|
|
15
15
|
email: {
|
|
16
|
-
open: 'Open in
|
|
17
|
-
why: 'You receive this email because of your notification settings in
|
|
18
|
-
digestSubject: 'Your
|
|
16
|
+
open: 'Open in Shutro ERP',
|
|
17
|
+
why: 'You receive this email because of your notification settings in Shutro ERP.',
|
|
18
|
+
digestSubject: 'Your Shutro ERP summary: {{count}} notifications',
|
|
19
19
|
digestIntro: 'What happened since your last summary, by record.',
|
|
20
20
|
},
|
|
21
21
|
},
|
package/dist/notify/routes.js
CHANGED
|
@@ -50,7 +50,7 @@ export function registerNotifyRoutes({ app }, options = {}) {
|
|
|
50
50
|
app.get('/api/v1/notifications/push/key', async (request) => {
|
|
51
51
|
await request.env(async () => undefined); // signed in
|
|
52
52
|
if (options.pusher === undefined)
|
|
53
|
-
throw new HttpProblem(404, 'push-not-configured', 'Push is not set up', 'This installation has no VAPID keys.', 'Set VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY and VAPID_SUBJECT (
|
|
53
|
+
throw new HttpProblem(404, 'push-not-configured', 'Push is not set up', 'This installation has no VAPID keys.', 'Set VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY and VAPID_SUBJECT (shutro-erp init writes them).');
|
|
54
54
|
return { publicKey: options.pusher.publicKey };
|
|
55
55
|
});
|
|
56
56
|
app.post('/api/v1/notifications/push', async (request) => {
|
|
@@ -11,7 +11,7 @@ export const messages = {
|
|
|
11
11
|
push: {
|
|
12
12
|
off: 'Push notifications on this device are off',
|
|
13
13
|
on: 'Push notifications on this device are on',
|
|
14
|
-
denied: 'This browser blocks notifications from
|
|
14
|
+
denied: 'This browser blocks notifications from Shutro ERP',
|
|
15
15
|
busy: 'One moment…',
|
|
16
16
|
turnOn: 'Turn on',
|
|
17
17
|
turnOff: 'Turn off',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: bae647ca883975a1
|
|
2
2
|
// Bindings of module `portal`: import the definition API from here to get types scoped to what it can see.
|
|
3
3
|
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
4
|
import { definitions } from '../../server/orm.js';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: bae647ca883975a1
|
|
2
2
|
// Schema view of module `portal` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
|
|
3
3
|
import type { F } from '../../server/orm.js';
|
|
4
4
|
|
|
5
5
|
/** Model name → model type (RFC 0002 §7.7). */
|
|
6
6
|
export interface SchemaView {
|
|
7
7
|
readonly 'audit.event': AuditEvent;
|
|
8
|
+
readonly 'auth.api_key': AuthApiKey;
|
|
8
9
|
readonly 'auth.credential': AuthCredential;
|
|
9
10
|
readonly 'auth.session': AuthSession;
|
|
10
11
|
readonly 'auth.user_grant': AuthUserGrant;
|
|
@@ -45,6 +46,34 @@ export interface AuditEvent {
|
|
|
45
46
|
export interface AuditEventMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'audit.event'> {
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
/** `auth.api_key` (owner: base). */
|
|
50
|
+
export interface AuthApiKey {
|
|
51
|
+
readonly name: 'auth.api_key';
|
|
52
|
+
readonly fields: {
|
|
53
|
+
readonly id: F.Id<'auth.api_key'>;
|
|
54
|
+
readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
55
|
+
readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
56
|
+
readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
57
|
+
readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
58
|
+
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
59
|
+
readonly name: F.Char<{ readonly required: true }>;
|
|
60
|
+
readonly user: F.Many2one<'res.users', { readonly required: true }>;
|
|
61
|
+
readonly tokenHash: F.Char<{ readonly required: true }>;
|
|
62
|
+
readonly prefix: F.Char<{ readonly required: true }>;
|
|
63
|
+
readonly scopes: F.Text<{ readonly required: true }>;
|
|
64
|
+
readonly expiresAt: F.Datetime<{ readonly required: true }>;
|
|
65
|
+
readonly lastUsedAt: F.Datetime;
|
|
66
|
+
readonly lastUsedIp: F.Char;
|
|
67
|
+
readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
68
|
+
readonly issuedBy: F.Many2one<'res.users'>;
|
|
69
|
+
};
|
|
70
|
+
readonly methods: AuthApiKeyMethods;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Methods of `auth.api_key`: declared ones and transitions. */
|
|
74
|
+
export interface AuthApiKeyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.api_key'> {
|
|
75
|
+
}
|
|
76
|
+
|
|
48
77
|
/** `auth.credential` (owner: base). */
|
|
49
78
|
export interface AuthCredential {
|
|
50
79
|
readonly name: 'auth.credential';
|
|
@@ -336,6 +365,7 @@ export interface ResUsers {
|
|
|
336
365
|
readonly companies: F.Many2many<'res.company', { readonly required: true }>;
|
|
337
366
|
readonly lang: F.Char<{ readonly default: true }>;
|
|
338
367
|
readonly tz: F.Char<{ readonly default: true }>;
|
|
368
|
+
readonly isService: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
339
369
|
readonly portalPartner: F.Many2one<'res.partner'>; // portal
|
|
340
370
|
};
|
|
341
371
|
readonly methods: ResUsersMethods;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 86d7229d7b275957
|
|
2
2
|
// Bindings of module `product`: import the definition API from here to get types scoped to what it can see.
|
|
3
3
|
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
4
|
import { definitions } from '../../server/orm.js';
|