@platformatic/sql-json-schema-mapper 0.31.1 → 0.33.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/index.js +18 -6
- package/package.json +2 -2
- package/test/simple.test.js +81 -1
package/index.js
CHANGED
|
@@ -60,7 +60,7 @@ function mapSQLTypeToOpenAPIType (sqlType) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function mapSQLEntityToJSONSchema (entity, ignore = {}) {
|
|
63
|
+
function mapSQLEntityToJSONSchema (entity, ignore = {}, noRequired = false) {
|
|
64
64
|
const fields = entity.fields
|
|
65
65
|
const properties = {}
|
|
66
66
|
const required = []
|
|
@@ -70,8 +70,16 @@ function mapSQLEntityToJSONSchema (entity, ignore = {}) {
|
|
|
70
70
|
continue
|
|
71
71
|
}
|
|
72
72
|
const type = mapSQLTypeToOpenAPIType(field.sqlType)
|
|
73
|
+
|
|
73
74
|
/* istanbul ignore next */
|
|
74
|
-
if (field.
|
|
75
|
+
if (field.isArray) {
|
|
76
|
+
properties[field.camelcase] = {
|
|
77
|
+
type: 'array',
|
|
78
|
+
items: {
|
|
79
|
+
type
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else if (field.sqlType === 'json') {
|
|
75
83
|
properties[field.camelcase] = {
|
|
76
84
|
type: 'object',
|
|
77
85
|
additionalProperties: true
|
|
@@ -79,10 +87,10 @@ function mapSQLEntityToJSONSchema (entity, ignore = {}) {
|
|
|
79
87
|
} else {
|
|
80
88
|
properties[field.camelcase] = { type }
|
|
81
89
|
}
|
|
82
|
-
if (field.isNullable) {
|
|
90
|
+
if (field.isNullable || noRequired || field.autoTimestamp) {
|
|
83
91
|
properties[field.camelcase].nullable = true
|
|
84
92
|
}
|
|
85
|
-
if (!field.isNullable && !field.primaryKey) {
|
|
93
|
+
if (!field.isNullable && !field.primaryKey && !noRequired && !field.autoTimestamp) {
|
|
86
94
|
// we skip the primary key for creation
|
|
87
95
|
required.push(field.camelcase)
|
|
88
96
|
}
|
|
@@ -94,13 +102,17 @@ function mapSQLEntityToJSONSchema (entity, ignore = {}) {
|
|
|
94
102
|
properties[field.camelcase].enum = field.enum
|
|
95
103
|
}
|
|
96
104
|
}
|
|
105
|
+
|
|
97
106
|
const res = {
|
|
98
107
|
$id: entity.name,
|
|
99
108
|
title: entity.name,
|
|
100
109
|
description: `A ${entity.name}`,
|
|
101
110
|
type: 'object',
|
|
102
|
-
properties
|
|
103
|
-
|
|
111
|
+
properties
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (required.length > 0) {
|
|
115
|
+
res.required = required.sort()
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
return res
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/sql-json-schema-mapper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "Map SQL entity to JSON schema",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"snazzy": "^9.0.0",
|
|
19
19
|
"standard": "^17.1.0",
|
|
20
20
|
"tap": "^16.3.6",
|
|
21
|
-
"@platformatic/sql-mapper": "0.
|
|
21
|
+
"@platformatic/sql-mapper": "0.33.0"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"code-block-writer": "^12.0.0",
|
package/test/simple.test.js
CHANGED
|
@@ -14,6 +14,7 @@ async function createBasicPages (db, sql) {
|
|
|
14
14
|
title VARCHAR(42) NOT NULL,
|
|
15
15
|
metadata JSON,
|
|
16
16
|
section NUMERIC,
|
|
17
|
+
created_at TIMESTAMP NOT NULL,
|
|
17
18
|
description TEXT
|
|
18
19
|
);`)
|
|
19
20
|
} else if (isPg) {
|
|
@@ -24,6 +25,7 @@ async function createBasicPages (db, sql) {
|
|
|
24
25
|
metadata JSON,
|
|
25
26
|
section NUMERIC,
|
|
26
27
|
description TEXT,
|
|
28
|
+
created_at TIMESTAMP NOT NULL,
|
|
27
29
|
type pagetype
|
|
28
30
|
);`)
|
|
29
31
|
} else {
|
|
@@ -33,6 +35,7 @@ async function createBasicPages (db, sql) {
|
|
|
33
35
|
metadata JSON,
|
|
34
36
|
section NUMERIC,
|
|
35
37
|
description TEXT,
|
|
38
|
+
created_at TIMESTAMP NOT NULL,
|
|
36
39
|
type ENUM ('blank', 'non-blank')
|
|
37
40
|
);`)
|
|
38
41
|
}
|
|
@@ -104,6 +107,47 @@ test('simple db, simple rest API', async (t) => {
|
|
|
104
107
|
}
|
|
105
108
|
})
|
|
106
109
|
|
|
110
|
+
test('noRequired = true', async (t) => {
|
|
111
|
+
const { pass, teardown } = t
|
|
112
|
+
|
|
113
|
+
const app = fastify()
|
|
114
|
+
app.register(sqlMapper, {
|
|
115
|
+
...connInfo,
|
|
116
|
+
async onDatabaseLoad (db, sql) {
|
|
117
|
+
pass('onDatabaseLoad called')
|
|
118
|
+
|
|
119
|
+
await clear(db, sql)
|
|
120
|
+
await createBasicPages(db, sql)
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
teardown(app.close.bind(app))
|
|
124
|
+
|
|
125
|
+
await app.ready()
|
|
126
|
+
|
|
127
|
+
{
|
|
128
|
+
const page = app.platformatic.entities.page
|
|
129
|
+
const pageJsonSchema = mapSQLEntityToJSONSchema(page, {}, true)
|
|
130
|
+
|
|
131
|
+
t.equal(pageJsonSchema.$id, 'Page')
|
|
132
|
+
t.equal(pageJsonSchema.title, 'Page')
|
|
133
|
+
t.equal(pageJsonSchema.description, 'A Page')
|
|
134
|
+
t.equal(pageJsonSchema.type, 'object')
|
|
135
|
+
t.same(pageJsonSchema.properties.id, { type: 'integer', nullable: true })
|
|
136
|
+
t.same(pageJsonSchema.properties.title, { type: 'string', nullable: true })
|
|
137
|
+
t.same(pageJsonSchema.properties.description, { type: 'string', nullable: true })
|
|
138
|
+
t.same(pageJsonSchema.properties.section, { type: 'string', nullable: true })
|
|
139
|
+
if (isMariaDB) {
|
|
140
|
+
t.same(pageJsonSchema.properties.metadata, { type: 'string', nullable: true })
|
|
141
|
+
} else {
|
|
142
|
+
t.same(pageJsonSchema.properties.metadata, { type: 'object', additionalProperties: true, nullable: true })
|
|
143
|
+
}
|
|
144
|
+
t.equal(pageJsonSchema.required, undefined)
|
|
145
|
+
if (!isSQLite) {
|
|
146
|
+
t.same(pageJsonSchema.properties.type, { type: 'string', nullable: true, enum: ['blank', 'non-blank'] })
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
|
|
107
151
|
test('ignore one field', async (t) => {
|
|
108
152
|
const { pass, teardown } = t
|
|
109
153
|
|
|
@@ -139,7 +183,7 @@ test('ignore one field', async (t) => {
|
|
|
139
183
|
} else {
|
|
140
184
|
t.same(pageJsonSchema.properties.metadata, { type: 'object', additionalProperties: true, nullable: true })
|
|
141
185
|
}
|
|
142
|
-
t.same(pageJsonSchema.required,
|
|
186
|
+
t.same(pageJsonSchema.required, undefined)
|
|
143
187
|
if (!isSQLite) {
|
|
144
188
|
t.same(pageJsonSchema.properties.type, { type: 'string', nullable: true, enum: ['blank', 'non-blank'] })
|
|
145
189
|
}
|
|
@@ -176,3 +220,39 @@ test('stored and virtual generated columns should be read only', async (t) => {
|
|
|
176
220
|
}
|
|
177
221
|
}
|
|
178
222
|
})
|
|
223
|
+
|
|
224
|
+
test('PG Arrays', { skip: !isPg }, async (t) => {
|
|
225
|
+
const { pass, teardown } = t
|
|
226
|
+
|
|
227
|
+
const app = fastify()
|
|
228
|
+
app.register(sqlMapper, {
|
|
229
|
+
...connInfo,
|
|
230
|
+
async onDatabaseLoad (db, sql) {
|
|
231
|
+
pass('onDatabaseLoad called')
|
|
232
|
+
|
|
233
|
+
await clear(db, sql)
|
|
234
|
+
await db.query(sql`CREATE TABLE pages (
|
|
235
|
+
id SERIAL PRIMARY KEY,
|
|
236
|
+
title VARCHAR(42) NOT NULL,
|
|
237
|
+
tags VARCHAR(42)[] NOT NULL
|
|
238
|
+
);`)
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
teardown(app.close.bind(app))
|
|
242
|
+
|
|
243
|
+
await app.ready()
|
|
244
|
+
|
|
245
|
+
{
|
|
246
|
+
const page = app.platformatic.entities.page
|
|
247
|
+
const pageJsonSchema = mapSQLEntityToJSONSchema(page)
|
|
248
|
+
|
|
249
|
+
t.equal(pageJsonSchema.$id, 'Page')
|
|
250
|
+
t.equal(pageJsonSchema.title, 'Page')
|
|
251
|
+
t.equal(pageJsonSchema.description, 'A Page')
|
|
252
|
+
t.equal(pageJsonSchema.type, 'object')
|
|
253
|
+
t.same(pageJsonSchema.properties.id, { type: 'integer' })
|
|
254
|
+
t.same(pageJsonSchema.properties.title, { type: 'string' })
|
|
255
|
+
t.same(pageJsonSchema.properties.tags, { type: 'array', items: { type: 'string' } })
|
|
256
|
+
t.same(pageJsonSchema.required, ['tags', 'title'])
|
|
257
|
+
}
|
|
258
|
+
})
|