pict-microapp 1.0.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.
@@ -0,0 +1,486 @@
1
+ /**
2
+ * Pict MicroApp — present a large pict application as a small, focused one.
3
+ *
4
+ * A "micro app" is not a fork and not a rebuild: it is the SAME application, booted the same way,
5
+ * with a smaller surface. You keep every view, provider, template, style and fix the host app
6
+ * already has — and an enhancement to the host lands in every micro app on its next build — but
7
+ * the routes, the navigation and the landing page are the micro app's own.
8
+ *
9
+ * The seam is narrow on purpose. A host pict application registers every route it owns through one
10
+ * funnel, `PictRouter.addRoute`. This provider wraps that funnel with an allow list taken from a
11
+ * declarative manifest, swaps the navigation graph, and re-points the landing route. Nothing else
12
+ * about the host's boot sequence changes, which is what keeps a micro app cheap to build and cheap
13
+ * to keep working as the host evolves.
14
+ *
15
+ * What this module deliberately does NOT do is make the JavaScript bundle smaller — the host's
16
+ * module graph is still bundled whole. It slims the app the user sees, not the bytes the browser
17
+ * downloads. See the README for the reasoning and for when that tradeoff stops being the right one.
18
+ *
19
+ * @author steven velozo <steven@velozo.com>
20
+ */
21
+
22
+ const libPictProvider = require('pict-provider');
23
+
24
+ const libManifest = require('./Pict-MicroApp-Manifest.js');
25
+
26
+ const _DEFAULT_PROVIDER_CONFIGURATION =
27
+ {
28
+ ProviderIdentifier: 'MicroApp',
29
+
30
+ AutoInitialize: true,
31
+ AutoInitializeOrdinal: 0,
32
+
33
+ // The micro app manifest. See Pict-MicroApp-Manifest.js for the shape and defaults.
34
+ Manifest: {},
35
+
36
+ // Service hash of the host's pict-router provider. Every host that uses pict-router registers
37
+ // it under this hash.
38
+ RouterProviderHash: 'PictRouter',
39
+
40
+ // Service hash of the host's pict-section-navigation provider, when it has one.
41
+ NavigationProviderHash: 'Pict-Navigation',
42
+
43
+ // Log each route the gate blocks. Noisy but invaluable while authoring a manifest, so it is on.
44
+ LogBlockedRoutes: true
45
+ };
46
+
47
+ class PictMicroApp extends libPictProvider
48
+ {
49
+ /**
50
+ * @param {Object} pFable - the fable instance
51
+ * @param {Object} [pOptions] - provider options, including the Manifest
52
+ * @param {String} [pServiceHash] - the service hash
53
+ */
54
+ constructor(pFable, pOptions, pServiceHash)
55
+ {
56
+ const tmpOptions = Object.assign({}, _DEFAULT_PROVIDER_CONFIGURATION, pOptions);
57
+ super(pFable, tmpOptions, pServiceHash);
58
+
59
+ /** @type {any} */
60
+ this.pict;
61
+
62
+ /** The normalized manifest — always fully populated, whatever the author wrote. */
63
+ this.manifest = libManifest.normalizeManifest(this.options.Manifest);
64
+
65
+ /** Route patterns the gate refused, in registration order. Read this when a screen is missing. */
66
+ this.blockedRoutes = [];
67
+ /** Route patterns the gate admitted with an entity guard. */
68
+ this.guardedRoutes = [];
69
+ /** Route patterns that survived untouched. */
70
+ this.allowedRoutes = [];
71
+
72
+ /** The original addRoute, kept so releaseRouter() can put the host back the way it was. */
73
+ this._originalAddRoute = null;
74
+ /** The original navigo `on`, for the same reason. */
75
+ this._originalRouterOn = null;
76
+ /** The router provider the gate is currently installed on. */
77
+ this._gatedRouter = null;
78
+ /** True while the provider-level gate is delegating into the navigo-level one. */
79
+ this._delegating = false;
80
+ }
81
+
82
+ /**
83
+ * The host's pict-router provider, or null before it exists.
84
+ *
85
+ * @return {Object|null} the router provider
86
+ */
87
+ get pictRouter()
88
+ {
89
+ const tmpProviders = (this.pict && this.pict.providers) ? this.pict.providers : {};
90
+ return tmpProviders[this.options.RouterProviderHash] || null;
91
+ }
92
+
93
+ /**
94
+ * The host's navigation provider, or null when the host has none.
95
+ *
96
+ * @return {Object|null} the navigation provider
97
+ */
98
+ get navigationProvider()
99
+ {
100
+ const tmpProviders = (this.pict && this.pict.providers) ? this.pict.providers : {};
101
+ return tmpProviders[this.options.NavigationProviderHash] || null;
102
+ }
103
+
104
+ /**
105
+ * Replace the manifest after construction. Only meaningful before the gate is installed.
106
+ *
107
+ * @param {Object} pManifest - a micro app manifest
108
+ * @return {Object} the normalized manifest
109
+ */
110
+ setManifest(pManifest)
111
+ {
112
+ this.manifest = libManifest.normalizeManifest(pManifest);
113
+ return this.manifest;
114
+ }
115
+
116
+ /**
117
+ * What would the gate do with this route? Exposed so an app (or a test) can ask without
118
+ * registering anything.
119
+ *
120
+ * @param {String} pRoute - a route pattern
121
+ * @return {{Mode: String, Route: String, Reason: String}} the decision
122
+ */
123
+ routeDecision(pRoute)
124
+ {
125
+ return libManifest.decideRoute(this.manifest, pRoute);
126
+ }
127
+
128
+ /**
129
+ * Install the route gate on the host's router.
130
+ *
131
+ * MUST be called after the router provider exists but BEFORE the host registers its routes. In
132
+ * a pict application that means after the provider that owns routing has been added (usually in
133
+ * onInitializeAsync) and before the login/data-load cycle that registers them.
134
+ *
135
+ * Wrapping the instance method rather than the prototype keeps the blast radius to this one
136
+ * router: a host that shares pict-router with an embedded module is unaffected.
137
+ *
138
+ * TWO funnels are wrapped, not one. Most code registers through the provider's `addRoute`, but
139
+ * some modules reach past it and call the underlying router's `on` directly — pict-section-
140
+ * recordset's list, dashboard, associate and bulk-delete views all do, which is every one of its
141
+ * highest-traffic screens. Gating only `addRoute` silently leaves those wide open, and because
142
+ * they still work you would never notice. The provider-level wrapper sets `_delegating` while it
143
+ * calls through, so a route that came in via `addRoute` is decided once, not twice.
144
+ *
145
+ * @param {Object} [pPictRouter] - the router provider; defaults to the configured one
146
+ * @return {Boolean} whether the gate was installed
147
+ */
148
+ gateRouter(pPictRouter)
149
+ {
150
+ const tmpRouter = pPictRouter || this.pictRouter;
151
+ if (!tmpRouter || (typeof tmpRouter.addRoute !== 'function'))
152
+ {
153
+ this.pict.log.warn(`MicroApp [${ this.manifest.Name }] could not gate routes: no router provider at '${ this.options.RouterProviderHash }'.`);
154
+ return false;
155
+ }
156
+ if (this._originalAddRoute)
157
+ {
158
+ // Already gated. Re-gating would double-wrap every handler.
159
+ return true;
160
+ }
161
+
162
+ this._gatedRouter = tmpRouter;
163
+ this._originalAddRoute = tmpRouter.addRoute.bind(tmpRouter);
164
+
165
+ tmpRouter.addRoute = (pRoute, pRenderable, pTitle, pHooks) =>
166
+ {
167
+ const tmpDecision = this.routeDecision(pRoute);
168
+ if (tmpDecision.Mode === 'Block')
169
+ {
170
+ this._noteBlocked(tmpDecision);
171
+ return;
172
+ }
173
+
174
+ const tmpGuarded = (tmpDecision.Mode === 'Guard');
175
+ if (tmpGuarded)
176
+ {
177
+ this.guardedRoutes.push(tmpDecision.Route);
178
+ }
179
+ else
180
+ {
181
+ this.allowedRoutes.push(tmpDecision.Route);
182
+ }
183
+
184
+ this._delegating = true;
185
+ try
186
+ {
187
+ return this._originalAddRoute(tmpDecision.Route,
188
+ tmpGuarded ? this._guardRenderable(tmpDecision.Route, pRenderable) : pRenderable, pTitle, pHooks);
189
+ }
190
+ finally
191
+ {
192
+ this._delegating = false;
193
+ }
194
+ };
195
+
196
+ // The second funnel: direct registrations against the underlying router.
197
+ if (tmpRouter.router && (typeof tmpRouter.router.on === 'function'))
198
+ {
199
+ this._originalRouterOn = tmpRouter.router.on.bind(tmpRouter.router);
200
+ tmpRouter.router.on = (pRoute, pHandler, pHooks) =>
201
+ {
202
+ // Already decided by the provider-level wrapper, or one of the router's other
203
+ // `on` shapes (a bare handler, or a route map) that carries no path to decide on.
204
+ if (this._delegating || (typeof pRoute !== 'string'))
205
+ {
206
+ return this._originalRouterOn(pRoute, pHandler, pHooks);
207
+ }
208
+
209
+ const tmpDecision = this.routeDecision(pRoute);
210
+ if (tmpDecision.Mode === 'Block')
211
+ {
212
+ this._noteBlocked(tmpDecision);
213
+ return this._gatedRouter.router;
214
+ }
215
+ if (tmpDecision.Mode === 'Guard')
216
+ {
217
+ this.guardedRoutes.push(tmpDecision.Route);
218
+ return this._originalRouterOn(tmpDecision.Route, this._guardRenderable(tmpDecision.Route, pHandler), pHooks);
219
+ }
220
+ this.allowedRoutes.push(tmpDecision.Route);
221
+ return this._originalRouterOn(pRoute, pHandler, pHooks);
222
+ };
223
+ }
224
+
225
+ return true;
226
+ }
227
+
228
+ /**
229
+ * Record (and optionally log) a route the gate refused.
230
+ *
231
+ * @param {{Route: String, Reason: String}} pDecision - the decision that blocked it
232
+ */
233
+ _noteBlocked(pDecision)
234
+ {
235
+ this.blockedRoutes.push(pDecision.Route);
236
+ if (this.options.LogBlockedRoutes)
237
+ {
238
+ this.pict.log.trace(`MicroApp [${ this.manifest.Name }] route not exposed: ${ pDecision.Route } (${ pDecision.Reason })`);
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Put the host's router back the way it was. Primarily for tests.
244
+ *
245
+ * @return {Boolean} whether a gate was removed
246
+ */
247
+ releaseRouter()
248
+ {
249
+ if (!this._gatedRouter || !this._originalAddRoute)
250
+ {
251
+ return false;
252
+ }
253
+ this._gatedRouter.addRoute = this._originalAddRoute;
254
+ if (this._originalRouterOn && this._gatedRouter.router)
255
+ {
256
+ this._gatedRouter.router.on = this._originalRouterOn;
257
+ }
258
+ this._originalAddRoute = null;
259
+ this._originalRouterOn = null;
260
+ this._gatedRouter = null;
261
+ return true;
262
+ }
263
+
264
+ /**
265
+ * Wrap an entity-parameterized route's handler so an entity the micro app does not expose
266
+ * bounces to the fallback instead of rendering.
267
+ *
268
+ * Wildcard record-set routes ('/PSRS/:RecordSet/List') are registered once by the host and fan
269
+ * out over every entity it knows. They cannot be refused per-entity at registration time, so
270
+ * this is where the subsetting has to happen.
271
+ *
272
+ * @param {String} pRoute - the canonical route pattern
273
+ * @param {Function|String} pRenderable - the host's handler
274
+ * @return {Function|String} the guarded handler, or the renderable untouched when it is a template
275
+ */
276
+ _guardRenderable(pRoute, pRenderable)
277
+ {
278
+ if (typeof pRenderable !== 'function')
279
+ {
280
+ return pRenderable;
281
+ }
282
+ const tmpEntityParameter = this.manifest.Routes.EntityParameter;
283
+ return (pRouteData) =>
284
+ {
285
+ const tmpEntity = (pRouteData && pRouteData.data) ? pRouteData.data[tmpEntityParameter] : null;
286
+ if (tmpEntity && !libManifest.entityPermitted(this.manifest, tmpEntity))
287
+ {
288
+ this.pict.log.trace(`MicroApp [${ this.manifest.Name }] entity not exposed on ${ pRoute }: ${ tmpEntity } — routing to ${ this.manifest.Routes.Fallback }.`);
289
+ return this.navigate(this.manifest.Routes.Fallback);
290
+ }
291
+ return pRenderable(pRouteData);
292
+ };
293
+ }
294
+
295
+ /**
296
+ * Send the browser to a route. Uses the host router when it is available so hooks and history
297
+ * behave the same as any other navigation.
298
+ *
299
+ * @param {String} pRoute - the route to navigate to
300
+ * @return {Boolean} whether a navigation was attempted
301
+ */
302
+ navigate(pRoute)
303
+ {
304
+ const tmpRoute = libManifest.normalizeRoute(pRoute);
305
+ const tmpRouter = this.pictRouter;
306
+ if (tmpRouter && (typeof tmpRouter.navigate === 'function'))
307
+ {
308
+ tmpRouter.navigate(tmpRoute);
309
+ return true;
310
+ }
311
+ if ((typeof window !== 'undefined') && window.location)
312
+ {
313
+ window.location.hash = tmpRoute;
314
+ return true;
315
+ }
316
+ return false;
317
+ }
318
+
319
+ /**
320
+ * Point a hash that matched no surviving route at the fallback, so a stale bookmark into a
321
+ * screen this micro app does not carry lands somewhere real instead of on a blank page.
322
+ *
323
+ * @param {Object} [pPictRouter] - the router provider; defaults to the configured one
324
+ * @return {Boolean} whether the handler was installed
325
+ */
326
+ installNotFound(pPictRouter)
327
+ {
328
+ if (!this.manifest.Routes.CatchUnmatched)
329
+ {
330
+ return false;
331
+ }
332
+ const tmpRouter = pPictRouter || this.pictRouter;
333
+ // `router` is the underlying navigo instance the pict provider wraps.
334
+ if (!tmpRouter || !tmpRouter.router || (typeof tmpRouter.router.notFound !== 'function'))
335
+ {
336
+ return false;
337
+ }
338
+ tmpRouter.router.notFound(() =>
339
+ {
340
+ this.pict.log.trace(`MicroApp [${ this.manifest.Name }] unmatched route — routing to ${ this.manifest.Routes.Fallback }.`);
341
+ this.navigate(this.manifest.Routes.Fallback);
342
+ });
343
+ return true;
344
+ }
345
+
346
+ /**
347
+ * Swap the host's navigation graph for the micro app's, and PIN it.
348
+ *
349
+ * Pinning is not paranoia. A host application of any size rebuilds its own navigation after the
350
+ * fact — as configuration loads, as permissions resolve, as dynamically registered sections
351
+ * appear — and each rebuild calls `setNavigationGraph` with the host's graph, silently undoing
352
+ * the swap. The symptom is the worst kind: the micro app's menu is correct at first paint and
353
+ * then quietly becomes the host's, usually after login, where nobody is looking.
354
+ *
355
+ * So rather than racing the host for the last write, the setter itself is wrapped: later calls
356
+ * still re-normalize and re-render, they just always land on the micro app's sections.
357
+ *
358
+ * @param {Object} [pNavigationProvider] - the navigation provider; defaults to the configured one
359
+ * @return {Boolean} whether the graph was swapped
360
+ */
361
+ applyNavigationGraph(pNavigationProvider)
362
+ {
363
+ const tmpSections = this.manifest.Navigation.Sections;
364
+ if (!tmpSections || (tmpSections.length < 1))
365
+ {
366
+ return false;
367
+ }
368
+ const tmpProvider = pNavigationProvider || this.navigationProvider;
369
+ if (!tmpProvider || (typeof tmpProvider.setNavigationGraph !== 'function'))
370
+ {
371
+ this.pict.log.warn(`MicroApp [${ this.manifest.Name }] could not set the navigation graph: no navigation provider at '${ this.options.NavigationProviderHash }'.`);
372
+ return false;
373
+ }
374
+
375
+ if (this.manifest.Navigation.PinGraph && !tmpProvider._microAppGraphPinned)
376
+ {
377
+ const fSetNavigationGraph = tmpProvider.setNavigationGraph.bind(tmpProvider);
378
+ tmpProvider.setNavigationGraph = () => fSetNavigationGraph(tmpSections);
379
+ tmpProvider._microAppGraphPinned = true;
380
+ }
381
+
382
+ tmpProvider.setNavigationGraph(tmpSections);
383
+ return true;
384
+ }
385
+
386
+ /**
387
+ * Install the micro app's navigation visibility gate.
388
+ *
389
+ * A host that serves many audiences usually trims its own (large) graph hard — the Headlight
390
+ * platform app, for instance, shows platform super-users only the handful of cross-customer
391
+ * destinations. Applied to a micro app graph, which is already the slimmed surface, that trim
392
+ * empties the menu completely. So the default here keeps the host's real gates (session,
393
+ * module, capability) and drops only the audience short-circuit.
394
+ *
395
+ * @param {Function} pHostPermitted - (pItem) => Boolean, the host's own per-item capability test
396
+ * @param {Object} [pOptions] - { IsPrivileged: () => Boolean } to keep privileged sessions unfiltered
397
+ * @return {Boolean} whether the gate was installed
398
+ */
399
+ applyNavigationGate(pHostPermitted, pOptions)
400
+ {
401
+ const tmpProvider = this.navigationProvider;
402
+ if (!tmpProvider || (typeof tmpProvider.setGlobalFilter !== 'function'))
403
+ {
404
+ return false;
405
+ }
406
+ const tmpOptions = pOptions || {};
407
+ const tmpIsPrivileged = (typeof tmpOptions.IsPrivileged === 'function') ? tmpOptions.IsPrivileged : (() => false);
408
+ const tmpHonorHostGates = this.manifest.Navigation.HonorHostGates;
409
+ const tmpSuperUserSeesEverything = this.manifest.Navigation.SuperUserSeesEverything;
410
+
411
+ tmpProvider.setGlobalFilter((pItem, pCategory) =>
412
+ {
413
+ if (pItem.Hidden || (pCategory && pCategory.Hidden))
414
+ {
415
+ return false;
416
+ }
417
+ if (!tmpHonorHostGates)
418
+ {
419
+ return true;
420
+ }
421
+ // A privileged session holds no entitlements in the customer's own tenancy, so running
422
+ // it through the capability test would blank the menu a second way. Show it everything.
423
+ if (tmpSuperUserSeesEverything && tmpIsPrivileged())
424
+ {
425
+ return true;
426
+ }
427
+ return (typeof pHostPermitted === 'function') ? !!pHostPermitted(pItem, pCategory) : true;
428
+ });
429
+ return true;
430
+ }
431
+
432
+ /**
433
+ * Point the host's routing provider at the micro app's landing route.
434
+ *
435
+ * @param {Object} pHostRouterProvider - the provider that owns `defaultRoute` (often a wrapper
436
+ * around pict-router rather than pict-router itself)
437
+ * @return {Boolean} whether the landing route was set
438
+ */
439
+ applyDefaultRoute(pHostRouterProvider)
440
+ {
441
+ if (!pHostRouterProvider)
442
+ {
443
+ return false;
444
+ }
445
+ // Hosts spell this without the leading slash (navigo's own convention for a default).
446
+ pHostRouterProvider.defaultRoute = this.manifest.DefaultRoute.replace(/^\//, '');
447
+ return true;
448
+ }
449
+
450
+ /**
451
+ * Apply the manifest's branding to the document.
452
+ *
453
+ * @return {Boolean} whether a title was set
454
+ */
455
+ applyBranding()
456
+ {
457
+ const tmpTitle = this.manifest.Branding.Title || this.manifest.Name;
458
+ if (!tmpTitle || (typeof document === 'undefined'))
459
+ {
460
+ return false;
461
+ }
462
+ document.title = tmpTitle;
463
+ return true;
464
+ }
465
+
466
+ /**
467
+ * A one-line summary of what the gate did, for the console and for tests.
468
+ *
469
+ * @return {{Name: String, Allowed: Number, Guarded: Number, Blocked: Number}} the tally
470
+ */
471
+ get routeTally()
472
+ {
473
+ return (
474
+ {
475
+ Name: this.manifest.Name,
476
+ Allowed: this.allowedRoutes.length,
477
+ Guarded: this.guardedRoutes.length,
478
+ Blocked: this.blockedRoutes.length
479
+ });
480
+ }
481
+ }
482
+
483
+ module.exports = PictMicroApp;
484
+ module.exports.default_configuration = _DEFAULT_PROVIDER_CONFIGURATION;
485
+ module.exports.Manifest = libManifest;
486
+ module.exports.composeMicroApp = require('./Pict-MicroApp-Compose.js');
@@ -0,0 +1,24 @@
1
+ export = composeMicroApp;
2
+ /**
3
+ * Build a micro app application class from a host application class and a manifest.
4
+ *
5
+ * @param {Function} pHostApplicationClass - the host pict application class to present a subset of
6
+ * @param {Object} pManifest - the micro app manifest (see Pict-MicroApp-Manifest.js)
7
+ * @param {Object} [pComposeOptions] - the host binding options above
8
+ * @return {Function} a class extending the host application class
9
+ */
10
+ declare function composeMicroApp(pHostApplicationClass: Function, pManifest: any, pComposeOptions?: any): Function;
11
+ declare namespace composeMicroApp {
12
+ export { _DEFAULT_COMPOSE_OPTIONS as default_compose_options };
13
+ }
14
+ declare namespace _DEFAULT_COMPOSE_OPTIONS {
15
+ let ProviderHash: string;
16
+ let RouterProviderHash: string;
17
+ let NavigationProviderHash: string;
18
+ let HostRouterProviderHash: string;
19
+ let AttachOn: string;
20
+ let NavigationGateMethod: string;
21
+ let HostPermittedMethod: string;
22
+ let IsPrivilegedMethod: string;
23
+ }
24
+ //# sourceMappingURL=Pict-MicroApp-Compose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pict-MicroApp-Compose.d.ts","sourceRoot":"","sources":["../source/Pict-MicroApp-Compose.js"],"names":[],"mappings":";AAqDA;;;;;;;GAOG;AACH,mHAoFC"}
@@ -0,0 +1,88 @@
1
+ declare namespace _DEFAULT_MANIFEST {
2
+ let Name: string;
3
+ let Hash: string;
4
+ let DefaultRoute: string;
5
+ namespace Routes {
6
+ let Allow: any[];
7
+ let Deny: any[];
8
+ let EntityParameter: string;
9
+ let Entities: any[];
10
+ let GuardEntityRoutes: boolean;
11
+ let Fallback: string;
12
+ let CatchUnmatched: boolean;
13
+ let AlwaysAllow: string[];
14
+ }
15
+ namespace Navigation {
16
+ let Sections: any[];
17
+ let PinGraph: boolean;
18
+ let SuperUserSeesEverything: boolean;
19
+ let HonorHostGates: boolean;
20
+ }
21
+ namespace Branding {
22
+ let Title: string;
23
+ let LoginTitle: string;
24
+ }
25
+ }
26
+ /**
27
+ * Deep-ish merge of an author manifest over the defaults. Only the three known sub-objects are
28
+ * merged a level down; everything else is a straight overwrite.
29
+ *
30
+ * @param {Object} [pManifest] - the author's manifest
31
+ * @return {Object} a fully populated manifest
32
+ */
33
+ export function normalizeManifest(pManifest?: any): any;
34
+ /**
35
+ * Strip a route to the canonical form used for comparison: no leading '#', exactly one leading '/',
36
+ * no trailing '/' (except the bare root).
37
+ *
38
+ * @param {String} pRoute - a route pattern or hash
39
+ * @return {String} the canonical route pattern
40
+ */
41
+ export function normalizeRoute(pRoute: string): string;
42
+ /**
43
+ * Does a canonical route pattern match one allow/deny entry? An entry ending in '*' is a prefix
44
+ * glob; anything else is an exact pattern match (so '/Asset/Workspace/:ID' matches only the route
45
+ * registered with that exact parameter spelling).
46
+ *
47
+ * @param {String} pRoute - a canonical route pattern
48
+ * @param {String} pEntry - a canonical allow/deny entry
49
+ * @return {Boolean} whether the entry matches
50
+ */
51
+ export function routeMatchesEntry(pRoute: string, pEntry: string): boolean;
52
+ /**
53
+ * Does this route pattern fan out over the manifest's entity parameter (for example
54
+ * '/PSRS/:RecordSet/List' with an EntityParameter of 'RecordSet')?
55
+ *
56
+ * @param {String} pRoute - a canonical route pattern
57
+ * @param {String} pEntityParameter - the parameter name that names an entity
58
+ * @return {Boolean} whether the route is entity-parameterized
59
+ */
60
+ export function routeIsEntityParameterized(pRoute: string, pEntityParameter: string): boolean;
61
+ /**
62
+ * Decide what the gate should do with a route the host is trying to register.
63
+ *
64
+ * Returns one of three modes:
65
+ * Allow — register it untouched.
66
+ * Guard — register it, but wrap the handler so disallowed entities bounce to the fallback.
67
+ * Block — do not register it at all.
68
+ *
69
+ * @param {Object} pManifest - a normalized manifest
70
+ * @param {String} pRoute - the route pattern the host passed to addRoute
71
+ * @return {{Mode: String, Route: String, Reason: String}} the decision
72
+ */
73
+ export function decideRoute(pManifest: any, pRoute: string): {
74
+ Mode: string;
75
+ Route: string;
76
+ Reason: string;
77
+ };
78
+ /**
79
+ * Is an entity name exposed by this micro app? An empty Entities list means every entity is
80
+ * exposed (the manifest author did not want to constrain the record-set surface).
81
+ *
82
+ * @param {Object} pManifest - a normalized manifest
83
+ * @param {String} pEntity - the entity name resolved from the route
84
+ * @return {Boolean} whether the entity is exposed
85
+ */
86
+ export function entityPermitted(pManifest: any, pEntity: string): boolean;
87
+ export { _DEFAULT_MANIFEST as default_manifest };
88
+ //# sourceMappingURL=Pict-MicroApp-Manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pict-MicroApp-Manifest.d.ts","sourceRoot":"","sources":["../source/Pict-MicroApp-Manifest.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAqGA;;;;;;GAMG;AACH,wDAiBC;AAlDD;;;;;;GAMG;AACH,uDAiBC;AA4BD;;;;;;;;GAQG;AACH,2EAWC;AAED;;;;;;;GAOG;AACH,8FAOC;AAED;;;;;;;;;;;GAWG;AACH,6DAFY;IAAC,IAAI,SAAS;IAAC,KAAK,SAAS;IAAC,MAAM,SAAQ;CAAC,CA2CxD;AAED;;;;;;;GAOG;AACH,0EAQC"}