@axinom/mosaic-cli 0.14.2-rc.8 → 0.15.0-rc.0
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/package.json +6 -5
- package/src/cli/README.md +60 -0
- package/src/cli/index.ts +47 -0
- package/src/commands/apply-templates/apply-templates.spec.ts +623 -0
- package/src/commands/apply-templates/apply-templates.ts +494 -0
- package/src/commands/apply-templates/bitwarden-vault.ts +130 -0
- package/src/commands/apply-templates/index.ts +1 -0
- package/src/commands/create-extension-config/create-extension-config.ts +92 -0
- package/src/commands/create-extension-config/index.ts +23 -0
- package/src/commands/get-access-token/get-access-token-options.ts +9 -0
- package/src/commands/get-access-token/get-dev-access-token.ts +32 -0
- package/src/commands/get-access-token/index.ts +66 -0
- package/src/commands/graphql-diff.ts +143 -0
- package/src/commands/msg-codegen/codegen.ts +891 -0
- package/src/commands/msg-codegen/index.ts +48 -0
- package/src/commands/msg-codegen/lint.ts +84 -0
- package/src/commands/msg-codegen/message-codegen-options.ts +7 -0
- package/src/commands/msg-diff/asyncapi-override.ts +31 -0
- package/src/commands/msg-diff/git-checkout-tmp.ts +73 -0
- package/src/commands/msg-diff/index.ts +53 -0
- package/src/commands/msg-diff/message-diff-options.ts +7 -0
- package/src/commands/msg-diff/msg-diff.spec.ts +412 -0
- package/src/commands/msg-diff/msg-diff.ts +364 -0
- package/src/commands/msg-diff/test-resources/0/1-asyncapi.yml +38 -0
- package/src/commands/msg-diff/test-resources/0/2-asyncapi.yml +36 -0
- package/src/commands/msg-diff/test-resources/0/command.json +74 -0
- package/src/commands/msg-diff/test-resources/0/event.json +25 -0
- package/src/commands/msg-diff/test-resources/1/1-asyncapi.yml +25 -0
- package/src/commands/msg-diff/test-resources/1/moved-event.json +25 -0
- package/src/commands/msg-diff/test-resources/common.json +20 -0
- package/src/commands/pg-dump/README.md +21 -0
- package/src/commands/pg-dump/generate.ts +146 -0
- package/src/commands/pg-dump/index.ts +39 -0
- package/src/commands/pg-dump/pg-dump-options.ts +6 -0
- package/src/commands/publish-schema-to-db/README.md +130 -0
- package/src/commands/publish-schema-to-db/abstractions/base-smart-tags.ts +6 -0
- package/src/commands/publish-schema-to-db/abstractions/index.ts +5 -0
- package/src/commands/publish-schema-to-db/abstractions/pg-column.ts +31 -0
- package/src/commands/publish-schema-to-db/abstractions/pg-fk-column.ts +6 -0
- package/src/commands/publish-schema-to-db/abstractions/pg-table.ts +55 -0
- package/src/commands/publish-schema-to-db/abstractions/pg-type.ts +8 -0
- package/src/commands/publish-schema-to-db/content-entity-model.ts +93 -0
- package/src/commands/publish-schema-to-db/generate.ts +82 -0
- package/src/commands/publish-schema-to-db/index.ts +49 -0
- package/src/commands/publish-schema-to-db/jest.config.js +9 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/fk-column.spec.ts +42 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/fk-column.ts +41 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/index.ts +4 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/pk-column.spec.ts +47 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/pk-column.ts +34 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/primitive-column.spec.ts +65 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/primitive-column.ts +62 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/virtual-fk-column.spec.ts +24 -0
- package/src/commands/publish-schema-to-db/pg-models/columns/virtual-fk-column.ts +34 -0
- package/src/commands/publish-schema-to-db/pg-models/json-schema-parse-utils.spec.ts +182 -0
- package/src/commands/publish-schema-to-db/pg-models/json-schema-parse-utils.ts +166 -0
- package/src/commands/publish-schema-to-db/pg-models/pg-sql-gen-utils.spec.ts +19 -0
- package/src/commands/publish-schema-to-db/pg-models/pg-sql-gen-utils.ts +237 -0
- package/src/commands/publish-schema-to-db/pg-models/pgl-utils.spec.ts +19 -0
- package/src/commands/publish-schema-to-db/pg-models/pgl-utils.ts +115 -0
- package/src/commands/publish-schema-to-db/pg-models/tables/content-entity-table.ts +104 -0
- package/src/commands/publish-schema-to-db/pg-models/tables/index.ts +3 -0
- package/src/commands/publish-schema-to-db/pg-models/tables/object-property-table.ts +113 -0
- package/src/commands/publish-schema-to-db/pg-models/tables/relations-table.ts +115 -0
- package/src/commands/publish-schema-to-db/postprocessors/collection-postprocessor.ts +33 -0
- package/src/commands/publish-schema-to-db/postprocessors/content-entity-model-postprocessor.ts +13 -0
- package/src/commands/publish-schema-to-db/postprocessors/episode-postprocessor.ts +37 -0
- package/src/commands/publish-schema-to-db/postprocessors/index.ts +6 -0
- package/src/commands/publish-schema-to-db/postprocessors/movie-postprocessor.ts +30 -0
- package/src/commands/publish-schema-to-db/postprocessors/postprocessing-utils.ts +21 -0
- package/src/commands/publish-schema-to-db/postprocessors/season-postprocessor.ts +37 -0
- package/src/commands/publish-schema-to-db/postprocessors/tvshow-postprocessor.ts +30 -0
- package/src/commands/publish-schema-to-db/publish-schema-to-db-options.ts +15 -0
- package/src/commands/publish-schema-to-db/types/sql-formatter.d.ts +10 -0
- package/src/exports.ts +2 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { PgColumn, PgTable, PgType } from '../../abstractions';
|
|
2
|
+
import { FkColumn } from './fk-column';
|
|
3
|
+
|
|
4
|
+
interface FkColumnTestInput {
|
|
5
|
+
pkType: PgType;
|
|
6
|
+
expectedExpression: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const testData: [string, FkColumnTestInput][] = [
|
|
10
|
+
[
|
|
11
|
+
'FK for TEXT PK',
|
|
12
|
+
{
|
|
13
|
+
pkType: 'TEXT',
|
|
14
|
+
expectedExpression: 'entity_id TEXT REFERENCES entity ON DELETE CASCADE',
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
'FK for INTEGER PK',
|
|
19
|
+
{
|
|
20
|
+
pkType: 'INTEGER',
|
|
21
|
+
expectedExpression:
|
|
22
|
+
'entity_id INTEGER REFERENCES entity ON DELETE CASCADE',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
];
|
|
26
|
+
describe('FkColumn', () => {
|
|
27
|
+
test.each(testData)('%s', (description: string, input: FkColumnTestInput) => {
|
|
28
|
+
// Arrange
|
|
29
|
+
const entityTablePk: PgColumn = {
|
|
30
|
+
name: 'id',
|
|
31
|
+
type: input.pkType,
|
|
32
|
+
table: { name: 'entity' } as PgTable,
|
|
33
|
+
} as PgColumn;
|
|
34
|
+
const propertyTable: PgTable = { name: 'object' } as PgTable;
|
|
35
|
+
const fk = new FkColumn(entityTablePk, propertyTable);
|
|
36
|
+
const expectedFkName = `${fk.table.name}_${fk.name}_fkey`;
|
|
37
|
+
|
|
38
|
+
// Act & Assert
|
|
39
|
+
expect(fk.buildExpression()).toBe(input.expectedExpression);
|
|
40
|
+
expect(fk.fkName).toBe(expectedFkName);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseSmartTags,
|
|
3
|
+
PgColumn,
|
|
4
|
+
PgFkColumn,
|
|
5
|
+
PgTable,
|
|
6
|
+
PgType,
|
|
7
|
+
} from '../../abstractions';
|
|
8
|
+
import { buildName } from '../pg-sql-gen-utils';
|
|
9
|
+
|
|
10
|
+
export class FkColumn implements PgFkColumn {
|
|
11
|
+
name: string;
|
|
12
|
+
readonly table: PgTable;
|
|
13
|
+
readonly type: PgType;
|
|
14
|
+
readonly referencedPk: PgColumn;
|
|
15
|
+
readonly targetPk: PgColumn;
|
|
16
|
+
readonly fkName: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Constructor for FkColumn.
|
|
20
|
+
* @param targetPk - PK to the 'target' table.
|
|
21
|
+
* @param table - Reference to the parent table.
|
|
22
|
+
*/
|
|
23
|
+
constructor(targetPk: PgColumn, table: PgTable) {
|
|
24
|
+
this.targetPk = targetPk;
|
|
25
|
+
this.name = buildName(targetPk.table.name, targetPk.name);
|
|
26
|
+
this.table = table;
|
|
27
|
+
this.fkName = buildName(table.name, this.name, 'fkey');
|
|
28
|
+
this.type = targetPk.type;
|
|
29
|
+
this.referencedPk = targetPk;
|
|
30
|
+
}
|
|
31
|
+
buildSmartTags(): BaseSmartTags {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
buildExpression(): string {
|
|
36
|
+
return `${this.name} ${this.type} REFERENCES ${this.referencedPk.table.name} ON DELETE CASCADE`;
|
|
37
|
+
}
|
|
38
|
+
buildAdditionalStatements(): string[] {
|
|
39
|
+
return [`CREATE INDEX ON ${this.table.buildFullName()} (${this.name})`];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PgTable, PgType } from '../../abstractions';
|
|
2
|
+
import { PkColumn } from './pk-column';
|
|
3
|
+
|
|
4
|
+
interface PkColumnTestInput {
|
|
5
|
+
type: PgType;
|
|
6
|
+
expectedExpression: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const dummyTable: PgTable = {} as PgTable;
|
|
10
|
+
|
|
11
|
+
const testData: [string, PkColumnTestInput][] = [
|
|
12
|
+
[
|
|
13
|
+
'PK with TEXT type',
|
|
14
|
+
{ type: 'TEXT', expectedExpression: 'id TEXT PRIMARY KEY' },
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
'PK with INTEGER type',
|
|
18
|
+
{
|
|
19
|
+
type: 'INTEGER',
|
|
20
|
+
expectedExpression:
|
|
21
|
+
'id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
describe('PkColumn', () => {
|
|
27
|
+
test.each(testData)('%s', (description: string, input: PkColumnTestInput) => {
|
|
28
|
+
// Arrange
|
|
29
|
+
const pkColumn = new PkColumn(dummyTable, input.type);
|
|
30
|
+
|
|
31
|
+
// Act & Assert
|
|
32
|
+
expect(pkColumn.buildExpression()).toBe(input.expectedExpression);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('PK column with unsupported type throws', () => {
|
|
36
|
+
// Arrange
|
|
37
|
+
const unsupportedType: PgType = 'BOOLEAN';
|
|
38
|
+
|
|
39
|
+
// Act
|
|
40
|
+
const action = (): void => {
|
|
41
|
+
new PkColumn(dummyTable, unsupportedType);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Assert
|
|
45
|
+
expect(action).toThrow(TypeError);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseSmartTags, PgColumn, PgTable, PgType } from '../../abstractions';
|
|
2
|
+
|
|
3
|
+
export class PkColumn implements PgColumn {
|
|
4
|
+
name: string;
|
|
5
|
+
readonly table: PgTable;
|
|
6
|
+
readonly type: PgType;
|
|
7
|
+
|
|
8
|
+
constructor(table: PgTable, type: PgType) {
|
|
9
|
+
if (type !== 'INTEGER' && type !== 'TEXT') {
|
|
10
|
+
throw new TypeError(`Type ${type} not supported as primary key.`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this.name = 'id';
|
|
14
|
+
this.table = table;
|
|
15
|
+
this.type = type;
|
|
16
|
+
}
|
|
17
|
+
buildSmartTags(): BaseSmartTags {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
buildAdditionalStatements(): string[] {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
buildExpression(): string {
|
|
26
|
+
let sql = `${this.name} ${this.type} PRIMARY KEY`;
|
|
27
|
+
|
|
28
|
+
if (this.type === 'INTEGER') {
|
|
29
|
+
sql = `${sql} GENERATED BY DEFAULT AS IDENTITY`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return sql;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { PgTable } from '../../abstractions';
|
|
2
|
+
import { PrimitiveColumn } from './primitive-column';
|
|
3
|
+
|
|
4
|
+
const dummyTable: PgTable = {
|
|
5
|
+
name: 'some_table',
|
|
6
|
+
buildFullName: () => 'schema.some_table',
|
|
7
|
+
} as PgTable;
|
|
8
|
+
|
|
9
|
+
describe('PrimitiveColumn', () => {
|
|
10
|
+
test('Default constructor', () => {
|
|
11
|
+
// Arrange & Act
|
|
12
|
+
const column = new PrimitiveColumn('some_column', 'TEXT', dummyTable);
|
|
13
|
+
|
|
14
|
+
// Assert
|
|
15
|
+
expect(column.buildExpression()).toBe('some_column TEXT');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('Options with extraParams', () => {
|
|
19
|
+
// Arrange & Act
|
|
20
|
+
const column = new PrimitiveColumn('some_column', 'TEXT', dummyTable, {
|
|
21
|
+
extraParams: 'NOT NULL',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Assert
|
|
25
|
+
expect(column.buildExpression()).toBe('some_column TEXT NOT NULL');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('Options with indexable', () => {
|
|
29
|
+
// Arrange & Act
|
|
30
|
+
const column = new PrimitiveColumn('some_column', 'TEXT', dummyTable, {
|
|
31
|
+
indexable: true,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Assert
|
|
35
|
+
expect(column.buildAdditionalStatements()).toEqual([
|
|
36
|
+
'CREATE INDEX ON schema.some_table (some_column)',
|
|
37
|
+
]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('Options with description', () => {
|
|
41
|
+
// Arrange & Act
|
|
42
|
+
const column = new PrimitiveColumn('some_column', 'TEXT', dummyTable, {
|
|
43
|
+
description: 'some description',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Assert
|
|
47
|
+
expect(column.buildSmartTags()).toEqual({
|
|
48
|
+
description: 'some description',
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('Setting a display name', () => {
|
|
53
|
+
// Arrange
|
|
54
|
+
const column = new PrimitiveColumn('some_column', 'TEXT', dummyTable);
|
|
55
|
+
|
|
56
|
+
// Act
|
|
57
|
+
column.displayName = 'column';
|
|
58
|
+
|
|
59
|
+
// Assert
|
|
60
|
+
expect(column.buildSmartTags()).toEqual({
|
|
61
|
+
description: undefined,
|
|
62
|
+
tags: { name: 'column' },
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { BaseSmartTags, PgColumn, PgTable, PgType } from '../../abstractions';
|
|
2
|
+
|
|
3
|
+
export interface PrimitiveColumnOptions {
|
|
4
|
+
description?: string;
|
|
5
|
+
indexable?: boolean;
|
|
6
|
+
extraParams?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Database column of primitive type.
|
|
11
|
+
*/
|
|
12
|
+
export class PrimitiveColumn implements PgColumn {
|
|
13
|
+
name: string;
|
|
14
|
+
displayName?: string;
|
|
15
|
+
readonly description?: string;
|
|
16
|
+
readonly table: PgTable;
|
|
17
|
+
readonly type: PgType;
|
|
18
|
+
private columnOptions?: PrimitiveColumnOptions;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
name: string,
|
|
22
|
+
type: PgType,
|
|
23
|
+
table: PgTable,
|
|
24
|
+
options?: PrimitiveColumnOptions,
|
|
25
|
+
) {
|
|
26
|
+
this.name = name;
|
|
27
|
+
this.description = options?.description;
|
|
28
|
+
this.table = table;
|
|
29
|
+
this.type = type;
|
|
30
|
+
this.columnOptions = options;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
buildExpression(): string {
|
|
34
|
+
const baseExpression = `${this.name} ${this.type}`;
|
|
35
|
+
if (this.columnOptions?.extraParams) {
|
|
36
|
+
return `${baseExpression} ${this.columnOptions.extraParams}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return baseExpression;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
buildAdditionalStatements(): string[] {
|
|
43
|
+
if (this.columnOptions?.indexable) {
|
|
44
|
+
return [`CREATE INDEX ON ${this.table.buildFullName()} (${this.name})`];
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
buildSmartTags(): BaseSmartTags {
|
|
50
|
+
const tags: BaseSmartTags = {
|
|
51
|
+
description: this.description,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (this.displayName) {
|
|
55
|
+
tags.tags = {
|
|
56
|
+
name: this.displayName,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return tags;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PgColumn, PgTable } from '../../abstractions';
|
|
2
|
+
import { VirtualFkColumn } from './virtual-fk-column';
|
|
3
|
+
|
|
4
|
+
describe('VirtualFkColumn', () => {
|
|
5
|
+
test('Virtual FK is created with correct references', () => {
|
|
6
|
+
// Arrange & Act
|
|
7
|
+
const entityTablePk: PgColumn = {
|
|
8
|
+
name: 'id',
|
|
9
|
+
type: 'TEXT',
|
|
10
|
+
table: { name: 'entity' } as PgTable,
|
|
11
|
+
} as PgColumn;
|
|
12
|
+
const relationsTable: PgTable = {
|
|
13
|
+
name: 'entity_relation',
|
|
14
|
+
buildFullName: () => 'schema.entity_relation',
|
|
15
|
+
} as PgTable;
|
|
16
|
+
const virtualFkColumn = new VirtualFkColumn(entityTablePk, relationsTable);
|
|
17
|
+
|
|
18
|
+
// Assert
|
|
19
|
+
expect(virtualFkColumn.buildExpression()).toBe('entity_id TEXT');
|
|
20
|
+
expect(virtualFkColumn.buildAdditionalStatements()).toEqual([
|
|
21
|
+
'CREATE INDEX ON schema.entity_relation (entity_id)',
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseSmartTags,
|
|
3
|
+
PgColumn,
|
|
4
|
+
PgFkColumn,
|
|
5
|
+
PgTable,
|
|
6
|
+
PgType,
|
|
7
|
+
} from '../../abstractions';
|
|
8
|
+
import { buildName } from '../pg-sql-gen-utils';
|
|
9
|
+
|
|
10
|
+
export class VirtualFkColumn implements PgFkColumn {
|
|
11
|
+
name: string;
|
|
12
|
+
readonly table: PgTable;
|
|
13
|
+
readonly type: PgType;
|
|
14
|
+
readonly additionalStatements: string[] = [];
|
|
15
|
+
readonly targetPk: PgColumn;
|
|
16
|
+
|
|
17
|
+
constructor(targetPk: PgColumn, table: PgTable) {
|
|
18
|
+
this.targetPk = targetPk;
|
|
19
|
+
this.name = buildName(targetPk.table.name, targetPk.name);
|
|
20
|
+
// Right now we just assume that all content types have the same PK type.
|
|
21
|
+
this.type = targetPk.type;
|
|
22
|
+
this.table = table;
|
|
23
|
+
}
|
|
24
|
+
buildSmartTags(): BaseSmartTags {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
buildExpression(): string {
|
|
28
|
+
return `${this.name} ${this.type}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
buildAdditionalStatements(): string[] {
|
|
32
|
+
return [`CREATE INDEX ON ${this.table.buildFullName()} (${this.name})`];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { JSONSchema4 } from 'json-schema';
|
|
2
|
+
import { PgType } from '../abstractions';
|
|
3
|
+
import { getPropertySchema, mapToPgType } from './json-schema-parse-utils';
|
|
4
|
+
|
|
5
|
+
describe('mapToPgType', () => {
|
|
6
|
+
interface TestInput {
|
|
7
|
+
schemaJson: string;
|
|
8
|
+
expectedPgType: PgType;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// I wish there was a better way - https://github.com/facebook/jest/issues/6413
|
|
12
|
+
const testData: [string, TestInput][] = [
|
|
13
|
+
[
|
|
14
|
+
'parse integer',
|
|
15
|
+
{
|
|
16
|
+
schemaJson: `
|
|
17
|
+
{
|
|
18
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
19
|
+
"properties": {
|
|
20
|
+
"prop":{
|
|
21
|
+
"type": "integer"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`,
|
|
26
|
+
expectedPgType: 'INTEGER',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
'parse integer array',
|
|
31
|
+
{
|
|
32
|
+
schemaJson: `
|
|
33
|
+
{
|
|
34
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
35
|
+
"properties": {
|
|
36
|
+
"prop": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"type": "integer"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`,
|
|
45
|
+
expectedPgType: 'INTEGER[]',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
'parse string',
|
|
50
|
+
{
|
|
51
|
+
schemaJson: `
|
|
52
|
+
{
|
|
53
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
54
|
+
"properties": {
|
|
55
|
+
"prop": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
expectedPgType: 'TEXT',
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
'parse string array',
|
|
66
|
+
{
|
|
67
|
+
schemaJson: `
|
|
68
|
+
{
|
|
69
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
70
|
+
"properties": {
|
|
71
|
+
"prop": {
|
|
72
|
+
"type": "array",
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "string"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
`,
|
|
80
|
+
expectedPgType: 'TEXT[]',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
'parse boolean',
|
|
85
|
+
{
|
|
86
|
+
schemaJson: `
|
|
87
|
+
{
|
|
88
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
89
|
+
"properties": {
|
|
90
|
+
"prop": {
|
|
91
|
+
"type": "boolean"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
expectedPgType: 'BOOLEAN',
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
'parse date',
|
|
101
|
+
{
|
|
102
|
+
schemaJson: `
|
|
103
|
+
{
|
|
104
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
105
|
+
"properties": {
|
|
106
|
+
"prop": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"format": "date-time"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
expectedPgType: 'TIMESTAMPTZ',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
test.each(testData)('%s', (description: string, input: TestInput) => {
|
|
119
|
+
// Arrange
|
|
120
|
+
const schema = JSON.parse(input.schemaJson) as JSONSchema4;
|
|
121
|
+
|
|
122
|
+
// Act
|
|
123
|
+
const pgType = mapToPgType(getPropertySchema(schema, 'prop'));
|
|
124
|
+
|
|
125
|
+
// Assert
|
|
126
|
+
expect(pgType).toBe(input.expectedPgType);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('getPropertySchema', () => {
|
|
131
|
+
test('Returns existing property', () => {
|
|
132
|
+
// Arrange
|
|
133
|
+
const schema = JSON.parse(`
|
|
134
|
+
{
|
|
135
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
136
|
+
"properties": {
|
|
137
|
+
"prop":{
|
|
138
|
+
"type": "integer"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}`) as JSONSchema4;
|
|
142
|
+
|
|
143
|
+
// Act
|
|
144
|
+
const propertySchema = getPropertySchema(schema, 'prop');
|
|
145
|
+
|
|
146
|
+
// Assert
|
|
147
|
+
expect(propertySchema).toBeDefined();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('Throws if properties are not defined', () => {
|
|
151
|
+
// Arrange
|
|
152
|
+
const schema = JSON.parse(`
|
|
153
|
+
{
|
|
154
|
+
"$schema": "http://json-schema.org/draft-04/schema"
|
|
155
|
+
}`) as JSONSchema4;
|
|
156
|
+
|
|
157
|
+
// Act
|
|
158
|
+
const action = () => getPropertySchema(schema, 'prop');
|
|
159
|
+
|
|
160
|
+
// Assert
|
|
161
|
+
expect(action).toThrow(Error);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test('Returns undefined if property does not exist', () => {
|
|
165
|
+
// Arrange
|
|
166
|
+
const schema = JSON.parse(`
|
|
167
|
+
{
|
|
168
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
169
|
+
"properties": {
|
|
170
|
+
"prop":{
|
|
171
|
+
"type": "integer"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}`) as JSONSchema4;
|
|
175
|
+
|
|
176
|
+
// Act
|
|
177
|
+
const propertySchema = getPropertySchema(schema, 'does_not_exist');
|
|
178
|
+
|
|
179
|
+
// Assert
|
|
180
|
+
expect(propertySchema).toBeUndefined();
|
|
181
|
+
});
|
|
182
|
+
});
|