@platformatic/sql-json-schema-mapper 0.46.1 → 0.47.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/sql-json-schema-mapper",
3
- "version": "0.46.1",
3
+ "version": "0.47.0",
4
4
  "description": "Map SQL entity to JSON schema",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -19,7 +19,7 @@
19
19
  "snazzy": "^9.0.0",
20
20
  "standard": "^17.1.0",
21
21
  "tap": "^16.3.6",
22
- "@platformatic/sql-mapper": "0.46.1"
22
+ "@platformatic/sql-mapper": "0.47.0"
23
23
  },
24
24
  "dependencies": {
25
25
  "code-block-writer": "^12.0.0",
package/test/helper.js DELETED
@@ -1,82 +0,0 @@
1
- 'use strict'
2
-
3
- // Needed to work with dates & postgresql
4
- // See https://node-postgres.com/features/types/
5
- process.env.TZ = 'UTC'
6
-
7
- const connInfo = {}
8
-
9
- if (!process.env.DB || process.env.DB === 'postgresql') {
10
- connInfo.connectionString = 'postgres://postgres:postgres@127.0.0.1/postgres'
11
- module.exports.isPg = true
12
- } else if (process.env.DB === 'mariadb') {
13
- connInfo.connectionString = 'mysql://root@127.0.0.1:3307/graph'
14
- connInfo.poolSize = 10
15
- module.exports.isMysql = true
16
- module.exports.isMariaDB = true
17
- } else if (process.env.DB === 'mysql') {
18
- connInfo.connectionString = 'mysql://root@127.0.0.1/graph'
19
- connInfo.poolSize = 10
20
- module.exports.isMysql = true
21
- } else if (process.env.DB === 'mysql8') {
22
- connInfo.connectionString = 'mysql://root@127.0.0.1:3308/graph'
23
- connInfo.poolSize = 10
24
- module.exports.isMysql = true
25
- } else if (process.env.DB === 'sqlite') {
26
- connInfo.connectionString = 'sqlite://:memory:'
27
- module.exports.isSQLite = true
28
- }
29
-
30
- module.exports.connInfo = connInfo
31
-
32
- module.exports.clear = async function (db, sql) {
33
- try {
34
- await db.query(sql`DROP TABLE pages`)
35
- } catch (err) {
36
- }
37
-
38
- try {
39
- await db.query(sql`DROP TABLE categories`)
40
- } catch {
41
- }
42
-
43
- try {
44
- await db.query(sql`DROP TABLE posts`)
45
- } catch {
46
- }
47
-
48
- try {
49
- await db.query(sql`DROP TABLE simple_types`)
50
- } catch {
51
- }
52
-
53
- try {
54
- await db.query(sql`DROP TABLE owners`)
55
- } catch {
56
- }
57
-
58
- try {
59
- await db.query(sql`DROP TABLE users`)
60
- } catch {
61
- }
62
-
63
- try {
64
- await db.query(sql`DROP TABLE versions`)
65
- } catch {
66
- }
67
-
68
- try {
69
- await db.query(sql`DROP TABLE graphs`)
70
- } catch {
71
- }
72
-
73
- try {
74
- await db.query(sql`DROP Type pagetype`)
75
- } catch {
76
- }
77
-
78
- try {
79
- await db.query(sql`DROP TABLE generated_test`)
80
- } catch {
81
- }
82
- }
@@ -1,258 +0,0 @@
1
- 'use strict'
2
-
3
- const t = require('tap')
4
- const sqlMapper = require('@platformatic/sql-mapper')
5
- const fastify = require('fastify')
6
- const { clear, connInfo, isSQLite, isMariaDB, isPg } = require('./helper')
7
- const { mapSQLEntityToJSONSchema } = require('..')
8
- const { test } = t
9
-
10
- async function createBasicPages (db, sql) {
11
- if (isSQLite) {
12
- await db.query(sql`CREATE TABLE pages (
13
- id INTEGER PRIMARY KEY,
14
- title VARCHAR(42) NOT NULL,
15
- metadata JSON,
16
- section NUMERIC,
17
- created_at TIMESTAMP NOT NULL,
18
- description TEXT
19
- );`)
20
- } else if (isPg) {
21
- await db.query(sql`CREATE TYPE pagetype as enum ('blank', 'non-blank');
22
- CREATE TABLE pages (
23
- id SERIAL PRIMARY KEY,
24
- title VARCHAR(42) NOT NULL,
25
- metadata JSON,
26
- section NUMERIC,
27
- description TEXT,
28
- created_at TIMESTAMP NOT NULL,
29
- type pagetype
30
- );`)
31
- } else {
32
- await db.query(sql`CREATE TABLE pages (
33
- id INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY,
34
- title VARCHAR(42) NOT NULL,
35
- metadata JSON,
36
- section NUMERIC,
37
- description TEXT,
38
- created_at TIMESTAMP NOT NULL,
39
- type ENUM ('blank', 'non-blank')
40
- );`)
41
- }
42
- }
43
-
44
- async function createBasicGeneratedTests (db, sql) {
45
- if (isSQLite) {
46
- await db.query(sql`CREATE TABLE generated_test (
47
- id INTEGER PRIMARY KEY,
48
- test INTEGER,
49
- test_stored INTEGER GENERATED ALWAYS AS (test*2) STORED,
50
- test_virtual INTEGER GENERATED ALWAYS AS (test*4) VIRTUAL
51
- );`)
52
- } else if (isPg) {
53
- await db.query(sql`CREATE TABLE generated_test (
54
- id SERIAL PRIMARY KEY,
55
- test INTEGER,
56
- test_stored INTEGER GENERATED ALWAYS AS (test*2) STORED
57
- );`)
58
- } else {
59
- await db.query(sql`CREATE TABLE generated_test (
60
- id INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY,
61
- test INTEGER,
62
- test_stored INTEGER GENERATED ALWAYS AS (test*2) STORED,
63
- test_virtual INTEGER GENERATED ALWAYS AS (test*4) VIRTUAL
64
- );`)
65
- await db.query(sql`INSERT INTO generated_test (test) VALUES(1);`)
66
- }
67
- }
68
-
69
- test('simple db, simple rest API', async (t) => {
70
- const { pass, teardown } = t
71
-
72
- const app = fastify()
73
- app.register(sqlMapper, {
74
- ...connInfo,
75
- async onDatabaseLoad (db, sql) {
76
- pass('onDatabaseLoad called')
77
-
78
- await clear(db, sql)
79
- await createBasicPages(db, sql)
80
- }
81
- })
82
- teardown(app.close.bind(app))
83
-
84
- await app.ready()
85
-
86
- {
87
- const page = app.platformatic.entities.page
88
- const pageJsonSchema = mapSQLEntityToJSONSchema(page)
89
-
90
- t.equal(pageJsonSchema.$id, 'Page')
91
- t.equal(pageJsonSchema.title, 'Page')
92
- t.equal(pageJsonSchema.description, 'A Page')
93
- t.equal(pageJsonSchema.type, 'object')
94
- t.same(pageJsonSchema.properties.id, { type: 'integer' })
95
- t.same(pageJsonSchema.properties.title, { type: 'string' })
96
- t.same(pageJsonSchema.properties.description, { type: 'string', nullable: true })
97
- t.same(pageJsonSchema.properties.section, { type: 'string', nullable: true })
98
- if (isMariaDB) {
99
- t.same(pageJsonSchema.properties.metadata, { type: 'string', nullable: true })
100
- } else {
101
- t.same(pageJsonSchema.properties.metadata, { type: 'object', additionalProperties: true, nullable: true })
102
- }
103
- t.same(pageJsonSchema.required, ['title'])
104
- if (!isSQLite) {
105
- t.same(pageJsonSchema.properties.type, { type: 'string', nullable: true, enum: ['blank', 'non-blank'] })
106
- }
107
- }
108
- })
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
-
151
- test('ignore one field', async (t) => {
152
- const { pass, teardown } = t
153
-
154
- const app = fastify()
155
- app.register(sqlMapper, {
156
- ...connInfo,
157
- async onDatabaseLoad (db, sql) {
158
- pass('onDatabaseLoad called')
159
-
160
- await clear(db, sql)
161
- await createBasicPages(db, sql)
162
- }
163
- })
164
- teardown(app.close.bind(app))
165
-
166
- await app.ready()
167
-
168
- {
169
- const page = app.platformatic.entities.page
170
- const pageJsonSchema = mapSQLEntityToJSONSchema(page, {
171
- title: true
172
- })
173
-
174
- t.equal(pageJsonSchema.$id, 'Page')
175
- t.equal(pageJsonSchema.title, 'Page')
176
- t.equal(pageJsonSchema.description, 'A Page')
177
- t.equal(pageJsonSchema.type, 'object')
178
- t.same(pageJsonSchema.properties.id, { type: 'integer' })
179
- t.equal(pageJsonSchema.properties.title, undefined)
180
- t.same(pageJsonSchema.properties.description, { type: 'string', nullable: true })
181
- if (isMariaDB) {
182
- t.same(pageJsonSchema.properties.metadata, { type: 'string', nullable: true })
183
- } else {
184
- t.same(pageJsonSchema.properties.metadata, { type: 'object', additionalProperties: true, nullable: true })
185
- }
186
- t.same(pageJsonSchema.required, undefined)
187
- if (!isSQLite) {
188
- t.same(pageJsonSchema.properties.type, { type: 'string', nullable: true, enum: ['blank', 'non-blank'] })
189
- }
190
- }
191
- })
192
-
193
- test('stored and virtual generated columns should be read only', async (t) => {
194
- const { pass, teardown } = t
195
-
196
- const app = fastify()
197
- app.register(sqlMapper, {
198
- ...connInfo,
199
- async onDatabaseLoad (db, sql) {
200
- pass('onDatabaseLoad called')
201
-
202
- await clear(db, sql)
203
- await createBasicGeneratedTests(db, sql)
204
- }
205
- })
206
- teardown(app.close.bind(app))
207
-
208
- await app.ready()
209
-
210
- {
211
- const generatedTest = app.platformatic.entities.generatedTest
212
- const generatedTestJsonSchema = mapSQLEntityToJSONSchema(generatedTest)
213
-
214
- // as of postgresql 15 virtual generated column is not supported
215
- if (isPg) {
216
- t.same(generatedTestJsonSchema.properties.testStored, { type: 'integer', nullable: true, readOnly: true })
217
- } else {
218
- t.same(generatedTestJsonSchema.properties.testStored, { type: 'integer', nullable: true, readOnly: true })
219
- t.same(generatedTestJsonSchema.properties.testVirtual, { type: 'integer', nullable: true, readOnly: true })
220
- }
221
- }
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
- })
@@ -1,211 +0,0 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const dtsgenerator = require('dtsgenerator')
5
- const { mapOpenAPItoTypes } = require('..')
6
-
7
- let structuredClone = globalThis.structuredClone
8
- if (structuredClone === undefined) {
9
- structuredClone = (obj) => JSON.parse(JSON.stringify(obj))
10
- }
11
-
12
- function referenceTest (name, obj, opts = {}) {
13
- const { only } = opts
14
- test(name, { only }, async t => {
15
- const reference = await dtsgenerator.default({ contents: [dtsgenerator.parseSchema(structuredClone(obj))] })
16
- const cloned = structuredClone(obj)
17
- const ours = mapOpenAPItoTypes(cloned, { id: { primaryKey: true } })
18
- t.not(cloned, obj)
19
- t.same(cloned, obj)
20
- t.same(ours.trim(), reference.trim())
21
- })
22
- }
23
-
24
- referenceTest('p1', {
25
- id: 'Page',
26
- title: 'Page',
27
- description: 'A Page',
28
- type: 'object',
29
- properties: {
30
- id: {
31
- type: 'integer'
32
- },
33
- description: {
34
- type: 'string',
35
- nullable: true
36
- },
37
- metadata: {
38
- type: 'object',
39
- additionalProperties: true,
40
- nullable: true
41
- },
42
- section: {
43
- type: 'number',
44
- nullable: true
45
- },
46
- title: {
47
- type: 'string'
48
- }
49
- },
50
- required: [
51
- 'title'
52
- ]
53
- })
54
-
55
- referenceTest('p2', {
56
- id: 'Page',
57
- title: 'Page',
58
- description: 'A Page',
59
- type: 'object',
60
- properties: {
61
- id: {
62
- type: 'integer'
63
- },
64
- description: {
65
- type: 'string',
66
- nullable: true
67
- },
68
- metadata: {
69
- type: 'object',
70
- additionalProperties: true,
71
- nullable: true
72
- },
73
- section: {
74
- type: 'number',
75
- nullable: true
76
- }
77
- },
78
- required: []
79
- })
80
-
81
- referenceTest('p3', {
82
- id: 'GeneratedTest',
83
- title: 'GeneratedTest',
84
- description: 'A GeneratedTest',
85
- type: 'object',
86
- properties: {
87
- id: {
88
- type: 'integer'
89
- },
90
- test: {
91
- type: 'integer',
92
- nullable: true
93
- },
94
- testStored: {
95
- type: 'integer',
96
- nullable: true,
97
- readOnly: true
98
- },
99
- testVirtual: {
100
- type: 'integer',
101
- nullable: true,
102
- readOnly: true
103
- }
104
- },
105
- required: []
106
- })
107
-
108
- referenceTest('multiple types', {
109
- id: 'Page',
110
- title: 'Page',
111
- description: 'A Page',
112
- type: 'object',
113
- properties: {
114
- id: {
115
- type: ['integer', 'string']
116
- },
117
- description: {
118
- type: 'string',
119
- nullable: true
120
- },
121
- metadata: {
122
- type: 'object',
123
- additionalProperties: true,
124
- nullable: true
125
- },
126
- section: {
127
- type: ['number', 'null']
128
- },
129
- title: {
130
- type: 'string'
131
- }
132
- },
133
- required: [
134
- 'title'
135
- ]
136
- })
137
-
138
- referenceTest('arrays', {
139
- id: 'Page',
140
- title: 'Page',
141
- description: 'A Page',
142
- type: 'object',
143
- properties: {
144
- id: {
145
- type: 'integer'
146
- },
147
- tags: {
148
- type: 'array',
149
- items: {
150
- type: 'string'
151
- }
152
- },
153
- title: {
154
- type: 'string'
155
- }
156
- },
157
- required: [
158
- 'title'
159
- ]
160
- })
161
-
162
- referenceTest('objects in arrays', {
163
- id: 'Page',
164
- title: 'Page',
165
- description: 'A Page',
166
- type: 'object',
167
- properties: {
168
- id: {
169
- type: 'integer'
170
- },
171
- tags: {
172
- type: 'array',
173
- items: {
174
- type: 'object',
175
- properties: {
176
- foo: {
177
- type: 'string'
178
- }
179
- }
180
- }
181
- },
182
- title: {
183
- type: 'string'
184
- }
185
- },
186
- required: [
187
- 'title'
188
- ]
189
- })
190
-
191
- referenceTest('enums', {
192
- id: 'Page',
193
- title: 'Page',
194
- description: 'A Page',
195
- type: 'object',
196
- properties: {
197
- id: {
198
- type: 'integer'
199
- },
200
- color: {
201
- type: 'string',
202
- enum: ['amber', 'green', 'red']
203
- },
204
- title: {
205
- type: 'string'
206
- }
207
- },
208
- required: [
209
- 'title'
210
- ]
211
- })