@harperfast/schema-codegen 1.0.0 → 1.0.2

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 CHANGED
@@ -6,8 +6,6 @@ Schema Codegen will generate TypeScript types for your GraphQL schemas, making i
6
6
 
7
7
  Install this with your favorite package manager!
8
8
 
9
- **Warning**: I haven't actually published this yet. :)
10
-
11
9
  ```bash
12
10
  npm install --save @harperfast/schema-codegen
13
11
  ```
@@ -89,8 +87,6 @@ declare module 'harperdb' {
89
87
 
90
88
  ## Development
91
89
 
92
- This code uses type stripping, so as long as you use a compatible version of Node, nothing needs to be compiled.
93
-
94
90
  To use this in an application, first link it:
95
91
 
96
92
  ```bash
package/config.yaml CHANGED
@@ -1 +1 @@
1
- extensionModule: ./extensionModule.ts
1
+ extensionModule: ./extensionModule.js
@@ -1,11 +1,14 @@
1
- import type { Scope } from 'harperdb';
2
- import { setLogger } from './utils/logger.ts';
3
- import { regenerateAll } from './utils/regenerateAll.ts';
4
- import { sleep } from './utils/sleep.ts';
1
+ /** @typedef {import('harperdb').Scope} Scope */
2
+ import { setLogger } from './utils/logger.js';
3
+ import { regenerateAll } from './utils/regenerateAll.js';
4
+ import { sleep } from './utils/sleep.js';
5
5
 
6
6
  export const suppressHandleApplicationWarning = true;
7
7
 
8
- export async function handleApplication(scope: Scope) {
8
+ /**
9
+ * @param {Scope} scope
10
+ */
11
+ export async function handleApplication(scope) {
9
12
  setLogger(scope.logger);
10
13
 
11
14
  if (!process.env.DEV_MODE) {
@@ -15,9 +18,9 @@ export async function handleApplication(scope: Scope) {
15
18
 
16
19
  const watchConfig = scope.options.get(['watch']);
17
20
  const shouldWatch = watchConfig === true || watchConfig === undefined;
18
- const globalTypes = (scope.options.get(['globalTypes']) as string) || './schema.globalTypes.d.ts';
19
- const schemaTypes = (scope.options.get(['schemaTypes']) as string) || './schema.types.ts';
20
- const jsdoc = scope.options.get(['jsdoc']) as string | undefined;
21
+ const globalTypes = /** @type {string} */ (scope.options.get(['globalTypes'])) || './schema.globalTypes.d.ts';
22
+ const schemaTypes = /** @type {string} */ (scope.options.get(['schemaTypes'])) || './schema.types.ts';
23
+ const jsdoc = /** @type {string | undefined} */ (scope.options.get(['jsdoc']));
21
24
 
22
25
  if (shouldWatch) {
23
26
  scope.on('close', scopeClosed);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harperfast/schema-codegen",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "commitlint": "commitlint --edit",
@@ -14,10 +14,10 @@
14
14
  "test:watch": "vitest"
15
15
  },
16
16
  "files": [
17
- "extensionModule.ts",
17
+ "extensionModule.js",
18
18
  "config.yaml",
19
19
  "utils/",
20
- "!utils/**/*.test.ts"
20
+ "!utils/**/*.test.js"
21
21
  ],
22
22
  "devDependencies": {
23
23
  "@commitlint/cli": "^20.0.0",
@@ -0,0 +1,20 @@
1
+ /** @typedef {import('harperdb').Table} Table */
2
+ import { databases as hdbDatabases } from 'harperdb';
3
+
4
+ /**
5
+ * @returns {(Table & { databaseName: string })[]}
6
+ */
7
+ export function collectTables() {
8
+ /** @type {(Table & { databaseName: string })[]} */
9
+ const tablesList = [];
10
+ for (const dbName of Object.keys(hdbDatabases || {})) {
11
+ const tables = hdbDatabases[dbName];
12
+ for (const tableName of Object.keys(tables || {})) {
13
+ const TableClass = tables[tableName];
14
+ if (!TableClass?.attributes) { continue; }
15
+ TableClass.databaseName = dbName;
16
+ tablesList.push(/** @type {Table & { databaseName: string }} */ (TableClass));
17
+ }
18
+ }
19
+ return tablesList;
20
+ }
@@ -1,9 +1,12 @@
1
- import type { Table } from 'harperdb';
2
- import { isNullable } from './isNullable.ts';
3
- import { mapType } from './mapType.ts';
4
- import { singularize } from './singularize.ts';
1
+ /** @typedef {import('harperdb').Table} Table */
2
+ import { isNullable } from './isNullable.js';
3
+ import { mapType } from './mapType.js';
4
+ import { singularize } from './singularize.js';
5
5
 
6
- export function generateInterface(table: Table & { databaseName?: string }) {
6
+ /**
7
+ * @param {Table & { databaseName?: string }} table
8
+ */
9
+ export function generateInterface(table) {
7
10
  const pluralRaw = table.tableName;
8
11
  const singularRaw = singularize(pluralRaw);
9
12
  const dbPrefix = table.databaseName && table.databaseName !== 'data' ? `${table.databaseName}_` : '';
@@ -12,14 +15,15 @@ export function generateInterface(table: Table & { databaseName?: string }) {
12
15
  const isDifferent = plural !== singular;
13
16
 
14
17
  let code = `\nexport interface ${singular} {\n`;
15
- const primaryKeys: string[] = [];
18
+ /** @type {string[]} */
19
+ const primaryKeys = [];
16
20
  for (const attribute of table.attributes || []) {
17
21
  const type = mapType(attribute);
18
22
  const primaryKey = !!attribute.isPrimaryKey;
19
23
  const nullable = !primaryKey && isNullable(attribute);
20
24
  code += `\t${attribute.name}${nullable ? '?' : ''}: ${type};\n`;
21
25
  if (primaryKey) {
22
- primaryKeys.push(attribute.name!);
26
+ primaryKeys.push(attribute.name);
23
27
  }
24
28
  }
25
29
  code += `}\n\n`;
@@ -1,7 +1,7 @@
1
- import type { Table } from 'harperdb';
2
- import { isNullable } from './isNullable.ts';
3
- import { mapType } from './mapType.ts';
4
- import { singularize } from './singularize.ts';
1
+ /** @typedef {import('harperdb').Table} Table */
2
+ import { isNullable } from './isNullable.js';
3
+ import { mapType } from './mapType.js';
4
+ import { singularize } from './singularize.js';
5
5
 
6
6
  /**
7
7
  * Generates JSDoc types for a given HarperDB table.
@@ -13,8 +13,10 @@ import { singularize } from './singularize.ts';
13
13
  * * @property {string} name
14
14
  * * @property {any} [mp3]
15
15
  * *\/
16
+ *
17
+ * @param {Table & { databaseName?: string }} table
16
18
  */
17
- export function generateJSDoc(table: Table & { databaseName?: string }) {
19
+ export function generateJSDoc(table) {
18
20
  const pluralRaw = table.tableName;
19
21
  const singularRaw = singularize(pluralRaw);
20
22
  const dbPrefix = table.databaseName && table.databaseName !== 'data' ? `${table.databaseName}_` : '';
@@ -23,14 +25,14 @@ export function generateJSDoc(table: Table & { databaseName?: string }) {
23
25
  const isDifferent = plural !== singular;
24
26
 
25
27
  let code = `\n/**\n * @typedef {Object} ${singular}\n`;
26
- const primaryKeys: string[] = [];
28
+ const primaryKeys = [];
27
29
  for (const attribute of table.attributes || []) {
28
30
  const type = mapType(attribute);
29
31
  const primaryKey = !!attribute.isPrimaryKey;
30
32
  const nullable = !primaryKey && isNullable(attribute);
31
33
  code += ` * @property {${type}} ${nullable ? '[' : ''}${attribute.name}${nullable ? ']' : ''}\n`;
32
34
  if (primaryKey) {
33
- primaryKeys.push(attribute.name!);
35
+ primaryKeys.push(attribute.name);
34
36
  }
35
37
  }
36
38
  code += ` */\n\n`;
@@ -1,18 +1,23 @@
1
- import type { Table } from 'harperdb';
2
- import { generateJSDoc } from './generateJSDoc.ts';
3
- import { singularize } from './singularize.ts';
4
- import type { TableMeta } from './tableMeta.ts';
1
+ /** @typedef {import('harperdb').Table} Table */
2
+ /** @import { TableMeta } from './tableMeta.js' */
3
+ import { generateJSDoc } from './generateJSDoc.js';
4
+ import { singularize } from './singularize.js';
5
5
 
6
+ /**
7
+ * @param {(Table & { databaseName: string })[]} tablesInput
8
+ * @param {string} label
9
+ */
6
10
  export function generateJSDocFromTables(
7
- tablesInput: (Table & { databaseName: string })[],
8
- label: string = 'HarperDB schemas',
11
+ tablesInput,
12
+ label = 'HarperDB schemas',
9
13
  ) {
10
14
  let jsCode = `/**
11
15
  Generated from ${label}
12
16
  Manual changes will be lost!
13
17
  > harper dev .
14
18
  */`;
15
- const tables: TableMeta[] = [];
19
+ /** @type {TableMeta[]} */
20
+ const tables = [];
16
21
 
17
22
  for (const table of tablesInput) {
18
23
  jsCode += generateJSDoc(table);
@@ -1,18 +1,24 @@
1
- import type { Table } from 'harperdb';
2
- import { generateInterface } from './generateInterface.ts';
3
- import { singularize } from './singularize.ts';
4
- import type { TableMeta } from './tableMeta.ts';
1
+ /** @typedef {import('harperdb').Table} Table */
2
+ /** @import { TableMeta } from './tableMeta.js' */
3
+ import { generateInterface } from './generateInterface.js';
4
+ import { singularize } from './singularize.js';
5
5
 
6
+ /**
7
+ * @param {(Table & { databaseName: string })[]} tablesInput
8
+ * @param {string} label
9
+ * @returns {{ tsCode: string, tables: TableMeta[] }}
10
+ */
6
11
  export function generateTSFromTables(
7
- tablesInput: (Table & { databaseName: string })[],
8
- label: string = 'HarperDB schemas',
12
+ tablesInput,
13
+ label = 'HarperDB schemas',
9
14
  ) {
10
15
  let tsCode = `/**
11
16
  Generated from ${label}
12
17
  Manual changes will be lost!
13
18
  > harper dev .
14
19
  */`;
15
- const tables: TableMeta[] = [];
20
+ /** @type {TableMeta[]} */
21
+ const tables = [];
16
22
 
17
23
  for (const table of tablesInput) {
18
24
  tsCode += generateInterface(table);
@@ -1,9 +1,14 @@
1
+ /** @import { TableMeta } from './tableMeta.js' */
1
2
  import fs from 'fs';
2
3
  import path from 'path';
3
- import { getLogger } from './logger.ts';
4
- import type { TableMeta } from './tableMeta.ts';
4
+ import { getLogger } from './logger.js';
5
5
 
6
- export function generateTablesDTS(globalTypesPath: string, schemaTypesPath: string, tables: TableMeta[]) {
6
+ /**
7
+ * @param {string} globalTypesPath
8
+ * @param {string} schemaTypesPath
9
+ * @param {TableMeta[]} tables
10
+ */
11
+ export function generateTablesDTS(globalTypesPath, schemaTypesPath, tables) {
7
12
  let content = `/**
8
13
  Generated from your schema files
9
14
  Manual changes will be lost!
@@ -12,7 +17,8 @@ export function generateTablesDTS(globalTypesPath: string, schemaTypesPath: stri
12
17
  `;
13
18
  content += `import type { Table } from 'harperdb';\n`;
14
19
  // Build a single import of all relevant types from schemaTypesPath
15
- const namesToImport = new Set<string>();
20
+ /** @type {Set<string>} */
21
+ const namesToImport = new Set();
16
22
  for (const table of tables) {
17
23
  namesToImport.add(table.singular);
18
24
  }
@@ -23,12 +29,14 @@ export function generateTablesDTS(globalTypesPath: string, schemaTypesPath: stri
23
29
  }
24
30
  content += '\n';
25
31
 
26
- const dbMap = new Map<string, TableMeta[]>();
32
+ /** @type {Map<string, TableMeta[]>} */
33
+ const dbMap = new Map();
27
34
  for (const table of tables) {
28
35
  if (!dbMap.has(table.databaseName)) {
29
- dbMap.set(table.databaseName, []);
36
+ dbMap.set(table.databaseName, [table]);
37
+ } else {
38
+ dbMap.get(table.databaseName)?.push(table);
30
39
  }
31
- dbMap.get(table.databaseName)!.push(table);
32
40
  }
33
41
 
34
42
  content += `declare module 'harperdb' {\n`;
@@ -60,6 +68,6 @@ export function generateTablesDTS(globalTypesPath: string, schemaTypesPath: stri
60
68
  const existingContent = fs.existsSync(outPath) && fs.readFileSync(outPath, 'utf8');
61
69
  if (existingContent !== content) {
62
70
  fs.writeFileSync(outPath, content, 'utf8');
63
- getLogger().debug?.(`Updated types in ${outPath}`);
71
+ getLogger()?.debug?.(`Updated types in ${outPath}`);
64
72
  }
65
73
  }
@@ -1,6 +1,9 @@
1
- import type { Attribute } from 'harperdb';
1
+ /** @typedef {import('harperdb').Attribute} Attribute */
2
2
 
3
- export function isNullable(attribute: Attribute) {
3
+ /**
4
+ * @param {Attribute} attribute
5
+ */
6
+ export function isNullable(attribute) {
4
7
  // Primary keys are always required
5
8
  if (attribute.isPrimaryKey) { return false; }
6
9
  return !!attribute.nullable || attribute.nullable === undefined;
@@ -0,0 +1,18 @@
1
+ /** @typedef {import('harperdb').Logger} Logger */
2
+
3
+ /** @type {Logger | null} */
4
+ let logger = null;
5
+
6
+ /**
7
+ * @param {Logger} newLogger
8
+ */
9
+ export function setLogger(newLogger) {
10
+ logger = newLogger;
11
+ }
12
+
13
+ /**
14
+ * @returns {Logger | null}
15
+ */
16
+ export function getLogger() {
17
+ return logger;
18
+ }
@@ -1,7 +1,11 @@
1
- import type { Attribute } from 'harperdb';
2
- import { singularize } from './singularize.ts';
1
+ /** @typedef {import('harperdb').Attribute} Attribute */
2
+ import { singularize } from './singularize.js';
3
3
 
4
- function mapObjectType(properties: Attribute[] | undefined): string {
4
+ /**
5
+ * @param {Attribute[] | undefined} properties
6
+ * @returns {string}
7
+ */
8
+ function mapObjectType(properties) {
5
9
  if (!properties || properties.length === 0) { return 'Record<string, any>'; }
6
10
  const fields = properties
7
11
  .map((prop) => {
@@ -12,7 +16,11 @@ function mapObjectType(properties: Attribute[] | undefined): string {
12
16
  return `{ ${fields} }`;
13
17
  }
14
18
 
15
- export function mapType(attribute: Attribute): string {
19
+ /**
20
+ * @param {Attribute} attribute
21
+ * @returns {string}
22
+ */
23
+ export function mapType(attribute) {
16
24
  const name = attribute?.type || 'Any';
17
25
  switch (name) {
18
26
  case 'String':
@@ -1,12 +1,16 @@
1
1
  import path from 'path';
2
- import { collectTables } from './collectTables.ts';
3
- import { generateJSDocFromTables } from './generateJSDocFromTables.ts';
4
- import { generateTablesDTS } from './generateTablesDTS.ts';
5
- import { generateTSFromTables } from './generateTS.ts';
6
- import type { TableMeta } from './tableMeta.ts';
7
- import { writeIfChanged } from './writeIfChanged.ts';
2
+ import { collectTables } from './collectTables.js';
3
+ import { generateJSDocFromTables } from './generateJSDocFromTables.js';
4
+ import { generateTablesDTS } from './generateTablesDTS.js';
5
+ import { generateTSFromTables } from './generateTS.js';
6
+ import { writeIfChanged } from './writeIfChanged.js';
8
7
 
9
- export function regenerateAll(globalTypes: string, schemaTypes: string, jsdoc?: string) {
8
+ /**
9
+ * @param {string} globalTypes
10
+ * @param {string} schemaTypes
11
+ * @param {string} [jsdoc]
12
+ */
13
+ export function regenerateAll(globalTypes, schemaTypes, jsdoc) {
10
14
  const list = collectTables();
11
15
 
12
16
  if (jsdoc) {
@@ -15,6 +19,6 @@ export function regenerateAll(globalTypes: string, schemaTypes: string, jsdoc?:
15
19
  } else {
16
20
  const { tsCode, tables } = generateTSFromTables(list, 'HarperDB schema');
17
21
  writeIfChanged(path.resolve(schemaTypes), tsCode);
18
- generateTablesDTS(path.resolve(globalTypes), path.resolve(schemaTypes), tables as TableMeta[]);
22
+ generateTablesDTS(path.resolve(globalTypes), path.resolve(schemaTypes), tables);
19
23
  }
20
24
  }
@@ -1,4 +1,8 @@
1
- export function singularize(word: string): string {
1
+ /**
2
+ * @param {string} word
3
+ * @returns {string}
4
+ */
5
+ export function singularize(word) {
2
6
  const lower = word.toLowerCase();
3
7
 
4
8
  // Nouns that are the same in singular and plural or should be treated as unchanged here
@@ -23,7 +27,8 @@ export function singularize(word: string): string {
23
27
  }
24
28
 
25
29
  // Irregular plurals not covered by suffix rules
26
- const irregular: Record<string, string> = {
30
+ /** @type {Record<string, string>} */
31
+ const irregular = {
27
32
  people: 'person',
28
33
  men: 'man',
29
34
  women: 'woman',
@@ -1,3 +1,6 @@
1
- export function sleep(ms: number) {
1
+ /**
2
+ * @param {number} ms
3
+ */
4
+ export function sleep(ms) {
2
5
  return new Promise(resolve => setTimeout(resolve, ms));
3
6
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @typedef {Object} TableMeta
3
+ * @property {string} singular
4
+ * @property {string} plural
5
+ * @property {string} databaseName
6
+ */
7
+ export {};
@@ -1,13 +1,17 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { getLogger } from './logger.ts';
3
+ import { getLogger } from './logger.js';
4
4
 
5
- export function writeIfChanged(filePath: string, content: string) {
5
+ /**
6
+ * @param {string} filePath
7
+ * @param {string} content
8
+ */
9
+ export function writeIfChanged(filePath, content) {
6
10
  const dir = path.dirname(filePath);
7
11
  if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); }
8
12
  const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : undefined;
9
13
  if (existing !== content) {
10
14
  fs.writeFileSync(filePath, content, 'utf8');
11
- getLogger().debug?.(`Updated types in ${filePath}`);
15
+ getLogger()?.debug?.(`Updated types in ${filePath}`);
12
16
  }
13
17
  }
@@ -1,16 +0,0 @@
1
- import type { Table } from 'harperdb';
2
- import { databases as hdbDatabases } from 'harperdb';
3
-
4
- export function collectTables() {
5
- const tablesList: (Table & { databaseName: string })[] = [];
6
- for (const dbName of Object.keys(hdbDatabases || {})) {
7
- const tables = (hdbDatabases as any)[dbName];
8
- for (const tableName of Object.keys(tables || {})) {
9
- const TableClass = tables[tableName];
10
- if (!TableClass?.attributes) { continue; }
11
- (TableClass as any).databaseName = dbName;
12
- tablesList.push(TableClass as Table & { databaseName: string });
13
- }
14
- }
15
- return tablesList;
16
- }
package/utils/logger.ts DELETED
@@ -1,11 +0,0 @@
1
- import type { Logger } from 'harperdb';
2
-
3
- let logger: Logger | null = null;
4
-
5
- export function setLogger(newLogger: Logger) {
6
- logger = newLogger;
7
- }
8
-
9
- export function getLogger(): Logger {
10
- return logger!;
11
- }
@@ -1,5 +0,0 @@
1
- export interface TableMeta {
2
- singular: string;
3
- plural: string;
4
- databaseName: string;
5
- }