@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 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.sqlType === 'json') {
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
- required
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.31.1",
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.31.1"
21
+ "@platformatic/sql-mapper": "0.33.0"
22
22
  },
23
23
  "dependencies": {
24
24
  "code-block-writer": "^12.0.0",
@@ -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
+ })