json-rest-api 1.0.7 → 1.0.8
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/.claude/agents/library-guide-expert.md +29 -0
- package/.claude/agents/rest-api-internals-expert.md +53 -0
- package/CLAUDE.md +139 -1
- package/README.md +2 -5
- package/docTest.js +238 -0
- package/docs/GUIDE/GUIDE_1_Initial_Setup.md +955 -0
- package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +54 -0
- package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +750 -0
- package/docs/GUIDE/GUIDE_2_3_BelongsTo_Relationships.md +494 -0
- package/docs/GUIDE/GUIDE_2_4_HasMany_Records.md +398 -0
- package/docs/GUIDE/GUIDE_2_5_HasMany_Polymorphic.md +882 -0
- package/docs/GUIDE/GUIDE_2_6_Many_To_Many.md +709 -0
- package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +1233 -0
- package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +796 -0
- package/{README_X_Relationship_Plugin.md → docs/GUIDE/GUIDE_2_9_Relationships_Urls.md} +1 -4
- package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +66 -0
- package/docs/GUIDE/GUIDE_3_Field_Transformations.md +1246 -0
- package/docs/GUIDE/GUIDE_5_Non-Db_Stores.md +0 -0
- package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +1490 -0
- package/{README_X_SocketIO.md → docs/GUIDE/GUIDE_X_SocketIO.md} +17 -17
- package/docs/GUIDE/index.md +58 -0
- package/docs/GUIDE.md +61 -2238
- package/docs/ONBOARDING/Computed_Properties_And_Sparse_Fields.md +398 -0
- package/docs/README.md +57 -2239
- package/{README_2_Computed_and_hidden_fields.md → docs/README_VARIOUS/GUIDE_2_Computed_and_hidden_fields.md} +22 -17
- package/docs/README_VARIOUS/GUIDE_IN_DOCS.md +2277 -0
- package/{README.ORIG.md → docs/README_VARIOUS/README.ORIG.md} +8 -8
- package/{README_8_Polymorphic_Relationships.md → docs/README_VARIOUS/README_8_Polymorphic_Relationships.md} +1 -1
- package/docs/README_VARIOUS/README_IN_DOCS.ms +2277 -0
- package/{RELATIONSHIPS_ADVANCED.md → docs/README_VARIOUS/RELATIONSHIPS_ADVANCED.md} +3 -3
- package/{correct-schema-format.md → docs/README_VARIOUS/correct-schema-format.md} +13 -13
- package/{pagination.md → docs/README_VARIOUS/pagination.md} +11 -8
- package/docs/assets/css/style.scss +78 -5
- package/docs/index.md +2 -12
- package/helper-reorganization-plan.md +85 -0
- package/helper-usage-analysis.md +94 -0
- package/package.json +5 -4
- package/plugins/core/bulk-operations-plugin.js +2 -2
- package/plugins/core/connectors/express-plugin.js +90 -32
- package/plugins/core/lib/querying/knex-cross-table-search.js +609 -0
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +491 -0
- package/plugins/core/lib/querying/knex-pagination-helpers.js +544 -0
- package/plugins/core/lib/{knex-process-includes.js → querying/knex-process-includes.js} +65 -50
- package/plugins/core/lib/querying/knex-query-helpers-base.js +74 -0
- package/plugins/core/lib/{knex-query-helpers.js → querying/knex-query-helpers.js} +416 -180
- package/plugins/core/lib/{knex-relationship-includes.js → querying/knex-relationship-includes.js} +430 -114
- package/plugins/core/lib/querying/knex-window-queries.js +328 -0
- package/plugins/core/lib/querying-writing/compile-schemas.js +328 -0
- package/plugins/core/{utils → lib/querying-writing}/connectors-query-parser.js +62 -57
- package/plugins/core/lib/{database-capabilities.js → querying-writing/database-capabilities.js} +113 -7
- package/plugins/core/lib/querying-writing/database-value-normalizers.js +369 -0
- package/plugins/core/lib/querying-writing/default-data-helpers.js +72 -0
- package/plugins/core/{utils → lib/querying-writing}/field-utils.js +41 -31
- package/plugins/core/{utils → lib/querying-writing}/knex-constants.js +1 -0
- package/plugins/core/lib/{knex-field-helpers.js → querying-writing/knex-field-helpers.js} +190 -57
- package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +162 -0
- package/plugins/core/lib/{payload-validators.js → querying-writing/payload-validators.js} +297 -217
- package/plugins/core/lib/querying-writing/schema-helpers.js +497 -0
- package/plugins/core/lib/querying-writing/scope-validations.js +431 -0
- package/plugins/core/lib/{simplified-helpers.js → querying-writing/simplified-helpers.js} +216 -176
- package/plugins/core/lib/writing/knex-json-api-transformers-writing.js +110 -0
- package/plugins/core/lib/writing/many-to-many-manipulations.js +300 -0
- package/plugins/core/lib/writing/relationship-processor.js +252 -0
- package/plugins/core/rest-api-knex-plugin.js +183 -62
- package/plugins/core/rest-api-plugin-hooks/compile-resource-schemas.js +7 -0
- package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +72 -0
- package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +102 -0
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +50 -0
- package/plugins/core/rest-api-plugin-hooks/validate-include-configurations.js +39 -0
- package/plugins/core/rest-api-plugin-methods/add-route.js +23 -0
- package/plugins/core/rest-api-plugin-methods/check-permissions.js +18 -0
- package/plugins/core/rest-api-plugin-methods/common.js +605 -0
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +115 -0
- package/plugins/core/rest-api-plugin-methods/delete.js +109 -0
- package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +186 -0
- package/plugins/core/rest-api-plugin-methods/get-related.js +295 -0
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +62 -0
- package/plugins/core/rest-api-plugin-methods/get.js +187 -0
- package/plugins/core/rest-api-plugin-methods/patch-relationship.js +56 -0
- package/plugins/core/rest-api-plugin-methods/patch.js +193 -0
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +104 -0
- package/plugins/core/rest-api-plugin-methods/post.js +157 -0
- package/plugins/core/rest-api-plugin-methods/put.js +257 -0
- package/plugins/core/rest-api-plugin-methods/query.js +208 -0
- package/plugins/core/rest-api-plugin.js +108 -2498
- package/plugins/core/socketio-plugin.js +28 -5
- package/plugins/storage/local-storage.js +2 -2
- package/tests/computed-fields.test.js +483 -0
- package/tests/cors.test.js +4 -4
- package/tests/curl.test.js +5 -4
- package/tests/custom-idproperty-relationships.test.js +891 -0
- package/tests/field-getters.test.js +353 -0
- package/tests/field-setters.test.js +310 -0
- package/tests/fixtures/api-configs.js +800 -28
- package/tests/jwt-auth.test.js +0 -2
- package/tests/nested-includes.test.js +1 -1
- package/tests/pagination-cursor-multifield.test.js +514 -0
- package/tests/pagination-enhanced.test.js +12 -9
- package/tests/polymorphic-relationships.test.js +10 -8
- package/tests/polymorphic-simple.test.js +6 -4
- package/tests/positioning-advanced.test.js +12 -12
- package/tests/positioning-extended.test.js +25 -25
- package/tests/positioning-multifilter.test.js +24 -24
- package/tests/positioning.test.js +3 -3
- package/tests/query-limits.test.js +24 -8
- package/tests/relationship-endpoints.test.js +4 -5
- package/tests/relationships.test.js +0 -1
- package/tests/socketio.test.js +12 -1
- package/tests/virtual-fields.test.js +13 -13
- package/PLAN_FOR_WEBSOCKETS.md +0 -398
- package/README_1_Initial_Setup.md +0 -393
- package/README_X_Hooks.md +0 -647
- package/TODO_rest-api-plugin-extras.todo +0 -23
- package/connectors_ideas/express-plugin.js +0 -120
- package/connectors_ideas/http-plugin.js +0 -138
- package/docs/examples/express-plugin.js +0 -366
- package/example.js +0 -301
- package/plugins/core/HELPER_MODULES.md +0 -285
- package/plugins/core/lib/compile-schemas.js +0 -245
- package/plugins/core/lib/database-value-normalizers.js +0 -192
- package/plugins/core/lib/default-data-helpers.js +0 -100
- package/plugins/core/lib/knex-cross-table-search.js +0 -442
- package/plugins/core/lib/knex-json-api-helpers.js +0 -84
- package/plugins/core/lib/knex-json-api-transformers.js +0 -449
- package/plugins/core/lib/knex-pagination-helpers.js +0 -193
- package/plugins/core/lib/knex-window-queries.js +0 -142
- package/plugins/core/lib/many-to-many-manipulations.js +0 -343
- package/plugins/core/lib/relationship-processor.js +0 -278
- package/plugins/core/lib/schema-helpers.js +0 -343
- package/plugins/core/lib/scope-validations.js +0 -252
- package/plugins/core/rest-api-relationships-plugin.js +0 -700
- package/plugins/core/utils/knex-query-helpers-base.js +0 -56
- /package/{README_X_Permissions.md → docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md} +0 -0
- /package/{README_X_Positioning.md → docs/GUIDE/GUIDE_6_Positioning.md} +0 -0
- /package/{README_X_Bulk_Operations.md → docs/GUIDE/GUIDE_X_Bulk_Operations.md} +0 -0
- /package/{README_X_Cors.md → docs/GUIDE/GUIDE_X_Cors.md} +0 -0
- /package/{README_X_Multihome.md → docs/GUIDE/GUIDE_X_Multihome.md} +0 -0
- /package/{README_X_Appendices.md → docs/GUIDE/GUIDE_Y_Appendices.md} +0 -0
- /package/{QUERY_DEPTH_PROTECTION.md → docs/README_VARIOUS/QUERY_DEPTH_PROTECTION.md} +0 -0
- /package/{RELATIONSHIPS.md → docs/README_VARIOUS/RELATIONSHIPS.md} +0 -0
- /package/{WEBSOCKET_IMPLEMENTATION_STATUS.md → docs/README_VARIOUS/WEBSOCKET_IMPLEMENTATION_STATUS.md} +0 -0
- /package/{helper-functions-chart.md → docs/README_VARIOUS/helper-functions-chart.md} +0 -0
- /package/docs/{implementation-hidden-computed-fields.md → README_VARIOUS/implementation-hidden-computed-fields.md} +0 -0
- /package/docs/{include-limits-migration-guide.md → README_VARIOUS/include-limits-migration-guide.md} +0 -0
- /package/{readmeSnippets → docs/README_VARIOUS}/test_put_behavior.js +0 -0
- /package/{readmeSnippets → docs/README_VARIOUS}/test_put_fields_without_defaults.js +0 -0
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
## Defining the Basic Tables
|
|
3
|
-
|
|
4
|
-
The documentation uses a consistent example throughout - a book catalog system with authors, publishers, and countries.
|
|
5
|
-
|
|
6
|
-
**Important**: The five tables defined below (countries, publishers, authors, books, and book_authors) form the foundation for all examples, tests, and documentation in this guide. We'll consistently reference this same schema structure to demonstrate all features of the library. At times, we will change the definition of some of them to show specific features.
|
|
7
|
-
|
|
8
|
-
Also for brevity, the `inspect()` function will be assumed to be set:
|
|
9
|
-
|
|
10
|
-
```javascript
|
|
11
|
-
import { RestApiPlugin, RestApiKnexPlugin } from 'json-rest-api';
|
|
12
|
-
import { Api } from 'hooked-api';
|
|
13
|
-
import knexLib from 'knex';
|
|
14
|
-
import util from 'util';
|
|
15
|
-
|
|
16
|
-
// Utility used throughout this guide
|
|
17
|
-
const inspect = (obj) => util.inspect(obj, { depth: 5 })
|
|
18
|
-
|
|
19
|
-
// Create a Knex instance connected to SQLite in-memory database
|
|
20
|
-
const knex = knexLib({
|
|
21
|
-
client: 'better-sqlite3',
|
|
22
|
-
connection: {
|
|
23
|
-
filename: ':memory:'
|
|
24
|
-
},
|
|
25
|
-
useNullAsDefault: true
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Create API instance
|
|
29
|
-
const api = new Api({
|
|
30
|
-
name: 'book-catalog-api',
|
|
31
|
-
version: '1.0.0'
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// Install plugins
|
|
35
|
-
await api.use(RestApiPlugin);
|
|
36
|
-
await api.use(RestApiKnexPlugin, { knex });
|
|
37
|
-
|
|
38
|
-
// Define schemas for our book catalog system
|
|
39
|
-
|
|
40
|
-
// Countries table
|
|
41
|
-
await api.addResource('countries', {
|
|
42
|
-
schema: {
|
|
43
|
-
id: { type: 'id' },
|
|
44
|
-
name: { type: 'string', required: true, max: 100, search: true },
|
|
45
|
-
code: { type: 'string', max: 2, unique: true, search: true }, // ISO country code
|
|
46
|
-
},
|
|
47
|
-
relationships: {
|
|
48
|
-
publishers: { hasMany: 'publishers', foreignKey: 'country_id' },
|
|
49
|
-
books: { hasMany: 'books', foreignKey: 'country_id' }
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
await api.resources.countries.createKnexTable()
|
|
53
|
-
|
|
54
|
-
// Publishers table
|
|
55
|
-
await api.addResource('publishers', {
|
|
56
|
-
schema: {
|
|
57
|
-
id: { type: 'id' },
|
|
58
|
-
name: { type: 'string', required: true, max: 200, search: true },
|
|
59
|
-
country_id: { type: 'number', belongsTo: 'countries', as: 'country' },
|
|
60
|
-
},
|
|
61
|
-
relationships: {
|
|
62
|
-
books: { hasMany: 'books', foreignKey: 'publisher_id' },
|
|
63
|
-
reviews: { hasMany: 'reviews', via: 'reviewable' }
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
await api.resources.publishers.createKnexTable()
|
|
67
|
-
|
|
68
|
-
// Authors table
|
|
69
|
-
await api.addResource('authors', {
|
|
70
|
-
schema: {
|
|
71
|
-
id: { type: 'id' },
|
|
72
|
-
name: { type: 'string', required: true, max: 200, search: true },
|
|
73
|
-
},
|
|
74
|
-
relationships: {
|
|
75
|
-
books: { hasMany: 'books', through: 'book_authors', foreignKey: 'author_id', otherKey: 'book_id' },
|
|
76
|
-
reviews: { hasMany: 'reviews', via: 'reviewable' }
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
await api.resources.authors.createKnexTable()
|
|
80
|
-
|
|
81
|
-
// Books table
|
|
82
|
-
await api.addResource('books', {
|
|
83
|
-
schema: {
|
|
84
|
-
id: { type: 'id' },
|
|
85
|
-
title: { type: 'string', required: true, max: 300, search: true },
|
|
86
|
-
country_id: { type: 'number', required: true, belongsTo: 'countries', as: 'country' },
|
|
87
|
-
publisher_id: { type: 'number', belongsTo: 'publishers', as: 'publisher' },
|
|
88
|
-
year: { type: 'number', search: true },
|
|
89
|
-
isbn: { type: 'string', search: true },
|
|
90
|
-
inStock: { type: 'boolean', default: true },
|
|
91
|
-
rating: { type: 'number', default: 0 },
|
|
92
|
-
tags: { type: 'array', default: [] },
|
|
93
|
-
metadata: { type: 'object', default: {} }
|
|
94
|
-
},
|
|
95
|
-
relationships: {
|
|
96
|
-
authors: { hasMany: 'authors', through: 'book_authors', foreignKey: 'book_id', otherKey: 'author_id' },
|
|
97
|
-
reviews: { hasMany: 'reviews', via: 'reviewable' }
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
await api.resources.books.createKnexTable()
|
|
101
|
-
|
|
102
|
-
// Book-Authors pivot table (many-to-many relationship)
|
|
103
|
-
await api.addResource('book_authors', {
|
|
104
|
-
schema: {
|
|
105
|
-
id: { type: 'id' },
|
|
106
|
-
book_id: { type: 'number', required: true, belongsTo: 'books', as: 'book' },
|
|
107
|
-
author_id: { type: 'number', required: true, belongsTo: 'authors', as: 'author' },
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
await api.resources.book_authors.createKnexTable()
|
|
111
|
-
|
|
112
|
-
// Reviews table (polymorphic - can review books, authors, or publishers)
|
|
113
|
-
await api.addResource('reviews', {
|
|
114
|
-
schema: {
|
|
115
|
-
id: { type: 'id' },
|
|
116
|
-
review_author: { type: 'string', required: true, max: 100 },
|
|
117
|
-
review_text: { type: 'string', required: true, max: 5000 },
|
|
118
|
-
review_rating: { type: 'number', required: true, min: 1, max: 5 },
|
|
119
|
-
reviewable_type: { type: 'string', required: true },
|
|
120
|
-
reviewable_id: { type: 'number', required: true },
|
|
121
|
-
// Define the polymorphic field
|
|
122
|
-
reviewable: {
|
|
123
|
-
belongsToPolymorphic: {
|
|
124
|
-
types: ['books', 'authors', 'publishers'],
|
|
125
|
-
typeField: 'reviewable_type',
|
|
126
|
-
idField: 'reviewable_id'
|
|
127
|
-
},
|
|
128
|
-
as: 'reviewable'
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
await api.resources.reviews.createKnexTable()
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Database Options
|
|
136
|
-
|
|
137
|
-
The `json-rest-api` library uses `knex` as its database abstraction layer, which supports a wide variety of SQL databases. In the example above, we configured `knex` to use an in-memory SQLite database for simplicity:
|
|
138
|
-
|
|
139
|
-
```javascript
|
|
140
|
-
const knex = knexLib({
|
|
141
|
-
client: 'sqlite3',
|
|
142
|
-
connection: {
|
|
143
|
-
filename: ':memory:' // In-memory database for quick examples
|
|
144
|
-
},
|
|
145
|
-
useNullAsDefault: true // Recommended for SQLite
|
|
146
|
-
});
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
To connect to a different database, you would simply change the `client` and `connection` properties in the `knexLib` configuration. Here are a few common examples:
|
|
150
|
-
|
|
151
|
-
**PostgreSQL:**
|
|
152
|
-
|
|
153
|
-
```javascript
|
|
154
|
-
const knex = knexLib({
|
|
155
|
-
client: 'pg', // PostgreSQL client
|
|
156
|
-
connection: {
|
|
157
|
-
host: '127.0.0.1',
|
|
158
|
-
user: 'your_username',
|
|
159
|
-
password: 'your_password',
|
|
160
|
-
database: 'your_database_name',
|
|
161
|
-
port: 5432 // Default PostgreSQL port
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
**MySQL / MariaDB:**
|
|
166
|
-
|
|
167
|
-
```javascript
|
|
168
|
-
const knex = knexLib({
|
|
169
|
-
client: 'mysql', // or 'mariasql' for MariaDB
|
|
170
|
-
connection: {
|
|
171
|
-
host: '127.0.0.1',
|
|
172
|
-
user: 'your_username',
|
|
173
|
-
password: 'your_password',
|
|
174
|
-
database: 'your_database_name',
|
|
175
|
-
port: 3306 // Default MySQL/MariaDB port
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Remember to install the corresponding `knex` driver for your chosen database (e.g., `npm install pg` for PostgreSQL, `npm install mysql2` for MySQL).
|
|
181
|
-
|
|
182
|
-
## Basic Usage
|
|
183
|
-
|
|
184
|
-
The `json-rest-api` plugin extends your `hooked-api` instance with powerful RESTful capabilities, allowing you to interact with your defined resources both programmatically within your application code and via standard HTTP requests.
|
|
185
|
-
|
|
186
|
-
### Programmatic Usage
|
|
187
|
-
|
|
188
|
-
Once your resources are defined using `api.addResource()`, you can directly call CRUD (Create, Read, Update, Delete) methods on `api.resources.<resourceName>`.
|
|
189
|
-
|
|
190
|
-
Let's start by creating a `country` record:
|
|
191
|
-
|
|
192
|
-
```javascript
|
|
193
|
-
// Example: Create a country
|
|
194
|
-
const countryUs = await api.resources.countries.post({
|
|
195
|
-
name: 'United States',
|
|
196
|
-
code: 'US'
|
|
197
|
-
});
|
|
198
|
-
console.log('Created Country:', inspect(countryUs));
|
|
199
|
-
// Expected Output:
|
|
200
|
-
// TODO: Check what this will return
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Now, let's retrieve this country data using its ID:
|
|
204
|
-
|
|
205
|
-
```javascript
|
|
206
|
-
// Example: Refetch a country by ID
|
|
207
|
-
const countryUsRefetched = await api.resources.countries.get({
|
|
208
|
-
id: countryUs.data.id, // Use the ID returned from the POST operation
|
|
209
|
-
});
|
|
210
|
-
console.log('Refetched Country:', inspect(countryUsRefetched));
|
|
211
|
-
// Expected Output:
|
|
212
|
-
// TODO: Check
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### REST Usage (HTTP Endpoints)
|
|
216
|
-
|
|
217
|
-
To expose your API resources via HTTP, you need to install one of the connector plugins:
|
|
218
|
-
|
|
219
|
-
* **`ExpressPlugin`**: If you are using `Express.js` in your application.
|
|
220
|
-
|
|
221
|
-
* **`(Coming soon)`**: Fastify and Koa are planned and coming soon
|
|
222
|
-
|
|
223
|
-
Thanks to the ExpressPlugin, json-rest-api is able to export an Express router that you can just `use()` in Express:
|
|
224
|
-
|
|
225
|
-
```javascript
|
|
226
|
-
// In your main application file (e.g., app.js)
|
|
227
|
-
import { ExpressPlugin, RestApiPlugin, RestApiKnexPlugin } from 'json-rest-api';
|
|
228
|
-
import { Api } from 'hooked-api';
|
|
229
|
-
import express from 'express';
|
|
230
|
-
import knexLib from 'knex';
|
|
231
|
-
import util from 'util';
|
|
232
|
-
|
|
233
|
-
// ... (Knex and API instance setup as shown in "Defining the Basic Tables")
|
|
234
|
-
|
|
235
|
-
const app = express();
|
|
236
|
-
|
|
237
|
-
// Install the Express Plugin
|
|
238
|
-
await api.use(ExpressPlugin, {
|
|
239
|
-
basePath: '/api' // All API routes will be under /api
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// Mount the API router
|
|
243
|
-
app.use(api.http.express.router); // Mounts the router generated by ExpressPlugin
|
|
244
|
-
// Alternatively, for more control: app.use('/my-custom-path', api.http.express.router);
|
|
245
|
-
|
|
246
|
-
app.listen(3000, () => {
|
|
247
|
-
console.log('Express server started on port 3000. API available at http://localhost:3000/api');
|
|
248
|
-
});
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### Making the CURL calls
|
|
252
|
-
|
|
253
|
-
Once the server is running, you can interact with your API using tools like `curl`.
|
|
254
|
-
|
|
255
|
-
**REST Example: Create a Country**
|
|
256
|
-
|
|
257
|
-
```bash
|
|
258
|
-
curl -X POST -H "Content-Type: application/vnd.api+json" \
|
|
259
|
-
-d '{
|
|
260
|
-
"data": {
|
|
261
|
-
"type": "countries",
|
|
262
|
-
"attributes": {
|
|
263
|
-
"name": "United Kingdom",
|
|
264
|
-
"code": "UK"
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}' http://localhost:3000/api/countries
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
**REST Example: Get a Country by ID**
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
curl -X GET http://localhost:3000/api/countries/2
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
**From now on, all examples will provide both programmatic usage and `curl` usage.** This ensures you understand how to interact with the API directly in your code and how it translates to standard HTTP requests.
|
|
278
|
-
|
|
279
|
-
### Simplified Mode
|
|
280
|
-
|
|
281
|
-
TODO: Explain what simplified mode is, and what its defaults are. API use is simplified, online use is non-simplified.
|
|
282
|
-
Explain where the settings come from
|
|
283
|
-
|
|
284
|
-
TODO: Explain how to declare 'books' simplified, and show that it will work in simplified mode. Note: cover simplifiedApi
|
|
285
|
-
and simplifiedTransport (as options).
|
|
286
|
-
|
|
287
|
-
In "simplified mode":
|
|
288
|
-
|
|
289
|
-
* **Input:** You can pass plain JavaScript objects directly for attributes, and related resource IDs for relationships.
|
|
290
|
-
|
|
291
|
-
* **Output:** Responses are flattened, with `id` and `attributes` merged directly into the top-level object, and `belongsTo` relationships are represented as foreign key IDs. <--- TODO: check this
|
|
292
|
-
|
|
293
|
-
The `simplified` mode is controlled by options passed during plugin installation or directly to method calls. It cascades, meaning a setting at a lower level overrides a higher one:
|
|
294
|
-
|
|
295
|
-
TODO: Redo the next bit, since now we have two different flags, one of the API and one for the network connections
|
|
296
|
-
1. **Global (default):** `RestApiPlugin`'s options (`simplified: true/false`).
|
|
297
|
-
|
|
298
|
-
2. **Per-Resource:** `addResource()` options (`simplified: true/false`).
|
|
299
|
-
|
|
300
|
-
3. **Per-Method Call:** The `params` object passed to individual `api.resources.<resource>.method()` calls.
|
|
301
|
-
|
|
302
|
-
By default, `simplifiedApi` is `true` and simplifiedTransport is `false` for HTTP calls (to maintain JSON:API compliance on the wire).
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
### Return Full Record
|
|
306
|
-
|
|
307
|
-
TODO: Explain the returnFullRecord option in detail
|
|
308
|
-
|
|
309
|
-
### Search (Filtering)
|
|
310
|
-
|
|
311
|
-
TODO
|
|
312
|
-
|
|
313
|
-
### Sparse Fields
|
|
314
|
-
|
|
315
|
-
The JSON:API specification allows clients to request only a subset of fields for a given resource, a feature known as "sparse fieldsets". This is crucial for optimizing network traffic by reducing the size of the response payload, especially when dealing with large records.
|
|
316
|
-
|
|
317
|
-
You can specify which fields to return using the `fields[resourceType]=field1,field2` query parameter.
|
|
318
|
-
|
|
319
|
-
**Programmatic Example: Get only `name` for `countries`**
|
|
320
|
-
|
|
321
|
-
```javascript
|
|
322
|
-
TODO
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
**HTTP Example: Get Books with only `title` and `isbn`**
|
|
326
|
-
|
|
327
|
-
TODO
|
|
328
|
-
|
|
329
|
-
Sparse fieldsets also apply to `included` resources. If you request related data, you can specify which fields of those related resources should be returned as well.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
## belongsTo records
|
|
334
|
-
|
|
335
|
-
### Search (belongsTo)
|
|
336
|
-
|
|
337
|
-
### Sparse fields (belongsTo)
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
## hasMany records
|
|
343
|
-
|
|
344
|
-
### Search (hasMany)
|
|
345
|
-
|
|
346
|
-
### Sparse fields (hasMany)
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
## hasMany records
|
|
352
|
-
|
|
353
|
-
### Search (hasMany)
|
|
354
|
-
|
|
355
|
-
### Sparse fields (hasMany)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
## Many to many (hasMany with through records)
|
|
361
|
-
|
|
362
|
-
### Search (many to many)
|
|
363
|
-
|
|
364
|
-
### Sparse fields (many to many)
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
## Next Steps
|
|
372
|
-
|
|
373
|
-
- [Schema Definition Guide](docs/schemas.md) - Learn about all field types and validation rules
|
|
374
|
-
- [Relationships Guide](docs/relationships.md) - Deep dive into relationship configuration
|
|
375
|
-
- [Querying Guide](docs/querying.md) - Advanced filtering, sorting, and pagination
|
|
376
|
-
- [File Uploads Guide](docs/file-uploads.md) - Handle file uploads with various storage backends
|
|
377
|
-
- [Authentication Guide](docs/authentication.md) - Add authentication and authorization
|
|
378
|
-
- [Testing Guide](docs/testing.md) - Write tests for your API
|
|
379
|
-
|
|
380
|
-
## License
|
|
381
|
-
|
|
382
|
-
GPL-3.0-or-later
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|