@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.
Files changed (181) hide show
  1. package/.mocharc.json +5 -0
  2. package/dist/F_Client_Collection_Registry.d.ts +18 -0
  3. package/dist/F_Client_Collection_Registry.js +36 -0
  4. package/dist/F_Client_Collection_Registry.js.map +1 -0
  5. package/dist/F_Collection.d.ts +21 -0
  6. package/dist/F_Collection.js +36 -0
  7. package/dist/F_Collection.js.map +1 -0
  8. package/dist/F_Collection_Registry.d.ts +11 -0
  9. package/dist/F_Collection_Registry.js +18 -0
  10. package/dist/F_Collection_Registry.js.map +1 -0
  11. package/dist/F_Compile.d.ts +4 -0
  12. package/dist/F_Compile.js +298 -0
  13. package/dist/F_Compile.js.map +1 -0
  14. package/dist/F_Security_Models/F_SM_Open_Access.d.ts +11 -0
  15. package/dist/F_Security_Models/F_SM_Open_Access.js +14 -0
  16. package/dist/F_Security_Models/F_SM_Open_Access.js.map +1 -0
  17. package/dist/F_Security_Models/F_SM_Ownership.d.ts +12 -0
  18. package/dist/F_Security_Models/F_SM_Ownership.js +46 -0
  19. package/dist/F_Security_Models/F_SM_Ownership.js.map +1 -0
  20. package/dist/F_Security_Models/F_SM_Role_Membership.d.ts +19 -0
  21. package/dist/F_Security_Models/F_SM_Role_Membership.js +73 -0
  22. package/dist/F_Security_Models/F_SM_Role_Membership.js.map +1 -0
  23. package/dist/F_Security_Models/F_Security_Model.d.ts +41 -0
  24. package/dist/F_Security_Models/F_Security_Model.js +29 -0
  25. package/dist/F_Security_Models/F_Security_Model.js.map +1 -0
  26. package/dist/code_generation/generate_client_library.d.ts +4 -0
  27. package/dist/code_generation/generate_client_library.js +158 -0
  28. package/dist/code_generation/generate_client_library.js.map +1 -0
  29. package/dist/code_generation/templates/.gitignore.mustache +383 -0
  30. package/dist/code_generation/templates/collection.mustache +106 -0
  31. package/dist/code_generation/templates/main.mustache +24 -0
  32. package/dist/code_generation/templates/package.json.mustache +18 -0
  33. package/dist/code_generation/templates/tsconfig.json.mustache +14 -0
  34. package/dist/code_generation/templates/types.mustache +4 -0
  35. package/dist/code_generation/templates/utils.ts.mustache +17 -0
  36. package/dist/code_generation/utils/tab_indent.d.ts +1 -0
  37. package/dist/code_generation/utils/tab_indent.js +4 -0
  38. package/dist/code_generation/utils/tab_indent.js.map +1 -0
  39. package/dist/code_generation/utils/type_from_zod.d.ts +2 -0
  40. package/dist/code_generation/utils/type_from_zod.js +102 -0
  41. package/dist/code_generation/utils/type_from_zod.js.map +1 -0
  42. package/dist/utils/cache.d.ts +13 -0
  43. package/dist/utils/cache.js +101 -0
  44. package/dist/utils/cache.js.map +1 -0
  45. package/dist/utils/mongoose_from_zod.d.ts +13 -0
  46. package/dist/utils/mongoose_from_zod.js +164 -0
  47. package/dist/utils/mongoose_from_zod.js.map +1 -0
  48. package/dist/utils/pretty_print_zod.d.ts +2 -0
  49. package/dist/utils/pretty_print_zod.js +63 -0
  50. package/dist/utils/pretty_print_zod.js.map +1 -0
  51. package/dist/utils/query_object_to_mongodb_query.d.ts +3 -0
  52. package/dist/utils/query_object_to_mongodb_query.js +61 -0
  53. package/dist/utils/query_object_to_mongodb_query.js.map +1 -0
  54. package/dist/utils/query_validator_from_zod.d.ts +6 -0
  55. package/dist/utils/query_validator_from_zod.js +216 -0
  56. package/dist/utils/query_validator_from_zod.js.map +1 -0
  57. package/package.json +36 -0
  58. package/src/F_Collection.ts +50 -0
  59. package/src/F_Collection_Registry.ts +29 -0
  60. package/src/F_Compile.ts +368 -0
  61. package/src/F_Security_Models/F_SM_Open_Access.ts +21 -0
  62. package/src/F_Security_Models/F_SM_Ownership.ts +72 -0
  63. package/src/F_Security_Models/F_SM_Role_Membership.ts +87 -0
  64. package/src/F_Security_Models/F_Security_Model.ts +85 -0
  65. package/src/code_generation/generate_client_library.ts +197 -0
  66. package/src/code_generation/templates/.gitignore.mustache +383 -0
  67. package/src/code_generation/templates/collection.mustache +106 -0
  68. package/src/code_generation/templates/main.mustache +24 -0
  69. package/src/code_generation/templates/package.json.mustache +18 -0
  70. package/src/code_generation/templates/tsconfig.json.mustache +14 -0
  71. package/src/code_generation/templates/types.mustache +4 -0
  72. package/src/code_generation/templates/utils.ts.mustache +17 -0
  73. package/src/code_generation/utils/tab_indent.ts +3 -0
  74. package/src/code_generation/utils/type_from_zod.ts +140 -0
  75. package/src/utils/cache.ts +149 -0
  76. package/src/utils/mongoose_from_zod.ts +191 -0
  77. package/src/utils/pretty_print_zod.ts +75 -0
  78. package/src/utils/query_object_to_mongodb_query.ts +73 -0
  79. package/src/utils/query_validator_from_zod.ts +246 -0
  80. package/test/0_0_mongoose_from_zod.test.ts +260 -0
  81. package/test/0_1_query_validator_from_zod.test.ts +518 -0
  82. package/test/0_2_query_validator_to_mongodb_query.test.ts +365 -0
  83. package/test/0_3_cache.test.ts +204 -0
  84. package/test/1_0_basic_server.test.ts +530 -0
  85. package/test/1_1_security_ownership.test.ts +328 -0
  86. package/test/1_2_role_membership.test.ts +731 -0
  87. package/test/2_0_client_library_basic_type_generation.test.ts +444 -0
  88. package/test/2_0_client_library_query_type_generation.test.ts +352 -0
  89. package/test/2_1_client_library_generation.test.ts +255 -0
  90. package/test/tmp/dist/Brief_News_Category.d.ts +16 -0
  91. package/test/tmp/dist/Brief_News_Category.js +85 -0
  92. package/test/tmp/dist/Brief_News_Category.js.map +1 -0
  93. package/test/tmp/dist/Client.d.ts +19 -0
  94. package/test/tmp/dist/Client.js +97 -0
  95. package/test/tmp/dist/Client.js.map +1 -0
  96. package/test/tmp/dist/Institution.d.ts +18 -0
  97. package/test/tmp/dist/Institution.js +94 -0
  98. package/test/tmp/dist/Institution.js.map +1 -0
  99. package/test/tmp/dist/Project.d.ts +16 -0
  100. package/test/tmp/dist/Project.js +85 -0
  101. package/test/tmp/dist/Project.js.map +1 -0
  102. package/test/tmp/dist/index.d.ts +4 -0
  103. package/test/tmp/dist/index.js +14 -0
  104. package/test/tmp/dist/index.js.map +1 -0
  105. package/test/tmp/dist/types/brief_news_category.d.ts +7 -0
  106. package/test/tmp/dist/types/brief_news_category.js +2 -0
  107. package/test/tmp/dist/types/brief_news_category.js.map +1 -0
  108. package/test/tmp/dist/types/brief_news_category_post.d.ts +7 -0
  109. package/test/tmp/dist/types/brief_news_category_post.js +2 -0
  110. package/test/tmp/dist/types/brief_news_category_post.js.map +1 -0
  111. package/test/tmp/dist/types/brief_news_category_put.d.ts +7 -0
  112. package/test/tmp/dist/types/brief_news_category_put.js +2 -0
  113. package/test/tmp/dist/types/brief_news_category_put.js.map +1 -0
  114. package/test/tmp/dist/types/brief_news_category_query.d.ts +26 -0
  115. package/test/tmp/dist/types/brief_news_category_query.js +2 -0
  116. package/test/tmp/dist/types/brief_news_category_query.js.map +1 -0
  117. package/test/tmp/dist/types/client.d.ts +5 -0
  118. package/test/tmp/dist/types/client.js +2 -0
  119. package/test/tmp/dist/types/client.js.map +1 -0
  120. package/test/tmp/dist/types/client_post.d.ts +5 -0
  121. package/test/tmp/dist/types/client_post.js +2 -0
  122. package/test/tmp/dist/types/client_post.js.map +1 -0
  123. package/test/tmp/dist/types/client_put.d.ts +5 -0
  124. package/test/tmp/dist/types/client_put.js +2 -0
  125. package/test/tmp/dist/types/client_put.js.map +1 -0
  126. package/test/tmp/dist/types/client_query.d.ts +18 -0
  127. package/test/tmp/dist/types/client_query.js +2 -0
  128. package/test/tmp/dist/types/client_query.js.map +1 -0
  129. package/test/tmp/dist/types/institution.d.ts +4 -0
  130. package/test/tmp/dist/types/institution.js +2 -0
  131. package/test/tmp/dist/types/institution.js.map +1 -0
  132. package/test/tmp/dist/types/institution_post.d.ts +4 -0
  133. package/test/tmp/dist/types/institution_post.js +2 -0
  134. package/test/tmp/dist/types/institution_post.js.map +1 -0
  135. package/test/tmp/dist/types/institution_put.d.ts +4 -0
  136. package/test/tmp/dist/types/institution_put.js +2 -0
  137. package/test/tmp/dist/types/institution_put.js.map +1 -0
  138. package/test/tmp/dist/types/institution_query.d.ts +14 -0
  139. package/test/tmp/dist/types/institution_query.js +2 -0
  140. package/test/tmp/dist/types/institution_query.js.map +1 -0
  141. package/test/tmp/dist/types/project.d.ts +7 -0
  142. package/test/tmp/dist/types/project.js +2 -0
  143. package/test/tmp/dist/types/project.js.map +1 -0
  144. package/test/tmp/dist/types/project_post.d.ts +7 -0
  145. package/test/tmp/dist/types/project_post.js +2 -0
  146. package/test/tmp/dist/types/project_post.js.map +1 -0
  147. package/test/tmp/dist/types/project_put.d.ts +7 -0
  148. package/test/tmp/dist/types/project_put.js +2 -0
  149. package/test/tmp/dist/types/project_put.js.map +1 -0
  150. package/test/tmp/dist/types/project_query.d.ts +27 -0
  151. package/test/tmp/dist/types/project_query.js +2 -0
  152. package/test/tmp/dist/types/project_query.js.map +1 -0
  153. package/test/tmp/dist/utils/utils.d.ts +11 -0
  154. package/test/tmp/dist/utils/utils.js +13 -0
  155. package/test/tmp/dist/utils/utils.js.map +1 -0
  156. package/test/tmp/package-lock.json +573 -0
  157. package/test/tmp/package.json +18 -0
  158. package/test/tmp/src/Brief_News_Category.ts +94 -0
  159. package/test/tmp/src/Client.ts +106 -0
  160. package/test/tmp/src/Institution.ts +103 -0
  161. package/test/tmp/src/Project.ts +94 -0
  162. package/test/tmp/src/index.ts +20 -0
  163. package/test/tmp/src/types/brief_news_category.ts +7 -0
  164. package/test/tmp/src/types/brief_news_category_post.ts +7 -0
  165. package/test/tmp/src/types/brief_news_category_put.ts +7 -0
  166. package/test/tmp/src/types/brief_news_category_query.ts +26 -0
  167. package/test/tmp/src/types/client.ts +5 -0
  168. package/test/tmp/src/types/client_post.ts +5 -0
  169. package/test/tmp/src/types/client_put.ts +5 -0
  170. package/test/tmp/src/types/client_query.ts +18 -0
  171. package/test/tmp/src/types/institution.ts +4 -0
  172. package/test/tmp/src/types/institution_post.ts +4 -0
  173. package/test/tmp/src/types/institution_put.ts +4 -0
  174. package/test/tmp/src/types/institution_query.ts +14 -0
  175. package/test/tmp/src/types/project.ts +7 -0
  176. package/test/tmp/src/types/project_post.ts +7 -0
  177. package/test/tmp/src/types/project_put.ts +7 -0
  178. package/test/tmp/src/types/project_query.ts +27 -0
  179. package/test/tmp/src/utils/utils.ts +17 -0
  180. package/test/tmp/tsconfig.json +14 -0
  181. 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
+ }