tutuca 0.9.89 → 0.9.91

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.
@@ -220,16 +220,32 @@ var Section = component({
220
220
  });
221
221
  var Example = component({
222
222
  name: "Example",
223
- fields: { id: "?", title: "?", description: "", value: null, view: "main" },
223
+ fields: {
224
+ id: "?",
225
+ title: "?",
226
+ description: "",
227
+ value: null,
228
+ view: "main",
229
+ requestHandlers: null
230
+ },
231
+ requestOverridesField: "requestHandlers",
224
232
  statics: {
225
- fromData({ id, title = "No Title Example", description = "", value = null, view = "main" }) {
233
+ fromData({
234
+ id,
235
+ title = "No Title Example",
236
+ description = "",
237
+ value = null,
238
+ view = "main",
239
+ requestHandlers = null
240
+ }) {
226
241
  id ??= slugify(title);
227
242
  return this.make({
228
243
  id,
229
244
  title,
230
245
  description,
231
246
  value,
232
- view
247
+ view,
248
+ requestHandlers
233
249
  });
234
250
  }
235
251
  },
@@ -276,15 +292,23 @@ function slugify(str) {
276
292
  return String(str).normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
277
293
  }
278
294
  function buildStorybook(modules) {
279
- const sections = modules.flatMap((m) => {
295
+ const rawSections = modules.flatMap((m) => {
280
296
  const raw = m.getExamples?.();
281
297
  if (raw == null)
282
298
  return [];
283
299
  return Array.isArray(raw) ? raw : [raw];
284
- }).map((s) => Section.Class.fromData(s)).sort((a, b) => a.title.localeCompare(b.title));
300
+ });
301
+ const sections = rawSections.map((s) => Section.Class.fromData(s)).sort((a, b) => a.title.localeCompare(b.title));
285
302
  const components = new Set([Storybook, Section, Example]);
286
303
  const macros = {};
287
304
  const requestHandlers = {};
305
+ const overrideNames = new Set;
306
+ for (const s of rawSections) {
307
+ for (const it of s?.items ?? []) {
308
+ for (const name in it?.requestHandlers ?? {})
309
+ overrideNames.add(name);
310
+ }
311
+ }
288
312
  for (const m of modules) {
289
313
  for (const c of m.getComponents?.() ?? []) {
290
314
  components.add(c);
@@ -298,8 +322,35 @@ function buildStorybook(modules) {
298
322
  root: Storybook.make({ sections }),
299
323
  components: [...components],
300
324
  macros,
301
- requestHandlers
325
+ requestHandlers,
326
+ overrideNames
327
+ };
328
+ }
329
+ function buildExampleRequestHandlers({ requestHandlers: reals, overrideNames }) {
330
+ const names = new Set([...Object.keys(reals), ...overrideNames]);
331
+ const makeMeta = (name) => async (...rest) => {
332
+ const ctx = rest.at(-1);
333
+ const args = rest.slice(0, -1);
334
+ let override = null;
335
+ ctx.walkPath((Comp, inst) => {
336
+ const field = Comp.extra?.requestOverridesField;
337
+ if (!field)
338
+ return;
339
+ const map = inst.get(field, null);
340
+ if (map && name in map) {
341
+ override = map[name];
342
+ return false;
343
+ }
344
+ });
345
+ const fn = override ?? reals[name];
346
+ if (!fn)
347
+ throw new Error(`Request not found: ${name}`);
348
+ return await fn(...args, ctx);
302
349
  };
350
+ const handlers = {};
351
+ for (const name of names)
352
+ handlers[name] = makeMeta(name);
353
+ return handlers;
303
354
  }
304
355
  async function mountStorybook(selector, modules, { compileCss, root, persistUrl = true } = {}) {
305
356
  const app = tutuca(selector);
@@ -307,7 +358,7 @@ async function mountStorybook(selector, modules, { compileCss, root, persistUrl
307
358
  app.state.set(root ?? built.root);
308
359
  const scope = app.registerComponents(built.components);
309
360
  scope.registerMacros(built.macros);
310
- scope.registerRequestHandlers(built.requestHandlers);
361
+ scope.registerRequestHandlers(buildExampleRequestHandlers(built));
311
362
  if (persistUrl) {
312
363
  scope.registerRequestHandlers({ persistState, loadState });
313
364
  }
@@ -351,6 +402,7 @@ export {
351
402
  getComponents,
352
403
  fuzzyMatch,
353
404
  buildStorybook,
405
+ buildExampleRequestHandlers,
354
406
  Storybook,
355
407
  Section,
356
408
  Example
@@ -250,6 +250,17 @@ class Path {
250
250
  }
251
251
  return curVal;
252
252
  }
253
+ resolveChain(root) {
254
+ const out = [root];
255
+ let curVal = root;
256
+ for (const step of this.steps) {
257
+ curVal = step.lookup(curVal, NONE);
258
+ if (curVal === NONE)
259
+ break;
260
+ out.push(curVal);
261
+ }
262
+ return out;
263
+ }
253
264
  setValue(root, v) {
254
265
  const intermediates = new Array(this.steps.length);
255
266
  let curVal = root;
@@ -2926,6 +2937,7 @@ class Transactor {
2926
2937
  const txnPath = path.toTransactionPath();
2927
2938
  const curLeaf = txnPath.lookup(curRoot);
2928
2939
  const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
2940
+ const reqCtx = new RequestContext(path, this, parent, curRoot);
2929
2941
  const resHandlerName = opts?.onResName ?? name;
2930
2942
  const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
2931
2943
  const push = (specificName, baseName, singleArg, result, error) => {
@@ -2934,7 +2946,7 @@ class Transactor {
2934
2946
  this.pushTransaction(t);
2935
2947
  };
2936
2948
  try {
2937
- const result = await handler.fn.apply(null, args);
2949
+ const result = await handler.fn.apply(null, [...args, reqCtx]);
2938
2950
  push(opts?.onOkName, resHandlerName, result, result, null);
2939
2951
  } catch (error) {
2940
2952
  push(opts?.onErrorName, resHandlerName, error, null, error);
@@ -3177,10 +3189,20 @@ class Task {
3177
3189
  }
3178
3190
 
3179
3191
  class Dispatcher {
3180
- constructor(path, transactor, parentTransaction) {
3192
+ constructor(path, transactor, parentTransaction, root = transactor.state.val) {
3181
3193
  this.path = path;
3182
3194
  this.transactor = transactor;
3183
3195
  this.parent = parentTransaction;
3196
+ this.root = root;
3197
+ }
3198
+ walkPath(callback) {
3199
+ const comps = this.transactor.comps;
3200
+ const chain = this.path.toTransactionPath().resolveChain(this.root);
3201
+ for (let i = chain.length - 1;i >= 0; i--) {
3202
+ const comp = comps.getCompFor(chain[i]);
3203
+ if (comp && callback(comp, chain[i]) === false)
3204
+ return;
3205
+ }
3184
3206
  }
3185
3207
  get at() {
3186
3208
  return new PathChanges(this);
@@ -3217,6 +3239,9 @@ class EventContext extends Dispatcher {
3217
3239
  }
3218
3240
  }
3219
3241
 
3242
+ class RequestContext extends Dispatcher {
3243
+ }
3244
+
3220
3245
  class PathChanges extends PathBuilder {
3221
3246
  constructor(dispatcher) {
3222
3247
  super();
package/dist/tutuca.js CHANGED
@@ -4623,6 +4623,17 @@ class Path {
4623
4623
  }
4624
4624
  return curVal;
4625
4625
  }
4626
+ resolveChain(root) {
4627
+ const out = [root];
4628
+ let curVal = root;
4629
+ for (const step of this.steps) {
4630
+ curVal = step.lookup(curVal, NONE);
4631
+ if (curVal === NONE)
4632
+ break;
4633
+ out.push(curVal);
4634
+ }
4635
+ return out;
4636
+ }
4626
4637
  setValue(root, v) {
4627
4638
  const intermediates = new Array(this.steps.length);
4628
4639
  let curVal = root;
@@ -7296,6 +7307,7 @@ class Transactor {
7296
7307
  const txnPath = path.toTransactionPath();
7297
7308
  const curLeaf = txnPath.lookup(curRoot);
7298
7309
  const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
7310
+ const reqCtx = new RequestContext(path, this, parent, curRoot);
7299
7311
  const resHandlerName = opts?.onResName ?? name;
7300
7312
  const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
7301
7313
  const push = (specificName, baseName, singleArg, result, error) => {
@@ -7304,7 +7316,7 @@ class Transactor {
7304
7316
  this.pushTransaction(t);
7305
7317
  };
7306
7318
  try {
7307
- const result = await handler.fn.apply(null, args);
7319
+ const result = await handler.fn.apply(null, [...args, reqCtx]);
7308
7320
  push(opts?.onOkName, resHandlerName, result, result, null);
7309
7321
  } catch (error) {
7310
7322
  push(opts?.onErrorName, resHandlerName, error, null, error);
@@ -7547,10 +7559,20 @@ class Task {
7547
7559
  }
7548
7560
 
7549
7561
  class Dispatcher {
7550
- constructor(path, transactor, parentTransaction) {
7562
+ constructor(path, transactor, parentTransaction, root = transactor.state.val) {
7551
7563
  this.path = path;
7552
7564
  this.transactor = transactor;
7553
7565
  this.parent = parentTransaction;
7566
+ this.root = root;
7567
+ }
7568
+ walkPath(callback) {
7569
+ const comps = this.transactor.comps;
7570
+ const chain = this.path.toTransactionPath().resolveChain(this.root);
7571
+ for (let i = chain.length - 1;i >= 0; i--) {
7572
+ const comp = comps.getCompFor(chain[i]);
7573
+ if (comp && callback(comp, chain[i]) === false)
7574
+ return;
7575
+ }
7554
7576
  }
7555
7577
  get at() {
7556
7578
  return new PathChanges(this);
@@ -7587,6 +7609,9 @@ class EventContext extends Dispatcher {
7587
7609
  }
7588
7610
  }
7589
7611
 
7612
+ class RequestContext extends Dispatcher {
7613
+ }
7614
+
7590
7615
  class PathChanges extends PathBuilder {
7591
7616
  constructor(dispatcher) {
7592
7617
  super();