json-rest-api 1.0.10 → 1.0.13
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/settings.local.json +9 -1
- package/AGENTS.md +34 -0
- package/CLAUDE.md +26 -1
- package/CRUSH.md +55 -0
- package/README.md +3 -3
- package/TODO.todo +8 -0
- package/docs/API.md +17 -18
- package/docs/COMPARISON.md +18 -13
- package/docs/GUIDE/GUIDE_1_Initial_Setup.md +17 -21
- package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +33 -2
- package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +61 -7
- package/docs/GUIDE/GUIDE_2_3_BelongsTo_Relationships.md +58 -61
- package/docs/GUIDE/GUIDE_2_4_HasMany_Records.md +37 -37
- package/docs/GUIDE/GUIDE_2_5_HasMany_Polymorphic.md +103 -87
- package/docs/GUIDE/GUIDE_2_6_Many_To_Many.md +37 -34
- package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +45 -42
- package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +3 -3
- package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +1 -1
- package/docs/GUIDE/GUIDE_3_Field_Transformations.md +5 -5
- package/docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md +498 -755
- package/docs/GUIDE/GUIDE_6_Positioning.md +1 -3
- package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +4 -5
- package/docs/GUIDE/GUIDE_X_Bulk_Operations.md +15 -6
- package/docs/GUIDE/GUIDE_X_Cors.md +2 -5
- package/docs/GUIDE/GUIDE_X_File_Uploads.md +2 -3
- package/docs/GUIDE/GUIDE_X_Multihome.md +1 -4
- package/docs/GUIDE/GUIDE_X_SocketIO.md +0 -2
- package/docs/GUIDE/GUIDE_X_URL_Management.md +317 -0
- package/docs/GUIDE/index.md +3 -0
- package/docs/QUICKSTART.md +12 -12
- package/docs/index.md +2 -2
- package/docs/mini-guides/file-uploads-complete.md +0 -1
- package/examples/url-override-example.js +137 -0
- package/index.js +7 -1
- package/package.json +7 -11
- package/plugins/core/bulk-operations-plugin.js +2 -0
- package/plugins/core/connectors/express-plugin.js +43 -24
- package/plugins/core/connectors/lib/request-helpers.js +2 -2
- package/plugins/core/lib/anyapi/anyapi-registry.js +821 -0
- package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +647 -0
- package/plugins/core/lib/anyapi/schema-utils.js +186 -0
- package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +113 -0
- package/plugins/core/lib/dbTablesOperations.js +305 -0
- package/plugins/core/lib/querying/knex-cross-table-search.js +64 -108
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +21 -27
- package/plugins/core/lib/querying/knex-pagination-helpers.js +36 -20
- package/plugins/core/lib/querying/knex-query-helpers-base.js +49 -14
- package/plugins/core/lib/querying/knex-query-helpers.js +378 -222
- package/plugins/core/lib/querying/knex-relationship-includes.js +262 -87
- package/plugins/core/lib/querying/url-helpers.js +119 -0
- package/plugins/core/lib/querying-writing/compile-schemas.js +36 -28
- package/plugins/core/lib/querying-writing/database-capabilities.js +10 -9
- package/plugins/core/lib/querying-writing/knex-field-helpers.js +9 -3
- package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +2 -2
- package/plugins/core/lib/querying-writing/payload-validators.js +10 -16
- package/plugins/core/lib/querying-writing/schema-helpers.js +52 -60
- package/plugins/core/lib/querying-writing/scope-validations.js +78 -22
- package/plugins/core/lib/querying-writing/simplified-helpers.js +208 -61
- package/plugins/core/lib/storage/storage-adapter.js +160 -0
- package/plugins/core/lib/writing/relationship-processor.js +4 -11
- package/plugins/core/rest-api-access.js +456 -0
- package/plugins/core/rest-api-anyapi-knex-plugin.js +2285 -0
- package/plugins/core/rest-api-knex-plugin.js +226 -87
- package/plugins/core/rest-api-multihome-plugin.js +89 -27
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +0 -1
- package/plugins/core/rest-api-plugin-methods/check-permissions.js +1 -5
- package/plugins/core/rest-api-plugin-methods/common.js +46 -10
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +31 -27
- package/plugins/core/rest-api-plugin-methods/delete.js +1 -4
- package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +13 -1
- package/plugins/core/rest-api-plugin-methods/get-related.js +114 -56
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +4 -3
- package/plugins/core/rest-api-plugin-methods/get.js +2 -5
- package/plugins/core/rest-api-plugin-methods/patch.js +15 -16
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +21 -14
- package/plugins/core/rest-api-plugin-methods/post.js +23 -11
- package/plugins/core/rest-api-plugin-methods/put.js +18 -21
- package/plugins/core/rest-api-plugin-methods/query.js +3 -4
- package/plugins/core/rest-api-plugin-methods/release.js +13 -0
- package/plugins/core/rest-api-plugin.js +3 -4
- package/plugins/core/rest-api-positioning-plugin.js +253 -76
- package/plugins/core/socketio-plugin.js +436 -502
- package/quickTest.js +2 -2
- package/scripts/debug-anyapi-review-filter.mjs +63 -0
- package/scripts/inspect-anyapi-descriptor-country.mjs +19 -0
- package/scripts/inspect-anyapi-descriptor.mjs +19 -0
- package/test-debug.js +59 -0
- package/tests/README.md +7 -1
- package/tests/anyapi-basic.test.js +102 -0
- package/tests/anyapi-cursor-pagination.test.js +144 -0
- package/tests/computed-fields.test.js +27 -12
- package/tests/cors.test.js +5 -6
- package/tests/curl.test.js +1 -1
- package/tests/custom-idproperty-relationships.test.js +37 -29
- package/tests/field-getters.test.js +25 -7
- package/tests/fixtures/api-configs.js +576 -150
- package/tests/helpers/storage-mode.js +65 -0
- package/tests/helpers/test-utils.js +85 -3
- package/tests/include-depth-validation.test.js +35 -1
- package/tests/nested-includes.test.js +130 -103
- package/tests/pagination-cursor-multifield.test.js +17 -13
- package/tests/pagination-enhanced.test.js +19 -24
- package/tests/polymorphic-simple.test.js +9 -9
- package/tests/positioning-advanced.test.js +19 -19
- package/tests/positioning-extended.test.js +25 -25
- package/tests/positioning-multifilter.test.js +62 -62
- package/tests/positioning.test.js +7 -7
- package/tests/queries.test.js +5 -5
- package/tests/query-limits.test.js +77 -92
- package/tests/rest-api-access.test.js +206 -0
- package/tests/searchschema-merge.test.js +182 -0
- package/tests/socketio.test.js +33 -14
- package/tests/virtual-fields.test.js +0 -1
- package/docs/DOCS_ALL.md +0 -21894
- package/plugins/core/jwt-auth-plugin.js +0 -897
- package/plugins/core/lib/jwt-auth-helpers.js +0 -130
- package/tests/jwt-auth.test.js +0 -692
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Custom URL Override Using Hooks
|
|
5
|
+
*
|
|
6
|
+
* This example demonstrates how to override URL generation using the
|
|
7
|
+
* hooked-api hooks system. This is the recommended approach for custom
|
|
8
|
+
* URL scenarios like API gateways, CDNs, or multi-tenant applications.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Api } from 'hooked-api';
|
|
12
|
+
import { RestApiPlugin, RestApiKnexPlugin, ExpressPlugin } from 'json-rest-api';
|
|
13
|
+
import knexLib from 'knex';
|
|
14
|
+
import express from 'express';
|
|
15
|
+
|
|
16
|
+
// Create in-memory database
|
|
17
|
+
const knex = knexLib({
|
|
18
|
+
client: 'better-sqlite3',
|
|
19
|
+
connection: { filename: ':memory:' },
|
|
20
|
+
useNullAsDefault: true
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Create API with URL override hook
|
|
24
|
+
const api = new Api({
|
|
25
|
+
name: 'url-override-demo',
|
|
26
|
+
|
|
27
|
+
// Define hooks at API creation time
|
|
28
|
+
hooks: {
|
|
29
|
+
// This hook runs at the start of each request
|
|
30
|
+
'transport:request': [
|
|
31
|
+
async (payload) => {
|
|
32
|
+
const { context, req } = payload;
|
|
33
|
+
|
|
34
|
+
// Example 1: Override based on custom header
|
|
35
|
+
// Useful for CDN or API gateway scenarios
|
|
36
|
+
if (req?.headers?.['x-public-url']) {
|
|
37
|
+
context.urlPrefixOverride = req.headers['x-public-url'];
|
|
38
|
+
console.log(`✓ URL overridden via X-Public-URL header: ${context.urlPrefixOverride}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Example 2: API versioning via header
|
|
42
|
+
// Route different API versions while maintaining same backend
|
|
43
|
+
else if (req?.headers?.['x-api-version'] === 'v2') {
|
|
44
|
+
context.urlPrefixOverride = 'https://api.example.com/v2';
|
|
45
|
+
console.log(`✓ URL overridden for API v2: ${context.urlPrefixOverride}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Example 3: Multi-tenant based on host
|
|
49
|
+
// Each tenant gets their own domain in responses
|
|
50
|
+
else if (req?.hostname?.includes('tenant-a')) {
|
|
51
|
+
context.urlPrefixOverride = `https://tenant-a.api.com${req.baseUrl || ''}`;
|
|
52
|
+
console.log(`✓ URL overridden for tenant-a: ${context.urlPrefixOverride}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Example 4: Environment-based override
|
|
56
|
+
// Force production URLs in staging environment
|
|
57
|
+
else if (process.env.FORCE_PRODUCTION_URLS === 'true') {
|
|
58
|
+
context.urlPrefixOverride = 'https://api.production.com/api';
|
|
59
|
+
console.log(`✓ URL overridden via environment: ${context.urlPrefixOverride}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return payload;
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Install plugins
|
|
69
|
+
await api.use(RestApiPlugin, {
|
|
70
|
+
returnRecordTransport: { post: 'full' } // Return full JSON:API response
|
|
71
|
+
});
|
|
72
|
+
await api.use(RestApiKnexPlugin, { knex });
|
|
73
|
+
await api.use(ExpressPlugin, { mountPath: '/api' });
|
|
74
|
+
|
|
75
|
+
// Define a simple resource
|
|
76
|
+
await api.addResource('items', {
|
|
77
|
+
schema: {
|
|
78
|
+
name: { type: 'string', required: true, max: 100 },
|
|
79
|
+
description: { type: 'string', max: 500 }
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
await api.resources.items.createKnexTable();
|
|
83
|
+
|
|
84
|
+
// Create some test data
|
|
85
|
+
console.log('\n📝 Creating test data...');
|
|
86
|
+
await api.resources.items.post({
|
|
87
|
+
inputRecord: {
|
|
88
|
+
data: {
|
|
89
|
+
type: 'items',
|
|
90
|
+
attributes: {
|
|
91
|
+
name: 'Test Item 1',
|
|
92
|
+
description: 'This is a test item'
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
simplified: false
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Create Express app
|
|
100
|
+
const app = express();
|
|
101
|
+
app.use(api.http.express.router);
|
|
102
|
+
|
|
103
|
+
// Start server
|
|
104
|
+
const PORT = process.env.PORT || 3333;
|
|
105
|
+
const server = app.listen(PORT, () => {
|
|
106
|
+
console.log(`\n🚀 Server running on http://localhost:${PORT}`);
|
|
107
|
+
console.log('\n📚 Try these examples:\n');
|
|
108
|
+
|
|
109
|
+
console.log('1. Default URL (auto-detected):');
|
|
110
|
+
console.log(` curl http://localhost:${PORT}/api/items`);
|
|
111
|
+
console.log(' → URLs will be: http://localhost:${PORT}/api/items/1\n');
|
|
112
|
+
|
|
113
|
+
console.log('2. Custom CDN URL:');
|
|
114
|
+
console.log(` curl -H "X-Public-URL: https://cdn.example.com/api" http://localhost:${PORT}/api/items`);
|
|
115
|
+
console.log(' → URLs will be: https://cdn.example.com/api/items/1\n');
|
|
116
|
+
|
|
117
|
+
console.log('3. API Version Header:');
|
|
118
|
+
console.log(` curl -H "X-API-Version: v2" http://localhost:${PORT}/api/items`);
|
|
119
|
+
console.log(' → URLs will be: https://api.example.com/v2/items/1\n');
|
|
120
|
+
|
|
121
|
+
console.log('4. Create with custom URL:');
|
|
122
|
+
console.log(` curl -X POST -H "Content-Type: application/vnd.api+json" \\`);
|
|
123
|
+
console.log(` -H "X-Public-URL: https://public.api.com/api" \\`);
|
|
124
|
+
console.log(` -d '{"data":{"type":"items","attributes":{"name":"New Item"}}}' \\`);
|
|
125
|
+
console.log(` http://localhost:${PORT}/api/items`);
|
|
126
|
+
console.log(' → Response URLs will use: https://public.api.com/api/items/2\n');
|
|
127
|
+
|
|
128
|
+
console.log('Press Ctrl+C to stop the server\n');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Graceful shutdown
|
|
132
|
+
process.on('SIGINT', async () => {
|
|
133
|
+
console.log('\n\n👋 Shutting down gracefully...');
|
|
134
|
+
server.close();
|
|
135
|
+
await knex.destroy();
|
|
136
|
+
process.exit(0);
|
|
137
|
+
});
|
package/index.js
CHANGED
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
// Core plugins
|
|
12
12
|
export { RestApiPlugin } from './plugins/core/rest-api-plugin.js';
|
|
13
13
|
export { FileHandlingPlugin } from './plugins/core/file-handling-plugin.js';
|
|
14
|
+
export { CorsPlugin } from './plugins/core/rest-api-cors-plugin.js';
|
|
15
|
+
export { AccessPlugin } from './plugins/core/rest-api-access.js';
|
|
14
16
|
|
|
15
17
|
// Database plugins
|
|
16
18
|
export { RestApiKnexPlugin } from './plugins/core/rest-api-knex-plugin.js';
|
|
19
|
+
export { RestApiAnyapiKnexPlugin } from './plugins/core/rest-api-anyapi-knex-plugin.js';
|
|
17
20
|
|
|
18
21
|
// Connector plugins
|
|
19
22
|
export { ExpressPlugin } from './plugins/core/connectors/express-plugin.js';
|
|
@@ -32,4 +35,7 @@ export {
|
|
|
32
35
|
} from './lib/rest-api-errors.js';
|
|
33
36
|
|
|
34
37
|
// Re-export everything for backward compatibility
|
|
35
|
-
export * from './lib/rest-api-errors.js';
|
|
38
|
+
export * from './lib/rest-api-errors.js';
|
|
39
|
+
|
|
40
|
+
// URL helper function for generating API URL prefix
|
|
41
|
+
export { getUrlPrefix } from './plugins/core/lib/querying/url-helpers.js';
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-rest-api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node --test tests/*.test.js",
|
|
8
|
+
"test:anyapi": "JSON_REST_API_STORAGE=anyapi node --test tests/*.test.js",
|
|
8
9
|
"docs": "node scripts/run-docs.js",
|
|
9
10
|
"sloc": "sloc --exclude \"(_site|node_modules|\\.git|vendor|docs)\" .",
|
|
10
11
|
"slod": "cd docs;echo 'DOC LINES:'; cat `find . -iname \\*md | grep -v _site | grep -v vendor` | wc"
|
|
@@ -21,8 +22,8 @@
|
|
|
21
22
|
"homepage": "https://mobily-enterprises.github.io/json-rest-api",
|
|
22
23
|
"description": "REST API plugin for hooked-api with JSON:API compliance",
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"hooked-api": "^1.0.
|
|
25
|
-
"json-rest-schema": "^1.0.
|
|
25
|
+
"hooked-api": "^1.0.22",
|
|
26
|
+
"json-rest-schema": "^1.0.10",
|
|
26
27
|
"semver": "^7.7.2"
|
|
27
28
|
},
|
|
28
29
|
"peerDependencies": {
|
|
@@ -32,8 +33,7 @@
|
|
|
32
33
|
"express": "^4.0.0 || ^5.0.0",
|
|
33
34
|
"formidable": "^3.0.0",
|
|
34
35
|
"fractional-indexing": "^3.2.0",
|
|
35
|
-
"
|
|
36
|
-
"jwks-rsa": "^3.2.0",
|
|
36
|
+
"jose": "^5.10.0",
|
|
37
37
|
"knex": "^3.1.0",
|
|
38
38
|
"raw-body": "^2.0.0",
|
|
39
39
|
"redis": "^5.6.0",
|
|
@@ -58,10 +58,7 @@
|
|
|
58
58
|
"fractional-indexing": {
|
|
59
59
|
"optional": true
|
|
60
60
|
},
|
|
61
|
-
"
|
|
62
|
-
"optional": true
|
|
63
|
-
},
|
|
64
|
-
"jwks-rsa": {
|
|
61
|
+
"jose": {
|
|
65
62
|
"optional": true
|
|
66
63
|
},
|
|
67
64
|
"knex": {
|
|
@@ -82,8 +79,7 @@
|
|
|
82
79
|
"better-sqlite3": "^11.10.0",
|
|
83
80
|
"express": "^5.1.0",
|
|
84
81
|
"fractional-indexing": "^3.2.0",
|
|
85
|
-
"
|
|
86
|
-
"jwks-rsa": "^3.2.0",
|
|
82
|
+
"jose": "^5.10.0",
|
|
87
83
|
"knex": "^3.1.0",
|
|
88
84
|
"redis": "^5.6.0",
|
|
89
85
|
"socket.io": "^4.8.1",
|
|
@@ -348,6 +348,8 @@ export const BulkOperationsPlugin = {
|
|
|
348
348
|
|
|
349
349
|
// Hook into scope creation to add bulk routes
|
|
350
350
|
addHook('afterAddScope', 'bulkOperationsRoutes', {}, async ({ scopeName }) => {
|
|
351
|
+
// Note: context is not available here during route registration
|
|
352
|
+
// The urlPrefix will be calculated per-request in the handler
|
|
351
353
|
const urlPrefix = api.vars.transport?.mountPath || '';
|
|
352
354
|
const scopePath = `${urlPrefix}/${scopeName}`;
|
|
353
355
|
|
|
@@ -24,6 +24,13 @@ export const ExpressPlugin = {
|
|
|
24
24
|
dependencies: ['rest-api'],
|
|
25
25
|
|
|
26
26
|
async install({ on, vars, helpers, pluginOptions, log, scopes, api, runHooks, addHook }) {
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
addHook('release', 'releaseHook', {},
|
|
30
|
+
async ({ api }) => {} // TODO: Anything to do here?
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
|
|
27
34
|
// Dynamic import for Express
|
|
28
35
|
let express;
|
|
29
36
|
try {
|
|
@@ -113,16 +120,15 @@ export const ExpressPlugin = {
|
|
|
113
120
|
router.use(async (req, res, next) => {
|
|
114
121
|
const context = createContext(req, res, 'express');
|
|
115
122
|
|
|
116
|
-
//
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
const protocol = req.get('x-forwarded-proto') || req.protocol || 'http';
|
|
120
|
-
const host = req.get('x-forwarded-host') || req.get('host');
|
|
121
|
-
if (host) {
|
|
122
|
-
vars.publicBaseUrl = `${protocol}://${host}${basePath}`;
|
|
123
|
-
}
|
|
123
|
+
// Check for Express middleware override first
|
|
124
|
+
if (req.urlPrefixOverride) {
|
|
125
|
+
context.urlPrefixOverride = req.urlPrefixOverride;
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
// Calculate and cache URL prefix (getUrlPrefix handles all logic)
|
|
129
|
+
const { getUrlPrefix } = await import('../lib/querying/url-helpers.js');
|
|
130
|
+
context.urlPrefix = getUrlPrefix(context, { vars: { transport: { mountPath: basePath } } }, req);
|
|
131
|
+
|
|
126
132
|
// Transport-specific data for hooks
|
|
127
133
|
const transportData = {
|
|
128
134
|
request: {
|
|
@@ -142,22 +148,28 @@ export const ExpressPlugin = {
|
|
|
142
148
|
|
|
143
149
|
// Add transport data to context
|
|
144
150
|
context.transport = transportData;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
status: String(context.rejection.status || 500),
|
|
156
|
-
title: context.rejection.title || 'Request Rejected',
|
|
157
|
-
detail: context.rejection.message
|
|
158
|
-
}]
|
|
159
|
-
});
|
|
151
|
+
|
|
152
|
+
// Run transport hooks - don't check return value for consistency with other hooks
|
|
153
|
+
// Hooks communicate via context flags (rejection, handled) not return values
|
|
154
|
+
await runHooks('transport:request', context);
|
|
155
|
+
|
|
156
|
+
// Check if request was rejected (e.g., authentication failure)
|
|
157
|
+
if (context.rejection) {
|
|
158
|
+
// Apply response headers from hooks
|
|
159
|
+
if (transportData.response.headers) {
|
|
160
|
+
res.set(transportData.response.headers);
|
|
160
161
|
}
|
|
162
|
+
return res.status(context.rejection.status || 500).json({
|
|
163
|
+
errors: [{
|
|
164
|
+
status: String(context.rejection.status || 500),
|
|
165
|
+
title: context.rejection.title || 'Request Rejected',
|
|
166
|
+
detail: context.rejection.message
|
|
167
|
+
}]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Check if request was already handled by a hook
|
|
172
|
+
if (context.handled) {
|
|
161
173
|
return;
|
|
162
174
|
}
|
|
163
175
|
|
|
@@ -345,7 +357,7 @@ export const ExpressPlugin = {
|
|
|
345
357
|
// Set Location header for any successful POST (201 or 204)
|
|
346
358
|
if (helpers.getLocation) {
|
|
347
359
|
const location = helpers.getLocation({ scopeName, id: context.id });
|
|
348
|
-
const baseUrl =
|
|
360
|
+
const baseUrl = context.urlPrefix || basePath;
|
|
349
361
|
res.set('Location', `${baseUrl}${location}`);
|
|
350
362
|
}
|
|
351
363
|
}
|
|
@@ -415,6 +427,13 @@ export const ExpressPlugin = {
|
|
|
415
427
|
// So we use them as-is without adding basePath to avoid double-prefixing
|
|
416
428
|
|
|
417
429
|
router[method.toLowerCase()](path, ...beforeMiddleware, expressHandler);
|
|
430
|
+
|
|
431
|
+
// Debug logging for route registration
|
|
432
|
+
|
|
433
|
+
// Check if the route was actually added
|
|
434
|
+
if (router.stack) {
|
|
435
|
+
const lastRoute = router.stack[router.stack.length - 1];
|
|
436
|
+
}
|
|
418
437
|
}
|
|
419
438
|
|
|
420
439
|
|
|
@@ -164,7 +164,7 @@ export function extractToken(req) {
|
|
|
164
164
|
return bearerMatch[1];
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
// Check cookies for session token (Auth.js pattern)
|
|
169
169
|
const cookies = parseCookies(req.headers.cookie || '');
|
|
170
170
|
if (cookies['__Secure-authjs.session-token']) {
|
|
@@ -173,7 +173,7 @@ export function extractToken(req) {
|
|
|
173
173
|
if (cookies['authjs.session-token']) {
|
|
174
174
|
return cookies['authjs.session-token'];
|
|
175
175
|
}
|
|
176
|
-
|
|
176
|
+
|
|
177
177
|
return null;
|
|
178
178
|
}
|
|
179
179
|
|