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.
- package/.env.sample +43 -6
- package/README.md +27 -13
- package/dist/bin/init_db.d.ts +3 -0
- package/dist/bin/init_db.d.ts.map +1 -0
- package/dist/bin/init_db.js +48 -0
- package/dist/bin/init_db.js.map +1 -0
- package/dist/bin/server.d.ts +4 -0
- package/dist/bin/server.d.ts.map +1 -0
- package/dist/bin/server.js +132 -0
- package/dist/bin/server.js.map +1 -0
- package/dist/bin/setup.d.ts +3 -0
- package/dist/bin/setup.d.ts.map +1 -0
- package/dist/bin/setup.js +185 -0
- package/dist/bin/setup.js.map +1 -0
- package/dist/globals.d.ts +14 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +3 -0
- package/dist/globals.js.map +1 -0
- package/dist/libs/aggregate_guard.d.ts +5 -0
- package/dist/libs/aggregate_guard.d.ts.map +1 -0
- package/dist/libs/aggregate_guard.js +58 -0
- package/dist/libs/aggregate_guard.js.map +1 -0
- package/dist/libs/bulkwrite_guard.d.ts +5 -0
- package/dist/libs/bulkwrite_guard.d.ts.map +1 -0
- package/dist/libs/bulkwrite_guard.js +44 -0
- package/dist/libs/bulkwrite_guard.js.map +1 -0
- package/dist/libs/cache.d.ts +2 -0
- package/dist/libs/cache.d.ts.map +1 -0
- package/dist/libs/cache.js +94 -0
- package/dist/libs/cache.js.map +1 -0
- package/dist/libs/call_guard.d.ts +3 -0
- package/dist/libs/call_guard.d.ts.map +1 -0
- package/dist/libs/call_guard.js +17 -0
- package/dist/libs/call_guard.js.map +1 -0
- package/dist/libs/connection_string.d.ts +3 -0
- package/dist/libs/connection_string.d.ts.map +1 -0
- package/dist/libs/connection_string.js +4 -0
- package/dist/libs/connection_string.js.map +1 -0
- package/dist/libs/datamunging.d.ts +2 -0
- package/dist/libs/datamunging.d.ts.map +1 -0
- package/dist/libs/datamunging.js +320 -0
- package/dist/libs/datamunging.js.map +1 -0
- package/dist/libs/docs-auth.d.ts +25 -0
- package/dist/libs/docs-auth.d.ts.map +1 -0
- package/dist/libs/docs-auth.js +205 -0
- package/dist/libs/docs-auth.js.map +1 -0
- package/dist/libs/docs.d.ts +2 -0
- package/dist/libs/docs.d.ts.map +1 -0
- package/dist/libs/docs.js +328 -0
- package/dist/libs/docs.js.map +1 -0
- package/dist/libs/groups.d.ts +2 -0
- package/dist/libs/groups.d.ts.map +1 -0
- package/dist/libs/groups.js +136 -0
- package/dist/libs/groups.js.map +1 -0
- package/dist/libs/jxp.d.ts +4 -0
- package/dist/libs/jxp.d.ts.map +1 -0
- package/dist/libs/jxp.js +1176 -0
- package/dist/libs/jxp.js.map +1 -0
- package/dist/libs/link_index.d.ts +14 -0
- package/dist/libs/link_index.d.ts.map +1 -0
- package/dist/libs/link_index.js +37 -0
- package/dist/libs/link_index.js.map +1 -0
- package/dist/libs/load-config.d.ts +16 -0
- package/dist/libs/load-config.d.ts.map +1 -0
- package/dist/libs/load-config.js +166 -0
- package/dist/libs/load-config.js.map +1 -0
- package/dist/libs/login.d.ts +2 -0
- package/dist/libs/login.d.ts.map +1 -0
- package/dist/libs/login.js +244 -0
- package/dist/libs/login.js.map +1 -0
- package/dist/libs/login_rate_limit.d.ts +16 -0
- package/dist/libs/login_rate_limit.d.ts.map +1 -0
- package/dist/libs/login_rate_limit.js +49 -0
- package/dist/libs/login_rate_limit.js.map +1 -0
- package/dist/libs/modeldir.d.ts +5 -0
- package/dist/libs/modeldir.d.ts.map +1 -0
- package/dist/libs/modeldir.js +15 -0
- package/dist/libs/modeldir.js.map +1 -0
- package/dist/libs/query_limits.d.ts +2 -0
- package/dist/libs/query_limits.d.ts.map +1 -0
- package/dist/libs/query_limits.js +84 -0
- package/dist/libs/query_limits.js.map +1 -0
- package/dist/libs/query_manipulation.d.ts +3 -0
- package/dist/libs/query_manipulation.d.ts.map +1 -0
- package/{libs → dist/libs}/query_manipulation.js +22 -21
- package/dist/libs/query_manipulation.js.map +1 -0
- package/dist/libs/query_sanitize.d.ts +5 -0
- package/dist/libs/query_sanitize.d.ts.map +1 -0
- package/dist/libs/query_sanitize.js +109 -0
- package/dist/libs/query_sanitize.js.map +1 -0
- package/dist/libs/response_sanitize.d.ts +7 -0
- package/dist/libs/response_sanitize.d.ts.map +1 -0
- package/dist/libs/response_sanitize.js +57 -0
- package/dist/libs/response_sanitize.js.map +1 -0
- package/dist/libs/safe_error.d.ts +3 -0
- package/dist/libs/safe_error.d.ts.map +1 -0
- package/dist/libs/safe_error.js +14 -0
- package/dist/libs/safe_error.js.map +1 -0
- package/dist/libs/schema.d.ts +14 -0
- package/dist/libs/schema.d.ts.map +1 -0
- package/dist/libs/schema.js +98 -0
- package/dist/libs/schema.js.map +1 -0
- package/dist/libs/schema_description.d.ts +3 -0
- package/dist/libs/schema_description.d.ts.map +1 -0
- package/{libs → dist/libs}/schema_description.js +12 -21
- package/dist/libs/schema_description.js.map +1 -0
- package/dist/libs/security.d.ts +2 -0
- package/dist/libs/security.d.ts.map +1 -0
- package/dist/libs/security.js +428 -0
- package/dist/libs/security.js.map +1 -0
- package/dist/libs/setup.d.ts +2 -0
- package/dist/libs/setup.d.ts.map +1 -0
- package/dist/libs/setup.js +87 -0
- package/dist/libs/setup.js.map +1 -0
- package/dist/libs/startup-deprecations.d.ts +2 -0
- package/dist/libs/startup-deprecations.d.ts.map +1 -0
- package/dist/libs/startup-deprecations.js +21 -0
- package/dist/libs/startup-deprecations.js.map +1 -0
- package/dist/libs/startup.d.ts +16 -0
- package/dist/libs/startup.d.ts.map +1 -0
- package/dist/libs/startup.js +63 -0
- package/dist/libs/startup.js.map +1 -0
- package/dist/libs/ws.d.ts +2 -0
- package/dist/libs/ws.d.ts.map +1 -0
- package/{libs → dist/libs}/ws.js +91 -73
- package/dist/libs/ws.js.map +1 -0
- package/dist/models/apikey_model.d.ts +10 -0
- package/dist/models/apikey_model.d.ts.map +1 -0
- package/dist/models/apikey_model.js +14 -0
- package/dist/models/apikey_model.js.map +1 -0
- package/dist/models/link_model.d.ts +9 -0
- package/dist/models/link_model.d.ts.map +1 -0
- package/dist/models/link_model.js +20 -0
- package/dist/models/link_model.js.map +1 -0
- package/dist/models/refreshtoken_model.d.ts +11 -0
- package/dist/models/refreshtoken_model.d.ts.map +1 -0
- package/dist/models/refreshtoken_model.js +22 -0
- package/dist/models/refreshtoken_model.js.map +1 -0
- package/dist/models/test_model.d.ts +24 -0
- package/dist/models/test_model.d.ts.map +1 -0
- package/dist/models/test_model.js +44 -0
- package/dist/models/test_model.js.map +1 -0
- package/dist/models/token_model.d.ts +14 -0
- package/dist/models/token_model.d.ts.map +1 -0
- package/dist/models/token_model.js +25 -0
- package/dist/models/token_model.js.map +1 -0
- package/dist/models/user_model.d.ts +15 -0
- package/dist/models/user_model.d.ts.map +1 -0
- package/dist/models/user_model.js +38 -0
- package/dist/models/user_model.js.map +1 -0
- package/dist/models/usergroups_model.d.ts +9 -0
- package/dist/models/usergroups_model.d.ts.map +1 -0
- package/dist/models/usergroups_model.js +18 -0
- package/dist/models/usergroups_model.js.map +1 -0
- package/dist/types/jxp-config.d.ts +151 -0
- package/dist/types/jxp-config.d.ts.map +1 -0
- package/dist/types/jxp-config.js +3 -0
- package/dist/types/jxp-config.js.map +1 -0
- package/dist/types/schema-fields.d.ts +43 -0
- package/dist/types/schema-fields.d.ts.map +1 -0
- package/dist/types/schema-fields.js +3 -0
- package/dist/types/schema-fields.js.map +1 -0
- package/docs/aggregations.md +40 -21
- package/docs/api.md +55 -15
- package/docs/authentication.md +60 -37
- package/docs/bulk_writes.md +11 -8
- package/docs/caching.md +28 -11
- package/docs/changelog.md +258 -31
- package/docs/configuration.md +126 -115
- package/docs/hooks.md +12 -8
- package/docs/index.md +17 -17
- package/docs/installation.md +23 -18
- package/docs/permissions.md +33 -19
- package/docs/queries.md +9 -5
- package/docs/schemas.md +21 -10
- package/docs/special.md +4 -4
- package/docs/typescript.md +86 -0
- package/docs/websocket.md +99 -1
- package/mkdocs.yml +1 -0
- package/package.json +121 -69
- package/templates/api.pug +32 -0
- package/templates/app-server.js +43 -0
- package/templates/app.env.sample +8 -0
- package/templates/assets/api-console.js +151 -0
- package/templates/assets/docs-login.js +66 -0
- package/templates/assets/docs.css +244 -0
- package/templates/index.pug +67 -2
- package/templates/layout.pug +21 -11
- package/templates/login.pug +39 -0
- package/templates/md.pug +1 -1
- package/templates/model.pug +117 -68
- package/templates/navbar.pug +25 -21
- package/templates/sidebar.pug +30 -0
- package/.env +0 -9
- package/.eslintrc.json +0 -20
- package/.jshintrc +0 -4
- package/.vscode/launch.json +0 -34
- package/.vscode/settings.json +0 -3
- package/Dockerfile +0 -7
- package/bin/init_db.js +0 -54
- package/bin/server.js +0 -131
- package/bin/setup.js +0 -190
- package/config_sample.json +0 -10
- package/docker-compose.yml +0 -32
- package/libs/cache.js +0 -92
- package/libs/connection_string.js +0 -24
- package/libs/datamunging.js +0 -335
- package/libs/docs.js +0 -162
- package/libs/groups.js +0 -133
- package/libs/jxp.js +0 -1208
- package/libs/login.js +0 -222
- package/libs/modeldir.js +0 -14
- package/libs/schema.js +0 -99
- package/libs/security.js +0 -410
- package/libs/setup.js +0 -90
- package/models/apikey_model.js +0 -10
- package/models/link_model.js +0 -17
- package/models/refreshtoken_model.js +0 -20
- package/models/test_model.js +0 -50
- package/models/token_model.js +0 -23
- package/models/user_model.js +0 -38
- package/models/usergroups_model.js +0 -15
- package/setup.sh +0 -3
- package/test/.eslintrc.json +0 -13
- package/test/auth.js +0 -190
- package/test/init.js +0 -92
- package/test/setup.test.js +0 -62
- package/test/test.js +0 -1527
- package/test/wstest.js.old +0 -124
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--docs-sidebar-width: 280px;
|
|
3
|
+
--docs-topbar-height: 56px;
|
|
4
|
+
--docs-accent: #0d6efd;
|
|
5
|
+
--docs-sidebar-bg: #f8f9fa;
|
|
6
|
+
--docs-border: #dee2e6;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
body.docs-body {
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
background: #fff;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.docs-topbar {
|
|
15
|
+
height: var(--docs-topbar-height);
|
|
16
|
+
border-bottom: 1px solid var(--docs-border);
|
|
17
|
+
background: #fff;
|
|
18
|
+
z-index: 1030;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.docs-brand {
|
|
22
|
+
font-weight: 600;
|
|
23
|
+
font-size: 1.1rem;
|
|
24
|
+
color: #212529;
|
|
25
|
+
text-decoration: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.docs-brand:hover {
|
|
29
|
+
color: var(--docs-accent);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.docs-shell {
|
|
33
|
+
display: flex;
|
|
34
|
+
min-height: calc(100vh - var(--docs-topbar-height));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.docs-sidebar {
|
|
38
|
+
width: var(--docs-sidebar-width);
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
border-right: 1px solid var(--docs-border);
|
|
41
|
+
background: var(--docs-sidebar-bg);
|
|
42
|
+
overflow-y: auto;
|
|
43
|
+
padding: 1rem 0;
|
|
44
|
+
position: sticky;
|
|
45
|
+
top: var(--docs-topbar-height);
|
|
46
|
+
height: calc(100vh - var(--docs-topbar-height));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.docs-main {
|
|
50
|
+
flex: 1;
|
|
51
|
+
min-width: 0;
|
|
52
|
+
padding: 1.5rem 2rem 3rem;
|
|
53
|
+
max-width: 960px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.docs-sidebar-section {
|
|
57
|
+
padding: 0 1rem;
|
|
58
|
+
margin-bottom: 1.25rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.docs-sidebar-title {
|
|
62
|
+
font-size: 0.7rem;
|
|
63
|
+
font-weight: 700;
|
|
64
|
+
text-transform: uppercase;
|
|
65
|
+
letter-spacing: 0.06em;
|
|
66
|
+
color: #6c757d;
|
|
67
|
+
margin-bottom: 0.5rem;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.docs-nav-link {
|
|
71
|
+
display: block;
|
|
72
|
+
padding: 0.35rem 0.75rem;
|
|
73
|
+
font-size: 0.875rem;
|
|
74
|
+
color: #495057;
|
|
75
|
+
text-decoration: none;
|
|
76
|
+
border-radius: 0.375rem;
|
|
77
|
+
border-left: 3px solid transparent;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.docs-nav-link:hover {
|
|
81
|
+
background: rgba(13, 110, 253, 0.08);
|
|
82
|
+
color: var(--docs-accent);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.docs-nav-link.active {
|
|
86
|
+
background: rgba(13, 110, 253, 0.12);
|
|
87
|
+
color: var(--docs-accent);
|
|
88
|
+
border-left-color: var(--docs-accent);
|
|
89
|
+
font-weight: 500;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.docs-api-key-wrap {
|
|
93
|
+
max-width: 220px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.docs-api-key-wrap .form-control {
|
|
97
|
+
font-size: 0.8rem;
|
|
98
|
+
font-family: ui-monospace, monospace;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@media (max-width: 991.98px) {
|
|
102
|
+
.docs-sidebar {
|
|
103
|
+
display: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.docs-main {
|
|
107
|
+
padding: 1rem;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.docs-hero {
|
|
112
|
+
padding: 2.5rem 0 2rem;
|
|
113
|
+
border-bottom: 1px solid var(--docs-border);
|
|
114
|
+
margin-bottom: 2rem;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.docs-hero h1 {
|
|
118
|
+
font-size: 2.25rem;
|
|
119
|
+
font-weight: 700;
|
|
120
|
+
margin-bottom: 0.5rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.docs-hero .lead {
|
|
124
|
+
color: #6c757d;
|
|
125
|
+
max-width: 36rem;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.docs-content h1,
|
|
129
|
+
.docs-content h2,
|
|
130
|
+
.docs-content h3 {
|
|
131
|
+
margin-top: 1.5rem;
|
|
132
|
+
margin-bottom: 0.75rem;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.docs-content pre {
|
|
136
|
+
background: #f8f9fa;
|
|
137
|
+
border: 1px solid var(--docs-border);
|
|
138
|
+
border-radius: 0.375rem;
|
|
139
|
+
padding: 1rem;
|
|
140
|
+
overflow-x: auto;
|
|
141
|
+
font-size: 0.85rem;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.docs-content code {
|
|
145
|
+
font-size: 0.875em;
|
|
146
|
+
color: #d63384;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.docs-content pre code {
|
|
150
|
+
color: inherit;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.docs-content table {
|
|
154
|
+
margin: 1rem 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.method-badge {
|
|
158
|
+
font-family: ui-monospace, monospace;
|
|
159
|
+
font-size: 0.75rem;
|
|
160
|
+
font-weight: 700;
|
|
161
|
+
min-width: 4.5rem;
|
|
162
|
+
text-align: center;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.method-get { background-color: #198754 !important; }
|
|
166
|
+
.method-post { background-color: #0d6efd !important; }
|
|
167
|
+
.method-put { background-color: #fd7e14 !important; }
|
|
168
|
+
.method-delete { background-color: #dc3545 !important; }
|
|
169
|
+
|
|
170
|
+
.endpoint-path {
|
|
171
|
+
font-family: ui-monospace, monospace;
|
|
172
|
+
font-size: 0.9rem;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.api-try-panel {
|
|
176
|
+
border: 1px solid var(--docs-border);
|
|
177
|
+
border-radius: 0.375rem;
|
|
178
|
+
padding: 1rem;
|
|
179
|
+
background: #fafbfc;
|
|
180
|
+
margin-top: 0.75rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.api-response {
|
|
184
|
+
font-family: ui-monospace, monospace;
|
|
185
|
+
font-size: 0.8rem;
|
|
186
|
+
background: #212529;
|
|
187
|
+
color: #e9ecef;
|
|
188
|
+
border-radius: 0.375rem;
|
|
189
|
+
padding: 1rem;
|
|
190
|
+
max-height: 320px;
|
|
191
|
+
overflow: auto;
|
|
192
|
+
white-space: pre-wrap;
|
|
193
|
+
word-break: break-word;
|
|
194
|
+
margin-top: 0.75rem;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.api-response.empty {
|
|
198
|
+
background: #f8f9fa;
|
|
199
|
+
color: #6c757d;
|
|
200
|
+
border: 1px dashed var(--docs-border);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.api-response-meta {
|
|
204
|
+
font-size: 0.8rem;
|
|
205
|
+
color: #6c757d;
|
|
206
|
+
margin-top: 0.5rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.field-details pre {
|
|
210
|
+
font-size: 0.75rem;
|
|
211
|
+
max-height: 200px;
|
|
212
|
+
overflow: auto;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.feature-card {
|
|
216
|
+
height: 100%;
|
|
217
|
+
border: 1px solid var(--docs-border);
|
|
218
|
+
transition: box-shadow 0.15s ease;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.feature-card:hover {
|
|
222
|
+
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.08);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.docs-security-note {
|
|
226
|
+
font-size: 0.8rem;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.docs-main-full {
|
|
230
|
+
max-width: 480px;
|
|
231
|
+
margin: 0 auto;
|
|
232
|
+
padding-top: 2rem;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.docs-login-wrap {
|
|
236
|
+
display: flex;
|
|
237
|
+
justify-content: center;
|
|
238
|
+
padding: 1rem 0 3rem;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.docs-login-card {
|
|
242
|
+
width: 100%;
|
|
243
|
+
max-width: 400px;
|
|
244
|
+
}
|
package/templates/index.pug
CHANGED
|
@@ -1,4 +1,69 @@
|
|
|
1
1
|
extends layout
|
|
2
2
|
|
|
3
|
-
block content
|
|
4
|
-
|
|
3
|
+
block content
|
|
4
|
+
.docs-hero
|
|
5
|
+
h1= name
|
|
6
|
+
p.lead
|
|
7
|
+
| REST API powered by
|
|
8
|
+
a(href="https://jxp.readthedocs.io" target="_blank" rel="noopener") JXP
|
|
9
|
+
| — define Mongoose schemas, get a full API with auth, permissions, and smart queries.
|
|
10
|
+
.d-flex.flex-wrap.gap-2.mt-3
|
|
11
|
+
if first_guide_url
|
|
12
|
+
a.btn.btn-primary(href=first_guide_url) Get started
|
|
13
|
+
a.btn.btn-outline-primary(href="/docs/api") Browse API
|
|
14
|
+
a.btn.btn-outline-secondary(href="/docs/md/api.md") REST reference
|
|
15
|
+
|
|
16
|
+
.row.g-4.mb-4
|
|
17
|
+
.col-md-6
|
|
18
|
+
.card.h-100
|
|
19
|
+
.card-header.fw-semibold Quick start
|
|
20
|
+
.card-body
|
|
21
|
+
p.mb-2 Authenticate with an API key header#{docs_access === 'public' ? ' (optional for exploring docs; required for live calls)' : ''}:
|
|
22
|
+
pre.mb-3
|
|
23
|
+
code.
|
|
24
|
+
curl -H "X-API-Key: YOUR_KEY" \
|
|
25
|
+
"#{base_url}/api/MODEL?limit=5"
|
|
26
|
+
p.mb-0.small.text-muted
|
|
27
|
+
if docs_access === 'protected'
|
|
28
|
+
| After signing in, your API key is filled in automatically for
|
|
29
|
+
strong Try it
|
|
30
|
+
| panels on API resource pages.
|
|
31
|
+
else
|
|
32
|
+
| Set your key in the top bar to use
|
|
33
|
+
strong Try it
|
|
34
|
+
| panels on API resource pages. Keys are stored in the browser only when “Remember” is checked.
|
|
35
|
+
.col-md-6
|
|
36
|
+
.card.h-100
|
|
37
|
+
.card-header.fw-semibold API at a glance
|
|
38
|
+
.card-body
|
|
39
|
+
p.mb-2
|
|
40
|
+
strong= model_list.length
|
|
41
|
+
| resource#{model_list.length !== 1 ? 's' : ''} registered
|
|
42
|
+
if model_list.length
|
|
43
|
+
.d-flex.flex-wrap.gap-1
|
|
44
|
+
each m in model_list.slice(0, 12)
|
|
45
|
+
a.badge.text-bg-light.text-decoration-none(href="/docs/model/" + m)= m
|
|
46
|
+
if model_list.length > 12
|
|
47
|
+
a.badge.text-bg-secondary.text-decoration-none(href="/docs/api") +#{model_list.length - 12} more
|
|
48
|
+
else
|
|
49
|
+
p.text-muted.mb-0 No models loaded yet.
|
|
50
|
+
|
|
51
|
+
h2.h4.mb-3 Features
|
|
52
|
+
.row.g-3.mb-4
|
|
53
|
+
each feature in features
|
|
54
|
+
.col-md-6.col-lg-4
|
|
55
|
+
.card.feature-card
|
|
56
|
+
.card-body
|
|
57
|
+
h3.h6.card-title= feature.title
|
|
58
|
+
p.card-text.small.text-muted.mb-0= feature.description
|
|
59
|
+
|
|
60
|
+
h2.h4.mb-3 Links
|
|
61
|
+
ul.list-unstyled
|
|
62
|
+
li.mb-1
|
|
63
|
+
a(href="https://www.npmjs.com/package/jxp" target="_blank" rel="noopener") JXP on NPM
|
|
64
|
+
li.mb-1
|
|
65
|
+
a(href="https://github.com/WorkSpaceMan/jxp" target="_blank" rel="noopener") GitHub
|
|
66
|
+
li.mb-1
|
|
67
|
+
a(href="https://www.npmjs.com/package/jxp-helper" target="_blank" rel="noopener") jxp-helper client
|
|
68
|
+
li
|
|
69
|
+
a(href="https://jxp.readthedocs.io" target="_blank" rel="noopener") Read the Docs
|
package/templates/layout.pug
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
doctype html
|
|
2
|
-
html
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
html(lang="en" data-docs-access=docs_access)
|
|
3
|
+
head
|
|
4
|
+
meta(charset="utf-8")
|
|
5
|
+
meta(name="viewport" content="width=device-width, initial-scale=1")
|
|
6
|
+
title= title
|
|
7
|
+
link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" crossorigin="anonymous")
|
|
8
|
+
link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css")
|
|
9
|
+
link(rel="stylesheet" href="/docs/assets/docs.css")
|
|
10
|
+
body.docs-body
|
|
11
|
+
include navbar
|
|
12
|
+
if hide_sidebar
|
|
13
|
+
main.docs-main.docs-main-full
|
|
14
|
+
block content
|
|
15
|
+
else
|
|
16
|
+
.docs-shell
|
|
17
|
+
include sidebar
|
|
18
|
+
main.docs-main
|
|
19
|
+
block content
|
|
20
|
+
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous")
|
|
21
|
+
script(src="/docs/assets/api-console.js" defer)
|
|
22
|
+
block javascripts
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
extends layout
|
|
2
|
+
|
|
3
|
+
block content
|
|
4
|
+
.docs-login-wrap
|
|
5
|
+
.card.docs-login-card.shadow-sm
|
|
6
|
+
.card-body.p-4
|
|
7
|
+
h1.h4.mb-1 Sign in to explore the API
|
|
8
|
+
p.text-muted.small.mb-4
|
|
9
|
+
| Use your normal API account (
|
|
10
|
+
code POST /login
|
|
11
|
+
| ). Guides and this site stay open; model pages and “Try it” need a session.
|
|
12
|
+
#docs-login-error.alert.alert-danger(role="alert" hidden)
|
|
13
|
+
form#docs-login-form
|
|
14
|
+
input(type="hidden" name="next" value=docs_next)
|
|
15
|
+
.mb-3
|
|
16
|
+
label.form-label(for="docs-login-email") Email
|
|
17
|
+
input#docs-login-email.form-control(
|
|
18
|
+
type="email"
|
|
19
|
+
name="email"
|
|
20
|
+
value=docs_user_email
|
|
21
|
+
required
|
|
22
|
+
autocomplete="username"
|
|
23
|
+
)
|
|
24
|
+
.mb-3
|
|
25
|
+
label.form-label(for="docs-login-password") Password
|
|
26
|
+
input#docs-login-password.form-control(
|
|
27
|
+
type="password"
|
|
28
|
+
name="password"
|
|
29
|
+
required
|
|
30
|
+
autocomplete="current-password"
|
|
31
|
+
)
|
|
32
|
+
button.btn.btn-primary.w-100(type="submit") Sign in
|
|
33
|
+
p.mt-3.mb-0.small.text-muted
|
|
34
|
+
a(href="/") Back to home
|
|
35
|
+
| ·
|
|
36
|
+
a(href="/docs/md/api.md") Read API docs without signing in
|
|
37
|
+
|
|
38
|
+
block javascripts
|
|
39
|
+
script(src="/docs/assets/docs-login.js" defer)
|
package/templates/md.pug
CHANGED
package/templates/model.pug
CHANGED
|
@@ -1,75 +1,124 @@
|
|
|
1
1
|
extends layout
|
|
2
2
|
|
|
3
3
|
block content
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
thead
|
|
10
|
-
tr
|
|
11
|
-
th User Group
|
|
12
|
-
th Create?
|
|
13
|
-
th Read?
|
|
14
|
-
th Update?
|
|
15
|
-
th Delete?
|
|
16
|
-
tbody
|
|
17
|
-
each value, key in perms
|
|
18
|
-
tr
|
|
19
|
-
td= key
|
|
20
|
-
td= value.includes("c") ? "x" : ""
|
|
21
|
-
td= value.includes("r") ? "x" : ""
|
|
22
|
-
td= value.includes("u") ? "x" : ""
|
|
23
|
-
td= value.includes("d") ? "x" : ""
|
|
24
|
-
else
|
|
25
|
-
.alert.alert-warning No permissions defined for this model, it will not be accessible through the API
|
|
4
|
+
nav.mb-3(aria-label="breadcrumb")
|
|
5
|
+
ol.breadcrumb
|
|
6
|
+
li.breadcrumb-item
|
|
7
|
+
a(href="/docs/api") API
|
|
8
|
+
li.breadcrumb-item.active(aria-current="page")= model_slug
|
|
26
9
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
h1.mb-1= model_slug
|
|
11
|
+
p.text-muted
|
|
12
|
+
| Collection:
|
|
13
|
+
code= collection_name
|
|
14
|
+
| ·
|
|
15
|
+
a(href="/docs/md/api.md") Query & filter docs
|
|
16
|
+
|
|
17
|
+
h2.h4.mt-4.mb-3 Endpoints
|
|
18
|
+
p.small.text-muted.mb-3
|
|
19
|
+
| Optional
|
|
20
|
+
code X-API-Key
|
|
21
|
+
| in the top bar.
|
|
22
|
+
span.text-warning Keys in the browser are for development only.
|
|
23
|
+
|
|
24
|
+
.accordion#apiEndpointsAccordion
|
|
25
|
+
each endpoint, idx in endpoints
|
|
26
|
+
.accordion-item
|
|
27
|
+
h2.accordion-header(id="heading-" + idx)
|
|
28
|
+
button.accordion-button(class=(idx === 0 ? '' : 'collapsed') type="button" data-bs-toggle="collapse" data-bs-target="#collapse-" + idx aria-expanded=(idx === 0 ? 'true' : 'false') aria-controls="collapse-" + idx)
|
|
29
|
+
span.badge.method-badge.me-2(class='method-' + endpoint.method.toLowerCase())= endpoint.method
|
|
30
|
+
span.endpoint-path= endpoint.path
|
|
31
|
+
.accordion-collapse.collapse(class=(idx === 0 ? 'show' : '') id="collapse-" + idx aria-labelledby="heading-" + idx data-bs-parent="#apiEndpointsAccordion")
|
|
32
|
+
.accordion-body
|
|
33
|
+
p.mb-2= endpoint.description
|
|
34
|
+
if endpoint.queryHint
|
|
35
|
+
p.small.text-muted= endpoint.queryHint
|
|
36
|
+
.api-try-panel(data-method=endpoint.method data-default-path=endpoint.path)
|
|
37
|
+
.mb-2
|
|
38
|
+
label.form-label.small.fw-semibold Request URL
|
|
39
|
+
.input-group.input-group-sm
|
|
40
|
+
span.input-group-text= endpoint.method
|
|
41
|
+
input.form-control.api-path-input(type="text" value=endpoint.path)
|
|
42
|
+
if endpoint.hasBody
|
|
43
|
+
.mb-2
|
|
44
|
+
label.form-label.small.fw-semibold JSON body
|
|
45
|
+
textarea.form-control.api-body-input.font-monospace(rows="4" placeholder='{"field": "value"}') {}
|
|
46
|
+
button.btn.btn-primary.btn-sm.api-send-btn(type="button")
|
|
47
|
+
i.bi.bi-play-fill.me-1
|
|
48
|
+
| Send request
|
|
49
|
+
.api-response.empty(role="status") Response will appear here…
|
|
50
|
+
.api-response-meta
|
|
51
|
+
|
|
52
|
+
hr.my-4
|
|
53
|
+
|
|
54
|
+
h2.h4 Permissions
|
|
55
|
+
if perms
|
|
56
|
+
.table-responsive
|
|
57
|
+
table.table.table-striped.table-sm
|
|
30
58
|
thead
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
th Indexed?
|
|
38
|
-
th Unique?
|
|
39
|
-
th Required?
|
|
59
|
+
tr
|
|
60
|
+
th User Group
|
|
61
|
+
th Create
|
|
62
|
+
th Read
|
|
63
|
+
th Update
|
|
64
|
+
th Delete
|
|
40
65
|
tbody
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
each value, key in perms
|
|
67
|
+
tr
|
|
68
|
+
td= key
|
|
69
|
+
td= value.includes("c") ? "✓" : ""
|
|
70
|
+
td= value.includes("r") ? "✓" : ""
|
|
71
|
+
td= value.includes("u") ? "✓" : ""
|
|
72
|
+
td= value.includes("d") ? "✓" : ""
|
|
73
|
+
else
|
|
74
|
+
.alert.alert-warning No permissions defined — this resource may not be accessible via the API.
|
|
75
|
+
|
|
76
|
+
h2.h4.mt-4 Fields
|
|
77
|
+
.table-responsive
|
|
78
|
+
table.table.table-striped.table-sm
|
|
79
|
+
thead
|
|
80
|
+
tr
|
|
81
|
+
th Name
|
|
82
|
+
th Type
|
|
83
|
+
th Link
|
|
84
|
+
th Maps To
|
|
85
|
+
th Default
|
|
86
|
+
th Indexed
|
|
87
|
+
th Unique
|
|
88
|
+
th Required
|
|
89
|
+
tbody
|
|
90
|
+
each fieldname in fields
|
|
91
|
+
- let field = safeFields[fieldname]
|
|
92
|
+
if field && field.path
|
|
93
|
+
tr
|
|
94
|
+
td
|
|
95
|
+
code= field.path
|
|
96
|
+
td
|
|
97
|
+
if field.arrayType
|
|
98
|
+
span.badge.text-bg-info Array of #{field.arrayType}
|
|
99
|
+
else
|
|
100
|
+
span.badge.text-bg-light.text-dark= field.instance
|
|
101
|
+
td= field.options.link || ''
|
|
102
|
+
td= field.options.map_to || ''
|
|
103
|
+
td.small= field.defaultValue != null ? field.defaultValue : ''
|
|
104
|
+
td= field.options.index ? "✓" : ""
|
|
105
|
+
td= field.options.unique ? "✓" : ""
|
|
106
|
+
td= field.isRequired ? "✓" : ""
|
|
75
107
|
|
|
108
|
+
h2.h4.mt-4 Field details
|
|
109
|
+
each fieldname in fields
|
|
110
|
+
- let field = safeFields[fieldname]
|
|
111
|
+
if field
|
|
112
|
+
.field-details.mb-3
|
|
113
|
+
h3.h6= field.path
|
|
114
|
+
pre.pre.small.bg-light.p-2.rounded= JSON.stringify(field, null, 2)
|
|
115
|
+
if field.schema
|
|
116
|
+
h4.h6 Nested schema
|
|
117
|
+
ul.small
|
|
118
|
+
each nestedField in field.schema
|
|
119
|
+
li #{nestedField.path}: #{nestedField.type}
|
|
120
|
+
if field.validators && field.validators.length
|
|
121
|
+
h4.h6 Validators
|
|
122
|
+
ul.small
|
|
123
|
+
each validator in field.validators
|
|
124
|
+
li #{validator.type}: #{validator.message}
|
package/templates/navbar.pug
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
header.docs-topbar.navbar.navbar-expand-lg.sticky-top
|
|
2
|
+
.container-fluid.px-3
|
|
3
|
+
button.btn.btn-outline-secondary.btn-sm.d-lg-none.me-2(type="button" data-bs-toggle="offcanvas" data-bs-target="#docsSidebarOffcanvas" aria-controls="docsSidebarOffcanvas" aria-label="Open navigation")
|
|
4
|
+
i.bi.bi-list
|
|
5
|
+
a.docs-brand.navbar-brand.mb-0(href="/")= name
|
|
6
|
+
span.badge.bg-secondary.ms-2.align-self-center v#{version}
|
|
7
|
+
.ms-auto.d-flex.align-items-center.gap-2.flex-wrap
|
|
8
|
+
if docs_access === 'protected' && !docs_authenticated
|
|
9
|
+
a.btn.btn-sm.btn-outline-primary(href="/docs/login?next=/docs/api") Explore API
|
|
10
|
+
if docs_access !== 'disabled' && (docs_access !== 'protected' || docs_authenticated)
|
|
11
|
+
.docs-api-key-wrap
|
|
12
|
+
label.visually-hidden(for="docs-api-key") API Key
|
|
13
|
+
input#docs-api-key.form-control.form-control-sm(
|
|
14
|
+
type="password"
|
|
15
|
+
placeholder=docs_access === 'protected' ? "X-API-Key" : "X-API-Key (optional)"
|
|
16
|
+
autocomplete="off"
|
|
17
|
+
)
|
|
18
|
+
.form-check.form-check-inline.mb-0.docs-security-note
|
|
19
|
+
input#docs-remember-key.form-check-input(type="checkbox")
|
|
20
|
+
label.form-check-label(for="docs-remember-key") Remember
|
|
21
|
+
if docs_access === 'protected'
|
|
22
|
+
form.d-inline(method="post" action="/docs/logout")
|
|
23
|
+
button.btn.btn-sm.btn-link.text-muted(type="submit") Sign out
|
|
24
|
+
else
|
|
25
|
+
span.docs-security-note.text-muted.d-none.d-md-inline Dev only
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
nav.docs-sidebar#docsSidebarDesktop(aria-label="Documentation navigation")
|
|
2
|
+
.docs-sidebar-section
|
|
3
|
+
.docs-sidebar-title Guides
|
|
4
|
+
each nav in guide_nav
|
|
5
|
+
- const label = Object.keys(nav)[0]
|
|
6
|
+
- const file = Object.values(nav)[0]
|
|
7
|
+
a.docs-nav-link(href="/docs/md/" + file class=(active_guide === file ? 'active' : ''))= label
|
|
8
|
+
.docs-sidebar-section
|
|
9
|
+
.docs-sidebar-title API
|
|
10
|
+
a.docs-nav-link(href="/docs/api" class=(active_section === 'api' && !active_model ? 'active' : '')) Overview
|
|
11
|
+
each model_name in model_list
|
|
12
|
+
a.docs-nav-link(href="/docs/model/" + model_name class=(active_model === model_name ? 'active' : ''))= model_name
|
|
13
|
+
|
|
14
|
+
//- Mobile offcanvas (same links)
|
|
15
|
+
.offcanvas.offcanvas-start#docsSidebarOffcanvas(tabindex="-1" aria-labelledby="docsSidebarOffcanvasLabel")
|
|
16
|
+
.offcanvas-header
|
|
17
|
+
h5.offcanvas-title#docsSidebarOffcanvasLabel Navigation
|
|
18
|
+
button.btn-close(type="button" data-bs-dismiss="offcanvas" aria-label="Close")
|
|
19
|
+
.offcanvas-body.p-0
|
|
20
|
+
.docs-sidebar-section
|
|
21
|
+
.docs-sidebar-title Guides
|
|
22
|
+
each nav in guide_nav
|
|
23
|
+
- const label = Object.keys(nav)[0]
|
|
24
|
+
- const file = Object.values(nav)[0]
|
|
25
|
+
a.docs-nav-link(href="/docs/md/" + file class=(active_guide === file ? 'active' : ''))= label
|
|
26
|
+
.docs-sidebar-section
|
|
27
|
+
.docs-sidebar-title API
|
|
28
|
+
a.docs-nav-link(href="/docs/api" class=(active_section === 'api' && !active_model ? 'active' : '')) Overview
|
|
29
|
+
each model_name in model_list
|
|
30
|
+
a.docs-nav-link(href="/docs/model/" + model_name class=(active_model === model_name ? 'active' : ''))= model_name
|