@harperfast/schema-codegen 1.0.2 → 1.0.5
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 +2 -2
- package/extensionModule.js +16 -15
- package/package.json +23 -11
- package/utils/collectTables.js +6 -6
- package/utils/generateInterface.js +2 -1
- package/utils/generateJSDoc.js +2 -1
- package/utils/generateJSDocFromTables.js +3 -5
- package/utils/generateTS.js +3 -5
- package/utils/generateTablesDTS.js +6 -4
- package/utils/isNullable.js +3 -1
- package/utils/mapType.js +5 -2
- package/utils/regenerateAll.js +1 -1
- package/utils/singularize.js +6 -1
- package/utils/writeIfChanged.js +3 -3
- package/utils/sleep.js +0 -6
package/README.md
CHANGED
|
@@ -75,11 +75,11 @@ import type { Track } from './types.ts';
|
|
|
75
75
|
|
|
76
76
|
declare module 'harperdb' {
|
|
77
77
|
export const tables: {
|
|
78
|
-
Tracks: { new(...args: any[]): Table<Track> };
|
|
78
|
+
Tracks: { new (...args: any[]): Table<Track> };
|
|
79
79
|
};
|
|
80
80
|
export const databases: {
|
|
81
81
|
data: {
|
|
82
|
-
Tracks: { new(...args: any[]): Table<Track> };
|
|
82
|
+
Tracks: { new (...args: any[]): Table<Track> };
|
|
83
83
|
};
|
|
84
84
|
};
|
|
85
85
|
}
|
package/extensionModule.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @typedef {import('harperdb').Scope} Scope */
|
|
2
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
2
3
|
import { setLogger } from './utils/logger.js';
|
|
3
4
|
import { regenerateAll } from './utils/regenerateAll.js';
|
|
4
|
-
import { sleep } from './utils/sleep.js';
|
|
5
5
|
|
|
6
6
|
export const suppressHandleApplicationWarning = true;
|
|
7
7
|
|
|
@@ -18,8 +18,10 @@ export async function handleApplication(scope) {
|
|
|
18
18
|
|
|
19
19
|
const watchConfig = scope.options.get(['watch']);
|
|
20
20
|
const shouldWatch = watchConfig === true || watchConfig === undefined;
|
|
21
|
-
const globalTypes = /** @type {string} */ (scope.options.get(['globalTypes'])) ||
|
|
22
|
-
|
|
21
|
+
const globalTypes = /** @type {string} */ (scope.options.get(['globalTypes'])) ||
|
|
22
|
+
'./schema.globalTypes.d.ts';
|
|
23
|
+
const schemaTypes = /** @type {string} */ (scope.options.get(['schemaTypes'])) ||
|
|
24
|
+
'./schema.types.ts';
|
|
23
25
|
const jsdoc = /** @type {string | undefined} */ (scope.options.get(['jsdoc']));
|
|
24
26
|
|
|
25
27
|
if (shouldWatch) {
|
|
@@ -27,18 +29,17 @@ export async function handleApplication(scope) {
|
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
// Do not await this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
32
|
+
delay(500).then(() => {
|
|
33
|
+
// Initial generation
|
|
34
|
+
regenerateAll(globalTypes, schemaTypes, jsdoc);
|
|
35
|
+
|
|
36
|
+
if (shouldWatch) {
|
|
37
|
+
// Watch for schema/database changes via events
|
|
38
|
+
scope.databaseEvents.on('updateTable', updateTable);
|
|
39
|
+
scope.databaseEvents.on('dropTable', dropTable);
|
|
40
|
+
scope.databaseEvents.on('dropDatabase', dropDatabase);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
42
43
|
|
|
43
44
|
function updateTable() {
|
|
44
45
|
regenerateAll(globalTypes, schemaTypes, jsdoc);
|
package/package.json
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harperfast/schema-codegen",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "Generate useful types from your Harper database schemas",
|
|
5
|
+
"keywords": [],
|
|
6
|
+
"homepage": "https://github.com/harperfast",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/harperfast/schema-codegen/issues"
|
|
9
|
+
},
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"author": {
|
|
12
|
+
"name": "Harper",
|
|
13
|
+
"email": "support@harperdb.io"
|
|
14
|
+
},
|
|
15
|
+
"repository": "github:HarperFast/schema-codegen",
|
|
16
|
+
"files": [
|
|
17
|
+
"extensionModule.js",
|
|
18
|
+
"config.yaml",
|
|
19
|
+
"utils/",
|
|
20
|
+
"!utils/**/*.test.js"
|
|
21
|
+
],
|
|
4
22
|
"type": "module",
|
|
5
23
|
"scripts": {
|
|
6
24
|
"commitlint": "commitlint --edit",
|
|
7
|
-
"format:check": "
|
|
8
|
-
"format:fix": "
|
|
9
|
-
"format:staged": "
|
|
25
|
+
"format:check": "oxfmt --check",
|
|
26
|
+
"format:fix": "oxfmt --write",
|
|
27
|
+
"format:staged": "oxfmt --check --list-different",
|
|
10
28
|
"lint:check": "oxlint .",
|
|
11
29
|
"lint:fix": "oxlint . --fix",
|
|
12
30
|
"test": "vitest run",
|
|
13
31
|
"test:coverage": "vitest run --coverage",
|
|
14
32
|
"test:watch": "vitest"
|
|
15
33
|
},
|
|
16
|
-
"files": [
|
|
17
|
-
"extensionModule.js",
|
|
18
|
-
"config.yaml",
|
|
19
|
-
"utils/",
|
|
20
|
-
"!utils/**/*.test.js"
|
|
21
|
-
],
|
|
22
34
|
"devDependencies": {
|
|
23
35
|
"@commitlint/cli": "^20.0.0",
|
|
24
36
|
"@commitlint/config-conventional": "^20.0.0",
|
|
@@ -31,8 +43,8 @@
|
|
|
31
43
|
"@types/react": "^19.2.10",
|
|
32
44
|
"@vitest/coverage-v8": "^4.0.18",
|
|
33
45
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
34
|
-
"dprint": "^0.52.0",
|
|
35
46
|
"harperdb": "^4.7.20",
|
|
47
|
+
"oxfmt": "^0.36.0",
|
|
36
48
|
"oxlint": "^1.51.0",
|
|
37
49
|
"semantic-release": "^25.0.2",
|
|
38
50
|
"vitest": "^4.0.18"
|
package/utils/collectTables.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** @typedef {import('harperdb').Table} Table */
|
|
2
|
-
import { databases as hdbDatabases } from 'harperdb';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* @returns {(Table & { databaseName: string })[]}
|
|
@@ -7,13 +6,14 @@ import { databases as hdbDatabases } from 'harperdb';
|
|
|
7
6
|
export function collectTables() {
|
|
8
7
|
/** @type {(Table & { databaseName: string })[]} */
|
|
9
8
|
const tablesList = [];
|
|
10
|
-
for (const
|
|
11
|
-
const tables =
|
|
9
|
+
for (const databaseName of Object.keys(databases || {})) {
|
|
10
|
+
const tables = databases[databaseName];
|
|
12
11
|
for (const tableName of Object.keys(tables || {})) {
|
|
13
12
|
const TableClass = tables[tableName];
|
|
14
|
-
if (!TableClass?.attributes) {
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
if (!TableClass?.attributes) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
tablesList.push(TableClass);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
return tablesList;
|
|
@@ -9,7 +9,8 @@ import { singularize } from './singularize.js';
|
|
|
9
9
|
export function generateInterface(table) {
|
|
10
10
|
const pluralRaw = table.tableName;
|
|
11
11
|
const singularRaw = singularize(pluralRaw);
|
|
12
|
-
const dbPrefix =
|
|
12
|
+
const dbPrefix =
|
|
13
|
+
table.databaseName && table.databaseName !== 'data' ? `${table.databaseName}_` : '';
|
|
13
14
|
const plural = `${dbPrefix}${pluralRaw}`;
|
|
14
15
|
const singular = `${dbPrefix}${singularRaw}`;
|
|
15
16
|
const isDifferent = plural !== singular;
|
package/utils/generateJSDoc.js
CHANGED
|
@@ -19,7 +19,8 @@ import { singularize } from './singularize.js';
|
|
|
19
19
|
export function generateJSDoc(table) {
|
|
20
20
|
const pluralRaw = table.tableName;
|
|
21
21
|
const singularRaw = singularize(pluralRaw);
|
|
22
|
-
const dbPrefix =
|
|
22
|
+
const dbPrefix =
|
|
23
|
+
table.databaseName && table.databaseName !== 'data' ? `${table.databaseName}_` : '';
|
|
23
24
|
const plural = `${dbPrefix}${pluralRaw}`;
|
|
24
25
|
const singular = `${dbPrefix}${singularRaw}`;
|
|
25
26
|
const isDifferent = plural !== singular;
|
|
@@ -7,10 +7,7 @@ import { singularize } from './singularize.js';
|
|
|
7
7
|
* @param {(Table & { databaseName: string })[]} tablesInput
|
|
8
8
|
* @param {string} label
|
|
9
9
|
*/
|
|
10
|
-
export function generateJSDocFromTables(
|
|
11
|
-
tablesInput,
|
|
12
|
-
label = 'HarperDB schemas',
|
|
13
|
-
) {
|
|
10
|
+
export function generateJSDocFromTables(tablesInput, label = 'HarperDB schemas') {
|
|
14
11
|
let jsCode = `/**
|
|
15
12
|
Generated from ${label}
|
|
16
13
|
Manual changes will be lost!
|
|
@@ -21,7 +18,8 @@ export function generateJSDocFromTables(
|
|
|
21
18
|
|
|
22
19
|
for (const table of tablesInput) {
|
|
23
20
|
jsCode += generateJSDoc(table);
|
|
24
|
-
const dbPrefix =
|
|
21
|
+
const dbPrefix =
|
|
22
|
+
table.databaseName && table.databaseName !== 'data' ? `${table.databaseName}_` : '';
|
|
25
23
|
const plural = `${dbPrefix}${table.tableName}`;
|
|
26
24
|
const singular = `${dbPrefix}${singularize(table.tableName)}`;
|
|
27
25
|
tables.push({ plural, singular, databaseName: table.databaseName });
|
package/utils/generateTS.js
CHANGED
|
@@ -8,10 +8,7 @@ import { singularize } from './singularize.js';
|
|
|
8
8
|
* @param {string} label
|
|
9
9
|
* @returns {{ tsCode: string, tables: TableMeta[] }}
|
|
10
10
|
*/
|
|
11
|
-
export function generateTSFromTables(
|
|
12
|
-
tablesInput,
|
|
13
|
-
label = 'HarperDB schemas',
|
|
14
|
-
) {
|
|
11
|
+
export function generateTSFromTables(tablesInput, label = 'HarperDB schemas') {
|
|
15
12
|
let tsCode = `/**
|
|
16
13
|
Generated from ${label}
|
|
17
14
|
Manual changes will be lost!
|
|
@@ -22,7 +19,8 @@ export function generateTSFromTables(
|
|
|
22
19
|
|
|
23
20
|
for (const table of tablesInput) {
|
|
24
21
|
tsCode += generateInterface(table);
|
|
25
|
-
const dbPrefix =
|
|
22
|
+
const dbPrefix =
|
|
23
|
+
table.databaseName && table.databaseName !== 'data' ? `${table.databaseName}_` : '';
|
|
26
24
|
const plural = `${dbPrefix}${table.tableName}`;
|
|
27
25
|
const singular = `${dbPrefix}${singularize(table.tableName)}`;
|
|
28
26
|
tables.push({ plural, singular, databaseName: table.databaseName });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import { TableMeta } from './tableMeta.js' */
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
4
|
import { getLogger } from './logger.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -54,7 +54,9 @@ export function generateTablesDTS(globalTypesPath, schemaTypesPath, tables) {
|
|
|
54
54
|
for (const [dbName, dbTables] of dbMap.entries()) {
|
|
55
55
|
content += `\t\t${dbName}: {\n`;
|
|
56
56
|
for (const table of dbTables) {
|
|
57
|
-
const pluralRaw = table.plural.startsWith(`${dbName}_`)
|
|
57
|
+
const pluralRaw = table.plural.startsWith(`${dbName}_`)
|
|
58
|
+
? table.plural.slice(dbName.length + 1)
|
|
59
|
+
: table.plural;
|
|
58
60
|
content += `\t\t\t${pluralRaw}: { new(...args: any[]): Table<${table.singular}> };\n`;
|
|
59
61
|
}
|
|
60
62
|
content += `\t\t};\n`;
|
|
@@ -64,7 +66,7 @@ export function generateTablesDTS(globalTypesPath, schemaTypesPath, tables) {
|
|
|
64
66
|
content += `}\n`;
|
|
65
67
|
const outPath = globalTypesPath;
|
|
66
68
|
const dir = path.dirname(outPath);
|
|
67
|
-
|
|
69
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
68
70
|
const existingContent = fs.existsSync(outPath) && fs.readFileSync(outPath, 'utf8');
|
|
69
71
|
if (existingContent !== content) {
|
|
70
72
|
fs.writeFileSync(outPath, content, 'utf8');
|
package/utils/isNullable.js
CHANGED
package/utils/mapType.js
CHANGED
|
@@ -6,7 +6,9 @@ import { singularize } from './singularize.js';
|
|
|
6
6
|
* @returns {string}
|
|
7
7
|
*/
|
|
8
8
|
function mapObjectType(properties) {
|
|
9
|
-
if (!properties
|
|
9
|
+
if (!properties?.length) {
|
|
10
|
+
return 'Record<string, any>';
|
|
11
|
+
}
|
|
10
12
|
const fields = properties
|
|
11
13
|
.map((prop) => {
|
|
12
14
|
const optional = prop.isPrimaryKey ? false : !!prop.nullable;
|
|
@@ -21,7 +23,8 @@ function mapObjectType(properties) {
|
|
|
21
23
|
* @returns {string}
|
|
22
24
|
*/
|
|
23
25
|
export function mapType(attribute) {
|
|
24
|
-
|
|
26
|
+
if (!attribute) return 'any';
|
|
27
|
+
const name = attribute.type || 'Any';
|
|
25
28
|
switch (name) {
|
|
26
29
|
case 'String':
|
|
27
30
|
case 'ID':
|
package/utils/regenerateAll.js
CHANGED
package/utils/singularize.js
CHANGED
|
@@ -55,7 +55,12 @@ export function singularize(word) {
|
|
|
55
55
|
return word.slice(0, -3) + 'y';
|
|
56
56
|
}
|
|
57
57
|
if (word.endsWith('es')) {
|
|
58
|
-
if (
|
|
58
|
+
if (
|
|
59
|
+
word.endsWith('xes') ||
|
|
60
|
+
word.endsWith('ses') ||
|
|
61
|
+
word.endsWith('ches') ||
|
|
62
|
+
word.endsWith('shes')
|
|
63
|
+
) {
|
|
59
64
|
return word.slice(0, -2);
|
|
60
65
|
}
|
|
61
66
|
}
|
package/utils/writeIfChanged.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
import { getLogger } from './logger.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -8,7 +8,7 @@ import { getLogger } from './logger.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export function writeIfChanged(filePath, content) {
|
|
10
10
|
const dir = path.dirname(filePath);
|
|
11
|
-
|
|
11
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
12
12
|
const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : undefined;
|
|
13
13
|
if (existing !== content) {
|
|
14
14
|
fs.writeFileSync(filePath, content, 'utf8');
|