@liminalfunctions/framework 1.0.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/.mocharc.json +5 -0
- package/dist/F_Client_Collection_Registry.d.ts +18 -0
- package/dist/F_Client_Collection_Registry.js +36 -0
- package/dist/F_Client_Collection_Registry.js.map +1 -0
- package/dist/F_Collection.d.ts +21 -0
- package/dist/F_Collection.js +36 -0
- package/dist/F_Collection.js.map +1 -0
- package/dist/F_Collection_Registry.d.ts +11 -0
- package/dist/F_Collection_Registry.js +18 -0
- package/dist/F_Collection_Registry.js.map +1 -0
- package/dist/F_Compile.d.ts +4 -0
- package/dist/F_Compile.js +298 -0
- package/dist/F_Compile.js.map +1 -0
- package/dist/F_Security_Models/F_SM_Open_Access.d.ts +11 -0
- package/dist/F_Security_Models/F_SM_Open_Access.js +14 -0
- package/dist/F_Security_Models/F_SM_Open_Access.js.map +1 -0
- package/dist/F_Security_Models/F_SM_Ownership.d.ts +12 -0
- package/dist/F_Security_Models/F_SM_Ownership.js +46 -0
- package/dist/F_Security_Models/F_SM_Ownership.js.map +1 -0
- package/dist/F_Security_Models/F_SM_Role_Membership.d.ts +19 -0
- package/dist/F_Security_Models/F_SM_Role_Membership.js +73 -0
- package/dist/F_Security_Models/F_SM_Role_Membership.js.map +1 -0
- package/dist/F_Security_Models/F_Security_Model.d.ts +41 -0
- package/dist/F_Security_Models/F_Security_Model.js +29 -0
- package/dist/F_Security_Models/F_Security_Model.js.map +1 -0
- package/dist/code_generation/generate_client_library.d.ts +4 -0
- package/dist/code_generation/generate_client_library.js +158 -0
- package/dist/code_generation/generate_client_library.js.map +1 -0
- package/dist/code_generation/templates/.gitignore.mustache +383 -0
- package/dist/code_generation/templates/collection.mustache +106 -0
- package/dist/code_generation/templates/main.mustache +24 -0
- package/dist/code_generation/templates/package.json.mustache +18 -0
- package/dist/code_generation/templates/tsconfig.json.mustache +14 -0
- package/dist/code_generation/templates/types.mustache +4 -0
- package/dist/code_generation/templates/utils.ts.mustache +17 -0
- package/dist/code_generation/utils/tab_indent.d.ts +1 -0
- package/dist/code_generation/utils/tab_indent.js +4 -0
- package/dist/code_generation/utils/tab_indent.js.map +1 -0
- package/dist/code_generation/utils/type_from_zod.d.ts +2 -0
- package/dist/code_generation/utils/type_from_zod.js +102 -0
- package/dist/code_generation/utils/type_from_zod.js.map +1 -0
- package/dist/utils/cache.d.ts +13 -0
- package/dist/utils/cache.js +101 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/mongoose_from_zod.d.ts +13 -0
- package/dist/utils/mongoose_from_zod.js +164 -0
- package/dist/utils/mongoose_from_zod.js.map +1 -0
- package/dist/utils/pretty_print_zod.d.ts +2 -0
- package/dist/utils/pretty_print_zod.js +63 -0
- package/dist/utils/pretty_print_zod.js.map +1 -0
- package/dist/utils/query_object_to_mongodb_query.d.ts +3 -0
- package/dist/utils/query_object_to_mongodb_query.js +61 -0
- package/dist/utils/query_object_to_mongodb_query.js.map +1 -0
- package/dist/utils/query_validator_from_zod.d.ts +6 -0
- package/dist/utils/query_validator_from_zod.js +216 -0
- package/dist/utils/query_validator_from_zod.js.map +1 -0
- package/package.json +36 -0
- package/src/F_Collection.ts +50 -0
- package/src/F_Collection_Registry.ts +29 -0
- package/src/F_Compile.ts +368 -0
- package/src/F_Security_Models/F_SM_Open_Access.ts +21 -0
- package/src/F_Security_Models/F_SM_Ownership.ts +72 -0
- package/src/F_Security_Models/F_SM_Role_Membership.ts +87 -0
- package/src/F_Security_Models/F_Security_Model.ts +85 -0
- package/src/code_generation/generate_client_library.ts +197 -0
- package/src/code_generation/templates/.gitignore.mustache +383 -0
- package/src/code_generation/templates/collection.mustache +106 -0
- package/src/code_generation/templates/main.mustache +24 -0
- package/src/code_generation/templates/package.json.mustache +18 -0
- package/src/code_generation/templates/tsconfig.json.mustache +14 -0
- package/src/code_generation/templates/types.mustache +4 -0
- package/src/code_generation/templates/utils.ts.mustache +17 -0
- package/src/code_generation/utils/tab_indent.ts +3 -0
- package/src/code_generation/utils/type_from_zod.ts +140 -0
- package/src/utils/cache.ts +149 -0
- package/src/utils/mongoose_from_zod.ts +191 -0
- package/src/utils/pretty_print_zod.ts +75 -0
- package/src/utils/query_object_to_mongodb_query.ts +73 -0
- package/src/utils/query_validator_from_zod.ts +246 -0
- package/test/0_0_mongoose_from_zod.test.ts +260 -0
- package/test/0_1_query_validator_from_zod.test.ts +518 -0
- package/test/0_2_query_validator_to_mongodb_query.test.ts +365 -0
- package/test/0_3_cache.test.ts +204 -0
- package/test/1_0_basic_server.test.ts +530 -0
- package/test/1_1_security_ownership.test.ts +328 -0
- package/test/1_2_role_membership.test.ts +731 -0
- package/test/2_0_client_library_basic_type_generation.test.ts +444 -0
- package/test/2_0_client_library_query_type_generation.test.ts +352 -0
- package/test/2_1_client_library_generation.test.ts +255 -0
- package/test/tmp/dist/Brief_News_Category.d.ts +16 -0
- package/test/tmp/dist/Brief_News_Category.js +85 -0
- package/test/tmp/dist/Brief_News_Category.js.map +1 -0
- package/test/tmp/dist/Client.d.ts +19 -0
- package/test/tmp/dist/Client.js +97 -0
- package/test/tmp/dist/Client.js.map +1 -0
- package/test/tmp/dist/Institution.d.ts +18 -0
- package/test/tmp/dist/Institution.js +94 -0
- package/test/tmp/dist/Institution.js.map +1 -0
- package/test/tmp/dist/Project.d.ts +16 -0
- package/test/tmp/dist/Project.js +85 -0
- package/test/tmp/dist/Project.js.map +1 -0
- package/test/tmp/dist/index.d.ts +4 -0
- package/test/tmp/dist/index.js +14 -0
- package/test/tmp/dist/index.js.map +1 -0
- package/test/tmp/dist/types/brief_news_category.d.ts +7 -0
- package/test/tmp/dist/types/brief_news_category.js +2 -0
- package/test/tmp/dist/types/brief_news_category.js.map +1 -0
- package/test/tmp/dist/types/brief_news_category_post.d.ts +7 -0
- package/test/tmp/dist/types/brief_news_category_post.js +2 -0
- package/test/tmp/dist/types/brief_news_category_post.js.map +1 -0
- package/test/tmp/dist/types/brief_news_category_put.d.ts +7 -0
- package/test/tmp/dist/types/brief_news_category_put.js +2 -0
- package/test/tmp/dist/types/brief_news_category_put.js.map +1 -0
- package/test/tmp/dist/types/brief_news_category_query.d.ts +26 -0
- package/test/tmp/dist/types/brief_news_category_query.js +2 -0
- package/test/tmp/dist/types/brief_news_category_query.js.map +1 -0
- package/test/tmp/dist/types/client.d.ts +5 -0
- package/test/tmp/dist/types/client.js +2 -0
- package/test/tmp/dist/types/client.js.map +1 -0
- package/test/tmp/dist/types/client_post.d.ts +5 -0
- package/test/tmp/dist/types/client_post.js +2 -0
- package/test/tmp/dist/types/client_post.js.map +1 -0
- package/test/tmp/dist/types/client_put.d.ts +5 -0
- package/test/tmp/dist/types/client_put.js +2 -0
- package/test/tmp/dist/types/client_put.js.map +1 -0
- package/test/tmp/dist/types/client_query.d.ts +18 -0
- package/test/tmp/dist/types/client_query.js +2 -0
- package/test/tmp/dist/types/client_query.js.map +1 -0
- package/test/tmp/dist/types/institution.d.ts +4 -0
- package/test/tmp/dist/types/institution.js +2 -0
- package/test/tmp/dist/types/institution.js.map +1 -0
- package/test/tmp/dist/types/institution_post.d.ts +4 -0
- package/test/tmp/dist/types/institution_post.js +2 -0
- package/test/tmp/dist/types/institution_post.js.map +1 -0
- package/test/tmp/dist/types/institution_put.d.ts +4 -0
- package/test/tmp/dist/types/institution_put.js +2 -0
- package/test/tmp/dist/types/institution_put.js.map +1 -0
- package/test/tmp/dist/types/institution_query.d.ts +14 -0
- package/test/tmp/dist/types/institution_query.js +2 -0
- package/test/tmp/dist/types/institution_query.js.map +1 -0
- package/test/tmp/dist/types/project.d.ts +7 -0
- package/test/tmp/dist/types/project.js +2 -0
- package/test/tmp/dist/types/project.js.map +1 -0
- package/test/tmp/dist/types/project_post.d.ts +7 -0
- package/test/tmp/dist/types/project_post.js +2 -0
- package/test/tmp/dist/types/project_post.js.map +1 -0
- package/test/tmp/dist/types/project_put.d.ts +7 -0
- package/test/tmp/dist/types/project_put.js +2 -0
- package/test/tmp/dist/types/project_put.js.map +1 -0
- package/test/tmp/dist/types/project_query.d.ts +27 -0
- package/test/tmp/dist/types/project_query.js +2 -0
- package/test/tmp/dist/types/project_query.js.map +1 -0
- package/test/tmp/dist/utils/utils.d.ts +11 -0
- package/test/tmp/dist/utils/utils.js +13 -0
- package/test/tmp/dist/utils/utils.js.map +1 -0
- package/test/tmp/package-lock.json +573 -0
- package/test/tmp/package.json +18 -0
- package/test/tmp/src/Brief_News_Category.ts +94 -0
- package/test/tmp/src/Client.ts +106 -0
- package/test/tmp/src/Institution.ts +103 -0
- package/test/tmp/src/Project.ts +94 -0
- package/test/tmp/src/index.ts +20 -0
- package/test/tmp/src/types/brief_news_category.ts +7 -0
- package/test/tmp/src/types/brief_news_category_post.ts +7 -0
- package/test/tmp/src/types/brief_news_category_put.ts +7 -0
- package/test/tmp/src/types/brief_news_category_query.ts +26 -0
- package/test/tmp/src/types/client.ts +5 -0
- package/test/tmp/src/types/client_post.ts +5 -0
- package/test/tmp/src/types/client_put.ts +5 -0
- package/test/tmp/src/types/client_query.ts +18 -0
- package/test/tmp/src/types/institution.ts +4 -0
- package/test/tmp/src/types/institution_post.ts +4 -0
- package/test/tmp/src/types/institution_put.ts +4 -0
- package/test/tmp/src/types/institution_query.ts +14 -0
- package/test/tmp/src/types/project.ts +7 -0
- package/test/tmp/src/types/project_post.ts +7 -0
- package/test/tmp/src/types/project_put.ts +7 -0
- package/test/tmp/src/types/project_query.ts +27 -0
- package/test/tmp/src/utils/utils.ts +17 -0
- package/test/tmp/tsconfig.json +14 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import { rimraf, rimrafSync, native, nativeSync } from 'rimraf'
|
|
4
|
+
|
|
5
|
+
import { z_mongodb_id } from '../dist/utils/mongoose_from_zod.js';
|
|
6
|
+
import { F_Collection } from '../dist/f_collection.js';
|
|
7
|
+
import { F_Collection_Registry } from '../dist/F_Collection_Registry.js'
|
|
8
|
+
import { F_SM_Open_Access } from '../dist/F_Security_Models/F_SM_Open_Access.js'
|
|
9
|
+
import { z, ZodBoolean, ZodDate, ZodNumber, ZodString } from 'zod'
|
|
10
|
+
import { generate_client_library } from '../dist/code_generation/generate_client_library.js'
|
|
11
|
+
|
|
12
|
+
import got from 'got'
|
|
13
|
+
import express, { Express, Request, Response, NextFunction } from 'express'
|
|
14
|
+
import mongoose, { mongo, Mongoose } from "mongoose";
|
|
15
|
+
import { Server } from "http";
|
|
16
|
+
import { mkdir, readFile } from "fs/promises";
|
|
17
|
+
|
|
18
|
+
/*mongoose.connection.on('connected', () => console.log('connected'));
|
|
19
|
+
mongoose.connection.on('open', () => console.log('open'));
|
|
20
|
+
mongoose.connection.on('disconnected', () => console.log('disconnected'));
|
|
21
|
+
mongoose.connection.on('reconnected', () => console.log('reconnected'));
|
|
22
|
+
mongoose.connection.on('disconnecting', () => console.log('disconnecting'));
|
|
23
|
+
mongoose.connection.on('close', () => console.log('close'));*/
|
|
24
|
+
|
|
25
|
+
const remove_whitespace = (input: string): string => input.replaceAll(/[\n\r\s]+/g, '')
|
|
26
|
+
|
|
27
|
+
describe('Client Library Generation: Query Types', function () {
|
|
28
|
+
|
|
29
|
+
// before any tests run, set up the server and the db connection
|
|
30
|
+
before(async function() {
|
|
31
|
+
|
|
32
|
+
// wait for a moment because otherwise stuff breaks for no reason
|
|
33
|
+
await new Promise(resolve => setTimeout(resolve, 200))
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
after(async function (){
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
beforeEach(async function(){
|
|
40
|
+
this.timeout(20000);
|
|
41
|
+
mongoose.connection.modelNames().forEach(ele => mongoose.connection.deleteModel(ele));
|
|
42
|
+
|
|
43
|
+
await rimraf('./test/tmp');
|
|
44
|
+
await mkdir('./test/tmp');
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it(`should be able to generate a query for a plain object`, async function () {
|
|
48
|
+
const validate_test_collection = z.object({});
|
|
49
|
+
|
|
50
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
51
|
+
|
|
52
|
+
let proto_registry = new F_Collection_Registry();
|
|
53
|
+
let registry = proto_registry.register(test_collection);
|
|
54
|
+
|
|
55
|
+
await generate_client_library('./test/tmp', registry);
|
|
56
|
+
|
|
57
|
+
assert.equal(
|
|
58
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
59
|
+
remove_whitespace(`export type test_collection_query = {
|
|
60
|
+
"limit"?: number
|
|
61
|
+
"cursor"?: string
|
|
62
|
+
"sort_order"?: ("ascending" | "descending")
|
|
63
|
+
"sort"?: ("")
|
|
64
|
+
}`)
|
|
65
|
+
)
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it(`should be able to generate a plain object containing a string`, async function () {
|
|
69
|
+
const validate_test_collection = z.object({
|
|
70
|
+
test: z.string(),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
74
|
+
|
|
75
|
+
let proto_registry = new F_Collection_Registry();
|
|
76
|
+
let registry = proto_registry.register(test_collection);
|
|
77
|
+
|
|
78
|
+
await generate_client_library('./test/tmp', registry);
|
|
79
|
+
|
|
80
|
+
assert.equal(
|
|
81
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
82
|
+
remove_whitespace(`export type test_collection_query = {
|
|
83
|
+
"limit"?: number
|
|
84
|
+
"cursor"?: string
|
|
85
|
+
"sort_order"?: ("ascending" | "descending")
|
|
86
|
+
"test"?: string
|
|
87
|
+
"test_gt"?: string
|
|
88
|
+
"test_lt"?: string
|
|
89
|
+
"test_in"?: string[]
|
|
90
|
+
"sort"?: ("test")
|
|
91
|
+
}`)
|
|
92
|
+
)
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it(`should be able to generate a plain object containing a number`, async function () {
|
|
96
|
+
const validate_test_collection = z.object({
|
|
97
|
+
test: z.number(),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
101
|
+
|
|
102
|
+
let proto_registry = new F_Collection_Registry();
|
|
103
|
+
let registry = proto_registry.register(test_collection);
|
|
104
|
+
|
|
105
|
+
await generate_client_library('./test/tmp', registry);
|
|
106
|
+
|
|
107
|
+
assert.equal(
|
|
108
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
109
|
+
remove_whitespace(`export type test_collection_query = {
|
|
110
|
+
"limit"?: number
|
|
111
|
+
"cursor"?: string
|
|
112
|
+
"sort_order"?: ("ascending" | "descending")
|
|
113
|
+
"test"?: number
|
|
114
|
+
"test_gt"?: number
|
|
115
|
+
"test_gte"?: number
|
|
116
|
+
"test_lt"?: number
|
|
117
|
+
"test_lte"?: number
|
|
118
|
+
"sort"?: ("test")
|
|
119
|
+
}`)
|
|
120
|
+
)
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it(`should be able to generate a plain object containing a boolean`, async function () {
|
|
124
|
+
const validate_test_collection = z.object({
|
|
125
|
+
test: z.boolean(),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
129
|
+
|
|
130
|
+
let proto_registry = new F_Collection_Registry();
|
|
131
|
+
let registry = proto_registry.register(test_collection);
|
|
132
|
+
|
|
133
|
+
await generate_client_library('./test/tmp', registry);
|
|
134
|
+
|
|
135
|
+
assert.equal(
|
|
136
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
137
|
+
remove_whitespace(`export type test_collection_query = {
|
|
138
|
+
"limit"?: number
|
|
139
|
+
"cursor"?: string
|
|
140
|
+
"sort_order"?: ("ascending" | "descending")
|
|
141
|
+
"test"?: boolean
|
|
142
|
+
"sort"?: ("test")
|
|
143
|
+
}`)
|
|
144
|
+
)
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it(`should be able to generate a plain object containing a date`, async function () {
|
|
148
|
+
const validate_test_collection = z.object({
|
|
149
|
+
test: z.date(),
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
153
|
+
|
|
154
|
+
let proto_registry = new F_Collection_Registry();
|
|
155
|
+
let registry = proto_registry.register(test_collection);
|
|
156
|
+
|
|
157
|
+
await generate_client_library('./test/tmp', registry);
|
|
158
|
+
|
|
159
|
+
assert.equal(
|
|
160
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
161
|
+
remove_whitespace(`export type test_collection_query = {
|
|
162
|
+
"limit"?: number
|
|
163
|
+
"cursor"?: string
|
|
164
|
+
"sort_order"?: ("ascending" | "descending")
|
|
165
|
+
"test"?: Date
|
|
166
|
+
"test_gt"?: Date
|
|
167
|
+
"test_lt"?: Date
|
|
168
|
+
"sort"?: ("test")
|
|
169
|
+
}`)
|
|
170
|
+
)
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it(`should be able to generate a plain object containing an objectID`, async function () {
|
|
174
|
+
const validate_test_collection = z.object({
|
|
175
|
+
test: z_mongodb_id,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
179
|
+
|
|
180
|
+
let proto_registry = new F_Collection_Registry();
|
|
181
|
+
let registry = proto_registry.register(test_collection);
|
|
182
|
+
|
|
183
|
+
await generate_client_library('./test/tmp', registry);
|
|
184
|
+
|
|
185
|
+
assert.equal(
|
|
186
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
187
|
+
remove_whitespace(`export type test_collection_query = {
|
|
188
|
+
"limit"?: number
|
|
189
|
+
"cursor"?: string
|
|
190
|
+
"sort_order"?: ("ascending" | "descending")
|
|
191
|
+
"test"?: string
|
|
192
|
+
"test_gt"?: string
|
|
193
|
+
"test_lt"?: string
|
|
194
|
+
"test_in"?: string[]
|
|
195
|
+
"sort"?: ("test")
|
|
196
|
+
}`)
|
|
197
|
+
)
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it(`should be able to generate an enum`, async function () {
|
|
201
|
+
const validate_test_collection = z.object({
|
|
202
|
+
test: z.enum(["red", "green", "blue"]),
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
206
|
+
|
|
207
|
+
let proto_registry = new F_Collection_Registry();
|
|
208
|
+
let registry = proto_registry.register(test_collection);
|
|
209
|
+
|
|
210
|
+
await generate_client_library('./test/tmp', registry);
|
|
211
|
+
|
|
212
|
+
assert.equal(
|
|
213
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
214
|
+
remove_whitespace(`export type test_collection_query = {
|
|
215
|
+
"limit"?: number
|
|
216
|
+
"cursor"?: string
|
|
217
|
+
"sort_order"?: ("ascending" | "descending")
|
|
218
|
+
"test"?: ("red" | "green" | "blue")
|
|
219
|
+
"test_in"?: ("red" | "green" | "blue")[]
|
|
220
|
+
"sort"?: ("test")
|
|
221
|
+
}`)
|
|
222
|
+
)
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
it(`should be able to generate a plain nested object`, async function () {
|
|
228
|
+
const validate_test_collection = z.object({
|
|
229
|
+
test: z.object({
|
|
230
|
+
}),
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
234
|
+
|
|
235
|
+
let proto_registry = new F_Collection_Registry();
|
|
236
|
+
let registry = proto_registry.register(test_collection);
|
|
237
|
+
|
|
238
|
+
await generate_client_library('./test/tmp', registry);
|
|
239
|
+
|
|
240
|
+
assert.equal(
|
|
241
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
242
|
+
remove_whitespace(`export type test_collection_query = {
|
|
243
|
+
"limit"?: number
|
|
244
|
+
"cursor"?: string
|
|
245
|
+
"sort_order"?: ("ascending" | "descending")
|
|
246
|
+
"sort"?: ("")
|
|
247
|
+
}`)
|
|
248
|
+
)
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it(`should be able to generate a plain nested with basic fields`, async function () {
|
|
252
|
+
const validate_test_collection = z.object({
|
|
253
|
+
test: z.object({
|
|
254
|
+
field_string: z.string(),
|
|
255
|
+
field_number: z.number(),
|
|
256
|
+
field_boolean: z.boolean(),
|
|
257
|
+
field_date: z.date(),
|
|
258
|
+
test_2: z.object({
|
|
259
|
+
field_doublenested: z.boolean(),
|
|
260
|
+
})
|
|
261
|
+
}),
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
265
|
+
|
|
266
|
+
let proto_registry = new F_Collection_Registry();
|
|
267
|
+
let registry = proto_registry.register(test_collection);
|
|
268
|
+
|
|
269
|
+
await generate_client_library('./test/tmp', registry);
|
|
270
|
+
|
|
271
|
+
assert.equal(
|
|
272
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
273
|
+
remove_whitespace(`export type test_collection_query = {
|
|
274
|
+
"limit"?: number
|
|
275
|
+
"cursor"?: string
|
|
276
|
+
"sort_order"?: ("ascending" | "descending")
|
|
277
|
+
|
|
278
|
+
"test.field_string"?: string
|
|
279
|
+
"test.field_string_gt"?: string
|
|
280
|
+
"test.field_string_lt"?: string
|
|
281
|
+
"test.field_string_in"?: string[]
|
|
282
|
+
|
|
283
|
+
"test.field_number"?: number
|
|
284
|
+
"test.field_number_gt"?: number
|
|
285
|
+
"test.field_number_gte"?: number
|
|
286
|
+
"test.field_number_lt"?: number
|
|
287
|
+
"test.field_number_lte"?: number
|
|
288
|
+
|
|
289
|
+
"test.field_boolean"?: boolean
|
|
290
|
+
|
|
291
|
+
"test.field_date"?: Date
|
|
292
|
+
"test.field_date_gt"?: Date
|
|
293
|
+
"test.field_date_lt"?: Date
|
|
294
|
+
|
|
295
|
+
"test.test_2.field_doublenested"?: boolean
|
|
296
|
+
"sort"?: ("test.field_string" | "test.field_number" | "test.field_boolean" | "test.field_date" | "test.test_2.field_doublenested")
|
|
297
|
+
}`)
|
|
298
|
+
)
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it(`should be able to generate arrays of primitive fields`, async function () {
|
|
302
|
+
const validate_test_collection = z.object({
|
|
303
|
+
field_string: z.array(z.string()),
|
|
304
|
+
field_number: z.array(z.number()),
|
|
305
|
+
field_boolean: z.array(z.boolean()),
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
309
|
+
|
|
310
|
+
let proto_registry = new F_Collection_Registry();
|
|
311
|
+
let registry = proto_registry.register(test_collection);
|
|
312
|
+
|
|
313
|
+
await generate_client_library('./test/tmp', registry);
|
|
314
|
+
|
|
315
|
+
assert.equal(
|
|
316
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
317
|
+
remove_whitespace(`export type test_collection_query = {
|
|
318
|
+
"limit"?: number
|
|
319
|
+
"cursor"?: string
|
|
320
|
+
"sort_order"?: ("ascending" | "descending")
|
|
321
|
+
"field_string"?: string
|
|
322
|
+
"field_number"?: number
|
|
323
|
+
"field_boolean"?: boolean
|
|
324
|
+
"sort"?: ("field_string" | "field_number" | "field_boolean")
|
|
325
|
+
}`)
|
|
326
|
+
)
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it(`should be able to generate a plain object containing a primitive with a default`, async function () {
|
|
330
|
+
const validate_test_collection = z.object({
|
|
331
|
+
test: z.boolean().default(true),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
let test_collection = new F_Collection('test_collection', validate_test_collection);
|
|
335
|
+
|
|
336
|
+
let proto_registry = new F_Collection_Registry();
|
|
337
|
+
let registry = proto_registry.register(test_collection);
|
|
338
|
+
|
|
339
|
+
await generate_client_library('./test/tmp', registry);
|
|
340
|
+
|
|
341
|
+
assert.equal(
|
|
342
|
+
remove_whitespace(await readFile('./test/tmp/src/types/test_collection_query.ts', { encoding: 'utf-8' })),
|
|
343
|
+
remove_whitespace(`export type test_collection_query = {
|
|
344
|
+
"limit"?: number
|
|
345
|
+
"cursor"?: string
|
|
346
|
+
"sort_order"?: ("ascending" | "descending")
|
|
347
|
+
"test"?: boolean
|
|
348
|
+
"sort"?: ("test")
|
|
349
|
+
}`)
|
|
350
|
+
)
|
|
351
|
+
});
|
|
352
|
+
});
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import { rimraf, rimrafSync, native, nativeSync } from 'rimraf'
|
|
4
|
+
|
|
5
|
+
import { z_mongodb_id } from '../dist/utils/mongoose_from_zod.js';
|
|
6
|
+
import { F_Collection } from '../dist/f_collection.js';
|
|
7
|
+
import { F_Collection_Registry } from '../dist/F_Collection_Registry.js'
|
|
8
|
+
import { F_SM_Open_Access } from '../dist/F_Security_Models/F_SM_Open_Access.js'
|
|
9
|
+
import { z, ZodBoolean, ZodDate, ZodNumber, ZodString } from 'zod'
|
|
10
|
+
import { generate_client_library } from '../dist/code_generation/generate_client_library.js'
|
|
11
|
+
|
|
12
|
+
import got from 'got'
|
|
13
|
+
import express, { Express, Request, Response, NextFunction } from 'express'
|
|
14
|
+
import mongoose, { mongo, Mongoose } from "mongoose";
|
|
15
|
+
import { Server } from "http";
|
|
16
|
+
import { mkdir, readFile } from "fs/promises";
|
|
17
|
+
|
|
18
|
+
import { exec, spawn } from "child_process";
|
|
19
|
+
|
|
20
|
+
/*mongoose.connection.on('connected', () => console.log('connected'));
|
|
21
|
+
mongoose.connection.on('open', () => console.log('open'));
|
|
22
|
+
mongoose.connection.on('disconnected', () => console.log('disconnected'));
|
|
23
|
+
mongoose.connection.on('reconnected', () => console.log('reconnected'));
|
|
24
|
+
mongoose.connection.on('disconnecting', () => console.log('disconnecting'));
|
|
25
|
+
mongoose.connection.on('close', () => console.log('close'));*/
|
|
26
|
+
|
|
27
|
+
const remove_whitespace = (input: string): string => input.replaceAll(/[\n\r\s]+/g, '')
|
|
28
|
+
|
|
29
|
+
describe('Client Library Generation: Library Generation', function () {
|
|
30
|
+
const port = 4601;
|
|
31
|
+
let express_app: Express;
|
|
32
|
+
let server: Server;
|
|
33
|
+
let db_connection: Mongoose;
|
|
34
|
+
|
|
35
|
+
const validate_institution = z.object({
|
|
36
|
+
_id: z_mongodb_id,
|
|
37
|
+
name: z.string(),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const validate_client = z.object({
|
|
41
|
+
_id: z_mongodb_id,
|
|
42
|
+
name: z.string(),
|
|
43
|
+
institution_id: z_mongodb_id,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const validate_project = z.object({
|
|
47
|
+
_id: z_mongodb_id,
|
|
48
|
+
name: z.string(),
|
|
49
|
+
institution_id: z_mongodb_id,
|
|
50
|
+
client_id: z_mongodb_id,
|
|
51
|
+
project_number: z.number(),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const validate_brief_news_category = z.object({
|
|
55
|
+
_id: z_mongodb_id,
|
|
56
|
+
name: z.string(),
|
|
57
|
+
slug: z.string(),
|
|
58
|
+
institution_id: z_mongodb_id,
|
|
59
|
+
client_id: z_mongodb_id,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
let collection_institution: F_Collection<'institution', typeof validate_institution>;
|
|
63
|
+
let collection_client: F_Collection<'client', typeof validate_client>;
|
|
64
|
+
let collection_project: F_Collection<'project', typeof validate_project>;
|
|
65
|
+
let collection_brief_news_category: F_Collection<'brief_news_category', typeof validate_brief_news_category>;
|
|
66
|
+
|
|
67
|
+
let registry: F_Collection_Registry;
|
|
68
|
+
|
|
69
|
+
// before any tests run, set up the server and the db connection
|
|
70
|
+
before(async function() {
|
|
71
|
+
this.timeout(10 * 1000)
|
|
72
|
+
|
|
73
|
+
express_app = express();
|
|
74
|
+
express_app.use(express.json());
|
|
75
|
+
db_connection = await mongoose.connect('mongodb://127.0.0.1:27017/');
|
|
76
|
+
|
|
77
|
+
await rimraf('./test/tmp');
|
|
78
|
+
await mkdir('./test/tmp');
|
|
79
|
+
|
|
80
|
+
collection_institution = new F_Collection('institution', validate_institution);
|
|
81
|
+
collection_institution.add_layers([], [new F_SM_Open_Access(collection_institution)])
|
|
82
|
+
|
|
83
|
+
collection_client = new F_Collection('client', validate_client);
|
|
84
|
+
collection_client.add_layers(['institution'], [new F_SM_Open_Access(collection_client)])
|
|
85
|
+
|
|
86
|
+
collection_project = new F_Collection('project', validate_project);
|
|
87
|
+
collection_project.add_layers(['institution', 'client'], [new F_SM_Open_Access(collection_project)])
|
|
88
|
+
|
|
89
|
+
collection_brief_news_category = new F_Collection('brief_news_category', validate_brief_news_category);
|
|
90
|
+
collection_brief_news_category.add_layers(['institution', 'client'], [new F_SM_Open_Access(collection_brief_news_category)])
|
|
91
|
+
|
|
92
|
+
let proto_registry = new F_Collection_Registry();
|
|
93
|
+
registry = proto_registry
|
|
94
|
+
.register(collection_institution)
|
|
95
|
+
.register(collection_client)
|
|
96
|
+
.register(collection_project)
|
|
97
|
+
.register(collection_brief_news_category)
|
|
98
|
+
registry.compile(express_app, '/api');
|
|
99
|
+
|
|
100
|
+
server = express_app.listen(port);
|
|
101
|
+
|
|
102
|
+
await generate_client_library('./test/tmp', registry);
|
|
103
|
+
|
|
104
|
+
await new Promise((resolve, rej) => {
|
|
105
|
+
exec('npm install', { cwd: './test/tmp/' }, (err, stdout, stderr) => {
|
|
106
|
+
if (err) {
|
|
107
|
+
// node couldn't execute the command
|
|
108
|
+
console.error(err)
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.error(stderr)
|
|
113
|
+
resolve('');
|
|
114
|
+
});
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
await new Promise((resolve, rej) => {
|
|
118
|
+
exec('npm run-script build', { cwd: './test/tmp/' }, (err, stdout, stderr) => {
|
|
119
|
+
if (err) {
|
|
120
|
+
// node couldn't execute the command
|
|
121
|
+
console.error(err)
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.error(stderr)
|
|
126
|
+
resolve('');
|
|
127
|
+
});
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// wait for a moment because otherwise stuff breaks for no reason
|
|
131
|
+
await new Promise(resolve => setTimeout(resolve, 200))
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
after(async function (){
|
|
135
|
+
await server.close();
|
|
136
|
+
mongoose.connection.modelNames().forEach(ele => mongoose.connection.deleteModel(ele));
|
|
137
|
+
db_connection.modelNames().forEach(ele => db_connection.deleteModel(ele));
|
|
138
|
+
await db_connection.disconnect()
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
beforeEach(async function(){
|
|
142
|
+
for(let collection of Object.values(registry.collections)){
|
|
143
|
+
//@ts-ignore
|
|
144
|
+
await collection.mongoose_model.collection.drop();
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
async function generate_test_setup(){
|
|
149
|
+
let institution = await collection_institution.mongoose_model.create({
|
|
150
|
+
name: 'test institution'
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
let client = await collection_client.mongoose_model.create({
|
|
154
|
+
name: 'test client',
|
|
155
|
+
institution_id: institution._id,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
let test_projects: z.infer<typeof collection_project.validator>[] = [];
|
|
159
|
+
for(let q = 0; q < 10; q++){
|
|
160
|
+
test_projects.push(await collection_project.mongoose_model.create({
|
|
161
|
+
name: 'test project',
|
|
162
|
+
institution_id: institution._id,
|
|
163
|
+
client_id: client._id,
|
|
164
|
+
project_number: 1
|
|
165
|
+
}))
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return { institution, client, test_projects}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
it(`should be able to service a basic GET request`, async function () {
|
|
172
|
+
let { api } = await import("./tmp/dist/index.js");
|
|
173
|
+
let { institution } = await generate_test_setup();
|
|
174
|
+
|
|
175
|
+
let result = await api(`http://localhost:${port}/api`, async () => "todd").collection('institution').document(institution._id).get();
|
|
176
|
+
assert.deepEqual(
|
|
177
|
+
JSON.parse(JSON.stringify(institution)),
|
|
178
|
+
result
|
|
179
|
+
)
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it(`should be able to service a basic query`, async function () {
|
|
183
|
+
let { api } = await import("./tmp/dist/index.js");
|
|
184
|
+
let { institution } = await generate_test_setup();
|
|
185
|
+
|
|
186
|
+
let result = await api(`http://localhost:${port}/api`, async () => "todd").collection('institution').query({});
|
|
187
|
+
assert.deepEqual(
|
|
188
|
+
[JSON.parse(JSON.stringify(institution))],
|
|
189
|
+
result
|
|
190
|
+
)
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it(`should be able to service a basic POST`, async function () {
|
|
194
|
+
let { api } = await import("./tmp/dist/index.js");
|
|
195
|
+
let { } = await generate_test_setup();
|
|
196
|
+
|
|
197
|
+
let result = await api(`http://localhost:${port}/api`, async () => "todd").collection('institution').post({
|
|
198
|
+
name: 'new institution',
|
|
199
|
+
});
|
|
200
|
+
assert.deepEqual(
|
|
201
|
+
JSON.parse(JSON.stringify(await collection_institution.mongoose_model.findById(result._id))),
|
|
202
|
+
JSON.parse(JSON.stringify(result)),
|
|
203
|
+
)
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it(`should be able to service a basic PUT`, async function () {
|
|
207
|
+
let { api } = await import("./tmp/dist/index.js");
|
|
208
|
+
let { institution } = await generate_test_setup();
|
|
209
|
+
|
|
210
|
+
let result = await api(`http://localhost:${port}/api`, async () => "todd").collection('institution').document(institution._id).put({
|
|
211
|
+
name: 'redo institution name',
|
|
212
|
+
});
|
|
213
|
+
assert.deepEqual(
|
|
214
|
+
JSON.parse(JSON.stringify(await collection_institution.mongoose_model.findById(institution._id))),
|
|
215
|
+
JSON.parse(JSON.stringify(result)),
|
|
216
|
+
)
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it(`should be able to service a basic DELETE`, async function () {
|
|
220
|
+
let { api } = await import("./tmp/dist/index.js");
|
|
221
|
+
let { institution } = await generate_test_setup();
|
|
222
|
+
|
|
223
|
+
let result = await api(`http://localhost:${port}/api`, async () => "todd").collection('institution').document(institution._id).remove();
|
|
224
|
+
assert.deepEqual(
|
|
225
|
+
await collection_institution.mongoose_model.findById(institution._id),
|
|
226
|
+
undefined,
|
|
227
|
+
)
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it(`should be able to service a basic query on nested collections`, async function () {
|
|
231
|
+
let { api } = await import("./tmp/dist/index.js");
|
|
232
|
+
let { institution, client, test_projects } = await generate_test_setup();
|
|
233
|
+
|
|
234
|
+
let result;
|
|
235
|
+
try {
|
|
236
|
+
result = await api(`http://localhost:${port}/api`, async () => "todd")
|
|
237
|
+
.collection('institution')
|
|
238
|
+
.document(institution._id)
|
|
239
|
+
.collection('client')
|
|
240
|
+
.document(client._id)
|
|
241
|
+
.collection("project")
|
|
242
|
+
.query({
|
|
243
|
+
project_number_gt: 5
|
|
244
|
+
});
|
|
245
|
+
} catch(err) {
|
|
246
|
+
console.error(await err.response.json())
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
assert.deepEqual(
|
|
250
|
+
JSON.parse(JSON.stringify(test_projects.filter(ele => ele.project_number > 5))),
|
|
251
|
+
result
|
|
252
|
+
)
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { brief_news_category } from "./types/brief_news_category.js";
|
|
2
|
+
import { brief_news_category_query } from "./types/brief_news_category_query.js";
|
|
3
|
+
import { brief_news_category_put } from "./types/brief_news_category_put.js";
|
|
4
|
+
import { brief_news_category_post } from "./types/brief_news_category_post.js";
|
|
5
|
+
export declare class Collection_Brief_News_Category {
|
|
6
|
+
path: string[];
|
|
7
|
+
get_auth: () => Promise<any>;
|
|
8
|
+
constructor(path: string[], get_auth: () => Promise<any>);
|
|
9
|
+
query(query: brief_news_category_query): Promise<brief_news_category[]>;
|
|
10
|
+
post(document: brief_news_category_post): Promise<brief_news_category>;
|
|
11
|
+
document(document_id: string): {
|
|
12
|
+
get(): Promise<brief_news_category>;
|
|
13
|
+
put(update: brief_news_category_put): Promise<brief_news_category>;
|
|
14
|
+
remove(): Promise<brief_news_category>;
|
|
15
|
+
};
|
|
16
|
+
}
|