New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@balena/abstract-sql-to-typescript

Package Overview
Dependencies
Maintainers
5
Versions
240
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@balena/abstract-sql-to-typescript - npm Package Compare versions

Comparing version 1.0.0-generate-interface-2bd172edacc5749b3a732db716f5674c4f16dba2 to 1.0.0-generate-interface-7a3c3a35b0f9dc1f0b5c77d2004685c276b89cd3

2

CHANGELOG.md

@@ -7,4 +7,4 @@ # Change Log

## 1.0.0 - 2020-10-05
## 1.0.0 - 2020-10-08
* Support generating typescript interfaces from an abstract sql model [Pagan Gazzard]
import { AbstractSqlModel } from '@balena/abstract-sql-compiler';
export declare const abstractSqlToTypescriptTypes: (m: AbstractSqlModel) => string;
export interface Options {
mode?: 'read' | 'write';
}
export declare const abstractSqlToTypescriptTypes: (m: AbstractSqlModel, opts?: Options) => string;

@@ -7,7 +7,16 @@ "use strict";

const trimNL = new common_tags_1.TemplateTag(common_tags_1.replaceResultTransformer(/^[\r\n]*|[\r\n]*$/g, ''));
const modelNameToTypescriptName = (s) => s
const modelNameToCamelCaseName = (s) => s
.split(/[ -]/)
.map((p) => p[0].toLocaleUpperCase() + p.slice(1))
.join('');
const sqlTypeToTypescriptType = (m, f) => {
const sqlTypeToTypescriptType = (m, f, opts) => {
if (!['ForeignKey', 'ConceptType'].includes(f.dataType) && f.checks) {
const inChecks = f.checks.find((checkTuple) => checkTuple[0] === 'In');
if (inChecks) {
const [, , ...allowedValues] = inChecks;
return allowedValues
.map(([type, value]) => (type === 'Text' ? `'${value}'` : value))
.join(' | ');
}
}
switch (f.dataType) {

@@ -21,3 +30,3 @@ case 'Boolean':

case 'Date Time':
return 'Date';
return opts.mode === 'read' ? 'DateString' : 'Date';
case 'Serial':

@@ -30,3 +39,6 @@ case 'Integer':

case 'ConceptType':
const referencedInterface = modelNameToTypescriptName(m.tables[f.references.resourceName].name);
if (opts.mode === 'write') {
return 'number';
}
const referencedInterface = modelNameToCamelCaseName(m.tables[f.references.resourceName].name);
const nullable = f.required ? '' : '?';

@@ -42,21 +54,30 @@ return `{ __id: number } | [${referencedInterface}${nullable}]`;

};
const fieldsToInterfaceProps = (m, fields) => fields
const fieldsToInterfaceProps = (m, fields, opts) => fields
.map((f) => {
const nullable = f.required ? '' : ' | null';
return trimNL `
${odata_to_abstract_sql_1.sqlNameToODataName(f.fieldName)}?: ${sqlTypeToTypescriptType(m, f)}${nullable};
${odata_to_abstract_sql_1.sqlNameToODataName(f.fieldName)}: ${sqlTypeToTypescriptType(m, f, opts)}${nullable};
`;
})
.join('\n');
const tableToInterface = (m, table) => trimNL `
interface ${modelNameToTypescriptName(table.name)} {
${fieldsToInterfaceProps(m, table.fields)}
const tableToInterface = (m, table, opts) => trimNL `
export interface ${modelNameToCamelCaseName(table.name)} {
${fieldsToInterfaceProps(m, table.fields, opts)}
}
`;
exports.abstractSqlToTypescriptTypes = (m) => Object.keys(m.tables)
.map((tableName) => {
const t = m.tables[tableName];
return tableToInterface(m, t);
})
.join('\n');
exports.abstractSqlToTypescriptTypes = (m, opts = {}) => {
const requiredOptions = {
mode: 'read',
...opts,
};
return trimNL `
export type DateString = string;
${Object.keys(m.tables)
.map((tableName) => {
const t = m.tables[tableName];
return tableToInterface(m, t, requiredOptions);
})
.join('\n\n')}
`;
};
//# sourceMappingURL=index.js.map
{
"name": "@balena/abstract-sql-to-typescript",
"version": "1.0.0-generate-interface-2bd172edacc5749b3a732db716f5674c4f16dba2",
"version": "1.0.0-generate-interface-7a3c3a35b0f9dc1f0b5c77d2004685c276b89cd3",
"description": "A translator for abstract sql into typescript types.",

@@ -5,0 +5,0 @@ "main": "out/index.js",

@@ -5,2 +5,3 @@ import {

AbstractSqlTable,
InNode,
} from '@balena/abstract-sql-compiler';

@@ -14,3 +15,3 @@ import { sqlNameToODataName } from '@balena/odata-to-abstract-sql';

const modelNameToTypescriptName = (s: string) =>
const modelNameToCamelCaseName = (s: string) =>
s

@@ -21,3 +22,19 @@ .split(/[ -]/)

const sqlTypeToTypescriptType = (m: AbstractSqlModel, f: AbstractSqlField) => {
const sqlTypeToTypescriptType = (
m: AbstractSqlModel,
f: AbstractSqlField,
opts: RequiredOptions,
) => {
if (!['ForeignKey', 'ConceptType'].includes(f.dataType) && f.checks) {
const inChecks = f.checks.find(
(checkTuple): checkTuple is InNode => checkTuple[0] === 'In',
);
if (inChecks) {
const [, , ...allowedValues] = inChecks;
return allowedValues
.map(([type, value]) => (type === 'Text' ? `'${value}'` : value))
.join(' | ');
}
}
switch (f.dataType) {

@@ -31,3 +48,3 @@ case 'Boolean':

case 'Date Time':
return 'Date';
return opts.mode === 'read' ? 'DateString' : 'Date';
case 'Serial':

@@ -41,3 +58,7 @@ case 'Integer':

case 'ConceptType':
const referencedInterface = modelNameToTypescriptName(
if (opts.mode === 'write') {
return 'number';
}
const referencedInterface = modelNameToCamelCaseName(
m.tables[f.references!.resourceName].name,

@@ -59,2 +80,3 @@ );

fields: AbstractSqlField[],
opts: RequiredOptions,
) =>

@@ -65,5 +87,6 @@ fields

return trimNL`
${sqlNameToODataName(f.fieldName)}?: ${sqlTypeToTypescriptType(
${sqlNameToODataName(f.fieldName)}: ${sqlTypeToTypescriptType(
m,
f,
opts,
)}${nullable};

@@ -77,14 +100,31 @@ `;

table: AbstractSqlTable,
opts: RequiredOptions,
) => trimNL`
interface ${modelNameToTypescriptName(table.name)} {
${fieldsToInterfaceProps(m, table.fields)}
export interface ${modelNameToCamelCaseName(table.name)} {
${fieldsToInterfaceProps(m, table.fields, opts)}
}
`;
export const abstractSqlToTypescriptTypes = (m: AbstractSqlModel) =>
Object.keys(m.tables)
.map((tableName) => {
const t = m.tables[tableName];
return tableToInterface(m, t);
})
.join('\n');
export interface Options {
mode?: 'read' | 'write';
}
type RequiredOptions = Required<Options>;
export const abstractSqlToTypescriptTypes = (
m: AbstractSqlModel,
opts: Options = {},
) => {
const requiredOptions: RequiredOptions = {
mode: 'read',
...opts,
};
return trimNL`
export type DateString = string;
${Object.keys(m.tables)
.map((tableName) => {
const t = m.tables[tableName];
return tableToInterface(m, t, requiredOptions);
})
.join('\n\n')}
`;
};
import { AbstractSqlModel } from '@balena/abstract-sql-compiler';
import { expect } from 'chai';
import { stripIndent } from 'common-tags';
import { abstractSqlToTypescriptTypes } from '../src';
import { source } from 'common-tags';
import { abstractSqlToTypescriptTypes, Options } from '../src';
const test = (s: string, m: Partial<AbstractSqlModel>, e: string) => {
it(`should generate ${s}`, () => {
const test = (
msg: string,
model: Partial<AbstractSqlModel>,
expectation: string,
mode?: Options['mode'],
) => {
it(`should generate ${msg}`, () => {
// Set defaults for required props

@@ -14,6 +19,10 @@ const t: AbstractSqlModel = {

rules: [],
...m,
...model,
};
expect(abstractSqlToTypescriptTypes(t)).to.equal(e);
// expect(abstractSqlToTypescriptTypes(t, {mode})).to.equal(expectation)
expect(abstractSqlToTypescriptTypes(t, { mode })).to.equal(source`
export type DateString = string;
${expectation}
`);
});

@@ -23,49 +32,64 @@ };

test('no types for an empty model', {}, '');
test('correct types for an actor table',
{
tables: {
actor: {
fields: [
{
dataType: 'Date Time',
fieldName: 'created at',
required: true,
defaultValue: 'CURRENT_TIMESTAMP',
},
{
dataType: 'Date Time',
fieldName: 'modified at',
required: true,
defaultValue: 'CURRENT_TIMESTAMP',
},
{
dataType: 'Serial',
fieldName: 'id',
required: true,
index: 'PRIMARY KEY',
},
],
primitive: false,
name: 'actor',
indexes: [],
idField: 'id',
resourceName: 'actor',
triggers: [
{
when: 'BEFORE',
operation: 'UPDATE',
level: 'ROW',
fnName: 'trigger_update_modified_at',
},
],
},
const actorTable: Partial<AbstractSqlModel> = {
tables: {
actor: {
fields: [
{
dataType: 'Date Time',
fieldName: 'created at',
required: true,
defaultValue: 'CURRENT_TIMESTAMP',
},
{
dataType: 'Date Time',
fieldName: 'modified at',
required: true,
defaultValue: 'CURRENT_TIMESTAMP',
},
{
dataType: 'Serial',
fieldName: 'id',
required: true,
index: 'PRIMARY KEY',
},
],
primitive: false,
name: 'actor',
indexes: [],
idField: 'id',
resourceName: 'actor',
triggers: [
{
when: 'BEFORE',
operation: 'UPDATE',
level: 'ROW',
fnName: 'trigger_update_modified_at',
},
],
},
},
stripIndent`
interface Actor {
created_at?: Date;
modified_at?: Date;
id?: number;
};
test(
'correct read types for an actor table',
actorTable,
source`
export interface Actor {
created_at: Date;
modified_at: Date;
id: number;
}
`,
);
test(
'correct write types for an actor table',
actorTable,
source`
export interface Actor {
created_at: Date;
modified_at: Date;
id: number;
}
`,
'write',
);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc