ivue 2.3.0 → 2.5.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.
package/bin/ivue.mjs CHANGED
@@ -10,6 +10,7 @@
10
10
  * the installed package, so the manual always matches the engine version
11
11
  * the project actually runs.
12
12
  */
13
+ import { createHash } from 'node:crypto';
13
14
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
15
  import { dirname, join, resolve } from 'node:path';
15
16
  import { fileURLToPath } from 'node:url';
@@ -27,7 +28,11 @@ if (command !== 'skill') {
27
28
 
28
29
  npx ivue skill [targets] [--force]
29
30
 
30
- Installs the ivue operating manual for coding agents. Targets:
31
+ Installs the ivue operating manual for coding agents, and (for the
32
+ Claude target) the house gate seed — your own extendable Standard
33
+ gate at .claude/skills/ivue/ivue-house-gate.ts. A house gate you have
34
+ customized is never overwritten; upgrade it with your AI agent using
35
+ the ivue skill, or --force. Targets:
31
36
  (none) / --claude .claude/skills/ivue/SKILL.md
32
37
  --cursor .cursor/rules/ivue.mdc
33
38
  --copilot .github/instructions/ivue.instructions.md
@@ -58,6 +63,50 @@ const skillDescription =
58
63
  /description:\s*([^\n]+)/.exec(skillText)?.[1] ??
59
64
  'The ivue operating manual.';
60
65
 
66
+ /**
67
+ * A SEED is a file the user is meant to edit (the house gate). The install
68
+ * stamps it with a hash of its own content; on upgrade, a matching stamp
69
+ * means "untouched since install" (safe to replace), anything else means
70
+ * the user customized it — leave it alone and point at AI reconciliation.
71
+ */
72
+ const SEED_STAMP = /^\/\/ ivue-seed: ([0-9a-f]{64})\n/;
73
+
74
+ function stampSeed(content) {
75
+ const hash = createHash('sha256').update(content).digest('hex');
76
+ return `// ivue-seed: ${hash}\n${content}`;
77
+ }
78
+
79
+ function seedUntouched(existing) {
80
+ const stamp = SEED_STAMP.exec(existing);
81
+ if (!stamp) return false;
82
+ const body = existing.slice(stamp[0].length);
83
+ return createHash('sha256').update(body).digest('hex') === stamp[1];
84
+ }
85
+
86
+ function installSeed(relativePath, content, label) {
87
+ const targetPath = join(process.cwd(), relativePath);
88
+ const stamped = stampSeed(content);
89
+ if (existsSync(targetPath)) {
90
+ const existing = readFileSync(targetPath, 'utf8');
91
+ if (existing === stamped) {
92
+ console.log(`ivue: ${label} already up to date (ivue v${version}).`);
93
+ return;
94
+ }
95
+ if (!seedUntouched(existing) && !force) {
96
+ console.log(
97
+ `ivue: ${label} at ${relativePath} was customized — keeping yours.\n` +
98
+ ' To upgrade it, ask your AI agent (with the ivue skill installed) to\n' +
99
+ " reconcile your gate with the new Standard's — it knows both sides.\n" +
100
+ ' Or re-run with --force to overwrite your customizations.',
101
+ );
102
+ return;
103
+ }
104
+ }
105
+ mkdirSync(dirname(targetPath), { recursive: true });
106
+ writeFileSync(targetPath, stamped);
107
+ console.log(`ivue: ${label} installed at ${relativePath} (ivue v${version}).`);
108
+ }
109
+
61
110
  /** Write one target idempotently; refuse to clobber local edits sans --force. */
62
111
  function install(relativePath, content, label) {
63
112
  const targetPath = join(process.cwd(), relativePath);
@@ -104,6 +153,18 @@ const wantClaude =
104
153
 
105
154
  if (wantClaude) {
106
155
  install('.claude/skills/ivue/SKILL.md', skillText, 'Claude skill');
156
+ // the house gate seed — the user's own gate, never clobbered once edited
157
+ const housePath = [
158
+ join(packageRoot, 'skills', 'ivue', 'ivue-house-gate.ts'),
159
+ join(packageRoot, '.claude', 'skills', 'ivue', 'ivue-house-gate.ts'),
160
+ ].find(existsSync);
161
+ if (housePath) {
162
+ const houseSeed = readFileSync(housePath, 'utf8')
163
+ .replace("from '../../lib/Static'", "from 'ivue/extras'")
164
+ .replace("from './ivue-standards-check'", "from 'ivue/skills/ivue/ivue-standards-check'")
165
+ .replace("from './ivue-generator-standard'", "from 'ivue/skills/ivue/ivue-generator-standard'");
166
+ installSeed('.claude/skills/ivue/ivue-house-gate.ts', houseSeed, 'house gate');
167
+ }
107
168
  }
108
169
  if (wantAll && !wantCursor) skipped('Cursor rule', '.cursor/', '--cursor');
109
170
  if (wantAll && !wantCopilot) skipped('Copilot instructions', '.github/', '--copilot');
@@ -32,7 +32,7 @@ export declare type VuePropsWithDefaults<T extends VuePropsObject> = {
32
32
  * @param val Any value
33
33
  * @returns boolean If it's a JavaScript Class returns true
34
34
  */
35
- export declare const isClass: (val: any) => boolean;
35
+ export declare function isClass(val: any): boolean;
36
36
  /**
37
37
  * Creates props with defaults in defineComponent() style.
38
38
  *
@@ -64,7 +64,7 @@ export declare const isClass: (val: any) => boolean;
64
64
  * @param customCloner Optional cloner used for object/array defaults (defaults to structuredClone)
65
65
  * @returns Props declared in defineComponent() style with all properties having default property declared.
66
66
  */
67
- export declare const propsWithDefaults: <T extends VuePropsObject>(defaults: Record<string, any>, typedProps: T, customCloner?: ((val: any) => any) | undefined) => VuePropsWithDefaults<T>;
67
+ export declare function propsWithDefaults<T extends VuePropsObject>(defaults: Record<string, any>, typedProps: T, customCloner?: (val: any) => any): VuePropsWithDefaults<T>;
68
68
  /**
69
69
  * Type Utilities
70
70
  */
@@ -84,8 +84,12 @@ export declare type ReactiveInstance<T> = T & WritableGetters<T> & {
84
84
  $watch: typeof watch;
85
85
  /** Register a watchEffect in the instance's lazy effect scope (same signature as Vue `watchEffect`). */
86
86
  $watchEffect: typeof watchEffect;
87
- /** Stop the instance's effect scope and drop cached cells. */
88
- $stopEffects: () => void;
87
+ /** Stop the instance's effect scope and drop cached cells (the next
88
+ * touch re-materializes). `{ reset: false }` stops watchers only —
89
+ * every cached cell survives with its current value. */
90
+ $stopEffects: (options?: {
91
+ reset?: boolean;
92
+ }) => void;
89
93
  };
90
94
  export declare type ReactiveClass<C extends new (...args: any) => any> = {
91
95
  [Key in keyof C]: C[Key];
@@ -114,11 +118,28 @@ export declare type ExtractEmitTypes<T extends Record<string, any>> = UnionToInt
114
118
  }>>;
115
119
  /**
116
120
  * Extract properties as all-assigned (non-optional) because every one of
117
- * them carries a default.
121
+ * them carries a default — the honesty check: a declared type without a
122
+ * default is a compile error. Props declared `required: true` are FILTERED
123
+ * OUT automatically (a required prop can never carry a default —
124
+ * propsWithDefaults skips them at runtime), so no manual `Omit` is needed;
125
+ * a deliberately default-free OPTIONAL prop is declared `key: undefined`,
126
+ * stating the ruling in the defaults object itself. The `required: true`
127
+ * literal survives `typeof` only through generic inference — declare the
128
+ * types map with `definePropTypes({...})`, never as a bare object const.
118
129
  */
119
130
  export declare type ExtractPropDefaultTypes<O> = {
120
- [K in keyof O]: K extends keyof ExtractPropTypes<O> ? ExtractPropTypes<O>[K] : never;
131
+ [K in keyof O as O[K] extends {
132
+ required: true;
133
+ } ? never : K]: K extends keyof ExtractPropTypes<O> ? ExtractPropTypes<O>[K] : never;
121
134
  };
135
+ /**
136
+ * Identity helper for a prop-TYPES map. Exists for one reason: in a bare
137
+ * `const propsTypes = {...}`, TypeScript widens `required: true` to
138
+ * `boolean`, which blinds ExtractPropDefaultTypes' required-key filter —
139
+ * generic inference through this call preserves the literal. Costs
140
+ * nothing at runtime.
141
+ */
142
+ export declare function definePropTypes<T extends VuePropsObject>(types: T): T;
122
143
  /**
123
144
  * Extend a slots interface T with prefixed 'before--' & 'after--' slots to
124
145
  * create fully extensible wrapped components.
package/dist/extras.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=Object.hasOwn;exports.LazyShared=class{constructor(s){this.make=s,this.constructed=!1,this.constructing=!1,this.stored=null}get value(){if(!this.constructed){if(this.constructing)throw new Error("LazyShared thunk cycle: this cell is read inside its own construction. Break the dependency between the two thunks.");this.constructing=!0;try{this.stored=this.make(),this.constructed=!0}finally{this.constructing=!1}}return this.stored}reset(){this.constructed=!1,this.stored=null}},exports.Static=function(s){const i=class extends s{},c=new Set;for(let r=s;r!==Function.prototype;r=Object.getPrototypeOf(r))for(const t of Reflect.ownKeys(r)){if(c.has(t))continue;c.add(t);const e=Object.getOwnPropertyDescriptor(r,t);if(typeof e.value=="function"){const o=e.value,n=typeof t=="string"?Symbol.for(`ivue.staticBound.${t}`):Symbol("ivue.staticBound");Object.defineProperty(i,t,{configurable:!0,enumerable:e.enumerable,get(){return u(this,n)||Object.defineProperty(this,n,{configurable:!0,value:o.bind(this)}),this[n]}})}else if(e.get&&!e.set&&typeof t=="string"&&t.startsWith("$")){const o=e.get,n=Symbol.for(`ivue.staticCache.${t}`);Object.defineProperty(i,t,{configurable:!0,enumerable:e.enumerable,get(){return u(this,n)||Object.defineProperty(this,n,{configurable:!0,value:o.call(this)}),this[n]}})}}return i};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=Object.hasOwn,c=new Set;exports.LazyShared=class{constructor(s){this.make=s,this.constructed=!1,this.constructing=!1,this.stored=null}get value(){if(!this.constructed){if(this.constructing)throw new Error("LazyShared thunk cycle: this cell is read inside its own construction. Break the dependency between the two thunks.");this.constructing=!0;try{this.stored=this.make(),this.constructed=!0}finally{this.constructing=!1}}return this.stored}reset(){this.constructed=!1,this.stored=null}},exports.Static=function(s){var a;const o=class extends s{},u=new Set;for(let n=s;n!==Function.prototype;n=Object.getPrototypeOf(n))for(const t of Reflect.ownKeys(n)){if(u.has(t)||(u.add(t),typeof t=="symbol"&&((a=Symbol.keyFor(t))==null?void 0:a.startsWith("ivue.static")))||c.has(t))continue;const i=Object.getOwnPropertyDescriptor(n,t);if(typeof i.value=="function"){const r=i.value,e=typeof t=="string"?Symbol.for(`ivue.staticBound.${t}`):Symbol("ivue.staticBound");c.add(e),Object.defineProperty(o,t,{configurable:!0,enumerable:i.enumerable,get(){return l(this,e)||Object.defineProperty(this,e,{configurable:!0,value:r.bind(this)}),this[e]}})}else if(i.get&&!i.set&&typeof t=="string"&&t.startsWith("$")){const r=i.get,e=Symbol.for(`ivue.staticCache.${t}`);c.add(e),Object.defineProperty(o,t,{configurable:!0,enumerable:i.enumerable,get(){return l(this,e)||Object.defineProperty(this,e,{configurable:!0,value:r.call(this)}),this[e]}})}}return o};
package/dist/extras.es.js CHANGED
@@ -1,30 +1,30 @@
1
- const u = Object.hasOwn;
2
- function a(i) {
3
- const n = class extends i {
4
- }, c = /* @__PURE__ */ new Set();
5
- for (let r = i; r !== Function.prototype; r = Object.getPrototypeOf(r))
6
- for (const t of Reflect.ownKeys(r)) {
7
- if (c.has(t))
1
+ const h = Object.hasOwn, c = /* @__PURE__ */ new Set();
2
+ function l(o) {
3
+ var a;
4
+ const i = class extends o {
5
+ }, u = /* @__PURE__ */ new Set();
6
+ for (let n = o; n !== Function.prototype; n = Object.getPrototypeOf(n))
7
+ for (const t of Reflect.ownKeys(n)) {
8
+ if (u.has(t) || (u.add(t), typeof t == "symbol" && ((a = Symbol.keyFor(t)) == null ? void 0 : a.startsWith("ivue.static"))) || c.has(t))
8
9
  continue;
9
- c.add(t);
10
- const e = Object.getOwnPropertyDescriptor(r, t);
11
- if (typeof e.value == "function") {
12
- const o = e.value, s = typeof t == "string" ? Symbol.for(`ivue.staticBound.${t}`) : Symbol("ivue.staticBound");
13
- Object.defineProperty(n, t, { configurable: !0, enumerable: e.enumerable, get() {
14
- return u(this, s) || Object.defineProperty(this, s, { configurable: !0, value: o.bind(this) }), this[s];
10
+ const s = Object.getOwnPropertyDescriptor(n, t);
11
+ if (typeof s.value == "function") {
12
+ const r = s.value, e = typeof t == "string" ? Symbol.for(`ivue.staticBound.${t}`) : Symbol("ivue.staticBound");
13
+ c.add(e), Object.defineProperty(i, t, { configurable: !0, enumerable: s.enumerable, get() {
14
+ return h(this, e) || Object.defineProperty(this, e, { configurable: !0, value: r.bind(this) }), this[e];
15
15
  } });
16
- } else if (e.get && !e.set && typeof t == "string" && t.startsWith("$")) {
17
- const o = e.get, s = Symbol.for(`ivue.staticCache.${t}`);
18
- Object.defineProperty(n, t, { configurable: !0, enumerable: e.enumerable, get() {
19
- return u(this, s) || Object.defineProperty(this, s, { configurable: !0, value: o.call(this) }), this[s];
16
+ } else if (s.get && !s.set && typeof t == "string" && t.startsWith("$")) {
17
+ const r = s.get, e = Symbol.for(`ivue.staticCache.${t}`);
18
+ c.add(e), Object.defineProperty(i, t, { configurable: !0, enumerable: s.enumerable, get() {
19
+ return h(this, e) || Object.defineProperty(this, e, { configurable: !0, value: r.call(this) }), this[e];
20
20
  } });
21
21
  }
22
22
  }
23
- return n;
23
+ return i;
24
24
  }
25
- class h {
26
- constructor(n) {
27
- this.make = n, this.constructed = !1, this.constructing = !1, this.stored = null;
25
+ class f {
26
+ constructor(i) {
27
+ this.make = i, this.constructed = !1, this.constructing = !1, this.stored = null;
28
28
  }
29
29
  get value() {
30
30
  if (!this.constructed) {
@@ -44,6 +44,6 @@ class h {
44
44
  }
45
45
  }
46
46
  export {
47
- h as LazyShared,
48
- a as Static
47
+ f as LazyShared,
48
+ l as Static
49
49
  };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("vue"),g=Object.hasOwn,y=Object.getPrototypeOf,w=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,a=Object.defineProperty,d=Object.prototype,b=Symbol.for("ivue.raw"),p=Symbol.for("ivue.scope"),h=Symbol.for("ivue.processed");function s(e){const r=l.toRaw(e);if(r!==e)return r[b]??(r[b]=r);const n=e[b];return n?n===e?n:l.toRaw(n):e[b]=e}function O(e,r,n,o){a(e,r,{configurable:!0,enumerable:!1,get(){const t=s(this);return t[n]??(t[n]=o.bind(t))},set(t){s(this)[n]=t}})}function S(e,r,n,o,t){const f=r[0]==="$";a(e,r,{configurable:!0,enumerable:!1,get:function(){const c=s(this);if(n in c)return c[n];const i=o.call(c);return f?(c[n]=i,i):(l.isRef(i)?c[n]=i:a(e,r,{configurable:!0,enumerable:!1,get(){return o.call(s(this))},set:t?function(u){return t.call(s(this),u)}:void 0}),i)},set:t?function(c){return t.call(s(this),c)}:void 0})}const v=e=>{var r;return typeof e=="function"&&!!e.prototype&&!((r=w(e,"prototype"))!=null&&r.writable)};exports.Reactive=function(e){const r=[];let n=e.prototype;for(;n&&n!==d;)r.push(n),n=y(n);r.reverse();for(const o of r){if(g(o,h))continue;const t=m(o),f=[];for(const c of t){if(c==="constructor")continue;const i=w(o,c);if(typeof i.value=="function"){const u=Symbol(c);f.push(u),O(o,c,u,i.value)}else if(i.get){const u=Symbol(c);f.push(u),S(o,c,u,i.get,i.set)}}a(o,h,{value:f})}return g(e.prototype,"$stopEffects")||(a(e.prototype,"$watch",{enumerable:!1,configurable:!0,writable:!0,value:function(...o){const t=s(this);return(t[p]??(t[p]=l.effectScope(!0))).run(()=>l.watch(...o))}}),a(e.prototype,"$watchEffect",{enumerable:!1,configurable:!0,writable:!0,value:function(...o){const t=s(this);return(t[p]??(t[p]=l.effectScope(!0))).run(()=>l.watchEffect(...o))}}),a(e.prototype,"$stopEffects",{enumerable:!1,configurable:!0,writable:!0,value:function(){const o=s(this);try{const t=o[p];t&&t.stop()}finally{delete o[p];let t=y(o);for(;t&&t!==d;){const f=t[h];if(f)for(const c of f)delete o[c];t=y(t)}}}})),e},exports.isClass=v,exports.propsWithDefaults=(e,r,n)=>{const o={};for(const t in r){const f=e==null?void 0:e[t],c=r[t];o[t]={...c},c.required||f===void 0||(typeof f=="object"&&f!==null?o[t].default=()=>n?n(f):structuredClone(f):v(f)?o[t].default=()=>f:o[t].default=f)}return o};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("vue"),d=Object.hasOwn,y=Object.getPrototypeOf,w=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,a=Object.defineProperty,g=Object.prototype,b=Symbol.for("ivue.raw"),p=Symbol.for("ivue.scope"),h=Symbol.for("ivue.processed");function i(e){const c=l.toRaw(e);if(c!==e)return c[b]??(c[b]=c);const r=e[b];return r?r===e?r:l.toRaw(r):e[b]=e}function O(e,c,r,o){a(e,c,{configurable:!0,enumerable:!1,get(){const t=i(this);return t[r]??(t[r]=o.bind(t))},set(t){i(this)[r]=t}})}function S(e,c,r,o,t){const n=c[0]==="$";a(e,c,{configurable:!0,enumerable:!1,get:function(){const u=i(this);if(r in u)return u[r];const f=o.call(u);return n?(u[r]=f,f):(l.isRef(f)?u[r]=f:a(e,c,{configurable:!0,enumerable:!1,get(){return o.call(i(this))},set:t?function(s){return t.call(i(this),s)}:void 0}),f)},set:t?function(u){return t.call(i(this),u)}:void 0})}function v(e){var c;return typeof e=="function"&&!!e.prototype&&!((c=w(e,"prototype"))!=null&&c.writable)}exports.Reactive=function(e){const c=[];let r=e.prototype;for(;r&&r!==g;)c.push(r),r=y(r);c.reverse();for(const o of c){if(d(o,h))continue;const t=m(o),n=[];for(const u of t){if(u==="constructor")continue;const f=w(o,u);if(typeof f.value=="function"){const s=Symbol(u);n.push(s),O(o,u,s,f.value)}else if(f.get){const s=Symbol(u);n.push(s),S(o,u,s,f.get,f.set)}}a(o,h,{value:n})}return d(e.prototype,"$stopEffects")||(a(e.prototype,"$watch",{enumerable:!1,configurable:!0,writable:!0,value:function(...o){const t=i(this);return(t[p]??(t[p]=l.effectScope(!0))).run(()=>l.watch(...o))}}),a(e.prototype,"$watchEffect",{enumerable:!1,configurable:!0,writable:!0,value:function(...o){const t=i(this);return(t[p]??(t[p]=l.effectScope(!0))).run(()=>l.watchEffect(...o))}}),a(e.prototype,"$stopEffects",{enumerable:!1,configurable:!0,writable:!0,value:function(o){const t=i(this);try{const n=t[p];n&&n.stop()}finally{if(delete t[p],(o==null?void 0:o.reset)!==!1){let n=y(t);for(;n&&n!==g;){const u=n[h];if(u)for(const f of u)delete t[f];n=y(n)}}}}})),e},exports.definePropTypes=function(e){return e},exports.isClass=v,exports.propsWithDefaults=function(e,c,r){const o={};for(const t in c){const n=e==null?void 0:e[t],u=c[t];o[t]={...u},u.required||n===void 0||(typeof n=="object"&&n!==null?o[t].default=()=>r?r(n):structuredClone(n):v(n)?o[t].default=()=>n:o[t].default=n)}return o};
package/dist/index.es.js CHANGED
@@ -1,97 +1,103 @@
1
- import { effectScope as h, watch as w, watchEffect as O, toRaw as g, isRef as j } from "vue";
2
- const m = Object.hasOwn, b = Object.getPrototypeOf, d = Object.getOwnPropertyDescriptor, S = Object.getOwnPropertyNames, a = Object.defineProperty, v = Object.prototype, p = Symbol.for("ivue.raw"), l = Symbol.for("ivue.scope"), y = Symbol.for("ivue.processed");
3
- function f(e) {
4
- const r = g(e);
5
- if (r !== e)
6
- return r[p] ?? (r[p] = r);
7
- const n = e[p];
8
- return n ? n === e ? n : g(n) : e[p] = e;
1
+ import { effectScope as h, watch as w, watchEffect as O, toRaw as d, isRef as j } from "vue";
2
+ const g = Object.hasOwn, b = Object.getPrototypeOf, v = Object.getOwnPropertyDescriptor, S = Object.getOwnPropertyNames, a = Object.defineProperty, m = Object.prototype, p = Symbol.for("ivue.raw"), l = Symbol.for("ivue.scope"), y = Symbol.for("ivue.processed");
3
+ function f(t) {
4
+ const c = d(t);
5
+ if (c !== t)
6
+ return c[p] ?? (c[p] = c);
7
+ const r = t[p];
8
+ return r ? r === t ? r : d(r) : t[p] = t;
9
9
  }
10
- function $(e, r, n, o) {
11
- a(e, r, { configurable: !0, enumerable: !1, get() {
12
- const t = f(this);
13
- return t[n] ?? (t[n] = o.bind(t));
14
- }, set(t) {
15
- f(this)[n] = t;
10
+ function P(t, c, r, o) {
11
+ a(t, c, { configurable: !0, enumerable: !1, get() {
12
+ const e = f(this);
13
+ return e[r] ?? (e[r] = o.bind(e));
14
+ }, set(e) {
15
+ f(this)[r] = e;
16
16
  } });
17
17
  }
18
- function E(e, r, n, o, t) {
19
- const s = r[0] === "$";
20
- a(e, r, { configurable: !0, enumerable: !1, get: function() {
21
- const c = f(this);
22
- if (n in c)
23
- return c[n];
24
- const u = o.call(c);
25
- return s ? (c[n] = u, u) : (j(u) ? c[n] = u : a(e, r, { configurable: !0, enumerable: !1, get() {
18
+ function $(t, c, r, o, e) {
19
+ const n = c[0] === "$";
20
+ a(t, c, { configurable: !0, enumerable: !1, get: function() {
21
+ const s = f(this);
22
+ if (r in s)
23
+ return s[r];
24
+ const u = o.call(s);
25
+ return n ? (s[r] = u, u) : (j(u) ? s[r] = u : a(t, c, { configurable: !0, enumerable: !1, get() {
26
26
  return o.call(f(this));
27
- }, set: t ? function(i) {
28
- return t.call(f(this), i);
27
+ }, set: e ? function(i) {
28
+ return e.call(f(this), i);
29
29
  } : void 0 }), u);
30
- }, set: t ? function(c) {
31
- return t.call(f(this), c);
30
+ }, set: e ? function(s) {
31
+ return e.call(f(this), s);
32
32
  } : void 0 });
33
33
  }
34
- function C(e) {
35
- const r = [];
36
- let n = e.prototype;
37
- for (; n && n !== v; )
38
- r.push(n), n = b(n);
39
- r.reverse();
40
- for (const o of r) {
41
- if (m(o, y))
34
+ function C(t) {
35
+ const c = [];
36
+ let r = t.prototype;
37
+ for (; r && r !== m; )
38
+ c.push(r), r = b(r);
39
+ c.reverse();
40
+ for (const o of c) {
41
+ if (g(o, y))
42
42
  continue;
43
- const t = S(o), s = [];
44
- for (const c of t) {
45
- if (c === "constructor")
43
+ const e = S(o), n = [];
44
+ for (const s of e) {
45
+ if (s === "constructor")
46
46
  continue;
47
- const u = d(o, c);
47
+ const u = v(o, s);
48
48
  if (typeof u.value == "function") {
49
- const i = Symbol(c);
50
- s.push(i), $(o, c, i, u.value);
49
+ const i = Symbol(s);
50
+ n.push(i), P(o, s, i, u.value);
51
51
  } else if (u.get) {
52
- const i = Symbol(c);
53
- s.push(i), E(o, c, i, u.get, u.set);
52
+ const i = Symbol(s);
53
+ n.push(i), $(o, s, i, u.get, u.set);
54
54
  }
55
55
  }
56
- a(o, y, { value: s });
56
+ a(o, y, { value: n });
57
57
  }
58
- return m(e.prototype, "$stopEffects") || (a(e.prototype, "$watch", { enumerable: !1, configurable: !0, writable: !0, value: function(...o) {
59
- const t = f(this);
60
- return (t[l] ?? (t[l] = h(!0))).run(() => w(...o));
61
- } }), a(e.prototype, "$watchEffect", { enumerable: !1, configurable: !0, writable: !0, value: function(...o) {
62
- const t = f(this);
63
- return (t[l] ?? (t[l] = h(!0))).run(() => O(...o));
64
- } }), a(e.prototype, "$stopEffects", { enumerable: !1, configurable: !0, writable: !0, value: function() {
65
- const o = f(this);
58
+ return g(t.prototype, "$stopEffects") || (a(t.prototype, "$watch", { enumerable: !1, configurable: !0, writable: !0, value: function(...o) {
59
+ const e = f(this);
60
+ return (e[l] ?? (e[l] = h(!0))).run(() => w(...o));
61
+ } }), a(t.prototype, "$watchEffect", { enumerable: !1, configurable: !0, writable: !0, value: function(...o) {
62
+ const e = f(this);
63
+ return (e[l] ?? (e[l] = h(!0))).run(() => O(...o));
64
+ } }), a(t.prototype, "$stopEffects", { enumerable: !1, configurable: !0, writable: !0, value: function(o) {
65
+ const e = f(this);
66
66
  try {
67
- const t = o[l];
68
- t && t.stop();
67
+ const n = e[l];
68
+ n && n.stop();
69
69
  } finally {
70
- delete o[l];
71
- let t = b(o);
72
- for (; t && t !== v; ) {
73
- const s = t[y];
74
- if (s)
75
- for (const c of s)
76
- delete o[c];
77
- t = b(t);
70
+ if (delete e[l], (o == null ? void 0 : o.reset) !== !1) {
71
+ let n = b(e);
72
+ for (; n && n !== m; ) {
73
+ const s = n[y];
74
+ if (s)
75
+ for (const u of s)
76
+ delete e[u];
77
+ n = b(n);
78
+ }
78
79
  }
79
80
  }
80
- } })), e;
81
+ } })), t;
81
82
  }
82
- const P = (e) => {
83
- var r;
84
- return typeof e == "function" && !!e.prototype && !((r = d(e, "prototype")) != null && r.writable);
85
- }, D = (e, r, n) => {
83
+ function E(t) {
84
+ var c;
85
+ return typeof t == "function" && !!t.prototype && !((c = v(t, "prototype")) != null && c.writable);
86
+ }
87
+ function D(t, c, r) {
86
88
  const o = {};
87
- for (const t in r) {
88
- const s = e == null ? void 0 : e[t], c = r[t];
89
- o[t] = { ...c }, c.required || s === void 0 || (typeof s == "object" && s !== null ? o[t].default = () => n ? n(s) : structuredClone(s) : P(s) ? o[t].default = () => s : o[t].default = s);
89
+ for (const e in c) {
90
+ const n = t == null ? void 0 : t[e], s = c[e];
91
+ o[e] = { ...s }, s.required || n === void 0 || (typeof n == "object" && n !== null ? o[e].default = () => r ? r(n) : structuredClone(n) : E(n) ? o[e].default = () => n : o[e].default = n);
90
92
  }
91
93
  return o;
92
- };
94
+ }
95
+ function q(t) {
96
+ return t;
97
+ }
93
98
  export {
94
99
  C as Reactive,
95
- P as isClass,
100
+ q as definePropTypes,
101
+ E as isClass,
96
102
  D as propsWithDefaults
97
103
  };
package/lib/Reactive.ts CHANGED
@@ -257,15 +257,19 @@ export function Reactive<C extends new (...args: any) => any>(
257
257
 
258
258
  /**
259
259
  * Tear down the instance: stop its effect scope (any watchers created via
260
- * $watch) and drop all cached cells so refs/computeds become collectable.
261
- * No hooks ivue never calls user code; compose richer cleanup as an
262
- * ordinary method that does its own work and then calls $stopEffects().
260
+ * $watch) and drop all cached cells so refs/computeds become collectable
261
+ * the next touch re-materializes fresh cells (disposal is a reset).
262
+ * Pass { reset: false } to stop the watchers ONLY: every cached cell
263
+ * survives with its current value, and the instance can $watch again in a
264
+ * fresh scope. No hooks — ivue never calls user code; compose richer
265
+ * cleanup as an ordinary method that does its own work and then calls
266
+ * $stopEffects().
263
267
  */
264
268
  defineProperty(targetClass.prototype, '$stopEffects', {
265
269
  enumerable: false,
266
270
  configurable: true,
267
271
  writable: true,
268
- value: function (this: any) {
272
+ value: function (this: any, options?: { reset?: boolean }) {
269
273
  const raw = resolveRaw(this);
270
274
  try {
271
275
  const scope = raw[SCOPE];
@@ -274,18 +278,22 @@ export function Reactive<C extends new (...args: any) => any>(
274
278
  // SCOPE is ivue-owned but is not a method/getter cache key.
275
279
  delete raw[SCOPE];
276
280
 
277
- // Each processed prototype's PROCESSED marker carries the
278
- // symbols it may cache on an instance. Walk Child -> Base and
279
- // remove only those known keys.
280
- let prototype = getPrototypeOf(raw);
281
- while (prototype && prototype !== objectPrototype) {
282
- const cacheKeys = prototype[PROCESSED] as
283
- | readonly symbol[]
284
- | undefined;
285
- if (cacheKeys) {
286
- for (const cacheKey of cacheKeys) delete raw[cacheKey];
281
+ // { reset: false } = stop watchers only; cells keep their
282
+ // values (a `return` here would swallow a throwing stop()).
283
+ if (options?.reset !== false) {
284
+ // Each processed prototype's PROCESSED marker carries the
285
+ // symbols it may cache on an instance. Walk Child -> Base and
286
+ // remove only those known keys.
287
+ let prototype = getPrototypeOf(raw);
288
+ while (prototype && prototype !== objectPrototype) {
289
+ const cacheKeys = prototype[PROCESSED] as
290
+ | readonly symbol[]
291
+ | undefined;
292
+ if (cacheKeys) {
293
+ for (const cacheKey of cacheKeys) delete raw[cacheKey];
294
+ }
295
+ prototype = getPrototypeOf(prototype);
287
296
  }
288
- prototype = getPrototypeOf(prototype);
289
297
  }
290
298
  }
291
299
  },
@@ -321,7 +329,7 @@ export type VuePropsWithDefaults<T extends VuePropsObject> = {
321
329
  * @param val Any value
322
330
  * @returns boolean If it's a JavaScript Class returns true
323
331
  */
324
- export const isClass = (val: any): boolean => {
332
+ export function isClass(val: any): boolean {
325
333
  if (typeof val !== 'function') return false; // Not a function, so not a class function either
326
334
 
327
335
  if (!val.prototype) return false; // Arrow function, so not a class
@@ -333,7 +341,7 @@ export const isClass = (val: any): boolean => {
333
341
  } else {
334
342
  return true; // Class -> Not a function
335
343
  }
336
- };
344
+ }
337
345
  /**
338
346
  * Creates props with defaults in defineComponent() style.
339
347
  *
@@ -365,12 +373,12 @@ export const isClass = (val: any): boolean => {
365
373
  * @param customCloner Optional cloner used for object/array defaults (defaults to structuredClone)
366
374
  * @returns Props declared in defineComponent() style with all properties having default property declared.
367
375
  */
368
- export const propsWithDefaults = <T extends VuePropsObject>(
376
+ export function propsWithDefaults<T extends VuePropsObject>(
369
377
  defaults: Record<string, any>,
370
378
  typedProps: T,
371
379
  // Optional: Allows user to pass a custom cloner if structuredClone isn't enough
372
380
  customCloner?: (val: any) => any,
373
- ): VuePropsWithDefaults<T> => {
381
+ ): VuePropsWithDefaults<T> {
374
382
  // NON-MUTATING: descriptor objects are routinely SHARED between props
375
383
  // maps (`{ ...baseParamsTypes, extra }` — the spread copies the outer
376
384
  // object but every inner `{ type }` descriptor stays the same reference).
@@ -396,7 +404,7 @@ export const propsWithDefaults = <T extends VuePropsObject>(
396
404
  }
397
405
  }
398
406
  return result as VuePropsWithDefaults<T>;
399
- };
407
+ }
400
408
 
401
409
  /**
402
410
  * Type Utilities
@@ -430,8 +438,10 @@ export type ReactiveInstance<T> = T &
430
438
  $watch: typeof watch;
431
439
  /** Register a watchEffect in the instance's lazy effect scope (same signature as Vue `watchEffect`). */
432
440
  $watchEffect: typeof watchEffect;
433
- /** Stop the instance's effect scope and drop cached cells. */
434
- $stopEffects: () => void;
441
+ /** Stop the instance's effect scope and drop cached cells (the next
442
+ * touch re-materializes). `{ reset: false }` stops watchers only —
443
+ * every cached cell survives with its current value. */
444
+ $stopEffects: (options?: { reset?: boolean }) => void;
435
445
  };
436
446
 
437
447
  export type ReactiveClass<C extends new (...args: any) => any> = {
@@ -476,14 +486,32 @@ export type ExtractEmitTypes<T extends Record<string, any>> =
476
486
 
477
487
  /**
478
488
  * Extract properties as all-assigned (non-optional) because every one of
479
- * them carries a default.
489
+ * them carries a default — the honesty check: a declared type without a
490
+ * default is a compile error. Props declared `required: true` are FILTERED
491
+ * OUT automatically (a required prop can never carry a default —
492
+ * propsWithDefaults skips them at runtime), so no manual `Omit` is needed;
493
+ * a deliberately default-free OPTIONAL prop is declared `key: undefined`,
494
+ * stating the ruling in the defaults object itself. The `required: true`
495
+ * literal survives `typeof` only through generic inference — declare the
496
+ * types map with `definePropTypes({...})`, never as a bare object const.
480
497
  */
481
498
  export type ExtractPropDefaultTypes<O> = {
482
- [K in keyof O]: K extends keyof ExtractPropTypes<O>
483
- ? ExtractPropTypes<O>[K]
484
- : never;
499
+ [K in keyof O as O[K] extends { required: true }
500
+ ? never
501
+ : K]: K extends keyof ExtractPropTypes<O> ? ExtractPropTypes<O>[K] : never;
485
502
  };
486
503
 
504
+ /**
505
+ * Identity helper for a prop-TYPES map. Exists for one reason: in a bare
506
+ * `const propsTypes = {...}`, TypeScript widens `required: true` to
507
+ * `boolean`, which blinds ExtractPropDefaultTypes' required-key filter —
508
+ * generic inference through this call preserves the literal. Costs
509
+ * nothing at runtime.
510
+ */
511
+ export function definePropTypes<T extends VuePropsObject>(types: T): T {
512
+ return types;
513
+ }
514
+
487
515
  /**
488
516
  * Extend a slots interface T with prefixed 'before--' & 'after--' slots to
489
517
  * create fully extensible wrapped components.
package/lib/Static.ts CHANGED
@@ -42,6 +42,11 @@ export type ClassConstructor = new (...arguments_: any[]) => any;
42
42
 
43
43
  const hasOwn = Object.hasOwn;
44
44
 
45
+ // Every bind/cache symbol this module ever issues — so a second wrap can
46
+ // recognize an ancestor's runtime residue even for the unregistered
47
+ // symbols that back symbol-keyed methods.
48
+ const issuedCacheKeys = new Set<PropertyKey>();
49
+
45
50
  export function Static<Class extends ClassConstructor>(targetClass: Class): Class {
46
51
  const SelectedClass = class extends targetClass {};
47
52
  const visitedKeys = new Set<PropertyKey>();
@@ -55,6 +60,13 @@ export function Static<Class extends ClassConstructor>(targetClass: Class): Clas
55
60
  if (visitedKeys.has(key)) continue;
56
61
  visitedKeys.add(key);
57
62
 
63
+ // An already-wrapped ancestor that has been READ owns its bind/cache
64
+ // symbol properties. They are runtime residue, not API — re-wrapping
65
+ // them would install an ancestor-bound function where the child's
66
+ // own chain lookup expects to bind for itself.
67
+ if (typeof key === 'symbol' && Symbol.keyFor(key)?.startsWith('ivue.static')) continue;
68
+ if (issuedCacheKeys.has(key)) continue; // the unregistered symbols backing symbol-keyed methods
69
+
58
70
  const descriptor = Object.getOwnPropertyDescriptor(currentClass, key)!;
59
71
 
60
72
  if (typeof descriptor.value === 'function') {
@@ -63,6 +75,7 @@ export function Static<Class extends ClassConstructor>(targetClass: Class): Clas
63
75
  typeof key === 'string'
64
76
  ? Symbol.for(`ivue.staticBound.${key}`)
65
77
  : Symbol('ivue.staticBound');
78
+ issuedCacheKeys.add(bindKey);
66
79
 
67
80
  Object.defineProperty(SelectedClass, key, {
68
81
  configurable: true,
@@ -85,6 +98,7 @@ export function Static<Class extends ClassConstructor>(targetClass: Class): Clas
85
98
  ) {
86
99
  const getter = descriptor.get;
87
100
  const cacheKey = Symbol.for(`ivue.staticCache.${key}`);
101
+ issuedCacheKeys.add(cacheKey);
88
102
 
89
103
  Object.defineProperty(SelectedClass, key, {
90
104
  configurable: true,