@rljson/io 0.0.20 → 0.0.22
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/dist/io-mem.d.ts +5 -4
- package/dist/io-tools.d.ts +40 -0
- package/dist/io.d.ts +8 -8
- package/dist/io.js +134 -29
- package/dist/src/example.ts +8 -4
- package/package.json +14 -14
package/dist/io-mem.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Io } from './io.ts';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class IoMem implements Io {
|
|
8
8
|
constructor();
|
|
9
|
-
static example: () => IoMem
|
|
9
|
+
static example: () => Promise<IoMem>;
|
|
10
10
|
isReady(): Promise<void>;
|
|
11
11
|
dump(): Promise<Rljson>;
|
|
12
12
|
dumpTable(request: {
|
|
@@ -18,20 +18,21 @@ export declare class IoMem implements Io {
|
|
|
18
18
|
[column: string]: JsonValue;
|
|
19
19
|
};
|
|
20
20
|
}): Promise<Rljson>;
|
|
21
|
+
rowCount(table: string): Promise<number>;
|
|
21
22
|
write(request: {
|
|
22
23
|
data: Rljson;
|
|
23
24
|
}): Promise<void>;
|
|
24
|
-
|
|
25
|
+
createOrExtendTable(request: {
|
|
25
26
|
tableCfg: TableCfg;
|
|
26
27
|
}): Promise<void>;
|
|
27
28
|
tableCfgs(): Promise<Rljson>;
|
|
28
|
-
|
|
29
|
+
private _ioTools;
|
|
29
30
|
private _isReady;
|
|
30
31
|
private _mem;
|
|
31
32
|
private _ioInit;
|
|
32
33
|
private _init;
|
|
33
34
|
private _initTableCfgs;
|
|
34
|
-
private
|
|
35
|
+
private _createOrExtendTable;
|
|
35
36
|
private _dump;
|
|
36
37
|
private _dumpTable;
|
|
37
38
|
private _write;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { TableCfg, TableKey } from '@rljson/rljson';
|
|
2
|
+
import { Io } from './io.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Provides utility functions for the Io interface.
|
|
5
|
+
*/
|
|
6
|
+
export declare class IoTools {
|
|
7
|
+
readonly io: Io;
|
|
8
|
+
/**
|
|
9
|
+
* Constructor
|
|
10
|
+
* @param io The Io interface to use
|
|
11
|
+
*/
|
|
12
|
+
constructor(io: Io);
|
|
13
|
+
/**
|
|
14
|
+
* Example object for test purposes
|
|
15
|
+
* @returns An instance of io tools
|
|
16
|
+
*/
|
|
17
|
+
static example: () => Promise<IoTools>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns a list with all table names
|
|
20
|
+
*/
|
|
21
|
+
allTableNames(): Promise<string[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Returns the configuration of a given table
|
|
24
|
+
*/
|
|
25
|
+
tableCfg(table: TableKey): Promise<TableCfg>;
|
|
26
|
+
/**
|
|
27
|
+
* Returns the configuration of a given table or null if it does not exist.
|
|
28
|
+
|
|
29
|
+
*/
|
|
30
|
+
tableCfgOrNull(table: TableKey): Promise<TableCfg | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Returns a list of all column names of a given table
|
|
33
|
+
*/
|
|
34
|
+
allColumnKeys(table: TableKey): Promise<string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Throws when a table update is not compatible with the current table
|
|
37
|
+
* configuration.
|
|
38
|
+
*/
|
|
39
|
+
throwWhenTableIsNotCompatible(update: TableCfg): Promise<void>;
|
|
40
|
+
}
|
package/dist/io.d.ts
CHANGED
|
@@ -13,21 +13,19 @@ export interface Io {
|
|
|
13
13
|
table: string;
|
|
14
14
|
}): Promise<Rljson>;
|
|
15
15
|
/**
|
|
16
|
-
* Creates a table with a given config
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Creates a table with a given config.
|
|
17
|
+
* If the table already exists, new columns are added to the existing table.
|
|
18
|
+
* If the table does not exist, it is created with the given config.
|
|
19
|
+
* If the table exists and columns are removed, an error is thrown.
|
|
20
|
+
* If the table exists and the column type is changed, an error is thrown.
|
|
19
21
|
*/
|
|
20
|
-
|
|
22
|
+
createOrExtendTable(request: {
|
|
21
23
|
tableCfg: TableCfg;
|
|
22
24
|
}): Promise<void>;
|
|
23
25
|
/**
|
|
24
26
|
* Returns a json structure returning current table configurations
|
|
25
27
|
*/
|
|
26
28
|
tableCfgs(): Promise<Rljson>;
|
|
27
|
-
/**
|
|
28
|
-
* Returns an rljson with all available tables without data
|
|
29
|
-
*/
|
|
30
|
-
allTableNames(): Promise<string[]>;
|
|
31
29
|
/** Writes Rljson data into the database */
|
|
32
30
|
write(request: {
|
|
33
31
|
data: Rljson;
|
|
@@ -39,5 +37,7 @@ export interface Io {
|
|
|
39
37
|
[column: string]: JsonValue;
|
|
40
38
|
};
|
|
41
39
|
}): Promise<Rljson>;
|
|
40
|
+
/** Returns the number of rows in the given table */
|
|
41
|
+
rowCount(table: string): Promise<number>;
|
|
42
42
|
}
|
|
43
43
|
export declare const exampleIo = "Checkout @rljson/io-mem for an example implementation";
|
package/dist/io.js
CHANGED
|
@@ -3,7 +3,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { hip, hsh } from "@rljson/hash";
|
|
5
5
|
import { IsReady } from "@rljson/is-ready";
|
|
6
|
-
import { copy, equals } from "@rljson/json";
|
|
6
|
+
import { jsonValueTypes, copy, equals } from "@rljson/json";
|
|
7
7
|
// @license
|
|
8
8
|
class IoInit {
|
|
9
9
|
constructor(io) {
|
|
@@ -15,15 +15,15 @@ class IoInit {
|
|
|
15
15
|
isHead: false,
|
|
16
16
|
isRoot: false,
|
|
17
17
|
isShared: true,
|
|
18
|
-
columns:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
columns: [
|
|
19
|
+
{ key: "table", type: "string" },
|
|
20
|
+
{ key: "predecessor", type: "string" },
|
|
21
|
+
{ key: "successor", type: "string" },
|
|
22
|
+
{ key: "timestamp", type: "number" },
|
|
23
|
+
{ key: "id", type: "string" }
|
|
24
|
+
]
|
|
25
25
|
};
|
|
26
|
-
await this.io.
|
|
26
|
+
await this.io.createOrExtendTable({ tableCfg });
|
|
27
27
|
});
|
|
28
28
|
this.io = io;
|
|
29
29
|
}
|
|
@@ -35,15 +35,117 @@ class IoInit {
|
|
|
35
35
|
isHead: false,
|
|
36
36
|
isRoot: false,
|
|
37
37
|
isShared: true,
|
|
38
|
-
columns:
|
|
39
|
-
key:
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
columns: [
|
|
39
|
+
{ key: "key", type: "string" },
|
|
40
|
+
{ key: "type", type: "string" }
|
|
41
|
+
]
|
|
42
42
|
});
|
|
43
43
|
return tableCfg;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
// @license
|
|
47
|
+
const _IoTools = class _IoTools {
|
|
48
|
+
/**
|
|
49
|
+
* Constructor
|
|
50
|
+
* @param io The Io interface to use
|
|
51
|
+
*/
|
|
52
|
+
constructor(io) {
|
|
53
|
+
this.io = io;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns a list with all table names
|
|
57
|
+
*/
|
|
58
|
+
async allTableNames() {
|
|
59
|
+
const result = (await this.io.tableCfgs()).tableCfgs._data.map(
|
|
60
|
+
(e) => e.key
|
|
61
|
+
);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Returns the configuration of a given table
|
|
66
|
+
*/
|
|
67
|
+
async tableCfg(table) {
|
|
68
|
+
const tableCfg = await this.tableCfgOrNull(table);
|
|
69
|
+
if (!tableCfg) {
|
|
70
|
+
throw new Error(`Table "${table}" not found`);
|
|
71
|
+
}
|
|
72
|
+
return tableCfg;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns the configuration of a given table or null if it does not exist.
|
|
76
|
+
|
|
77
|
+
*/
|
|
78
|
+
async tableCfgOrNull(table) {
|
|
79
|
+
const tableCfgs = await this.io.tableCfgs();
|
|
80
|
+
const tableCfg = tableCfgs.tableCfgs._data.find((e) => e.key === table);
|
|
81
|
+
return tableCfg ?? null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Returns a list of all column names of a given table
|
|
85
|
+
*/
|
|
86
|
+
async allColumnKeys(table) {
|
|
87
|
+
const tableCfg = await this.tableCfg(table);
|
|
88
|
+
const result = tableCfg.columns.map((column) => column.key);
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Throws when a table update is not compatible with the current table
|
|
93
|
+
* configuration.
|
|
94
|
+
*/
|
|
95
|
+
async throwWhenTableIsNotCompatible(update) {
|
|
96
|
+
const prefix = `Invalid update of table able "${update.key}"`;
|
|
97
|
+
for (const column of update.columns) {
|
|
98
|
+
if (!jsonValueTypes.includes(column.type)) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`${prefix}: Column "${column.key}" has an unsupported type "${column.type}"`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const existing = await this.tableCfgOrNull(update.key);
|
|
105
|
+
if (existing) {
|
|
106
|
+
if (existing.columns.length > update.columns.length) {
|
|
107
|
+
const deletedColumnKeys = existing.columns.map((column) => column.key).filter(
|
|
108
|
+
(key) => !update.columns.some((column) => column.key === key)
|
|
109
|
+
);
|
|
110
|
+
if (deletedColumnKeys.length > 0) {
|
|
111
|
+
const deletedColumns = deletedColumnKeys.join(", ");
|
|
112
|
+
throw new Error(
|
|
113
|
+
`${prefix}: Columns must not be deleted. Deleted columns: ${deletedColumns}}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (let i = 0; i < existing.columns.length; i++) {
|
|
118
|
+
const before = existing.columns[i].key;
|
|
119
|
+
const after = update.columns[i].key;
|
|
120
|
+
if (before !== after) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`${prefix}: Column keys must not change! Column "${before}" was renamed into "${after}".`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (let i = 0; i < existing.columns.length; i++) {
|
|
127
|
+
const column = existing.columns[i].key;
|
|
128
|
+
const before = existing.columns[i].type;
|
|
129
|
+
const after = update.columns[i].type;
|
|
130
|
+
if (before !== after) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`${prefix}: Column types must not change! Type of column "${column}" was changed from "${before}" to ${after}.`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Example object for test purposes
|
|
141
|
+
* @returns An instance of io tools
|
|
142
|
+
*/
|
|
143
|
+
__publicField(_IoTools, "example", async () => {
|
|
144
|
+
const io = await IoMem.example();
|
|
145
|
+
return new _IoTools(io);
|
|
146
|
+
});
|
|
147
|
+
let IoTools = _IoTools;
|
|
148
|
+
// @license
|
|
47
149
|
const _IoMem = class _IoMem {
|
|
48
150
|
// ...........................................................................
|
|
49
151
|
// Constructor & example
|
|
@@ -51,6 +153,7 @@ const _IoMem = class _IoMem {
|
|
|
51
153
|
// ######################
|
|
52
154
|
// Private
|
|
53
155
|
// ######################
|
|
156
|
+
__publicField(this, "_ioTools");
|
|
54
157
|
__publicField(this, "_isReady", new IsReady());
|
|
55
158
|
__publicField(this, "_mem", hip({}));
|
|
56
159
|
__publicField(this, "_ioInit");
|
|
@@ -84,6 +187,13 @@ const _IoMem = class _IoMem {
|
|
|
84
187
|
readRows(request) {
|
|
85
188
|
return this._readRows(request);
|
|
86
189
|
}
|
|
190
|
+
async rowCount(table) {
|
|
191
|
+
const tableData = this._mem[table];
|
|
192
|
+
if (!tableData) {
|
|
193
|
+
throw new Error(`Table "${table}" not found`);
|
|
194
|
+
}
|
|
195
|
+
return Promise.resolve(tableData._data.length);
|
|
196
|
+
}
|
|
87
197
|
// ...........................................................................
|
|
88
198
|
// Write
|
|
89
199
|
write(request) {
|
|
@@ -91,8 +201,8 @@ const _IoMem = class _IoMem {
|
|
|
91
201
|
}
|
|
92
202
|
// ...........................................................................
|
|
93
203
|
// Table management
|
|
94
|
-
|
|
95
|
-
return this.
|
|
204
|
+
createOrExtendTable(request) {
|
|
205
|
+
return this._createOrExtendTable(request);
|
|
96
206
|
}
|
|
97
207
|
async tableCfgs() {
|
|
98
208
|
const tables = this._mem.tableCfgs._data;
|
|
@@ -113,25 +223,19 @@ const _IoMem = class _IoMem {
|
|
|
113
223
|
}
|
|
114
224
|
});
|
|
115
225
|
}
|
|
116
|
-
async allTableNames() {
|
|
117
|
-
const tables = Object.keys(this._mem).filter((key) => !key.startsWith("_"));
|
|
118
|
-
return tables;
|
|
119
|
-
}
|
|
120
226
|
// ...........................................................................
|
|
121
227
|
async _init() {
|
|
228
|
+
this._ioTools = new IoTools(this);
|
|
122
229
|
this._ioInit = new IoInit(this);
|
|
123
230
|
this._initTableCfgs();
|
|
124
231
|
await this._ioInit.initRevisionsTable();
|
|
125
232
|
this._isReady.resolve();
|
|
126
233
|
}
|
|
127
234
|
// ...........................................................................
|
|
128
|
-
async
|
|
235
|
+
async _createOrExtendTable(request) {
|
|
129
236
|
var _a;
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
if (existing) {
|
|
133
|
-
throw new Error(`Table ${key} already exists`);
|
|
134
|
-
}
|
|
237
|
+
await this._ioTools.throwWhenTableIsNotCompatible(request.tableCfg);
|
|
238
|
+
const { type, key } = request.tableCfg;
|
|
135
239
|
const newConfig = hsh(request.tableCfg);
|
|
136
240
|
const existingConfig = this._mem.tableCfgs._data.find(
|
|
137
241
|
(cfg) => cfg._hash === newConfig._hash
|
|
@@ -139,9 +243,10 @@ const _IoMem = class _IoMem {
|
|
|
139
243
|
if (!existingConfig) {
|
|
140
244
|
this._mem.tableCfgs._data.push(newConfig);
|
|
141
245
|
this._mem.tableCfgs._hash = "";
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
246
|
+
hip(this._mem.tableCfgs, {
|
|
247
|
+
updateExistingHashes: false,
|
|
248
|
+
throwOnWrongHashes: false
|
|
249
|
+
});
|
|
145
250
|
}
|
|
146
251
|
const table = {
|
|
147
252
|
_data: [],
|
|
@@ -217,7 +322,7 @@ const _IoMem = class _IoMem {
|
|
|
217
322
|
return result;
|
|
218
323
|
}
|
|
219
324
|
};
|
|
220
|
-
__publicField(_IoMem, "example", () => {
|
|
325
|
+
__publicField(_IoMem, "example", async () => {
|
|
221
326
|
return new _IoMem();
|
|
222
327
|
});
|
|
223
328
|
let IoMem = _IoMem;
|
package/dist/src/example.ts
CHANGED
|
@@ -17,11 +17,15 @@ export const example = async () => {
|
|
|
17
17
|
const rowWithHash = hsh(row);
|
|
18
18
|
|
|
19
19
|
// Create a table config first
|
|
20
|
-
const tableCfg = hip({
|
|
20
|
+
const tableCfg = hip<TableCfg>({
|
|
21
21
|
key: 'tableA',
|
|
22
22
|
type: 'ingredients',
|
|
23
|
-
columns:
|
|
24
|
-
|
|
23
|
+
columns: [],
|
|
24
|
+
version: 1,
|
|
25
|
+
isHead: true,
|
|
26
|
+
isRoot: true,
|
|
27
|
+
isShared: false,
|
|
28
|
+
});
|
|
25
29
|
|
|
26
30
|
await ioMem.write({
|
|
27
31
|
data: {
|
|
@@ -33,7 +37,7 @@ export const example = async () => {
|
|
|
33
37
|
});
|
|
34
38
|
|
|
35
39
|
// Create a table first
|
|
36
|
-
await ioMem.
|
|
40
|
+
await ioMem.createOrExtendTable({ tableCfg: tableCfg });
|
|
37
41
|
|
|
38
42
|
// Write data into the table
|
|
39
43
|
await ioMem.write({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rljson/io",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"packageManager": "pnpm@10.6.2",
|
|
5
5
|
"description": "Low level interface for reading and writing RLJSON data",
|
|
6
6
|
"homepage": "https://github.com/rljson/io",
|
|
@@ -29,24 +29,24 @@
|
|
|
29
29
|
"updateGoldens": "cross-env UPDATE_GOLDENS=true pnpm test"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/node": "^22.
|
|
33
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
34
|
-
"@typescript-eslint/parser": "^8.
|
|
35
|
-
"@vitest/coverage-v8": "^3.1.
|
|
32
|
+
"@types/node": "^22.15.2",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
|
34
|
+
"@typescript-eslint/parser": "^8.31.0",
|
|
35
|
+
"@vitest/coverage-v8": "^3.1.2",
|
|
36
36
|
"cross-env": "^7.0.3",
|
|
37
|
-
"eslint": "^9.
|
|
38
|
-
"eslint-plugin-jsdoc": "^50.6.
|
|
37
|
+
"eslint": "^9.25.1",
|
|
38
|
+
"eslint-plugin-jsdoc": "^50.6.11",
|
|
39
39
|
"eslint-plugin-tsdoc": "^0.4.0",
|
|
40
40
|
"globals": "^16.0.0",
|
|
41
41
|
"jsdoc": "^4.0.4",
|
|
42
42
|
"read-pkg": "^9.0.1",
|
|
43
|
-
"typescript": "~5.8.
|
|
44
|
-
"typescript-eslint": "^8.
|
|
45
|
-
"vite": "^6.
|
|
46
|
-
"vite-node": "^3.1.
|
|
43
|
+
"typescript": "~5.8.3",
|
|
44
|
+
"typescript-eslint": "^8.31.0",
|
|
45
|
+
"vite": "^6.3.3",
|
|
46
|
+
"vite-node": "^3.1.2",
|
|
47
47
|
"vite-plugin-dts": "^4.5.3",
|
|
48
48
|
"vite-tsconfig-paths": "^5.1.4",
|
|
49
|
-
"vitest": "^3.1.
|
|
49
|
+
"vitest": "^3.1.2",
|
|
50
50
|
"vitest-dom": "^0.1.1"
|
|
51
51
|
},
|
|
52
52
|
"pnpm": {
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@rljson/hash": "^0.0.13",
|
|
60
60
|
"@rljson/is-ready": "^0.0.17",
|
|
61
61
|
"@rljson/json": "^0.0.18",
|
|
62
|
-
"@rljson/rljson": "^0.0.
|
|
63
|
-
"@rljson/validate": "^0.0.
|
|
62
|
+
"@rljson/rljson": "^0.0.40",
|
|
63
|
+
"@rljson/validate": "^0.0.10"
|
|
64
64
|
}
|
|
65
65
|
}
|