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.
- package/dist/tutuca-cli.js +52 -9
- package/dist/tutuca-dev.ext.js +34 -4
- package/dist/tutuca-dev.js +34 -4
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +27 -2
- package/dist/tutuca-extra.js +27 -2
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca-storybook.js +59 -7
- package/dist/tutuca.ext.js +27 -2
- package/dist/tutuca.js +27 -2
- package/dist/tutuca.min.js +2 -2
- package/package.json +1 -1
- package/skill/tutuca/SKILL.md +1 -0
- package/skill/tutuca/cli.md +4 -26
- package/skill/tutuca/core.md +20 -1
- package/skill/tutuca/patterns/README.md +4 -0
- package/skill/tutuca/patterns/add-a-story.md +26 -0
- package/skill/tutuca/request-response.md +10 -1
- package/skill/tutuca/storybook.md +151 -0
- package/skill/tutuca-source/tutuca.ext.js +27 -2
package/dist/tutuca-storybook.js
CHANGED
|
@@ -220,16 +220,32 @@ var Section = component({
|
|
|
220
220
|
});
|
|
221
221
|
var Example = component({
|
|
222
222
|
name: "Example",
|
|
223
|
-
fields: {
|
|
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({
|
|
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
|
|
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
|
-
})
|
|
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
|
|
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
|
package/dist/tutuca.ext.js
CHANGED
|
@@ -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();
|