@balena/abstract-sql-to-typescript
Advanced tools
Comparing version 5.0.4-build-renovate-major-22-node-eb139de0d737ac67172fc616e5cbf711ee00ce91-1 to 5.1.0-build-joshbwlng-serial-206e29c66965efbbf36bc072b2adf0edb1793e12-1
{ | ||
"name": "@balena/abstract-sql-to-typescript", | ||
"version": "5.0.4", | ||
"version": "5.1.0", | ||
"description": "A translator for abstract sql into typescript types.", | ||
@@ -25,3 +25,3 @@ "type": "commonjs", | ||
"@balena/odata-to-abstract-sql": "^7.0.0", | ||
"@types/node": "^22.0.0", | ||
"@types/node": "^20.16.5", | ||
"common-tags": "^1.8.2" | ||
@@ -58,4 +58,4 @@ }, | ||
"versionist": { | ||
"publishedAt": "2024-12-05T19:44:40.044Z" | ||
"publishedAt": "2024-12-06T01:06:14.225Z" | ||
} | ||
} |
import type { AbstractSqlModel } from '@balena/abstract-sql-compiler'; | ||
type RequiredModelSubset = Pick<AbstractSqlModel, 'tables' | 'relationships' | 'synonyms'>; | ||
export declare const abstractSqlToTypescriptTypes: (m: RequiredModelSubset) => string; | ||
export type Options = { | ||
convertSerialToInteger?: boolean; | ||
inlineWriteReferences?: boolean; | ||
}; | ||
export declare const abstractSqlToTypescriptTypes: (m: RequiredModelSubset, opts?: Options) => string; | ||
export {}; |
@@ -8,2 +8,3 @@ "use strict"; | ||
const trimNL = new common_tags_1.TemplateTag((0, common_tags_1.replaceResultTransformer)(/^[\r\n]*|[\r\n]*$/g, '')); | ||
const replaceSerial = (s) => s.replace(/serial$/i, 'Integer'); | ||
const modelNameToCamelCaseName = (s) => s | ||
@@ -14,3 +15,3 @@ .split(/[ -]/) | ||
const getReferencedInterface = (modelName, mode) => `${modelNameToCamelCaseName(modelName)}['${mode}']`; | ||
const sqlTypeToTypescriptType = (m, f, mode) => { | ||
const sqlTypeToTypescriptType = (m, f, mode, opts) => { | ||
if (!['ForeignKey', 'ConceptType'].includes(f.dataType) && f.checks) { | ||
@@ -31,2 +32,8 @@ const inChecks = f.checks.find((checkTuple) => checkTuple[0] === 'In'); | ||
if (mode === 'Write') { | ||
if (opts?.inlineWriteReferences && f.references != null) { | ||
const referencedField = m.tables[f.references.resourceName].fields.find(({ fieldName }) => fieldName === f.references.fieldName); | ||
if (referencedField?.computed != null) { | ||
return `Types['${opts?.convertSerialToInteger ? replaceSerial(referencedField.dataType) : referencedField.dataType}']['${mode}']`; | ||
} | ||
} | ||
return referencedFieldType; | ||
@@ -38,6 +45,6 @@ } | ||
default: | ||
return `Types['${f.dataType}']['${mode}']`; | ||
return `Types['${opts?.convertSerialToInteger ? replaceSerial(f.dataType) : f.dataType}']['${mode}']`; | ||
} | ||
}; | ||
const fieldToInterfaceProps = (key, m, f, mode) => { | ||
const fieldToInterfaceProps = (key, m, f, mode, opts) => { | ||
if (mode === 'Write' && f.computed != null) { | ||
@@ -47,6 +54,6 @@ return; | ||
const nullable = f.required ? '' : ' | null'; | ||
return `${(0, odata_to_abstract_sql_1.sqlNameToODataName)(key)}: ${sqlTypeToTypescriptType(m, f, mode)}${nullable};`; | ||
return `${(0, odata_to_abstract_sql_1.sqlNameToODataName)(key)}: ${sqlTypeToTypescriptType(m, f, mode, opts)}${nullable};`; | ||
}; | ||
const fieldsToInterfaceProps = (m, fields, mode) => fields | ||
.map((f) => fieldToInterfaceProps(f.fieldName, m, f, mode)) | ||
const fieldsToInterfaceProps = (m, fields, mode, opts) => fields | ||
.map((f) => fieldToInterfaceProps(f.fieldName, m, f, mode, opts)) | ||
.filter((f) => f != null); | ||
@@ -123,6 +130,6 @@ const getSynonyms = (s, inverseSynonyms) => { | ||
}; | ||
const tableToInterface = (m, table) => { | ||
const tableToInterface = (m, table, opts) => { | ||
const writableFields = table.definition != null | ||
? [] | ||
: fieldsToInterfaceProps(m, table.fields, 'Write'); | ||
: fieldsToInterfaceProps(m, table.fields, 'Write', opts); | ||
const writeType = writableFields.length === 0 | ||
@@ -138,3 +145,3 @@ ? | ||
${[ | ||
...fieldsToInterfaceProps(m, table.fields, 'Read'), | ||
...fieldsToInterfaceProps(m, table.fields, 'Read', opts), | ||
...relationshipsToInterfaceProps(m, table, 'Read'), | ||
@@ -147,3 +154,3 @@ ].join('\n\t\t')} | ||
}; | ||
const abstractSqlToTypescriptTypes = (m) => { | ||
const abstractSqlToTypescriptTypes = (m, opts) => { | ||
return trimNL ` | ||
@@ -157,3 +164,3 @@ // These types were generated by @balena/abstract-sql-to-typescript v${package_json_1.version} | ||
const t = m.tables[tableName]; | ||
return tableToInterface(m, t); | ||
return tableToInterface(m, t, opts); | ||
}) | ||
@@ -160,0 +167,0 @@ .join('\n\n')} |
{ | ||
"name": "@balena/abstract-sql-to-typescript", | ||
"version": "5.0.4-build-renovate-major-22-node-eb139de0d737ac67172fc616e5cbf711ee00ce91-1", | ||
"version": "5.1.0-build-joshbwlng-serial-206e29c66965efbbf36bc072b2adf0edb1793e12-1", | ||
"description": "A translator for abstract sql into typescript types.", | ||
@@ -25,3 +25,3 @@ "type": "commonjs", | ||
"@balena/odata-to-abstract-sql": "^7.0.0", | ||
"@types/node": "^22.0.0", | ||
"@types/node": "^20.16.5", | ||
"common-tags": "^1.8.2" | ||
@@ -58,4 +58,4 @@ }, | ||
"versionist": { | ||
"publishedAt": "2024-12-05T19:44:40.044Z" | ||
"publishedAt": "2024-12-06T01:06:14.225Z" | ||
} | ||
} |
@@ -20,2 +20,7 @@ import type { | ||
export type Options = { | ||
convertSerialToInteger?: boolean; | ||
inlineWriteReferences?: boolean; | ||
}; | ||
const trimNL = new TemplateTag( | ||
@@ -25,2 +30,4 @@ replaceResultTransformer(/^[\r\n]*|[\r\n]*$/g, ''), | ||
const replaceSerial = (s: string): string => s.replace(/serial$/i, 'Integer'); | ||
const modelNameToCamelCaseName = (s: string): string => | ||
@@ -39,2 +46,3 @@ s | ||
mode: Mode, | ||
opts?: Options, | ||
): string => { | ||
@@ -62,2 +70,12 @@ if (!['ForeignKey', 'ConceptType'].includes(f.dataType) && f.checks) { | ||
if (mode === 'Write') { | ||
if (opts?.inlineWriteReferences && f.references != null) { | ||
const referencedField = m.tables[ | ||
f.references.resourceName | ||
].fields.find( | ||
({ fieldName }) => fieldName === f.references!.fieldName, | ||
); | ||
if (referencedField?.computed != null) { | ||
return `Types['${opts?.convertSerialToInteger ? replaceSerial(referencedField.dataType) : referencedField.dataType}']['${mode}']`; | ||
} | ||
} | ||
return referencedFieldType; | ||
@@ -70,3 +88,3 @@ } | ||
default: | ||
return `Types['${f.dataType}']['${mode}']`; | ||
return `Types['${opts?.convertSerialToInteger ? replaceSerial(f.dataType) : f.dataType}']['${mode}']`; | ||
} | ||
@@ -80,2 +98,3 @@ }; | ||
mode: Mode, | ||
opts?: Options, | ||
): string | undefined => { | ||
@@ -91,2 +110,3 @@ if (mode === 'Write' && f.computed != null) { | ||
mode, | ||
opts, | ||
)}${nullable};`; | ||
@@ -99,5 +119,6 @@ }; | ||
mode: Mode, | ||
opts?: Options, | ||
): string[] => | ||
fields | ||
.map((f) => fieldToInterfaceProps(f.fieldName, m, f, mode)) | ||
.map((f) => fieldToInterfaceProps(f.fieldName, m, f, mode, opts)) | ||
.filter((f) => f != null); | ||
@@ -219,7 +240,11 @@ | ||
const tableToInterface = (m: RequiredModelSubset, table: AbstractSqlTable) => { | ||
const tableToInterface = ( | ||
m: RequiredModelSubset, | ||
table: AbstractSqlTable, | ||
opts?: Options, | ||
) => { | ||
const writableFields = | ||
table.definition != null | ||
? [] | ||
: fieldsToInterfaceProps(m, table.fields, 'Write'); | ||
: fieldsToInterfaceProps(m, table.fields, 'Write', opts); | ||
const writeType = | ||
@@ -236,3 +261,3 @@ writableFields.length === 0 | ||
${[ | ||
...fieldsToInterfaceProps(m, table.fields, 'Read'), | ||
...fieldsToInterfaceProps(m, table.fields, 'Read', opts), | ||
...relationshipsToInterfaceProps(m, table, 'Read'), | ||
@@ -250,2 +275,3 @@ ].join('\n\t\t')} | ||
m: RequiredModelSubset, | ||
opts?: Options, | ||
): string => { | ||
@@ -260,3 +286,3 @@ return trimNL` | ||
const t = m.tables[tableName]; | ||
return tableToInterface(m, t); | ||
return tableToInterface(m, t, opts); | ||
}) | ||
@@ -263,0 +289,0 @@ .join('\n\n')} |
import type { AbstractSqlModel } from '@balena/abstract-sql-compiler'; | ||
import { expect } from 'chai'; | ||
import { source } from 'common-tags'; | ||
import { abstractSqlToTypescriptTypes } from '../src/generate'; | ||
import { abstractSqlToTypescriptTypes, type Options } from '../src/generate'; | ||
import { version } from '../package.json'; | ||
@@ -11,2 +11,3 @@ | ||
expectation: string, | ||
opts?: Options, | ||
) => { | ||
@@ -23,3 +24,3 @@ it(`should generate ${msg}`, () => { | ||
}; | ||
const result = abstractSqlToTypescriptTypes(t); | ||
const result = abstractSqlToTypescriptTypes(t, opts); | ||
@@ -69,2 +70,3 @@ expect(result).to.equal(source` | ||
index: 'PRIMARY KEY', | ||
computed: ['Field', 'id'], | ||
}, | ||
@@ -105,2 +107,3 @@ ], | ||
index: 'PRIMARY KEY', | ||
computed: ['Field', 'id'], | ||
}, | ||
@@ -141,2 +144,3 @@ ], | ||
index: 'PRIMARY KEY', | ||
computed: ['Field', 'id'], | ||
}, | ||
@@ -219,2 +223,3 @@ { | ||
index: 'PRIMARY KEY', | ||
computed: ['Field', 'id'], | ||
}, | ||
@@ -324,3 +329,2 @@ ], | ||
modified_at: Types['Date Time']['Write']; | ||
id: Types['Serial']['Write']; | ||
}; | ||
@@ -339,3 +343,2 @@ } | ||
modified_at: Types['Date Time']['Write']; | ||
id: Types['Serial']['Write']; | ||
}; | ||
@@ -362,3 +365,2 @@ } | ||
modified_at: Types['Date Time']['Write']; | ||
id: Types['Serial']['Write']; | ||
a_date: Types['Date']['Write']; | ||
@@ -384,3 +386,2 @@ a_file: Types['WebResource']['Write']; | ||
tag_key: Types['Short Text']['Write']; | ||
id: Types['Serial']['Write']; | ||
}; | ||
@@ -399,1 +400,254 @@ } | ||
); | ||
test( | ||
'correct types for a test table with convertSerialToInteger=true', | ||
testTable, | ||
source` | ||
export interface Parent { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Integer']['Read']; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
}; | ||
} | ||
export interface Other { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Integer']['Read']; | ||
is_referenced_by__test?: Array<Test['Read']>; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
}; | ||
} | ||
export interface Test { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Integer']['Read']; | ||
a_date: Types['Date']['Read']; | ||
a_file: Types['WebResource']['Read']; | ||
parent: { __id: Parent['Read']['id'] } | [Parent['Read']]; | ||
references__other: { __id: Other['Read']['id'] } | [Other['Read']]; | ||
aliased__tag?: Array<TestTag['Read']>; | ||
references__test__has__tag_key?: Array<TestTag['Read']>; | ||
references__test_tag?: Array<TestTag['Read']>; | ||
test__has__tag_key?: Array<TestTag['Read']>; | ||
test_tag?: Array<TestTag['Read']>; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
a_date: Types['Date']['Write']; | ||
a_file: Types['WebResource']['Write']; | ||
parent: Parent['Write']['id']; | ||
references__other: Other['Write']['id']; | ||
}; | ||
} | ||
export interface TestTag { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
test: { __id: Test['Read']['id'] } | [Test['Read']]; | ||
tag_key: Types['Short Text']['Read']; | ||
id: Types['Integer']['Read']; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
test: Test['Write']['id']; | ||
tag_key: Types['Short Text']['Write']; | ||
}; | ||
} | ||
export default interface $Model { | ||
parent: Parent; | ||
other: Other; | ||
test: Test; | ||
test__has__tag_key: TestTag; | ||
// Synonyms | ||
test_tag: TestTag; | ||
} | ||
`, | ||
{ | ||
convertSerialToInteger: true, | ||
}, | ||
); | ||
test( | ||
'correct types for a test table with noMissingReferences=true', | ||
testTable, | ||
source` | ||
export interface Parent { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Serial']['Read']; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
}; | ||
} | ||
export interface Other { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Serial']['Read']; | ||
is_referenced_by__test?: Array<Test['Read']>; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
}; | ||
} | ||
export interface Test { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Serial']['Read']; | ||
a_date: Types['Date']['Read']; | ||
a_file: Types['WebResource']['Read']; | ||
parent: { __id: Parent['Read']['id'] } | [Parent['Read']]; | ||
references__other: { __id: Other['Read']['id'] } | [Other['Read']]; | ||
aliased__tag?: Array<TestTag['Read']>; | ||
references__test__has__tag_key?: Array<TestTag['Read']>; | ||
references__test_tag?: Array<TestTag['Read']>; | ||
test__has__tag_key?: Array<TestTag['Read']>; | ||
test_tag?: Array<TestTag['Read']>; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
a_date: Types['Date']['Write']; | ||
a_file: Types['WebResource']['Write']; | ||
parent: Types['Serial']['Write']; | ||
references__other: Types['Serial']['Write']; | ||
}; | ||
} | ||
export interface TestTag { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
test: { __id: Test['Read']['id'] } | [Test['Read']]; | ||
tag_key: Types['Short Text']['Read']; | ||
id: Types['Serial']['Read']; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
test: Types['Serial']['Write']; | ||
tag_key: Types['Short Text']['Write']; | ||
}; | ||
} | ||
export default interface $Model { | ||
parent: Parent; | ||
other: Other; | ||
test: Test; | ||
test__has__tag_key: TestTag; | ||
// Synonyms | ||
test_tag: TestTag; | ||
} | ||
`, | ||
{ | ||
inlineWriteReferences: true, | ||
}, | ||
); | ||
test( | ||
'correct types for a test table with noMissingReferences=true and noSerial=true', | ||
testTable, | ||
source` | ||
export interface Parent { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Integer']['Read']; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
}; | ||
} | ||
export interface Other { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Integer']['Read']; | ||
is_referenced_by__test?: Array<Test['Read']>; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
}; | ||
} | ||
export interface Test { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
id: Types['Integer']['Read']; | ||
a_date: Types['Date']['Read']; | ||
a_file: Types['WebResource']['Read']; | ||
parent: { __id: Parent['Read']['id'] } | [Parent['Read']]; | ||
references__other: { __id: Other['Read']['id'] } | [Other['Read']]; | ||
aliased__tag?: Array<TestTag['Read']>; | ||
references__test__has__tag_key?: Array<TestTag['Read']>; | ||
references__test_tag?: Array<TestTag['Read']>; | ||
test__has__tag_key?: Array<TestTag['Read']>; | ||
test_tag?: Array<TestTag['Read']>; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
a_date: Types['Date']['Write']; | ||
a_file: Types['WebResource']['Write']; | ||
parent: Types['Integer']['Write']; | ||
references__other: Types['Integer']['Write']; | ||
}; | ||
} | ||
export interface TestTag { | ||
Read: { | ||
created_at: Types['Date Time']['Read']; | ||
modified_at: Types['Date Time']['Read']; | ||
test: { __id: Test['Read']['id'] } | [Test['Read']]; | ||
tag_key: Types['Short Text']['Read']; | ||
id: Types['Integer']['Read']; | ||
}; | ||
Write: { | ||
created_at: Types['Date Time']['Write']; | ||
modified_at: Types['Date Time']['Write']; | ||
test: Types['Integer']['Write']; | ||
tag_key: Types['Short Text']['Write']; | ||
}; | ||
} | ||
export default interface $Model { | ||
parent: Parent; | ||
other: Other; | ||
test: Test; | ||
test__has__tag_key: TestTag; | ||
// Synonyms | ||
test_tag: TestTag; | ||
} | ||
`, | ||
{ | ||
inlineWriteReferences: true, | ||
convertSerialToInteger: true, | ||
}, | ||
); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
468755
1143
+ Added@types/node@20.17.10(transitive)
+ Addedundici-types@6.19.8(transitive)
- Removed@types/node@22.10.2(transitive)
- Removedundici-types@6.20.0(transitive)
Updated@types/node@^20.16.5