inertia-sails 1.3.0 → 1.3.2
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/index.js +73 -22
- package/lib/helpers/request-context.js +1 -1
- package/lib/render.js +10 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -110,6 +110,38 @@ module.exports = function defineInertiaHook(sails) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Configure phase — runs after all hooks' defaults are merged but BEFORE
|
|
116
|
+
* any hook's initialize(). This is the right place to inject HTTP middleware
|
|
117
|
+
* because the HTTP hook hasn't read the middleware order yet.
|
|
118
|
+
*/
|
|
119
|
+
configure: function () {
|
|
120
|
+
// Inject AsyncLocalStorage context middleware into the HTTP stack
|
|
121
|
+
// BEFORE the router. This guarantees context is available in ALL
|
|
122
|
+
// routes.before handlers from all hooks, regardless of hook load order.
|
|
123
|
+
//
|
|
124
|
+
// Lifecycle:
|
|
125
|
+
// cookieParser → session → bodyParser → ... → inertiaContext → router
|
|
126
|
+
//
|
|
127
|
+
// By the time any routes.before handler calls sails.inertia.share(),
|
|
128
|
+
// the request is already wrapped in AsyncLocalStorage context.
|
|
129
|
+
if (sails.config.http && sails.config.http.middleware) {
|
|
130
|
+
const mw = sails.config.http.middleware
|
|
131
|
+
if (mw.order && mw.order.indexOf('inertiaContext') === -1) {
|
|
132
|
+
const routerIdx = mw.order.indexOf('router')
|
|
133
|
+
if (routerIdx !== -1) {
|
|
134
|
+
mw.order.splice(routerIdx, 0, 'inertiaContext')
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!mw.inertiaContext) {
|
|
138
|
+
mw.inertiaContext = function inertiaContext(req, res, next) {
|
|
139
|
+
requestContext.run(req, res, next)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
|
|
113
145
|
initialize: async function () {
|
|
114
146
|
hook = this
|
|
115
147
|
sails.inertia = hook
|
|
@@ -127,19 +159,36 @@ module.exports = function defineInertiaHook(sails) {
|
|
|
127
159
|
},
|
|
128
160
|
|
|
129
161
|
/**
|
|
130
|
-
* Hook routes
|
|
131
|
-
*
|
|
162
|
+
* Hook routes — fallback context setup for socket requests.
|
|
163
|
+
* HTTP requests already have context from the inertiaContext middleware.
|
|
164
|
+
* Socket requests bypass Express middleware, so they need this.
|
|
132
165
|
*/
|
|
133
166
|
routes: {
|
|
134
167
|
before: {
|
|
135
168
|
'GET /*': {
|
|
136
169
|
skipAssets: true,
|
|
137
|
-
fn: (req, res, next) =>
|
|
170
|
+
fn: (req, res, next) => {
|
|
171
|
+
// Skip if context already set up by HTTP middleware
|
|
172
|
+
if (requestContext.getContext()) return next()
|
|
173
|
+
requestContext.run(req, res, next)
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
'POST /*': (req, res, next) => {
|
|
177
|
+
if (requestContext.getContext()) return next()
|
|
178
|
+
requestContext.run(req, res, next)
|
|
138
179
|
},
|
|
139
|
-
'
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
180
|
+
'PUT /*': (req, res, next) => {
|
|
181
|
+
if (requestContext.getContext()) return next()
|
|
182
|
+
requestContext.run(req, res, next)
|
|
183
|
+
},
|
|
184
|
+
'PATCH /*': (req, res, next) => {
|
|
185
|
+
if (requestContext.getContext()) return next()
|
|
186
|
+
requestContext.run(req, res, next)
|
|
187
|
+
},
|
|
188
|
+
'DELETE /*': (req, res, next) => {
|
|
189
|
+
if (requestContext.getContext()) return next()
|
|
190
|
+
requestContext.run(req, res, next)
|
|
191
|
+
}
|
|
143
192
|
}
|
|
144
193
|
},
|
|
145
194
|
|
|
@@ -152,14 +201,17 @@ module.exports = function defineInertiaHook(sails) {
|
|
|
152
201
|
* @returns {*} - The value that was shared
|
|
153
202
|
*/
|
|
154
203
|
share(key, value = null) {
|
|
155
|
-
// If we're in a request context, share for this request only
|
|
156
204
|
const context = requestContext.getContext()
|
|
157
205
|
if (context) {
|
|
158
206
|
requestContext.setSharedProp(key, value)
|
|
159
207
|
return value
|
|
160
208
|
}
|
|
161
|
-
//
|
|
162
|
-
|
|
209
|
+
// Never fall back to global — that causes data to leak across requests.
|
|
210
|
+
// Use shareGlobally() for truly global data like app name.
|
|
211
|
+
sails.log.warn(
|
|
212
|
+
`sails.inertia.share('${key}') called outside request context. ` +
|
|
213
|
+
'Value was not stored. Use shareGlobally() for global data.'
|
|
214
|
+
)
|
|
163
215
|
return value
|
|
164
216
|
},
|
|
165
217
|
|
|
@@ -190,27 +242,24 @@ module.exports = function defineInertiaHook(sails) {
|
|
|
190
242
|
|
|
191
243
|
/**
|
|
192
244
|
* Flush shared properties for the current request.
|
|
193
|
-
*
|
|
194
|
-
*
|
|
245
|
+
* Always flushes from both request-scoped AND global storage to prevent
|
|
246
|
+
* stale data from leaking across requests.
|
|
195
247
|
* @param {string|null} key - The key of the property to flush, or null to flush all
|
|
196
|
-
* @param {boolean} [global=false] - Whether to also flush global props (rarely needed)
|
|
197
248
|
*/
|
|
198
|
-
flushShared(key
|
|
249
|
+
flushShared(key) {
|
|
199
250
|
const context = requestContext.getContext()
|
|
200
251
|
if (key) {
|
|
201
252
|
if (context) {
|
|
202
253
|
delete context.sharedProps[key]
|
|
203
254
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
255
|
+
// Always clean global too — prevents stale data from a previous
|
|
256
|
+
// request (or a share() that fell through before context was ready)
|
|
257
|
+
delete sails.inertia.globalSharedProps[key]
|
|
207
258
|
} else {
|
|
208
259
|
if (context) {
|
|
209
260
|
context.sharedProps = {}
|
|
210
261
|
}
|
|
211
|
-
|
|
212
|
-
sails.inertia.globalSharedProps = {}
|
|
213
|
-
}
|
|
262
|
+
sails.inertia.globalSharedProps = {}
|
|
214
263
|
}
|
|
215
264
|
},
|
|
216
265
|
|
|
@@ -227,8 +276,10 @@ module.exports = function defineInertiaHook(sails) {
|
|
|
227
276
|
requestContext.setSharedLocal(key, value)
|
|
228
277
|
return value
|
|
229
278
|
}
|
|
230
|
-
|
|
231
|
-
|
|
279
|
+
sails.log.warn(
|
|
280
|
+
`sails.inertia.local('${key}') called outside request context. ` +
|
|
281
|
+
'Value was not stored. Use localGlobally() for global data.'
|
|
282
|
+
)
|
|
232
283
|
return value
|
|
233
284
|
},
|
|
234
285
|
|
|
@@ -46,7 +46,7 @@ module.exports = {
|
|
|
46
46
|
refreshOnceProps: [], // Props to force-refresh for this request
|
|
47
47
|
rootView: null // Request-scoped root view template
|
|
48
48
|
}
|
|
49
|
-
return requestContext.run(context, callback)
|
|
49
|
+
return requestContext.run(context, () => callback())
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
/**
|
package/lib/render.js
CHANGED
|
@@ -32,6 +32,15 @@ module.exports = async function render(req, res, data) {
|
|
|
32
32
|
return res.json(page)
|
|
33
33
|
} else {
|
|
34
34
|
// Implements full page reload
|
|
35
|
-
|
|
35
|
+
//
|
|
36
|
+
// We pass locals both as top-level properties AND nested under a `locals`
|
|
37
|
+
// key. This is necessary because Sails's default EJS renderer creates an
|
|
38
|
+
// `options.locals` object (for blocks, layout, partial helpers). EJS wraps
|
|
39
|
+
// templates in `with(data) { ... }`, so inside the template `locals`
|
|
40
|
+
// resolves to `data.locals` (the nested object) rather than the `locals`
|
|
41
|
+
// function parameter. By pre-populating `data.locals` with our values,
|
|
42
|
+
// `<%= locals.title %>` in the EJS template correctly resolves to the
|
|
43
|
+
// dynamic value instead of undefined.
|
|
44
|
+
return res.view(rootView, { page, ...allLocals, locals: { ...allLocals } })
|
|
36
45
|
}
|
|
37
46
|
}
|