jxp 3.0.0 → 4.1.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 (229) hide show
  1. package/.env.sample +43 -6
  2. package/README.md +27 -13
  3. package/dist/bin/init_db.d.ts +3 -0
  4. package/dist/bin/init_db.d.ts.map +1 -0
  5. package/dist/bin/init_db.js +48 -0
  6. package/dist/bin/init_db.js.map +1 -0
  7. package/dist/bin/server.d.ts +4 -0
  8. package/dist/bin/server.d.ts.map +1 -0
  9. package/dist/bin/server.js +132 -0
  10. package/dist/bin/server.js.map +1 -0
  11. package/dist/bin/setup.d.ts +3 -0
  12. package/dist/bin/setup.d.ts.map +1 -0
  13. package/dist/bin/setup.js +185 -0
  14. package/dist/bin/setup.js.map +1 -0
  15. package/dist/globals.d.ts +14 -0
  16. package/dist/globals.d.ts.map +1 -0
  17. package/dist/globals.js +3 -0
  18. package/dist/globals.js.map +1 -0
  19. package/dist/libs/aggregate_guard.d.ts +5 -0
  20. package/dist/libs/aggregate_guard.d.ts.map +1 -0
  21. package/dist/libs/aggregate_guard.js +58 -0
  22. package/dist/libs/aggregate_guard.js.map +1 -0
  23. package/dist/libs/bulkwrite_guard.d.ts +5 -0
  24. package/dist/libs/bulkwrite_guard.d.ts.map +1 -0
  25. package/dist/libs/bulkwrite_guard.js +44 -0
  26. package/dist/libs/bulkwrite_guard.js.map +1 -0
  27. package/dist/libs/cache.d.ts +2 -0
  28. package/dist/libs/cache.d.ts.map +1 -0
  29. package/dist/libs/cache.js +94 -0
  30. package/dist/libs/cache.js.map +1 -0
  31. package/dist/libs/call_guard.d.ts +3 -0
  32. package/dist/libs/call_guard.d.ts.map +1 -0
  33. package/dist/libs/call_guard.js +17 -0
  34. package/dist/libs/call_guard.js.map +1 -0
  35. package/dist/libs/connection_string.d.ts +3 -0
  36. package/dist/libs/connection_string.d.ts.map +1 -0
  37. package/dist/libs/connection_string.js +4 -0
  38. package/dist/libs/connection_string.js.map +1 -0
  39. package/dist/libs/datamunging.d.ts +2 -0
  40. package/dist/libs/datamunging.d.ts.map +1 -0
  41. package/dist/libs/datamunging.js +320 -0
  42. package/dist/libs/datamunging.js.map +1 -0
  43. package/dist/libs/docs-auth.d.ts +25 -0
  44. package/dist/libs/docs-auth.d.ts.map +1 -0
  45. package/dist/libs/docs-auth.js +205 -0
  46. package/dist/libs/docs-auth.js.map +1 -0
  47. package/dist/libs/docs.d.ts +2 -0
  48. package/dist/libs/docs.d.ts.map +1 -0
  49. package/dist/libs/docs.js +328 -0
  50. package/dist/libs/docs.js.map +1 -0
  51. package/dist/libs/groups.d.ts +2 -0
  52. package/dist/libs/groups.d.ts.map +1 -0
  53. package/dist/libs/groups.js +136 -0
  54. package/dist/libs/groups.js.map +1 -0
  55. package/dist/libs/jxp.d.ts +4 -0
  56. package/dist/libs/jxp.d.ts.map +1 -0
  57. package/dist/libs/jxp.js +1176 -0
  58. package/dist/libs/jxp.js.map +1 -0
  59. package/dist/libs/link_index.d.ts +14 -0
  60. package/dist/libs/link_index.d.ts.map +1 -0
  61. package/dist/libs/link_index.js +37 -0
  62. package/dist/libs/link_index.js.map +1 -0
  63. package/dist/libs/load-config.d.ts +16 -0
  64. package/dist/libs/load-config.d.ts.map +1 -0
  65. package/dist/libs/load-config.js +166 -0
  66. package/dist/libs/load-config.js.map +1 -0
  67. package/dist/libs/login.d.ts +2 -0
  68. package/dist/libs/login.d.ts.map +1 -0
  69. package/dist/libs/login.js +244 -0
  70. package/dist/libs/login.js.map +1 -0
  71. package/dist/libs/login_rate_limit.d.ts +16 -0
  72. package/dist/libs/login_rate_limit.d.ts.map +1 -0
  73. package/dist/libs/login_rate_limit.js +49 -0
  74. package/dist/libs/login_rate_limit.js.map +1 -0
  75. package/dist/libs/modeldir.d.ts +5 -0
  76. package/dist/libs/modeldir.d.ts.map +1 -0
  77. package/dist/libs/modeldir.js +15 -0
  78. package/dist/libs/modeldir.js.map +1 -0
  79. package/dist/libs/query_limits.d.ts +2 -0
  80. package/dist/libs/query_limits.d.ts.map +1 -0
  81. package/dist/libs/query_limits.js +84 -0
  82. package/dist/libs/query_limits.js.map +1 -0
  83. package/dist/libs/query_manipulation.d.ts +3 -0
  84. package/dist/libs/query_manipulation.d.ts.map +1 -0
  85. package/{libs → dist/libs}/query_manipulation.js +22 -21
  86. package/dist/libs/query_manipulation.js.map +1 -0
  87. package/dist/libs/query_sanitize.d.ts +5 -0
  88. package/dist/libs/query_sanitize.d.ts.map +1 -0
  89. package/dist/libs/query_sanitize.js +109 -0
  90. package/dist/libs/query_sanitize.js.map +1 -0
  91. package/dist/libs/response_sanitize.d.ts +7 -0
  92. package/dist/libs/response_sanitize.d.ts.map +1 -0
  93. package/dist/libs/response_sanitize.js +57 -0
  94. package/dist/libs/response_sanitize.js.map +1 -0
  95. package/dist/libs/safe_error.d.ts +3 -0
  96. package/dist/libs/safe_error.d.ts.map +1 -0
  97. package/dist/libs/safe_error.js +14 -0
  98. package/dist/libs/safe_error.js.map +1 -0
  99. package/dist/libs/schema.d.ts +14 -0
  100. package/dist/libs/schema.d.ts.map +1 -0
  101. package/dist/libs/schema.js +98 -0
  102. package/dist/libs/schema.js.map +1 -0
  103. package/dist/libs/schema_description.d.ts +3 -0
  104. package/dist/libs/schema_description.d.ts.map +1 -0
  105. package/{libs → dist/libs}/schema_description.js +12 -21
  106. package/dist/libs/schema_description.js.map +1 -0
  107. package/dist/libs/security.d.ts +2 -0
  108. package/dist/libs/security.d.ts.map +1 -0
  109. package/dist/libs/security.js +428 -0
  110. package/dist/libs/security.js.map +1 -0
  111. package/dist/libs/setup.d.ts +2 -0
  112. package/dist/libs/setup.d.ts.map +1 -0
  113. package/dist/libs/setup.js +87 -0
  114. package/dist/libs/setup.js.map +1 -0
  115. package/dist/libs/startup-deprecations.d.ts +2 -0
  116. package/dist/libs/startup-deprecations.d.ts.map +1 -0
  117. package/dist/libs/startup-deprecations.js +21 -0
  118. package/dist/libs/startup-deprecations.js.map +1 -0
  119. package/dist/libs/startup.d.ts +16 -0
  120. package/dist/libs/startup.d.ts.map +1 -0
  121. package/dist/libs/startup.js +63 -0
  122. package/dist/libs/startup.js.map +1 -0
  123. package/dist/libs/ws.d.ts +2 -0
  124. package/dist/libs/ws.d.ts.map +1 -0
  125. package/{libs → dist/libs}/ws.js +91 -73
  126. package/dist/libs/ws.js.map +1 -0
  127. package/dist/models/apikey_model.d.ts +10 -0
  128. package/dist/models/apikey_model.d.ts.map +1 -0
  129. package/dist/models/apikey_model.js +14 -0
  130. package/dist/models/apikey_model.js.map +1 -0
  131. package/dist/models/link_model.d.ts +9 -0
  132. package/dist/models/link_model.d.ts.map +1 -0
  133. package/dist/models/link_model.js +20 -0
  134. package/dist/models/link_model.js.map +1 -0
  135. package/dist/models/refreshtoken_model.d.ts +11 -0
  136. package/dist/models/refreshtoken_model.d.ts.map +1 -0
  137. package/dist/models/refreshtoken_model.js +22 -0
  138. package/dist/models/refreshtoken_model.js.map +1 -0
  139. package/dist/models/test_model.d.ts +24 -0
  140. package/dist/models/test_model.d.ts.map +1 -0
  141. package/dist/models/test_model.js +44 -0
  142. package/dist/models/test_model.js.map +1 -0
  143. package/dist/models/token_model.d.ts +14 -0
  144. package/dist/models/token_model.d.ts.map +1 -0
  145. package/dist/models/token_model.js +25 -0
  146. package/dist/models/token_model.js.map +1 -0
  147. package/dist/models/user_model.d.ts +15 -0
  148. package/dist/models/user_model.d.ts.map +1 -0
  149. package/dist/models/user_model.js +38 -0
  150. package/dist/models/user_model.js.map +1 -0
  151. package/dist/models/usergroups_model.d.ts +9 -0
  152. package/dist/models/usergroups_model.d.ts.map +1 -0
  153. package/dist/models/usergroups_model.js +18 -0
  154. package/dist/models/usergroups_model.js.map +1 -0
  155. package/dist/types/jxp-config.d.ts +151 -0
  156. package/dist/types/jxp-config.d.ts.map +1 -0
  157. package/dist/types/jxp-config.js +3 -0
  158. package/dist/types/jxp-config.js.map +1 -0
  159. package/dist/types/schema-fields.d.ts +43 -0
  160. package/dist/types/schema-fields.d.ts.map +1 -0
  161. package/dist/types/schema-fields.js +3 -0
  162. package/dist/types/schema-fields.js.map +1 -0
  163. package/docs/aggregations.md +40 -21
  164. package/docs/api.md +55 -15
  165. package/docs/authentication.md +60 -37
  166. package/docs/bulk_writes.md +11 -8
  167. package/docs/caching.md +28 -11
  168. package/docs/changelog.md +258 -31
  169. package/docs/configuration.md +126 -115
  170. package/docs/hooks.md +12 -8
  171. package/docs/index.md +17 -17
  172. package/docs/installation.md +23 -18
  173. package/docs/permissions.md +33 -19
  174. package/docs/queries.md +9 -5
  175. package/docs/schemas.md +21 -10
  176. package/docs/special.md +4 -4
  177. package/docs/typescript.md +86 -0
  178. package/docs/websocket.md +99 -1
  179. package/mkdocs.yml +1 -0
  180. package/package.json +121 -69
  181. package/templates/api.pug +32 -0
  182. package/templates/app-server.js +43 -0
  183. package/templates/app.env.sample +8 -0
  184. package/templates/assets/api-console.js +151 -0
  185. package/templates/assets/docs-login.js +66 -0
  186. package/templates/assets/docs.css +244 -0
  187. package/templates/index.pug +67 -2
  188. package/templates/layout.pug +21 -11
  189. package/templates/login.pug +39 -0
  190. package/templates/md.pug +1 -1
  191. package/templates/model.pug +117 -68
  192. package/templates/navbar.pug +25 -21
  193. package/templates/sidebar.pug +30 -0
  194. package/.env +0 -9
  195. package/.eslintrc.json +0 -20
  196. package/.jshintrc +0 -4
  197. package/.vscode/launch.json +0 -34
  198. package/.vscode/settings.json +0 -3
  199. package/Dockerfile +0 -7
  200. package/bin/init_db.js +0 -54
  201. package/bin/server.js +0 -131
  202. package/bin/setup.js +0 -190
  203. package/config_sample.json +0 -10
  204. package/docker-compose.yml +0 -32
  205. package/libs/cache.js +0 -92
  206. package/libs/connection_string.js +0 -24
  207. package/libs/datamunging.js +0 -335
  208. package/libs/docs.js +0 -162
  209. package/libs/groups.js +0 -133
  210. package/libs/jxp.js +0 -1208
  211. package/libs/login.js +0 -222
  212. package/libs/modeldir.js +0 -14
  213. package/libs/schema.js +0 -99
  214. package/libs/security.js +0 -410
  215. package/libs/setup.js +0 -90
  216. package/models/apikey_model.js +0 -10
  217. package/models/link_model.js +0 -17
  218. package/models/refreshtoken_model.js +0 -20
  219. package/models/test_model.js +0 -50
  220. package/models/token_model.js +0 -23
  221. package/models/user_model.js +0 -38
  222. package/models/usergroups_model.js +0 -15
  223. package/setup.sh +0 -3
  224. package/test/.eslintrc.json +0 -13
  225. package/test/auth.js +0 -190
  226. package/test/init.js +0 -92
  227. package/test/setup.test.js +0 -62
  228. package/test/test.js +0 -1527
  229. package/test/wstest.js.old +0 -124
package/libs/login.js DELETED
@@ -1,222 +0,0 @@
1
- const axios = require("axios");
2
- const jwt = require("jsonwebtoken");
3
- const bcrypt = require('bcryptjs');
4
- const security = require("../libs/security");
5
- const nodemailer = require('nodemailer');
6
- const errors = require("restify-errors");
7
- const smtpTransport = require('nodemailer-smtp-transport');
8
- const path = require("path");
9
- let User = null;
10
-
11
- var init = function (config) {
12
- User = require(path.join(config.model_dir, 'user_model'));
13
- security.init(config);
14
- };
15
-
16
- const recover = async (req, res) => {
17
- try {
18
- // create reusable transporter object using SMTP transport
19
- const transporter = nodemailer.createTransport(smtpTransport({
20
- host: req.config.smtp_server,
21
- port: 25,
22
- auth: {
23
- user: req.config.smtp_username,
24
- pass: req.config.smtp_password,
25
- },
26
- // secure: true,
27
- tls: { rejectUnauthorized: false }
28
- }));
29
- const email = req.body.email;
30
- if (!email) {
31
- console.error("Missing email parameter");
32
- throw new errors.BadRequestError("Missing email parameter");
33
- }
34
- const user = await User.findOne({ email });
35
- if (!user) {
36
- throw new errors.NotFoundError(`User with email ${email} Not Found`);
37
- }
38
- const result = await security.generateApiKey(user._id);
39
- const token = jwt.sign({ apikey: result.apikey, email: user.email, id: user._id }, req.config.shared_secret, { expiresIn: "2d" });
40
- var text = `Someone (hopefully you) requested a password reset. Please click on the following url to recover your password. If you did not request a password reset, you can ignore this message. \n${req.config.password_recovery_url}/${token}`;
41
- var html = text;
42
- var mail_format = req.params.mail_format || req.body.mail_format;
43
- if (mail_format) {
44
- html = mail_format;
45
- html = html.replace(/\{\{recover_url\}\}/i, req.config.password_recovery_url + "/" + token);
46
- }
47
- transporter.sendMail({
48
- from: req.config.smtp_from,
49
- to: user.email,
50
- subject: "Password Recovery",
51
- text: text,
52
- html: html
53
- }, function (result) {
54
- console.log({ msg: "Mailer result", result });
55
- });
56
- res.send({ status: "ok", message: "Sent recovery email" });
57
- } catch (err) {
58
- if (err.code) throw err;
59
- throw new errors.UnauthorizedError(err.toString());
60
- }
61
- }
62
-
63
- const logout = async (req, res) => {
64
- try {
65
- if (!res.user) throw new errors.ForbiddenError("You don't seem to be logged in");
66
- await security.revokeToken(res.user._id);
67
- res.send({ status: "ok", message: "User logged out" });
68
- } catch (err) {
69
- console.error(err);
70
- if (err.code) throw err;
71
- throw new errors.InternalServerError(err.toString());
72
- }
73
- }
74
-
75
- const oauth = (req, res, next) => { // Log in through an OAuth2 provider, defined in config.js
76
- const provider_config = req.config.oauth[req.params.provider];
77
- if (!provider_config) {
78
- throw new errors.InternalServerError(`oAuth ${req.params.provider} config not defined`);
79
- }
80
- const state = Math.random().toString(36).substring(7);
81
- const uri = `${provider_config.auth_uri}?client_id=${provider_config.app_id}&redirect_uri=${req.config.url}/login/oauth/callback/${req.params.provider}&scope=${provider_config.scope}&state=${state}&response_type=code`;
82
- res.redirect(uri, next);
83
- }
84
-
85
- const oauth_callback = async (req, res) => {
86
- const provider = req.params.provider;
87
- const provider_config = req.config.oauth[provider];
88
- const code = req.query.code;
89
- try {
90
- if (req.query.error) {
91
- throw (req.query.error);
92
- }
93
- if (!code) {
94
- throw ("missing_code");
95
- }
96
- const token = (await axios.post(provider_config.token_uri, {
97
- client_id: provider_config.app_id,
98
- redirect_uri: `${req.config.url}/login/oauth/callback/${req.params.provider}`,
99
- client_secret: provider_config.app_secret,
100
- code: code,
101
- grant_type: "authorization_code"
102
- })).data;
103
- if (!token.access_token) {
104
- throw ("missing_access_token");
105
- }
106
- const data = (await axios.get(provider_config.api_uri, { headers: { Authorization: `Bearer ${token.access_token}` } })).data;
107
- if (data.emailAddress) {
108
- data.email = data.emailAddress;
109
- }
110
- if (data.elements && data.elements[0] && data.elements[0]["handle~"] && data.elements[0]["handle~"].emailAddress) { // LinkedIn
111
- data.email = data.elements[0]["handle~"].emailAddress;
112
- }
113
- if (!data.email) {
114
- throw ("missing_data");
115
- }
116
- var search = {};
117
- search[provider + ".id"] = data.id;
118
- const user = await User.findOne(search);
119
- if (!user) {
120
- throw ("no_user");
121
- }
122
- user[provider] = data;
123
- await user.save();
124
- const apikey = await security.generateApiKey(user._id)
125
- var jwt_token = jwt.sign({ apikey: apikey.apikey, user: user }, req.config.shared_secret, {
126
- expiresIn: "1m"
127
- });
128
- res.redirect(`${req.config.oauth.success_uri}?token=${jwt_token}`);
129
- } catch (err) {
130
- console.error(err);
131
- if (typeof err === 'string' || err instanceof String) {
132
- res.redirect(`${req.config.oauth.fail_uri}?error=${err}&provider=${provider}`);
133
- } else {
134
- res.redirect(`${req.config.oauth.fail_uri}?error=unknown&provider=${provider}`);
135
- }
136
- return;
137
- }
138
- }
139
-
140
- const login = async (req, res) => {
141
- const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
142
- let email = req.params.email || req.body.email;
143
- let password = req.params.password || req.body.password;
144
- const userpass = security.basicAuthData(req);
145
- if (userpass) {
146
- email = userpass[0];
147
- password = userpass[1];
148
- }
149
- if ((!password) || (!email)) {
150
- console.error(new Date(), "Missing email or password parameters");
151
- throw new errors.ForbiddenError("Missing email or password parameters");
152
- }
153
- try {
154
- const user = await User.findOne({ email });
155
- if (!user) {
156
- console.error(new Date(), `Authentication failed - user not found`, ip, email);
157
- throw new errors.ForbiddenError("Incorrect email or password");
158
- }
159
- if (!(await bcrypt.compare(password, user.password))) {
160
- console.error(new Date(), `Authentication failed - invalid password`, ip, email);
161
- throw new errors.ForbiddenError("Incorrect email or password");
162
- }
163
- const token = await security.refreshToken(user._id);
164
- const refreshtoken = await security.ensureRefreshToken(user._id);
165
- const apikey = await security.generateApiKey(user._id)
166
- res.result = ({
167
- user_id: user._id,
168
- token: token.access_token,
169
- apikey: apikey.apikey,
170
- token_expires: security.tokenExpires(token),
171
- refresh_token: refreshtoken.refresh_token,
172
- refresh_token_expires: security.tokenExpires(refreshtoken),
173
- provider: token.provider,
174
- });
175
- } catch (err) {
176
- console.error(new Date(), `Authentication failed`, ip, err);
177
- if (err.code) throw err;
178
- throw new errors.ForbiddenError("Incorrect email or password");
179
- }
180
- }
181
-
182
- const getJWT = async (req, res) => {
183
- var user = null;
184
- if (!res.user.admin) {
185
- throw new errors.UnauthorizedError("Unauthorized");
186
- }
187
- var email = req.params.email || req.body.email;
188
- if (!email) {
189
- throw new errors.BadRequestError("Email required");
190
- }
191
- try {
192
- const result = await User.findOne({ email: email });
193
- if (!result || !result._id) {
194
- throw new errors.NotFoundError("User not found");
195
- }
196
- user = result;
197
- try {
198
- const apikey = await security.generateApiKey(user._id)
199
- var token = jwt.sign({ apikey: apikey.apikey, email: user.email, id: user._id }, req.config.shared_secret, {
200
- expiresIn: "2d"
201
- });
202
- res.send({ email: user.email, token: token });
203
- } catch (err) {
204
- throw new errors.UnauthorizedError("Unauthorized");
205
- }
206
- } catch (err) {
207
- if (err.code) throw err;
208
- throw new errors.InternalServerError(err.toString());
209
- }
210
- }
211
-
212
- const Login = {
213
- init,
214
- recover,
215
- logout,
216
- oauth,
217
- oauth_callback,
218
- login,
219
- getJWT
220
- };
221
-
222
- module.exports = Login;
package/libs/modeldir.js DELETED
@@ -1,14 +0,0 @@
1
- const glob = require("glob");
2
- const path = require("path");
3
-
4
- const findModelDir = (dir) => {
5
- if (dir === "/") throw("Model dir not found");
6
- let result = glob.sync(path.join(dir, "**/user_model.js"));
7
- if (result.length) {
8
- return path.dirname(result.pop());
9
- }
10
- const found = findModelDir(path.join(dir, "../"));
11
- return found;
12
- }
13
-
14
- module.exports = { findModelDir }
package/libs/schema.js DELETED
@@ -1,99 +0,0 @@
1
- /* global ObjectId */
2
-
3
- // Our general requirements
4
- const mongoose = require('mongoose');
5
- const path = require("path");
6
- const config = require("config");
7
- const JXPHelper = require('jxp-helper');
8
- const modeldir = require("./modeldir");
9
-
10
- // Set some global types
11
- global.ObjectId = mongoose.Schema.Types.ObjectId;
12
- global.Mixed = mongoose.Schema.Types.Mixed;
13
- // Add this to the top of your model to avoid eslint warnings: /* global ObjectId Mixed */
14
-
15
- const model_dir = config.model_dir || modeldir.findModelDir(path.dirname(process.argv[1]));
16
-
17
- const getModelFileFromRef = ref => {
18
- return path.join(model_dir, `${String(ref).toLowerCase()}_model`);
19
- }
20
-
21
- class Schema extends mongoose.Schema {
22
- constructor(definition, opts) {
23
- // Set default options
24
- opts = Object.assign({
25
- timestamps: true,
26
- toJSON: { virtuals: true },
27
- toObject: { virtuals: true }
28
- }, opts);
29
- // Set default defiitions
30
- definition = Object.assign({
31
- _deleted: { type: Boolean, default: false, index: true },
32
- _owner_id: { type: ObjectId, link: "User", map_to: "_owner", index: true },
33
- _updated_by_id: { type: ObjectId, link: "User", map_to: "_updated_by", index: true },
34
- }, definition);
35
- // Set up our jxp-helper so that we call call the API from within the API (if we've set config.apikey)
36
- if (!global.jxphelper) {
37
- const jxp_settings = {};
38
- if (global.apikey) jxp_settings.apikey = global.apikey;
39
- if (global.server) jxp_settings.server = global.server;
40
- if (jxp_settings.apikey && jxp_settings.server) global.jxphelper = new JXPHelper(jxp_settings);
41
- }
42
- // construct our parent
43
- super(definition, opts);
44
- // Some properties
45
- this.opts = opts;
46
- this.definition = definition;
47
- // Action!
48
- this.index({ createdAt: -1 });
49
- this.index({ updatedAt: -1 });
50
- this.setPerms();
51
- this.generateLinks();
52
- }
53
-
54
- setPerms() {
55
- // Create the perms
56
- this.set("_perms", Object.assign({
57
- admin: "", // CRUD = Create, Retrieve, Update and Delete
58
- owner: "",
59
- user: "",
60
- all: "" // Unauthenticated users will be able to read from test, but that is all
61
- }, this.opts.perms));
62
- }
63
-
64
- generateLinks() {
65
- let loaded_files = [];
66
- // Find the links in our definitions and create virtuals for non-destructive populating
67
- // Example: link_id: { type: ObjectId, link: "link", }
68
- // Example with a custom key: link_id: { type: ObjectId, link: "link", map_to: "custom_name" }
69
- for (let key of Object.keys(this.definition)) {
70
- let def = this.definition[key];
71
- let is_array = false;
72
- if (def[0]) {
73
- def = def[0];
74
- is_array = true;
75
- }
76
- if (!def.link) continue;
77
- const virtual_name = def.map_to || def.virtual || String(def.link).toLowerCase();
78
- if (!loaded_files.includes(def.link)) {
79
- require(getModelFileFromRef(def.link));
80
- loaded_files.push(def.link);
81
- }
82
- this.virtual(virtual_name, {
83
- ref: def.link,
84
- localField: key,
85
- foreignField: "_id",
86
- justOne: def.justOne || !is_array,
87
- options: Object.assign({}, def.options)
88
- })
89
- }
90
- }
91
- }
92
-
93
- // Now we don't even need to import mongoose into our models for type
94
- Schema.Types = mongoose.Schema.Types;
95
-
96
- // Slightly self-referential, try not to think about it
97
- Schema.model = mongoose.model;
98
-
99
- module.exports = Schema;