@poveste/shared 0.6.0 → 0.7.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.
Files changed (49) hide show
  1. package/dist/codegen/const.d.ts +0 -1
  2. package/dist/codegen/index.d.ts +0 -1
  3. package/dist/codegen/serialize-js.d.ts +0 -1
  4. package/dist/codegen/util.d.ts +0 -1
  5. package/dist/index.d.ts +0 -1
  6. package/dist/setup.d.ts +0 -1
  7. package/dist/state.d.ts +0 -1
  8. package/dist/story.d.ts +0 -1
  9. package/dist/type-utils.d.ts +0 -1
  10. package/dist/types/command.d.ts +0 -1
  11. package/dist/types/config.d.ts +0 -1
  12. package/dist/types/index.d.ts +0 -1
  13. package/dist/types/plugin.d.ts +0 -1
  14. package/dist/types/prompt.d.ts +0 -1
  15. package/dist/types/story.d.ts +0 -1
  16. package/package.json +14 -4
  17. package/dist/codegen/const.d.ts.map +0 -1
  18. package/dist/codegen/index.d.ts.map +0 -1
  19. package/dist/codegen/serialize-js.d.ts.map +0 -1
  20. package/dist/codegen/util.d.ts.map +0 -1
  21. package/dist/index.d.ts.map +0 -1
  22. package/dist/setup.d.ts.map +0 -1
  23. package/dist/state.d.ts.map +0 -1
  24. package/dist/story.d.ts.map +0 -1
  25. package/dist/type-utils.d.ts.map +0 -1
  26. package/dist/types/command.d.ts.map +0 -1
  27. package/dist/types/config.d.ts.map +0 -1
  28. package/dist/types/index.d.ts.map +0 -1
  29. package/dist/types/plugin.d.ts.map +0 -1
  30. package/dist/types/prompt.d.ts.map +0 -1
  31. package/dist/types/story.d.ts.map +0 -1
  32. package/src/__tests__/setup.spec.ts +0 -60
  33. package/src/__tests__/state.spec.ts +0 -353
  34. package/src/codegen/const.ts +0 -17
  35. package/src/codegen/index.ts +0 -3
  36. package/src/codegen/serialize-js.ts +0 -143
  37. package/src/codegen/util.ts +0 -77
  38. package/src/index.ts +0 -6
  39. package/src/setup.ts +0 -29
  40. package/src/state.ts +0 -374
  41. package/src/story.ts +0 -10
  42. package/src/type-utils.ts +0 -1
  43. package/src/types/command.ts +0 -38
  44. package/src/types/config.ts +0 -288
  45. package/src/types/index.ts +0 -5
  46. package/src/types/plugin.ts +0 -135
  47. package/src/types/prompt.ts +0 -25
  48. package/src/types/story.ts +0 -221
  49. package/tsconfig.json +0 -51
@@ -1,3 +0,0 @@
1
- export * from './const.js'
2
- export * from './serialize-js.js'
3
- export * from './util.js'
@@ -1,143 +0,0 @@
1
- const KEY_ESCAPE_REG = /[\s\-.:|#@$£*%]/
2
- const MAX_SINGLE_LINE_ARRAY_LENGTH = 3
3
-
4
- interface Line {
5
- spaces: number
6
- line: string
7
- }
8
-
9
- export function serializeJs(value: any): string {
10
- const seen = new Set()
11
-
12
- if (value === undefined) {
13
- return 'undefined'
14
- }
15
- if (value === null) {
16
- return 'null'
17
- }
18
- if (typeof value === 'string') {
19
- return `'${value}'`
20
- }
21
- if (typeof value === 'boolean') {
22
- return value ? 'true' : 'false'
23
- }
24
- if (Array.isArray(value)) {
25
- return printLines(arrayToSourceLines(value, seen))
26
- }
27
- if (typeof value === 'object') {
28
- return printLines(objectToSourceLines(value, seen))
29
- }
30
- if (value?.__autoBuildingObject) {
31
- return value
32
- }
33
- if (typeof value === 'function' && value.name) {
34
- return value.name
35
- }
36
- return value.toString()
37
- }
38
-
39
- function printLines(lines: Line[]) {
40
- return lines.map(line => ' '.repeat(line.spaces) + line.line).join('\n')
41
- }
42
-
43
- function objectToSourceLines(object, seen: Set<unknown>, indentCount = 0) {
44
- if (seen.has(object)) {
45
- object = {}
46
- }
47
- else {
48
- seen.add(object)
49
- }
50
-
51
- return createLines(indentCount, (lines) => {
52
- lines.push('{')
53
- lines.push(...createLines(1, (lines) => {
54
- for (const key in object) {
55
- const value = object[key]
56
-
57
- let printedKey = key
58
- if (KEY_ESCAPE_REG.test(key)) {
59
- printedKey = `'${printedKey}'`
60
- }
61
-
62
- addLinesFromValue(lines, value, `${printedKey}: `, ',', seen)
63
- }
64
- }))
65
- lines.push('}')
66
- })
67
- }
68
-
69
- function arrayToSourceLines(array: any[], seen: Set<unknown>, indentCount = 0): Array<Line> {
70
- if (seen.has(array)) {
71
- array = []
72
- }
73
- else {
74
- seen.add(array)
75
- }
76
-
77
- return createLines(indentCount, (lines) => {
78
- const contentLines = createLines(1, (lines) => {
79
- for (const value of array) {
80
- addLinesFromValue(lines, value, '', ',', seen)
81
- }
82
- })
83
- if (contentLines.length === 0) {
84
- lines.push('[]')
85
- }
86
- else if (contentLines.length <= MAX_SINGLE_LINE_ARRAY_LENGTH && !contentLines.some(line => line.spaces > 1)) {
87
- const [first] = contentLines
88
- first.line = contentLines.map(({ line }) => line.substring(0, line.length - 1)).join(', ')
89
- first.line = `[${first.line}]`
90
- first.spaces--
91
- lines.push(first)
92
- }
93
- else {
94
- lines.push('[', ...contentLines, ']')
95
- }
96
- })
97
- }
98
-
99
- function createLines(indentCount: number, handler: (lines: any[]) => unknown): Array<Line> {
100
- const lines: any[] = []
101
- handler(lines)
102
- return lines.map((line) => {
103
- if (line.spaces != null) {
104
- line.spaces += indentCount
105
- return line
106
- }
107
- return { spaces: indentCount, line }
108
- })
109
- }
110
-
111
- function addLinesFromValue(lines: Line[], value, before, after, seen) {
112
- let result
113
- if (Array.isArray(value)) {
114
- lines.push(...wrap(arrayToSourceLines(value, seen), before, after))
115
- return
116
- }
117
- else if (value && typeof value === 'object') {
118
- lines.push(...wrap(objectToSourceLines(value, seen), before, after))
119
- return
120
- }
121
- else if (typeof value === 'string') {
122
- result = value.includes('\'') ? `\`${value}\`` : `'${value}'`
123
- }
124
- else if (typeof value === 'undefined') {
125
- result = 'undefined'
126
- }
127
- else if (value === null) {
128
- result = 'null'
129
- }
130
- else if (typeof value === 'boolean') {
131
- result = value ? 'true' : 'false'
132
- }
133
- else {
134
- result = value
135
- }
136
- lines.push(before + result + after)
137
- }
138
-
139
- function wrap(lines: Line[], before: string, after: string) {
140
- lines[0].line = before + lines[0].line
141
- lines[lines.length - 1].line += after
142
- return lines
143
- }
@@ -1,77 +0,0 @@
1
- export function indent(lines: string[], count = 1) {
2
- return lines.map(line => `${' '.repeat(count)}${line}`)
3
- }
4
-
5
- export function unindent(code: string) {
6
- const lines = code.split('\n')
7
- let indentLevel = -1
8
- let indentText: string
9
- const linesToAnalyze = lines.filter(line => line.trim().length > 0)
10
- for (const line of linesToAnalyze) {
11
- const match = /^\s*/.exec(line)
12
- if (match && (indentLevel === -1 || indentLevel > match[0].length)) {
13
- indentLevel = match[0].length
14
- indentText = match[0]
15
- }
16
- }
17
- const result: string[] = []
18
- for (const line of lines) {
19
- result.push(line.replace(indentText, ''))
20
- }
21
- return result.join('\n').trim()
22
- }
23
-
24
- interface AutoBuildingOject {
25
- key: string
26
- cache: Record<string | symbol, AutoBuildingOject>
27
- target: any
28
- proxy: any
29
- }
30
-
31
- export function createAutoBuildingObject(format?: (key: string) => string, specialKeysHandler?: (target: any, p: string | symbol) => (() => unknown) | null, key = '', depth = 0): AutoBuildingOject {
32
- const cache: Record<string | symbol, AutoBuildingOject> = {}
33
- if (depth > 32) return { key, cache, target: {}, proxy: () => key }
34
- const target: any = () => {
35
- const k = `${key}()`
36
- return format ? format(k) : k
37
- }
38
- const proxy = new Proxy(target, {
39
- get(_, p) {
40
- if (p === '__autoBuildingObject') {
41
- return true
42
- }
43
- if (p === '__autoBuildingObjectGetKey') {
44
- return key
45
- }
46
- if (specialKeysHandler) {
47
- const fn = specialKeysHandler(target, p)
48
- if (fn) {
49
- return fn()
50
- }
51
- }
52
- if (p === 'toString') {
53
- const k = `${key}.toString()`
54
- return () => format ? format(k) : k
55
- }
56
- if (p === Symbol.toPrimitive) {
57
- return () => format ? format(key) : key
58
- }
59
- if (!cache[p]) {
60
- const childKey = key ? `${key}.${p.toString()}` : p.toString()
61
- const child = createAutoBuildingObject(format, specialKeysHandler, childKey, depth + 1)
62
- cache[p] = { key: childKey, ...child }
63
- }
64
- return cache[p].proxy
65
- },
66
- apply(_, thisArg, args) {
67
- const k = `${key}(${args.join(', ')})`
68
- return format ? format(k) : k
69
- },
70
- })
71
- return {
72
- key,
73
- cache,
74
- target,
75
- proxy,
76
- }
77
- }
package/src/index.ts DELETED
@@ -1,6 +0,0 @@
1
- export * from './codegen/index.js'
2
- export * from './setup.js'
3
- export * from './state.js'
4
- export * from './story.js'
5
- export * from './type-utils.js'
6
- export * from './types/index.js'
package/src/setup.ts DELETED
@@ -1,29 +0,0 @@
1
- export type SetupModule = Record<string, unknown> | undefined
2
-
3
- /**
4
- * Reads a setup hook (`setupVanilla`, `setupVue3`, ...) out of a setup module.
5
- *
6
- * Takes the module as an argument instead of letting callers access it inline:
7
- * the setup modules are namespace imports of virtual or user-provided files that
8
- * aren't guaranteed to declare every hook, and a static `namespace.setupVue3`
9
- * access makes Rollup warn `"setupVue3" is not exported by ...` in every
10
- * consumer build. Passing the namespace through a call forces it to be
11
- * materialized, so the lookup happens at runtime where it belongs.
12
- */
13
- export function getSetupHook<T>(mod: SetupModule, name: string | string[]): T | undefined {
14
- const names = typeof name === 'string' ? [name] : name
15
- const present = names.filter(candidate => typeof mod?.[candidate] === 'function')
16
-
17
- // Earlier names win, so a plugin lists its established hook first and a newer
18
- // alias after it: an existing setup file keeps the exact behaviour it had.
19
- // Running both instead would apply the same setup twice, which for Vue means
20
- // a second `app.use()` for every plugin the user registers.
21
- if (present.length > 1) {
22
- console.warn(
23
- `[poveste] Setup file exports ${present.length} interchangeable setup hooks (${present.join(', ')}). `
24
- + `Only ${present[0]} runs. Keep one — they are aliases, not separate hooks.`,
25
- )
26
- }
27
-
28
- return present.length > 0 ? mod![present[0]] as T : undefined
29
- }
package/src/state.ts DELETED
@@ -1,374 +0,0 @@
1
- export function clone(data) {
2
- try {
3
- return structuredClone(data)
4
- }
5
- catch (e) {
6
- console.warn(e, `Fallback to JSON cloning`)
7
- try {
8
- return JSON.parse(JSON.stringify(data))
9
- }
10
- catch (e) {
11
- console.error(e)
12
- }
13
- return data
14
- }
15
- }
16
-
17
- export function omit(data, keys: string[]) {
18
- const copy = {}
19
- for (const key in data) {
20
- if (!keys.includes(key)) {
21
- copy[key] = data[key]
22
- }
23
- }
24
- return copy
25
- }
26
-
27
- function isPlainObject(value: any) {
28
- if (value === null || typeof value !== 'object') {
29
- return false
30
- }
31
-
32
- const proto = Object.getPrototypeOf(value)
33
- return proto === Object.prototype || proto === null
34
- }
35
-
36
- /**
37
- * Structural comparison, deliberately narrow: it recurses into plain objects and
38
- * arrays and compares everything else by `Object.is`.
39
- *
40
- * That narrowness is the point. Anything with a prototype of its own — a `Date`,
41
- * a `Map`, a class instance, a DOM node — carries state that own enumerable keys
42
- * do not describe, and two distinct `Date`s would otherwise compare equal on an
43
- * empty key list. Reporting "not equivalent" for those is the safe answer: the
44
- * caller writes, which is what it did before this existed.
45
- *
46
- * `Object.is` is not an arbitrary choice either — it is exactly the predicate
47
- * Vue's `hasChanged` uses, so a value this reports as equivalent is a value Vue
48
- * would have refused to trigger on anyway.
49
- */
50
- export function isEquivalent(a: any, b: any, seen?: WeakMap<object, WeakSet<object>>): boolean {
51
- if (Object.is(a, b)) {
52
- return true
53
- }
54
-
55
- const bothArrays = Array.isArray(a) && Array.isArray(b)
56
-
57
- if (!bothArrays && !(isPlainObject(a) && isPlainObject(b))) {
58
- return false
59
- }
60
-
61
- if (bothArrays && a.length !== b.length) {
62
- return false
63
- }
64
-
65
- // State is user data and can be cyclic. A pair already on the stack is
66
- // assumed equivalent — the usual co-inductive treatment, and it terminates.
67
- const visited = seen ?? new WeakMap<object, WeakSet<object>>()
68
- let peers = visited.get(a)
69
-
70
- if (peers?.has(b)) {
71
- return true
72
- }
73
-
74
- if (!peers) {
75
- peers = new WeakSet<object>()
76
- visited.set(a, peers)
77
- }
78
-
79
- peers.add(b)
80
-
81
- const keys = Object.keys(a)
82
-
83
- if (keys.length !== Object.keys(b).length) {
84
- return false
85
- }
86
-
87
- return keys.every(key => Object.hasOwn(b, key) && isEquivalent(a[key], b[key], visited))
88
- }
89
-
90
- /**
91
- * Whether a key's value is merged one level rather than replaced whole.
92
- *
93
- * One rule, stated once, because it has to hold in three places at once:
94
- * `applyState` writes by it, `diffState` narrows by it — sending less than the
95
- * whole object is only safe as far as the write will merge — and the baseline in
96
- * `createStateBaseline` records by it. They drifted apart when it was three
97
- * copies, and the `_h` clause was the one that went missing.
98
- *
99
- * `_h`-prefixed keys are never merged: the sandbox needs those replaced outright
100
- * so a nested key the story dropped actually disappears.
101
- *
102
- * Both sides have to be objects worth merging. `existing` is loose about how it
103
- * got its prototype, because a target may hold anything a story put there; the
104
- * incoming value must be a plain object, because merging a primitive or an array
105
- * into an object writes nothing useful — `for (const nested in 5)` iterates
106
- * nothing at all, and the assignment is then skipped entirely.
107
- */
108
- function mergesNested(key: string, existing: any, incoming: any) {
109
- return !key.startsWith('_h')
110
- && isPlainObject(incoming)
111
- && existing != null
112
- && typeof existing === 'object'
113
- && !Array.isArray(existing)
114
- }
115
-
116
- /**
117
- * Copies `state` onto `target`, and reports whether it wrote anything.
118
- *
119
- * The return value is what the syncs in `plugin-svelte` and the sandbox bridge
120
- * use to decide whether to expect an echo. Each holds a flag meaning "the next
121
- * firing is mine, ignore it", and that flag is only safe to set when a firing is
122
- * actually coming. See #95.
123
- *
124
- * `plugin-vue` no longer needs it: `createStateBaseline` recognises an echo by
125
- * it not being a change, so there is no flag left to keep honest. The two are
126
- * the same idea at different strengths, and the others can move across (#96).
127
- */
128
- export function applyState(target: any, state: any, override = false) {
129
- let wrote = false
130
-
131
- for (const key in state) {
132
- const current = target[key]
133
-
134
- // Skip writes that cannot change anything. Vue drops a re-assigned primitive
135
- // on its own, but never an object: `state` here has always been rebuilt by a
136
- // `toRawDeep`/`clone` on the way in, so assigning one lands a fresh identity
137
- // over an equal-but-distinct old one, and triggers every watcher on it.
138
- //
139
- // Those spurious triggers were load-bearing, which is the whole of #95 — the
140
- // syncs counted on them to keep their flags alternating. Skipping them is
141
- // both the efficiency win and the thing that makes `wrote` mean something.
142
- //
143
- // The key has to exist first. `undefined` is equivalent to `undefined`, so a
144
- // key the target does not have yet and whose incoming value is `undefined`
145
- // would otherwise never be created — and a story that declares its shape
146
- // upfront (`initState: () => ({ pending: undefined })`) would get no control
147
- // for it, because the panel lists the keys the state actually has.
148
- if (Object.hasOwn(target, key) && isEquivalent(current, state[key])) {
149
- continue
150
- }
151
-
152
- // iframe sync needs to update properties without overriding them
153
- if (!override && mergesNested(key, current, state[key])) {
154
- // Not `Object.assign`, because the reason the two are not equivalent may
155
- // be a key that `current` has and `state[key]` does not — a removal, which
156
- // this merge cannot express. Assigning the rest would then change nothing
157
- // while still looking like a write, and a caller that took that for a
158
- // write would wait for an echo that never comes. Compare per key and
159
- // report only what actually moved.
160
- let merged = false
161
-
162
- for (const nested in state[key]) {
163
- if (isEquivalent(current[nested], state[key][nested])) {
164
- continue
165
- }
166
-
167
- try {
168
- current[nested] = state[key][nested]
169
- merged = true
170
- }
171
- catch {
172
- // noop
173
- }
174
- }
175
-
176
- if (!merged) {
177
- continue
178
- }
179
- }
180
- else {
181
- try {
182
- target[key] = state[key]
183
- }
184
- catch {
185
- // noop
186
- }
187
- }
188
-
189
- wrote = true
190
- }
191
-
192
- return wrote
193
- }
194
-
195
- /**
196
- * The nested keys of `after` that differ from `before`, or `null` for none.
197
- *
198
- * One level, and no deeper, because that is exactly how far `applyState` merges:
199
- * it walks the keys of a nested object and assigns each, so a value handed to it
200
- * at depth two is written whole. Narrow past that and the write lands the narrow
201
- * subset *as* the object and takes its siblings with it.
202
- *
203
- * Whether a key gets here at all is `mergesNested`'s call, not this function's.
204
- */
205
- function narrowState(before: any, after: any): Record<string, any> | null {
206
- let changes: Record<string, any> | null = null
207
-
208
- for (const key in after) {
209
- if (Object.hasOwn(before, key) && isEquivalent(before[key], after[key])) {
210
- continue
211
- }
212
-
213
- changes ??= {}
214
- changes[key] = after[key]
215
- }
216
-
217
- return changes
218
- }
219
-
220
- /**
221
- * The subset of `next` that differs from `baseline`, shaped so `applyState` can
222
- * copy it faithfully: a key it will merge is narrowed to the nested keys that
223
- * moved, and everything else is carried whole. `null` when nothing changed.
224
- *
225
- * The narrowing is what lets two sides edit one object at once without either
226
- * clobbering the other — whatever is not sent cannot be overwritten — so it has
227
- * to line up with how `applyState` writes, exactly. Both ask `mergesNested`.
228
- * A key it refuses, `_h`-prefixed ones included, crosses whole, so concurrent
229
- * edits *inside* one of those still race; ordinary story state does not live
230
- * there.
231
- *
232
- * Only keys `next` has are considered. A key `baseline` has and `next` does not
233
- * is a removal, which `applyState` cannot express, so reporting it would produce
234
- * a write that changes nothing — and, worse, one the baseline would go on
235
- * reporting forever. Removals stay unmirrored, exactly as they were.
236
- */
237
- export function diffState(baseline: any, next: any): Record<string, any> | null {
238
- let changes: Record<string, any> | null = null
239
-
240
- for (const key in next) {
241
- const before = baseline[key]
242
- const after = next[key]
243
- const known = Object.hasOwn(baseline, key)
244
-
245
- if (known && isEquivalent(before, after)) {
246
- continue
247
- }
248
-
249
- let value = after
250
-
251
- if (known && mergesNested(key, before, after)) {
252
- value = narrowState(before, after)
253
-
254
- // Only a removal, then. Nothing to send.
255
- if (value === null) {
256
- continue
257
- }
258
- }
259
-
260
- changes ??= {}
261
- changes[key] = value
262
- }
263
-
264
- return changes
265
- }
266
-
267
- /**
268
- * A structural copy, narrow in exactly the way `isEquivalent` is: plain objects
269
- * and arrays get fresh containers, everything else is carried by reference —
270
- * which is right, because those are the values `isEquivalent` compares by
271
- * `Object.is`, so a reference is the identity the comparison is about.
272
- */
273
- function copyState(value: any, seen = new WeakMap<object, any>()) {
274
- if (!Array.isArray(value) && !isPlainObject(value)) {
275
- return value
276
- }
277
-
278
- if (seen.has(value)) {
279
- return seen.get(value)
280
- }
281
-
282
- const copy: any = Array.isArray(value) ? [] : {}
283
- seen.set(value, copy)
284
-
285
- for (const key in value) {
286
- copy[key] = copyState(value[key], seen)
287
- }
288
-
289
- return copy
290
- }
291
-
292
- /**
293
- * Records `changes` — the shape `diffState` returns — into `baseline`, on the
294
- * same terms `applyState` writes it: `mergesNested` decides, the one narrowed
295
- * level is merged, everything under it taken whole. Keys the diff did not
296
- * mention survive, which is what keeps a removal the far side could not mirror
297
- * from being replayed.
298
- *
299
- * Getting that predicate wrong here is quiet and permanent. Merge an `_h` key
300
- * that the write replaced and the baseline keeps a nested key the real state has
301
- * dropped — it can never match again, so every later pass reports the same
302
- * phantom change, forever.
303
- *
304
- * Copies on the way in. The same `changes` object goes to `applyState`, which
305
- * assigns its values straight into a reactive state; sharing them would let a
306
- * later write through that state's proxy mutate the baseline as well, and a
307
- * baseline that tracks a live side reports every one of that side's edits as
308
- * already agreed — which is to say, drops them.
309
- */
310
- function recordState(baseline: any, changes: any) {
311
- for (const key in changes) {
312
- const value = changes[key]
313
-
314
- if (mergesNested(key, baseline[key], value)) {
315
- for (const nested in value) {
316
- baseline[key][nested] = copyState(value[nested])
317
- }
318
- }
319
- else {
320
- baseline[key] = copyState(value)
321
- }
322
- }
323
- }
324
-
325
- /**
326
- * Tracks the last state both sides of a sync agreed on.
327
- *
328
- * The syncs used to mirror whole state objects and coordinate with a boolean
329
- * meaning "the next firing is my own echo, ignore it". That has two costs. An
330
- * echo is only distinguishable from a genuine edit by counting firings, which
331
- * is what made the flag load-bearing and fragile (#95). And a side that mirrors
332
- * everything it holds also mirrors the keys it did *not* change, stale by one
333
- * edit if the far side changed them in the same tick — so the second firing
334
- * reverted the first side's edit and it was lost from both (#96).
335
- *
336
- * A baseline answers both. Ask it for what a side changed and it reports that
337
- * side's own edits, never the far side's; an echo diffs to nothing and needs no
338
- * flag to recognise, because it is not a change.
339
- */
340
- export function createStateBaseline() {
341
- const baseline: Record<string, any> = {}
342
-
343
- return {
344
- /**
345
- * What `next` changed since both sides last agreed, or `null` for nothing.
346
- * The changes count as agreed from here, so ask once per firing and mirror
347
- * what you get.
348
- */
349
- take(next: any): Record<string, any> | null {
350
- const changes = diffState(baseline, next)
351
-
352
- if (changes) {
353
- recordState(baseline, changes)
354
- }
355
-
356
- return changes
357
- },
358
-
359
- /**
360
- * Take `changes` as agreed without reporting them.
361
- *
362
- * What a peer just sent is by definition something both sides now hold, and
363
- * it must not come back the other way. Two sides sharing one baseline —
364
- * `plugin-vue`, where both watchers run in one context — never need this,
365
- * because `take` on either side records for both. Two sides holding a
366
- * baseline each — the sandbox bridge, split across a `postMessage` — do:
367
- * the receiver has to record what arrived, or its own watcher will read the
368
- * applied write as a local edit and echo it straight back.
369
- */
370
- record(changes: any) {
371
- recordState(baseline, changes)
372
- },
373
- }
374
- }
package/src/story.ts DELETED
@@ -1,10 +0,0 @@
1
- export const omitInheritStoryProps = [
2
- 'id',
3
- 'title',
4
- 'group',
5
- 'layout',
6
- 'variants',
7
- 'file',
8
- 'slots',
9
- 'lastSelectedVariant',
10
- ]
package/src/type-utils.ts DELETED
@@ -1 +0,0 @@
1
- export type Awaitable<T> = Promise<T> | T
@@ -1,38 +0,0 @@
1
- import type { RouteLocationNormalizedLoaded } from 'vue-router'
2
- import type { Prompt } from './prompt.js'
3
- import type { Story, Variant } from './story.js'
4
-
5
- export interface CommonCommandOptions {
6
- icon?: string
7
- searchText?: string
8
- prompts?: Prompt[]
9
- }
10
-
11
- export interface Command extends CommonCommandOptions {
12
- id: string
13
- label: string
14
- }
15
-
16
- export interface ClientCommandOptions extends CommonCommandOptions {
17
- showIf?: (ctx: ClientCommandContext) => boolean
18
- getParams?: (ctx: ClientCommandContext & { answers?: Record<string, any> }) => Record<string, any>
19
- clientAction?: (params: Record<string, any>, ctx: ClientCommandContext) => unknown
20
- }
21
-
22
- /**
23
- * A command that can be executed from the search bar.
24
- */
25
- export type ClientCommand = Command & ClientCommandOptions
26
-
27
- export interface ClientCommandContext {
28
- route: RouteLocationNormalizedLoaded
29
- currentStory: Story
30
- currentVariant: Variant
31
- }
32
-
33
- export interface PluginCommand<
34
- TParams = Record<string, any>,
35
- > extends Command {
36
- serverAction?: (params: TParams) => unknown // @TODO ctx
37
- clientSetupFile?: string | { file: string, importName: string }
38
- }