@ekwo-ai/core 0.4.0
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 +76 -0
- package/dist/books/backend.d.ts +118 -0
- package/dist/books/backend.d.ts.map +1 -0
- package/dist/books/backend.js +69 -0
- package/dist/books/backend.js.map +1 -0
- package/dist/books/columns.d.ts +68 -0
- package/dist/books/columns.d.ts.map +1 -0
- package/dist/books/columns.js +466 -0
- package/dist/books/columns.js.map +1 -0
- package/dist/books/contacts.d.ts +43 -0
- package/dist/books/contacts.d.ts.map +1 -0
- package/dist/books/contacts.js +67 -0
- package/dist/books/contacts.js.map +1 -0
- package/dist/books/documents.d.ts +87 -0
- package/dist/books/documents.d.ts.map +1 -0
- package/dist/books/documents.js +413 -0
- package/dist/books/documents.js.map +1 -0
- package/dist/books/format.d.ts +21 -0
- package/dist/books/format.d.ts.map +1 -0
- package/dist/books/format.js +49 -0
- package/dist/books/format.js.map +1 -0
- package/dist/books/index.d.ts +18 -0
- package/dist/books/index.d.ts.map +1 -0
- package/dist/books/index.js +18 -0
- package/dist/books/index.js.map +1 -0
- package/dist/books/payments.d.ts +57 -0
- package/dist/books/payments.d.ts.map +1 -0
- package/dist/books/payments.js +255 -0
- package/dist/books/payments.js.map +1 -0
- package/dist/books/rounding.d.ts +25 -0
- package/dist/books/rounding.d.ts.map +1 -0
- package/dist/books/rounding.js +35 -0
- package/dist/books/rounding.js.map +1 -0
- package/dist/books/shared.d.ts +33 -0
- package/dist/books/shared.d.ts.map +1 -0
- package/dist/books/shared.js +98 -0
- package/dist/books/shared.js.map +1 -0
- package/dist/client.d.ts +73 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +138 -0
- package/dist/client.js.map +1 -0
- package/dist/fec.d.ts +14 -0
- package/dist/fec.d.ts.map +1 -0
- package/dist/fec.js +13 -0
- package/dist/fec.js.map +1 -0
- package/dist/identity.d.ts +46 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +62 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/refusal.d.ts +27 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +38 -0
- package/dist/refusal.js.map +1 -0
- package/dist/schema.d.ts +23 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +42 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +466 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +170 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @ekwo-ai/core
|
|
2
|
+
|
|
3
|
+
TypeScript row types and a typed client for the
|
|
4
|
+
[Ekwo OS](https://github.com/Ekwo-ai/ekwo-os) accounting schema.
|
|
5
|
+
|
|
6
|
+
- **Types of the whole schema**, hand written so they stay readable: accounts,
|
|
7
|
+
journals, entries and lines, documents and lines, taxes and tax postings,
|
|
8
|
+
and the row shapes the report functions return.
|
|
9
|
+
- **The French FEC lives in [`@ekwo-ai/fec`](../formats/fec/)**, which is MIT
|
|
10
|
+
and depends on nothing. It is no longer re-exported here: import it from
|
|
11
|
+
there.
|
|
12
|
+
- **A thin client** over the functions that carry the accounting rules —
|
|
13
|
+
`post_document`, `reconcile`, `trial_balance`, `vat_return`, `fec_lines`.
|
|
14
|
+
Everything else is a table, and Supabase already exposes those as REST.
|
|
15
|
+
- **No runtime dependency of its own.** `@supabase/supabase-js` is an optional
|
|
16
|
+
peer; `@ekwo-ai/fec` is there because `generateFec()` on the client writes
|
|
17
|
+
the file it has just fetched.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm install @ekwo-ai/core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { EkwoClient } from '@ekwo-ai/core';
|
|
29
|
+
import { fecFileName } from '@ekwo-ai/fec';
|
|
30
|
+
import { createClient } from '@supabase/supabase-js';
|
|
31
|
+
|
|
32
|
+
const ekwo = new EkwoClient(createClient(url, key));
|
|
33
|
+
|
|
34
|
+
const entry = await ekwo.postDocument(documentId);
|
|
35
|
+
await ekwo.reconcile(receivableLineId, bankLineId);
|
|
36
|
+
|
|
37
|
+
const balance = await ekwo.trialBalance({ companyId, from: '2026-01-01', to: '2026-12-31' });
|
|
38
|
+
const boxes = await ekwo.vatReturn({ companyId, from: '2026-07-01', to: '2026-09-30' });
|
|
39
|
+
const aged = await ekwo.agedBalance(companyId, '2026-09-30', 'receivable');
|
|
40
|
+
|
|
41
|
+
const fec = await ekwo.generateFec({ companyId, from: '2026-01-01', to: '2026-12-31' });
|
|
42
|
+
await writeFile(fecFileName('123456789', '2026-12-31'), fec, 'utf8');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Without a Supabase client, format the file yourself from the rows of
|
|
46
|
+
`fec_lines()`:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { checkFec, fromQueryRow, generateFec } from '@ekwo-ai/fec';
|
|
50
|
+
|
|
51
|
+
const lines = rows.map(fromQueryRow);
|
|
52
|
+
const violations = checkFec(lines); // [] when the file is clean
|
|
53
|
+
const file = generateFec(lines, { decimalSeparator: ',', fieldSeparator: '|' });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## API
|
|
57
|
+
|
|
58
|
+
| Export | Description |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `EkwoClient` | Wrapper over the accounting functions of the schema. |
|
|
61
|
+
| `initInstance`, `claimInstanceAdmin` | Record the installation and take the first administrator seat. |
|
|
62
|
+
| `registerInstance`, `unregisterInstance` | Opt into being reachable by Ekwo, and out again. Never required. |
|
|
63
|
+
| `ACCOUNT_TYPES`, `internalGroup(type)` | The eighteen account types and their balance-sheet group. |
|
|
64
|
+
| `isRegistered(instance)` | Whether the operator opted into registering with Ekwo. |
|
|
65
|
+
| `isSale`, `isCreditNote`, `isAccountable` | Document type predicates. |
|
|
66
|
+
| `createContact`, `createDocument`, `addDocumentLine`, `updateDocumentLines`, `postDocument`, `recordPayment`, `reconcile`, `settleFromStatement`, `listDocuments`, `getDocument`, … | Keeping the books, once for every surface: the functions the MCP server and the `ekwo` command line both call. Each takes a `Backend` — five operations, `select` `insert` `update` `remove` `rpc` — that the caller implements over whatever reaches the database as a user. No accounting rule is in them; the schema holds those. |
|
|
67
|
+
| `BooksError`, `isRefusalState`, `socleCode`, `isServiceRoleKey` | What an error of that layer looks like, what counts as the database refusing, and the one key no surface accepts. |
|
|
68
|
+
| Types | `Instance`, `InstanceAdmin`, `MemberRole`, `CompanyRole`, `Account`, `Journal`, `Entry`, `EntryLine`, `EkwoDocument`, `DocumentLine`, `Tax`, `TaxPosting`, `Contact`, `TrialBalanceRow`, `AgedBalanceRow`, `VatReturnRow`, … |
|
|
69
|
+
|
|
70
|
+
Amounts come back from Postgres as strings, and the types say so: `numeric`
|
|
71
|
+
is carried as `Decimal = string` rather than rounded into a float on the way
|
|
72
|
+
in.
|
|
73
|
+
|
|
74
|
+
## Licence
|
|
75
|
+
|
|
76
|
+
[AGPL-3.0-only](../../LICENSE) © Ekwo AI.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one interface every bookkeeping function is written against.
|
|
3
|
+
*
|
|
4
|
+
* There are two ways to reach an Ekwo database and neither of them is a
|
|
5
|
+
* privileged one. The recommended route is PostgREST with the signed-in
|
|
6
|
+
* user's own token, which is how the schema is meant to be read and written:
|
|
7
|
+
* row level security decides, exactly as it would for that person in a
|
|
8
|
+
* browser. The second is a direct Postgres connection, for a self-hosted
|
|
9
|
+
* installation and for the tests — and even there the claims and the role are
|
|
10
|
+
* set on every call, so the same policies apply.
|
|
11
|
+
*
|
|
12
|
+
* The functions of this folder therefore never see a client, a token or a
|
|
13
|
+
* connection string. They see `select`, `insert`, `update`, `remove` and
|
|
14
|
+
* `rpc`, and what comes back is whatever the policies let through.
|
|
15
|
+
*
|
|
16
|
+
* This lived in the MCP server. The command line keeps the same books through
|
|
17
|
+
* the same functions, so the interface and the functions moved here, and each
|
|
18
|
+
* surface brings its own implementation of it: the server's over
|
|
19
|
+
* `@supabase/supabase-js` or a Postgres driver, the command line's over
|
|
20
|
+
* `fetch`. Nothing in this folder imports anything from outside the core.
|
|
21
|
+
*/
|
|
22
|
+
export type Value = string | number | boolean | null;
|
|
23
|
+
export type Filter = {
|
|
24
|
+
column: string;
|
|
25
|
+
op: 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte';
|
|
26
|
+
value: Value;
|
|
27
|
+
} | {
|
|
28
|
+
column: string;
|
|
29
|
+
op: 'in';
|
|
30
|
+
value: Value[];
|
|
31
|
+
} | {
|
|
32
|
+
column: string;
|
|
33
|
+
op: 'ilike';
|
|
34
|
+
value: string;
|
|
35
|
+
} | {
|
|
36
|
+
column: string;
|
|
37
|
+
op: 'is';
|
|
38
|
+
value: null;
|
|
39
|
+
};
|
|
40
|
+
export interface Order {
|
|
41
|
+
column: string;
|
|
42
|
+
ascending?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface SelectQuery {
|
|
45
|
+
table: string;
|
|
46
|
+
/**
|
|
47
|
+
* The Postgres schema the table lives in. Undefined is `public`, which is
|
|
48
|
+
* the socle; a module names its own — `assets`, `budgets` — and PostgREST
|
|
49
|
+
* serves it only once the project lists it under its exposed schemas.
|
|
50
|
+
*/
|
|
51
|
+
schema?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Columns to read. A `numeric` column is asked for as `amount::text`, so it
|
|
54
|
+
* arrives as the decimal string Postgres holds rather than as a float that
|
|
55
|
+
* JSON happened to survive. Both backends understand that spelling.
|
|
56
|
+
*/
|
|
57
|
+
columns: string[];
|
|
58
|
+
where?: Filter[];
|
|
59
|
+
order?: Order[];
|
|
60
|
+
limit?: number;
|
|
61
|
+
}
|
|
62
|
+
export type Row = Record<string, unknown>;
|
|
63
|
+
export interface Backend {
|
|
64
|
+
/** Which route this is, for `status` and for the error messages. */
|
|
65
|
+
readonly mode: 'postgrest' | 'sql';
|
|
66
|
+
/** Who we are acting as, when that is known. */
|
|
67
|
+
readonly actingAs: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Calls a function of the schema. Always an array of rows, whatever the
|
|
70
|
+
* function returns: PostgREST hands back an object for a function returning
|
|
71
|
+
* one composite row and an array for a set, and a tool should not have to
|
|
72
|
+
* care which route it came over.
|
|
73
|
+
*/
|
|
74
|
+
rpc<T = Row>(fn: string, args?: Record<string, unknown>, schema?: string): Promise<T[]>;
|
|
75
|
+
/** The same, for a function that returns nothing. */
|
|
76
|
+
rpcVoid(fn: string, args?: Record<string, unknown>, schema?: string): Promise<void>;
|
|
77
|
+
select<T = Row>(query: SelectQuery): Promise<T[]>;
|
|
78
|
+
insert<T = Row>(table: string, rows: Row[], returning?: string[], schema?: string): Promise<T[]>;
|
|
79
|
+
update<T = Row>(table: string, patch: Row, where: Filter[], returning?: string[], schema?: string): Promise<T[]>;
|
|
80
|
+
remove(table: string, where: Filter[], schema?: string): Promise<void>;
|
|
81
|
+
close(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* An error of this layer, or one that carries what the database said.
|
|
85
|
+
*
|
|
86
|
+
* The accounting rules live in the schema and they raise with a prefixed code
|
|
87
|
+
* — `period_locked:`, `entry_unbalanced:`, `document_total_mismatch:`. Those
|
|
88
|
+
* messages are the most useful thing we can hand a model, so they travel up
|
|
89
|
+
* unchanged; `hint` adds the sentence a human would add, never a replacement.
|
|
90
|
+
*/
|
|
91
|
+
export declare class BooksError extends Error {
|
|
92
|
+
name: string;
|
|
93
|
+
readonly code: string | undefined;
|
|
94
|
+
readonly hint: string | undefined;
|
|
95
|
+
constructor(message: string, options?: {
|
|
96
|
+
code?: string | undefined;
|
|
97
|
+
hint?: string;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Refuses anything that is not a plain lowercase identifier.
|
|
102
|
+
*
|
|
103
|
+
* Table and column names in this package are written in this package — none
|
|
104
|
+
* of them comes from a tool argument. This function is the proof of that
|
|
105
|
+
* rather than a defence against it, and it costs nothing to keep true.
|
|
106
|
+
*/
|
|
107
|
+
/**
|
|
108
|
+
* `assets.assets`, or `assets` when there is no schema to name.
|
|
109
|
+
*
|
|
110
|
+
* Both halves go through `identifier()`, so a module code that came from the
|
|
111
|
+
* registry rather than from this package still cannot be anything but a plain
|
|
112
|
+
* lowercase name.
|
|
113
|
+
*/
|
|
114
|
+
export declare function qualified(schema: string | undefined, name: string): string;
|
|
115
|
+
export declare function identifier(name: string): string;
|
|
116
|
+
/** `amount::text` reads back as `amount`; every other column is itself. */
|
|
117
|
+
export declare function columnName(column: string): string;
|
|
118
|
+
//# sourceMappingURL=backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/books/backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one interface every bookkeeping function is written against.
|
|
3
|
+
*
|
|
4
|
+
* There are two ways to reach an Ekwo database and neither of them is a
|
|
5
|
+
* privileged one. The recommended route is PostgREST with the signed-in
|
|
6
|
+
* user's own token, which is how the schema is meant to be read and written:
|
|
7
|
+
* row level security decides, exactly as it would for that person in a
|
|
8
|
+
* browser. The second is a direct Postgres connection, for a self-hosted
|
|
9
|
+
* installation and for the tests — and even there the claims and the role are
|
|
10
|
+
* set on every call, so the same policies apply.
|
|
11
|
+
*
|
|
12
|
+
* The functions of this folder therefore never see a client, a token or a
|
|
13
|
+
* connection string. They see `select`, `insert`, `update`, `remove` and
|
|
14
|
+
* `rpc`, and what comes back is whatever the policies let through.
|
|
15
|
+
*
|
|
16
|
+
* This lived in the MCP server. The command line keeps the same books through
|
|
17
|
+
* the same functions, so the interface and the functions moved here, and each
|
|
18
|
+
* surface brings its own implementation of it: the server's over
|
|
19
|
+
* `@supabase/supabase-js` or a Postgres driver, the command line's over
|
|
20
|
+
* `fetch`. Nothing in this folder imports anything from outside the core.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* An error of this layer, or one that carries what the database said.
|
|
24
|
+
*
|
|
25
|
+
* The accounting rules live in the schema and they raise with a prefixed code
|
|
26
|
+
* — `period_locked:`, `entry_unbalanced:`, `document_total_mismatch:`. Those
|
|
27
|
+
* messages are the most useful thing we can hand a model, so they travel up
|
|
28
|
+
* unchanged; `hint` adds the sentence a human would add, never a replacement.
|
|
29
|
+
*/
|
|
30
|
+
export class BooksError extends Error {
|
|
31
|
+
name = 'BooksError';
|
|
32
|
+
code;
|
|
33
|
+
hint;
|
|
34
|
+
constructor(message, options = {}) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.code = options.code;
|
|
37
|
+
this.hint = options.hint;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const IDENTIFIER = /^[a-z_][a-z0-9_]*$/;
|
|
41
|
+
/**
|
|
42
|
+
* Refuses anything that is not a plain lowercase identifier.
|
|
43
|
+
*
|
|
44
|
+
* Table and column names in this package are written in this package — none
|
|
45
|
+
* of them comes from a tool argument. This function is the proof of that
|
|
46
|
+
* rather than a defence against it, and it costs nothing to keep true.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* `assets.assets`, or `assets` when there is no schema to name.
|
|
50
|
+
*
|
|
51
|
+
* Both halves go through `identifier()`, so a module code that came from the
|
|
52
|
+
* registry rather than from this package still cannot be anything but a plain
|
|
53
|
+
* lowercase name.
|
|
54
|
+
*/
|
|
55
|
+
export function qualified(schema, name) {
|
|
56
|
+
return schema === undefined ? identifier(name) : `${identifier(schema)}.${identifier(name)}`;
|
|
57
|
+
}
|
|
58
|
+
export function identifier(name) {
|
|
59
|
+
if (!IDENTIFIER.test(name)) {
|
|
60
|
+
throw new BooksError(`bad_identifier: ${name} is not a plain column or table name`);
|
|
61
|
+
}
|
|
62
|
+
return name;
|
|
63
|
+
}
|
|
64
|
+
/** `amount::text` reads back as `amount`; every other column is itself. */
|
|
65
|
+
export function columnName(column) {
|
|
66
|
+
const cast = column.indexOf('::');
|
|
67
|
+
return identifier(cast === -1 ? column : column.slice(0, cast));
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/books/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA+DH;;;;;;;GAOG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC1B,IAAI,GAAG,YAAY,CAAC;IACpB,IAAI,CAAqB;IACzB,IAAI,CAAqB;IAElC,YAAY,OAAe,EAAE,UAAwD,EAAE;QACrF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC;;;;;;GAMG;AACH;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,MAA0B,EAAE,IAAY;IAChE,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,mBAAmB,IAAI,sCAAsC,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each tool reads back, written once.
|
|
3
|
+
*
|
|
4
|
+
* Two rules run through every list. A `numeric` column is asked for as
|
|
5
|
+
* `amount::text`, so the exact decimal arrives rather than a float; a `date`
|
|
6
|
+
* or a timestamp likewise, so `2026-06-15` is a string on both routes instead
|
|
7
|
+
* of whatever a driver decided a date object should be. Everything else —
|
|
8
|
+
* uuid, text, boolean, integer — crosses unchanged.
|
|
9
|
+
*/
|
|
10
|
+
export declare const COMPANY: string[];
|
|
11
|
+
export declare const FISCAL_YEAR: string[];
|
|
12
|
+
export declare const ACCOUNT: string[];
|
|
13
|
+
export declare const JOURNAL: string[];
|
|
14
|
+
export declare const CONTACT: string[];
|
|
15
|
+
export declare const TAX: string[];
|
|
16
|
+
export declare const DOCUMENT: string[];
|
|
17
|
+
/**
|
|
18
|
+
* The mentions the law of a country puts on one document, from the view that
|
|
19
|
+
* decides which of them apply. `text` is the sentence in the language the
|
|
20
|
+
* document was written in and `language` says which one that is; `text_i18n`
|
|
21
|
+
* crosses as it is, for a renderer printing a second language beside it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const DOCUMENT_LEGAL_MENTION: string[];
|
|
24
|
+
/**
|
|
25
|
+
* What the country of a document requires of it, beside the mentions: the
|
|
26
|
+
* payment term the law sets, how the number is built, when the tax falls due
|
|
27
|
+
* and how the document is exchanged. Read from `country_defaults`, which
|
|
28
|
+
* holds null wherever the pack has said nothing — and null is the answer, not
|
|
29
|
+
* an invitation to substitute another country's.
|
|
30
|
+
*/
|
|
31
|
+
export declare const COUNTRY_DOCUMENT_RULES: string[];
|
|
32
|
+
/**
|
|
33
|
+
* The header of a document, from the view that assembles it: the seller, the
|
|
34
|
+
* buyer, the amounts, where it is paid and what the country of the document
|
|
35
|
+
* requires. `document_line_items` is the lines and `document_legal_mentions`
|
|
36
|
+
* the sentences — three reads, and no client holding a copy of the
|
|
37
|
+
* letterhead.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DOCUMENT_HEADER: string[];
|
|
40
|
+
export declare const PRODUCT: string[];
|
|
41
|
+
export declare const DOCUMENT_LINE: string[];
|
|
42
|
+
export declare const ENTRY: string[];
|
|
43
|
+
export declare const ENTRY_LINE: string[];
|
|
44
|
+
export declare const BANK_ACCOUNT: string[];
|
|
45
|
+
export declare const BANK_TRANSACTION: string[];
|
|
46
|
+
export declare const PAYMENT: string[];
|
|
47
|
+
/**
|
|
48
|
+
* An invitation, without its secret. `token_hash` is deliberately absent: it
|
|
49
|
+
* is of no use to a client, and a list of hashes is a thing to leak rather
|
|
50
|
+
* than a thing to show.
|
|
51
|
+
*/
|
|
52
|
+
/** What one person chose for themselves. Null everywhere is the fresh state. */
|
|
53
|
+
export declare const USER_PREFERENCES: string[];
|
|
54
|
+
export declare const INVITATION: string[];
|
|
55
|
+
/** A machine key, without its hash. The secret is returned once, elsewhere. */
|
|
56
|
+
export declare const API_KEY: string[];
|
|
57
|
+
/** A public link onto a document, without its secret. There is only a hash. */
|
|
58
|
+
export declare const DOCUMENT_SHARE: string[];
|
|
59
|
+
export declare const INSTANCE: string[];
|
|
60
|
+
export declare const RECONCILIATION: string[];
|
|
61
|
+
export declare const AUDIT_LOG: string[];
|
|
62
|
+
/**
|
|
63
|
+
* `country_packs` — which pack this installation holds, and where its rules
|
|
64
|
+
* come from. `sources` is the register the pack declares: a reader that wants
|
|
65
|
+
* to check a rate rather than trust it starts there.
|
|
66
|
+
*/
|
|
67
|
+
export declare const COUNTRY_PACK: string[];
|
|
68
|
+
//# sourceMappingURL=columns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columns.d.ts","sourceRoot":"","sources":["../../src/books/columns.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,OAAO,UAqCnB,CAAC;AAEF,eAAO,MAAM,WAAW,UAAoE,CAAC;AAE7F,eAAO,MAAM,OAAO,UAUnB,CAAC;AAEF,eAAO,MAAM,OAAO,UAAmD,CAAC;AAExE,eAAO,MAAM,OAAO,UAcnB,CAAC;AAEF,eAAO,MAAM,GAAG,UAsBf,CAAC;AAEF,eAAO,MAAM,QAAQ,UAwBpB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,UAQlC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,UAWlC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,UAoE3B,CAAC;AAEF,eAAO,MAAM,OAAO,UAgBnB,CAAC;AAEF,eAAO,MAAM,aAAa,UAmBzB,CAAC;AAEF,eAAO,MAAM,KAAK,UAejB,CAAC;AAEF,eAAO,MAAM,UAAU,UAsBtB,CAAC;AAEF,eAAO,MAAM,YAAY,UAUxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,UAiB5B,CAAC;AAEF,eAAO,MAAM,OAAO,UAgBnB,CAAC;AAEF;;;;GAIG;AACH,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,UAS5B,CAAC;AAEF,eAAO,MAAM,UAAU,UAYtB,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,OAAO,UAWnB,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,cAAc,UAW1B,CAAC;AAEF,eAAO,MAAM,QAAQ,UAQpB,CAAC;AAEF,eAAO,MAAM,cAAc,UAa1B,CAAC;AAEF,eAAO,MAAM,SAAS,UAarB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAYxB,CAAC"}
|