@framesquared/app 0.1.0 → 0.2.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/dist/index.d.ts +4 -4
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/dist/index.d.ts
CHANGED
|
@@ -95,8 +95,8 @@ declare class ViewModel {
|
|
|
95
95
|
getStore(name: string): any;
|
|
96
96
|
getParent(): ViewModel | null;
|
|
97
97
|
getRoot(): ViewModel;
|
|
98
|
-
on(event: string, fn:
|
|
99
|
-
un(event: string, fn:
|
|
98
|
+
on(event: string, fn: (...args: any[]) => void): void;
|
|
99
|
+
un(event: string, fn: (...args: any[]) => void): void;
|
|
100
100
|
private fire;
|
|
101
101
|
private getByPath;
|
|
102
102
|
private setByPath;
|
|
@@ -191,9 +191,9 @@ declare const Scheduler: {
|
|
|
191
191
|
*/
|
|
192
192
|
flush(): void;
|
|
193
193
|
/** Register a flush callback. */
|
|
194
|
-
onFlush(fn:
|
|
194
|
+
onFlush(fn: () => void): void;
|
|
195
195
|
/** Unregister a flush callback. */
|
|
196
|
-
offFlush(fn:
|
|
196
|
+
offFlush(fn: () => void): void;
|
|
197
197
|
/** Begin a formula evaluation cycle. */
|
|
198
198
|
beginCycle(): void;
|
|
199
199
|
/** End a formula evaluation cycle. */
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,13 @@ var Application = class {
|
|
|
6
6
|
_controllers = /* @__PURE__ */ new Map();
|
|
7
7
|
_stores = /* @__PURE__ */ new Map();
|
|
8
8
|
/** Overridable lifecycle hooks. */
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
9
10
|
onInit = () => {
|
|
10
11
|
};
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
11
13
|
onBeforeLaunch = () => {
|
|
12
14
|
};
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
13
16
|
onLaunch = () => {
|
|
14
17
|
};
|
|
15
18
|
constructor(config) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Application.ts","../src/ViewController.ts","../src/ViewModel.ts","../src/Binding.ts","../src/Router.ts","../src/state/Scheduler.ts","../src/state/Stub.ts"],"sourcesContent":["/**\n * @framesquared/app – Application\n *\n * The entry point for an framesquared application. Manages lifecycle\n * (init → beforeLaunch → launch → onLaunch), controller and\n * store registries, and provides a singleton accessor.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { ViewController } from './ViewController.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface ApplicationConfig {\n name: string;\n appFolder?: string;\n controllers?: string[];\n stores?: string[];\n mainView?: string;\n launch?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Singleton\n// ---------------------------------------------------------------------------\n\nlet instance: Application | null = null;\n\n// ---------------------------------------------------------------------------\n// Application\n// ---------------------------------------------------------------------------\n\nexport class Application {\n private _name: string;\n private _launchFn: (() => void) | null;\n private _controllers = new Map<string, ViewController>();\n private _stores = new Map<string, any>();\n\n /** Overridable lifecycle hooks. */\n onInit: () => void = () => {};\n onBeforeLaunch: () => void = () => {};\n onLaunch: () => void = () => {};\n\n constructor(config: ApplicationConfig) {\n this._name = config.name;\n this._launchFn = config.launch ?? null;\n instance = this;\n }\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n start(): void {\n this.onInit();\n this.onBeforeLaunch();\n this._launchFn?.();\n this.onLaunch();\n }\n\n // -----------------------------------------------------------------------\n // Accessors\n // -----------------------------------------------------------------------\n\n getName(): string {\n return this._name;\n }\n\n // -----------------------------------------------------------------------\n // Controllers\n // -----------------------------------------------------------------------\n\n registerController(name: string, controller: ViewController): void {\n this._controllers.set(name, controller);\n }\n\n getController(name: string): ViewController | undefined {\n return this._controllers.get(name);\n }\n\n // -----------------------------------------------------------------------\n // Stores\n // -----------------------------------------------------------------------\n\n registerStore(name: string, store: any): void {\n this._stores.set(name, store);\n }\n\n getStore(name: string): any {\n return this._stores.get(name);\n }\n\n // -----------------------------------------------------------------------\n // Singleton\n // -----------------------------------------------------------------------\n\n static getInstance(): Application | null {\n return instance;\n }\n\n static clearInstance(): void {\n instance = null;\n }\n}\n","/**\n * @framesquared/app – ViewController\n *\n * Tied to a specific view (Component). Provides `control` config\n * for auto-wiring DOM event handlers via CSS selectors, view reference\n * lookup, and lifecycle management.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface ViewControllerConfig {\n id?: string;\n control?: Record<string, Record<string, string>>;\n listen?: Record<string, any>;\n routes?: Record<string, string>;\n}\n\nexport class ViewController {\n private _id: string;\n private _view: any = null;\n private _control: Record<string, Record<string, string>>;\n private _cleanups: (() => void)[] = [];\n\n constructor(config: ViewControllerConfig = {}) {\n this._id = config.id ?? '';\n this._control = config.control ?? {};\n }\n\n getId(): string {\n return this._id;\n }\n\n // -----------------------------------------------------------------------\n // View lifecycle\n // -----------------------------------------------------------------------\n\n init(view: any): void {\n this._view = view;\n }\n\n destroy(): void {\n for (const cleanup of this._cleanups) cleanup();\n this._cleanups = [];\n this._view = null;\n }\n\n getView(): any {\n return this._view;\n }\n\n // -----------------------------------------------------------------------\n // References\n // -----------------------------------------------------------------------\n\n lookupReference(ref: string): any {\n return this._view?.lookupReference?.(ref) ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n fireViewEvent(eventName: string, ...args: unknown[]): void {\n const view = this._view;\n if (!view) return;\n if (typeof view.fireEvent === 'function') {\n view.fireEvent(eventName, ...args);\n } else if (typeof view.fire === 'function') {\n view.fire(eventName, ...args);\n }\n }\n\n // -----------------------------------------------------------------------\n // Control — auto-wire DOM events\n // -----------------------------------------------------------------------\n\n applyControl(): void {\n if (!this._view?.el) return;\n\n for (const [selector, events] of Object.entries(this._control)) {\n // Convert ExtJS-style selectors to CSS\n const cssSelector = this.toCssSelector(selector);\n const elements = this._view.el.querySelectorAll(cssSelector);\n\n for (const el of elements) {\n for (const [eventName, methodName] of Object.entries(events)) {\n const method = (this as any)[methodName];\n if (typeof method !== 'function') continue;\n const handler = (...args: unknown[]) => method.call(this, ...args);\n (el as HTMLElement).addEventListener(eventName, handler);\n this._cleanups.push(() => (el as HTMLElement).removeEventListener(eventName, handler));\n }\n }\n }\n }\n\n private toCssSelector(sel: string): string {\n // Convert #id to [id=\"id\"], keep other selectors as-is\n return sel.replace(/#(\\w+)/g, '[id=\"$1\"]');\n }\n\n // -----------------------------------------------------------------------\n // Routing\n // -----------------------------------------------------------------------\n\n redirectTo(hash: string, _force?: boolean): void {\n window.location.hash = hash;\n }\n}\n","/**\n * @framesquared/app – ViewModel\n *\n * Provides data binding for views. Supports nested path access,\n * computed formulas with automatic dependency tracking via get(),\n * named stores, parent→child hierarchy with inheritance, and\n * change notification.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface ViewModelConfig {\n data?: Record<string, unknown>;\n formulas?: Record<string, (get: (path: string) => unknown) => unknown>;\n stores?: Record<string, { data: unknown[] }>;\n parent?: ViewModel;\n}\n\nexport class ViewModel {\n private _data: Record<string, unknown>;\n private _formulas: Record<string, (get: (path: string) => unknown) => unknown>;\n private _stores: Record<string, { data: unknown[] }>;\n private _listeners: Record<string, Function[]> = {};\n private _parent: ViewModel | null;\n private _children: ViewModel[] = [];\n private _parentHandler: Function | null = null;\n\n constructor(config: ViewModelConfig = {}) {\n this._data = config.data ? this.deepClone(config.data) : {};\n this._formulas = config.formulas ?? {};\n this._stores = {};\n this._parent = config.parent ?? null;\n\n // Create stores\n if (config.stores) {\n for (const [name, storeCfg] of Object.entries(config.stores)) {\n this._stores[name] = { data: [...(storeCfg.data ?? [])] };\n }\n }\n\n // Register with parent\n if (this._parent) {\n this._parent._children.push(this);\n this._parentHandler = () => this.fire('datachange', this);\n this._parent.on('datachange', this._parentHandler);\n }\n }\n\n // -----------------------------------------------------------------------\n // Data access\n // -----------------------------------------------------------------------\n\n get(path: string): unknown {\n // Check formulas first (local only)\n if (path in this._formulas) {\n return this.computeFormula(path);\n }\n\n // Check local data\n const localVal = this.getByPath(this._data, path);\n if (localVal !== undefined) return localVal;\n\n // Fall back to parent\n if (this._parent) return this._parent.get(path);\n return undefined;\n }\n\n set(pathOrObj: string | Record<string, unknown>, value?: unknown): void {\n if (typeof pathOrObj === 'string') {\n this.setByPath(this._data, pathOrObj, value);\n } else {\n for (const [key, val] of Object.entries(pathOrObj)) {\n this.setByPath(this._data, key, val);\n }\n }\n this.fire('datachange', this);\n }\n\n // -----------------------------------------------------------------------\n // Formulas — get() callback reads both data and other formulas\n // -----------------------------------------------------------------------\n\n private computeFormula(name: string): unknown {\n const fn = this._formulas[name];\n if (!fn) return undefined;\n // The getter passed to formulas uses this.get() so formulas can\n // read other formulas and parent data transparently.\n const getter = (path: string): unknown => this.get(path);\n return fn(getter);\n }\n\n // -----------------------------------------------------------------------\n // Stores\n // -----------------------------------------------------------------------\n\n getStore(name: string): any {\n return this._stores[name] ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Hierarchy\n // -----------------------------------------------------------------------\n\n getParent(): ViewModel | null {\n return this._parent;\n }\n\n getRoot(): ViewModel {\n let current: ViewModel = this;\n while (current._parent) current = current._parent;\n return current;\n }\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n on(event: string, fn: Function): void {\n (this._listeners[event] ??= []).push(fn);\n }\n\n un(event: string, fn: Function): void {\n const list = this._listeners[event];\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n private fire(event: string, ...args: unknown[]): void {\n (this._listeners[event] ?? []).forEach(fn => fn(...args));\n }\n\n // -----------------------------------------------------------------------\n // Path helpers\n // -----------------------------------------------------------------------\n\n private getByPath(obj: any, path: string): unknown {\n const parts = path.split('.');\n let current = obj;\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n return current;\n }\n\n private setByPath(obj: any, path: string, value: unknown): void {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (current[parts[i]] == null) current[parts[i]] = {};\n current = current[parts[i]];\n }\n current[parts[parts.length - 1]] = value;\n }\n\n private deepClone(obj: Record<string, unknown>): Record<string, unknown> {\n return JSON.parse(JSON.stringify(obj));\n }\n}\n","/**\n * @framesquared/app – Binding\n *\n * Parses and evaluates binding expressions that connect ViewModel\n * data to component configs. Supports simple paths, negation,\n * expression templates, and two-way binding.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { ViewModel } from './ViewModel.js';\n\n// ---------------------------------------------------------------------------\n// Parsed binding\n// ---------------------------------------------------------------------------\n\nexport interface ParsedBinding {\n paths: string[];\n negated: boolean;\n expression: boolean;\n template: string;\n}\n\n// ---------------------------------------------------------------------------\n// Binding\n// ---------------------------------------------------------------------------\n\nconst PATH_RE = /\\{(!?)([^}]+)\\}/g;\n\nexport const Binding = {\n /**\n * Parse a binding expression string.\n *\n * - `'{name}'` → simple path\n * - `'{!isAdmin}'` → negated path\n * - `'{firstName} {last}'` → expression with multiple paths\n * - `'{user.email}'` → nested path\n */\n parse(expr: string): ParsedBinding {\n const paths: string[] = [];\n let negated = false;\n let match: RegExpExecArray | null;\n const re = new RegExp(PATH_RE.source, PATH_RE.flags);\n\n while ((match = re.exec(expr)) !== null) {\n if (match[1] === '!') negated = true;\n paths.push(match[2]);\n }\n\n const expression = paths.length > 1 ||\n expr.replace(PATH_RE, '').trim().length > 0;\n\n return { paths, negated, expression, template: expr };\n },\n\n /**\n * Evaluate a parsed binding against a ViewModel.\n */\n evaluate(binding: ParsedBinding, vm: ViewModel): unknown {\n if (binding.expression) {\n // Template expression: replace each {path} with its value\n return binding.template.replace(PATH_RE, (_match, _neg, path) => {\n const val = vm.get(path);\n return val === null || val === undefined ? '' : String(val);\n });\n }\n\n // Single path\n const value = vm.get(binding.paths[0]);\n if (binding.negated) return !value;\n return value;\n },\n\n /**\n * Create a two-way binding. Calls `onChange` whenever the path\n * changes in the ViewModel. Returns a cleanup function.\n */\n twoWay(vm: ViewModel, path: string, onChange: (value: unknown) => void): () => void {\n const handler = () => {\n onChange(vm.get(path));\n };\n vm.on('datachange', handler);\n return () => vm.un('datachange', handler);\n },\n\n /**\n * Multi-bind: bind to multiple paths, callback receives all values\n * as an array whenever any path changes.\n */\n multiBind(vm: ViewModel, paths: string[], onChange: (values: unknown[]) => void): () => void {\n const handler = () => {\n onChange(paths.map(p => vm.get(p)));\n };\n vm.on('datachange', handler);\n return () => vm.un('datachange', handler);\n },\n\n /**\n * Deep bind: notifies when any nested property under the given\n * path changes. Uses the datachange event (fires on every set).\n */\n deepBind(vm: ViewModel, path: string, onChange: (value: unknown) => void): () => void {\n const handler = () => {\n onChange(vm.get(path));\n };\n vm.on('datachange', handler);\n return () => vm.un('datachange', handler);\n },\n};\n","/**\n * @framesquared/app – Router\n *\n * Hash-based routing using the hashchange event. Routes are\n * patterns like 'user/:id' that extract named parameters.\n * Supports wildcard routes, before-route guards, and navigateTo.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface RouteEntry {\n pattern: string;\n paramNames: string[];\n regex: RegExp;\n handler: (params: Record<string, string>) => void;\n wildcard: string | null;\n}\n\nlet routes: RouteEntry[] = [];\nlet beforeRouteFn: ((hash: string) => boolean) | null = null;\nlet hashListener: ((e: Event) => void) | null = null;\nlet started = false;\n\nfunction compileRoute(pattern: string): { paramNames: string[]; regex: RegExp; wildcard: string | null } {\n const paramNames: string[] = [];\n let wildcard: string | null = null;\n\n let regexStr = '^';\n const parts = pattern.split('/');\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (i > 0) regexStr += '\\\\/';\n\n if (part.startsWith('*')) {\n // Wildcard — captures everything after this point\n wildcard = part.slice(1);\n paramNames.push(wildcard);\n regexStr += '(.+)';\n break; // wildcard consumes the rest\n } else if (part.startsWith(':')) {\n paramNames.push(part.slice(1));\n regexStr += '([^\\\\/]+)';\n } else {\n regexStr += part.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n }\n\n regexStr += '$';\n return { paramNames, regex: new RegExp(regexStr), wildcard };\n}\n\nfunction onHashChange(): void {\n const hash = Router.getCurrentHash();\n\n // Before route guard\n if (beforeRouteFn && beforeRouteFn(hash) === false) return;\n\n for (const route of routes) {\n const match = hash.match(route.regex);\n if (match) {\n const params: Record<string, string> = {};\n for (let i = 0; i < route.paramNames.length; i++) {\n params[route.paramNames[i]] = match[i + 1] ?? '';\n }\n route.handler(params);\n return;\n }\n }\n}\n\nexport const Router = {\n addRoute(pattern: string, handler: (params: Record<string, string>) => void): void {\n const { paramNames, regex, wildcard } = compileRoute(pattern);\n routes.push({ pattern, paramNames, regex, handler, wildcard });\n },\n\n getRoutes(): RouteEntry[] {\n return [...routes];\n },\n\n start(): void {\n if (started) return;\n started = true;\n hashListener = () => onHashChange();\n window.addEventListener('hashchange', hashListener);\n },\n\n stop(): void {\n if (hashListener) {\n window.removeEventListener('hashchange', hashListener);\n hashListener = null;\n }\n started = false;\n routes = [];\n beforeRouteFn = null;\n },\n\n setBeforeRoute(fn: ((hash: string) => boolean) | null): void {\n beforeRouteFn = fn;\n },\n\n navigateTo(hash: string): void {\n window.location.hash = hash;\n },\n\n getCurrentHash(): string {\n return window.location.hash.replace(/^#\\/?/, '');\n },\n};\n","/**\n * @framesquared/app – Scheduler\n *\n * Batches multiple state changes into a single notification cycle.\n * Uses microtask (queueMicrotask) for async batching. Provides\n * synchronous flush() for immediate processing. Detects circular\n * dependencies during formula evaluation.\n */\n\nlet pending = false;\nlet flushing = false;\nconst flushListeners: Function[] = [];\nconst processing = new Set<string>();\n\nexport const Scheduler = {\n /**\n * Schedule a flush. Multiple calls before the flush coalesce\n * into a single notification cycle.\n */\n schedule(): void {\n if (pending) return;\n pending = true;\n queueMicrotask(() => {\n if (pending) Scheduler.flush();\n });\n },\n\n /**\n * Synchronous flush — process all pending notifications immediately.\n */\n flush(): void {\n if (flushing) return;\n flushing = true;\n pending = false;\n for (const fn of flushListeners) fn();\n flushing = false;\n },\n\n /** Register a flush callback. */\n onFlush(fn: Function): void {\n if (!flushListeners.includes(fn)) flushListeners.push(fn);\n },\n\n /** Unregister a flush callback. */\n offFlush(fn: Function): void {\n const idx = flushListeners.indexOf(fn);\n if (idx >= 0) flushListeners.splice(idx, 1);\n },\n\n // -----------------------------------------------------------------------\n // Circular dependency detection\n // -----------------------------------------------------------------------\n\n /** Begin a formula evaluation cycle. */\n beginCycle(): void {\n processing.clear();\n },\n\n /** End a formula evaluation cycle. */\n endCycle(): void {\n processing.clear();\n },\n\n /**\n * Mark a stub as currently being processed. If it's already\n * being processed, we have a circular dependency.\n */\n markProcessing(name: string): void {\n if (processing.has(name)) {\n throw new Error(`Circular dependency detected: \"${name}\" is already being evaluated`);\n }\n processing.add(name);\n },\n\n /** Unmark a stub after processing completes. */\n unmarkProcessing(name: string): void {\n processing.delete(name);\n },\n\n /** Reset all state (for tests). */\n reset(): void {\n pending = false;\n flushing = false;\n flushListeners.length = 0;\n processing.clear();\n },\n};\n","/**\n * @framesquared/app – Stub\n *\n * Internal representation of data nodes in the ViewModel.\n * ValueStub holds plain values with dirty tracking.\n * FormulaStub holds computed functions with dependency management.\n */\n\n// ---------------------------------------------------------------------------\n// Base Stub\n// ---------------------------------------------------------------------------\n\nexport abstract class Stub {\n readonly name: string;\n private _dependents: Stub[] = [];\n\n constructor(name: string) {\n this.name = name;\n }\n\n addDependent(stub: Stub): void {\n if (!this._dependents.includes(stub)) {\n this._dependents.push(stub);\n }\n }\n\n removeDependent(stub: Stub): void {\n const idx = this._dependents.indexOf(stub);\n if (idx >= 0) this._dependents.splice(idx, 1);\n }\n\n getDependents(): Stub[] {\n return [...this._dependents];\n }\n}\n\n// ---------------------------------------------------------------------------\n// ValueStub\n// ---------------------------------------------------------------------------\n\nexport class ValueStub extends Stub {\n private _value: unknown;\n private _dirty = false;\n\n constructor(name: string, value: unknown) {\n super(name);\n this._value = value;\n }\n\n getValue(): unknown {\n return this._value;\n }\n\n setValue(value: unknown): void {\n if (this._value !== value) {\n this._value = value;\n this._dirty = true;\n }\n }\n\n isDirty(): boolean {\n return this._dirty;\n }\n\n clearDirty(): void {\n this._dirty = false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// FormulaStub\n// ---------------------------------------------------------------------------\n\nexport class FormulaStub extends Stub {\n private _fn: () => unknown;\n private _dependencies: Stub[] = [];\n private _cachedValue: unknown = undefined;\n private _dirty = true;\n\n constructor(name: string, fn: () => unknown) {\n super(name);\n this._fn = fn;\n }\n\n compute(): unknown {\n this._cachedValue = this._fn();\n this._dirty = false;\n return this._cachedValue;\n }\n\n getCachedValue(): unknown {\n return this._cachedValue;\n }\n\n markDirty(): void {\n this._dirty = true;\n }\n\n isDirty(): boolean {\n return this._dirty;\n }\n\n addDependency(stub: Stub): void {\n if (!this._dependencies.includes(stub)) {\n this._dependencies.push(stub);\n stub.addDependent(this);\n }\n }\n\n getDependencies(): Stub[] {\n return [...this._dependencies];\n }\n\n clearDependencies(): void {\n for (const dep of this._dependencies) {\n dep.removeDependent(this);\n }\n this._dependencies = [];\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/Application.ts","../src/ViewController.ts","../src/ViewModel.ts","../src/Binding.ts","../src/Router.ts","../src/state/Scheduler.ts","../src/state/Stub.ts"],"sourcesContent":["/**\n * @framesquared/app – Application\n *\n * The entry point for an framesquared application. Manages lifecycle\n * (init → beforeLaunch → launch → onLaunch), controller and\n * store registries, and provides a singleton accessor.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { ViewController } from './ViewController.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface ApplicationConfig {\n name: string;\n appFolder?: string;\n controllers?: string[];\n stores?: string[];\n mainView?: string;\n launch?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Singleton\n// ---------------------------------------------------------------------------\n\nlet instance: Application | null = null;\n\n// ---------------------------------------------------------------------------\n// Application\n// ---------------------------------------------------------------------------\n\nexport class Application {\n private _name: string;\n private _launchFn: (() => void) | null;\n private _controllers = new Map<string, ViewController>();\n private _stores = new Map<string, any>();\n\n /** Overridable lifecycle hooks. */\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n onInit: () => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n onBeforeLaunch: () => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n onLaunch: () => void = () => {};\n\n constructor(config: ApplicationConfig) {\n this._name = config.name;\n this._launchFn = config.launch ?? null;\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n instance = this;\n }\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n start(): void {\n this.onInit();\n this.onBeforeLaunch();\n this._launchFn?.();\n this.onLaunch();\n }\n\n // -----------------------------------------------------------------------\n // Accessors\n // -----------------------------------------------------------------------\n\n getName(): string {\n return this._name;\n }\n\n // -----------------------------------------------------------------------\n // Controllers\n // -----------------------------------------------------------------------\n\n registerController(name: string, controller: ViewController): void {\n this._controllers.set(name, controller);\n }\n\n getController(name: string): ViewController | undefined {\n return this._controllers.get(name);\n }\n\n // -----------------------------------------------------------------------\n // Stores\n // -----------------------------------------------------------------------\n\n registerStore(name: string, store: any): void {\n this._stores.set(name, store);\n }\n\n getStore(name: string): any {\n return this._stores.get(name);\n }\n\n // -----------------------------------------------------------------------\n // Singleton\n // -----------------------------------------------------------------------\n\n static getInstance(): Application | null {\n return instance;\n }\n\n static clearInstance(): void {\n instance = null;\n }\n}\n","/**\n * @framesquared/app – ViewController\n *\n * Tied to a specific view (Component). Provides `control` config\n * for auto-wiring DOM event handlers via CSS selectors, view reference\n * lookup, and lifecycle management.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface ViewControllerConfig {\n id?: string;\n control?: Record<string, Record<string, string>>;\n listen?: Record<string, any>;\n routes?: Record<string, string>;\n}\n\nexport class ViewController {\n private _id: string;\n private _view: any = null;\n private _control: Record<string, Record<string, string>>;\n private _cleanups: (() => void)[] = [];\n\n constructor(config: ViewControllerConfig = {}) {\n this._id = config.id ?? '';\n this._control = config.control ?? {};\n }\n\n getId(): string {\n return this._id;\n }\n\n // -----------------------------------------------------------------------\n // View lifecycle\n // -----------------------------------------------------------------------\n\n init(view: any): void {\n this._view = view;\n }\n\n destroy(): void {\n for (const cleanup of this._cleanups) cleanup();\n this._cleanups = [];\n this._view = null;\n }\n\n getView(): any {\n return this._view;\n }\n\n // -----------------------------------------------------------------------\n // References\n // -----------------------------------------------------------------------\n\n lookupReference(ref: string): any {\n return this._view?.lookupReference?.(ref) ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n fireViewEvent(eventName: string, ...args: unknown[]): void {\n const view = this._view;\n if (!view) return;\n if (typeof view.fireEvent === 'function') {\n view.fireEvent(eventName, ...args);\n } else if (typeof view.fire === 'function') {\n view.fire(eventName, ...args);\n }\n }\n\n // -----------------------------------------------------------------------\n // Control — auto-wire DOM events\n // -----------------------------------------------------------------------\n\n applyControl(): void {\n if (!this._view?.el) return;\n\n for (const [selector, events] of Object.entries(this._control)) {\n // Convert ExtJS-style selectors to CSS\n const cssSelector = this.toCssSelector(selector);\n const elements = this._view.el.querySelectorAll(cssSelector);\n\n for (const el of elements) {\n for (const [eventName, methodName] of Object.entries(events)) {\n const method = (this as any)[methodName];\n if (typeof method !== 'function') continue;\n const handler = (...args: unknown[]) => method.call(this, ...args);\n (el as HTMLElement).addEventListener(eventName, handler);\n this._cleanups.push(() => (el as HTMLElement).removeEventListener(eventName, handler));\n }\n }\n }\n }\n\n private toCssSelector(sel: string): string {\n // Convert #id to [id=\"id\"], keep other selectors as-is\n return sel.replace(/#(\\w+)/g, '[id=\"$1\"]');\n }\n\n // -----------------------------------------------------------------------\n // Routing\n // -----------------------------------------------------------------------\n\n redirectTo(hash: string, _force?: boolean): void {\n window.location.hash = hash;\n }\n}\n","/**\n * @framesquared/app – ViewModel\n *\n * Provides data binding for views. Supports nested path access,\n * computed formulas with automatic dependency tracking via get(),\n * named stores, parent→child hierarchy with inheritance, and\n * change notification.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface ViewModelConfig {\n data?: Record<string, unknown>;\n formulas?: Record<string, (get: (path: string) => unknown) => unknown>;\n stores?: Record<string, { data: unknown[] }>;\n parent?: ViewModel;\n}\n\nexport class ViewModel {\n private _data: Record<string, unknown>;\n private _formulas: Record<string, (get: (path: string) => unknown) => unknown>;\n private _stores: Record<string, { data: unknown[] }>;\n\n private _listeners: Record<string, ((...args: any[]) => void)[]> = {};\n private _parent: ViewModel | null;\n private _children: ViewModel[] = [];\n\n private _parentHandler: ((...args: any[]) => void) | null = null;\n\n constructor(config: ViewModelConfig = {}) {\n this._data = config.data ? this.deepClone(config.data) : {};\n this._formulas = config.formulas ?? {};\n this._stores = {};\n this._parent = config.parent ?? null;\n\n // Create stores\n if (config.stores) {\n for (const [name, storeCfg] of Object.entries(config.stores)) {\n this._stores[name] = { data: [...(storeCfg.data ?? [])] };\n }\n }\n\n // Register with parent\n if (this._parent) {\n this._parent._children.push(this);\n this._parentHandler = () => this.fire('datachange', this);\n this._parent.on('datachange', this._parentHandler);\n }\n }\n\n // -----------------------------------------------------------------------\n // Data access\n // -----------------------------------------------------------------------\n\n get(path: string): unknown {\n // Check formulas first (local only)\n if (path in this._formulas) {\n return this.computeFormula(path);\n }\n\n // Check local data\n const localVal = this.getByPath(this._data, path);\n if (localVal !== undefined) return localVal;\n\n // Fall back to parent\n if (this._parent) return this._parent.get(path);\n return undefined;\n }\n\n set(pathOrObj: string | Record<string, unknown>, value?: unknown): void {\n if (typeof pathOrObj === 'string') {\n this.setByPath(this._data, pathOrObj, value);\n } else {\n for (const [key, val] of Object.entries(pathOrObj)) {\n this.setByPath(this._data, key, val);\n }\n }\n this.fire('datachange', this);\n }\n\n // -----------------------------------------------------------------------\n // Formulas — get() callback reads both data and other formulas\n // -----------------------------------------------------------------------\n\n private computeFormula(name: string): unknown {\n const fn = this._formulas[name];\n if (!fn) return undefined;\n // The getter passed to formulas uses this.get() so formulas can\n // read other formulas and parent data transparently.\n const getter = (path: string): unknown => this.get(path);\n return fn(getter);\n }\n\n // -----------------------------------------------------------------------\n // Stores\n // -----------------------------------------------------------------------\n\n getStore(name: string): any {\n return this._stores[name] ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Hierarchy\n // -----------------------------------------------------------------------\n\n getParent(): ViewModel | null {\n return this._parent;\n }\n\n getRoot(): ViewModel {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let current: ViewModel = this;\n while (current._parent) current = current._parent;\n return current;\n }\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n on(event: string, fn: (...args: any[]) => void): void {\n (this._listeners[event] ??= []).push(fn);\n }\n\n un(event: string, fn: (...args: any[]) => void): void {\n const list = this._listeners[event];\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n private fire(event: string, ...args: unknown[]): void {\n (this._listeners[event] ?? []).forEach((fn) => fn(...args));\n }\n\n // -----------------------------------------------------------------------\n // Path helpers\n // -----------------------------------------------------------------------\n\n private getByPath(obj: any, path: string): unknown {\n const parts = path.split('.');\n let current = obj;\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n return current;\n }\n\n private setByPath(obj: any, path: string, value: unknown): void {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (current[parts[i]] == null) current[parts[i]] = {};\n current = current[parts[i]];\n }\n current[parts[parts.length - 1]] = value;\n }\n\n private deepClone(obj: Record<string, unknown>): Record<string, unknown> {\n return JSON.parse(JSON.stringify(obj));\n }\n}\n","/**\n * @framesquared/app – Binding\n *\n * Parses and evaluates binding expressions that connect ViewModel\n * data to component configs. Supports simple paths, negation,\n * expression templates, and two-way binding.\n */\n\nimport type { ViewModel } from './ViewModel.js';\n\n// ---------------------------------------------------------------------------\n// Parsed binding\n// ---------------------------------------------------------------------------\n\nexport interface ParsedBinding {\n paths: string[];\n negated: boolean;\n expression: boolean;\n template: string;\n}\n\n// ---------------------------------------------------------------------------\n// Binding\n// ---------------------------------------------------------------------------\n\nconst PATH_RE = /\\{(!?)([^}]+)\\}/g;\n\nexport const Binding = {\n /**\n * Parse a binding expression string.\n *\n * - `'{name}'` → simple path\n * - `'{!isAdmin}'` → negated path\n * - `'{firstName} {last}'` → expression with multiple paths\n * - `'{user.email}'` → nested path\n */\n parse(expr: string): ParsedBinding {\n const paths: string[] = [];\n let negated = false;\n let match: RegExpExecArray | null;\n const re = new RegExp(PATH_RE.source, PATH_RE.flags);\n\n while ((match = re.exec(expr)) !== null) {\n if (match[1] === '!') negated = true;\n paths.push(match[2]);\n }\n\n const expression = paths.length > 1 || expr.replace(PATH_RE, '').trim().length > 0;\n\n return { paths, negated, expression, template: expr };\n },\n\n /**\n * Evaluate a parsed binding against a ViewModel.\n */\n evaluate(binding: ParsedBinding, vm: ViewModel): unknown {\n if (binding.expression) {\n // Template expression: replace each {path} with its value\n return binding.template.replace(PATH_RE, (_match, _neg, path) => {\n const val = vm.get(path);\n return val === null || val === undefined ? '' : String(val);\n });\n }\n\n // Single path\n const value = vm.get(binding.paths[0]);\n if (binding.negated) return !value;\n return value;\n },\n\n /**\n * Create a two-way binding. Calls `onChange` whenever the path\n * changes in the ViewModel. Returns a cleanup function.\n */\n twoWay(vm: ViewModel, path: string, onChange: (value: unknown) => void): () => void {\n const handler = () => {\n onChange(vm.get(path));\n };\n vm.on('datachange', handler);\n return () => vm.un('datachange', handler);\n },\n\n /**\n * Multi-bind: bind to multiple paths, callback receives all values\n * as an array whenever any path changes.\n */\n multiBind(vm: ViewModel, paths: string[], onChange: (values: unknown[]) => void): () => void {\n const handler = () => {\n onChange(paths.map((p) => vm.get(p)));\n };\n vm.on('datachange', handler);\n return () => vm.un('datachange', handler);\n },\n\n /**\n * Deep bind: notifies when any nested property under the given\n * path changes. Uses the datachange event (fires on every set).\n */\n deepBind(vm: ViewModel, path: string, onChange: (value: unknown) => void): () => void {\n const handler = () => {\n onChange(vm.get(path));\n };\n vm.on('datachange', handler);\n return () => vm.un('datachange', handler);\n },\n};\n","/**\n * @framesquared/app – Router\n *\n * Hash-based routing using the hashchange event. Routes are\n * patterns like 'user/:id' that extract named parameters.\n * Supports wildcard routes, before-route guards, and navigateTo.\n */\n\ninterface RouteEntry {\n pattern: string;\n paramNames: string[];\n regex: RegExp;\n handler: (params: Record<string, string>) => void;\n wildcard: string | null;\n}\n\nlet routes: RouteEntry[] = [];\nlet beforeRouteFn: ((hash: string) => boolean) | null = null;\nlet hashListener: ((e: Event) => void) | null = null;\nlet started = false;\n\nfunction compileRoute(pattern: string): {\n paramNames: string[];\n regex: RegExp;\n wildcard: string | null;\n} {\n const paramNames: string[] = [];\n let wildcard: string | null = null;\n\n let regexStr = '^';\n const parts = pattern.split('/');\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (i > 0) regexStr += '\\\\/';\n\n if (part.startsWith('*')) {\n // Wildcard — captures everything after this point\n wildcard = part.slice(1);\n paramNames.push(wildcard);\n regexStr += '(.+)';\n break; // wildcard consumes the rest\n } else if (part.startsWith(':')) {\n paramNames.push(part.slice(1));\n regexStr += '([^\\\\/]+)';\n } else {\n regexStr += part.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n }\n\n regexStr += '$';\n return { paramNames, regex: new RegExp(regexStr), wildcard };\n}\n\nfunction onHashChange(): void {\n const hash = Router.getCurrentHash();\n\n // Before route guard\n if (beforeRouteFn && beforeRouteFn(hash) === false) return;\n\n for (const route of routes) {\n const match = hash.match(route.regex);\n if (match) {\n const params: Record<string, string> = {};\n for (let i = 0; i < route.paramNames.length; i++) {\n params[route.paramNames[i]] = match[i + 1] ?? '';\n }\n route.handler(params);\n return;\n }\n }\n}\n\nexport const Router = {\n addRoute(pattern: string, handler: (params: Record<string, string>) => void): void {\n const { paramNames, regex, wildcard } = compileRoute(pattern);\n routes.push({ pattern, paramNames, regex, handler, wildcard });\n },\n\n getRoutes(): RouteEntry[] {\n return [...routes];\n },\n\n start(): void {\n if (started) return;\n started = true;\n hashListener = () => onHashChange();\n window.addEventListener('hashchange', hashListener);\n },\n\n stop(): void {\n if (hashListener) {\n window.removeEventListener('hashchange', hashListener);\n hashListener = null;\n }\n started = false;\n routes = [];\n beforeRouteFn = null;\n },\n\n setBeforeRoute(fn: ((hash: string) => boolean) | null): void {\n beforeRouteFn = fn;\n },\n\n navigateTo(hash: string): void {\n window.location.hash = hash;\n },\n\n getCurrentHash(): string {\n return window.location.hash.replace(/^#\\/?/, '');\n },\n};\n","/**\n * @framesquared/app – Scheduler\n *\n * Batches multiple state changes into a single notification cycle.\n * Uses microtask (queueMicrotask) for async batching. Provides\n * synchronous flush() for immediate processing. Detects circular\n * dependencies during formula evaluation.\n */\n\nlet pending = false;\nlet flushing = false;\nconst flushListeners: (() => void)[] = [];\nconst processing = new Set<string>();\n\nexport const Scheduler = {\n /**\n * Schedule a flush. Multiple calls before the flush coalesce\n * into a single notification cycle.\n */\n schedule(): void {\n if (pending) return;\n pending = true;\n queueMicrotask(() => {\n if (pending) Scheduler.flush();\n });\n },\n\n /**\n * Synchronous flush — process all pending notifications immediately.\n */\n flush(): void {\n if (flushing) return;\n flushing = true;\n pending = false;\n for (const fn of flushListeners) fn();\n flushing = false;\n },\n\n /** Register a flush callback. */\n onFlush(fn: () => void): void {\n if (!flushListeners.includes(fn)) flushListeners.push(fn);\n },\n\n /** Unregister a flush callback. */\n offFlush(fn: () => void): void {\n const idx = flushListeners.indexOf(fn);\n if (idx >= 0) flushListeners.splice(idx, 1);\n },\n\n // -----------------------------------------------------------------------\n // Circular dependency detection\n // -----------------------------------------------------------------------\n\n /** Begin a formula evaluation cycle. */\n beginCycle(): void {\n processing.clear();\n },\n\n /** End a formula evaluation cycle. */\n endCycle(): void {\n processing.clear();\n },\n\n /**\n * Mark a stub as currently being processed. If it's already\n * being processed, we have a circular dependency.\n */\n markProcessing(name: string): void {\n if (processing.has(name)) {\n throw new Error(`Circular dependency detected: \"${name}\" is already being evaluated`);\n }\n processing.add(name);\n },\n\n /** Unmark a stub after processing completes. */\n unmarkProcessing(name: string): void {\n processing.delete(name);\n },\n\n /** Reset all state (for tests). */\n reset(): void {\n pending = false;\n flushing = false;\n flushListeners.length = 0;\n processing.clear();\n },\n};\n","/**\n * @framesquared/app – Stub\n *\n * Internal representation of data nodes in the ViewModel.\n * ValueStub holds plain values with dirty tracking.\n * FormulaStub holds computed functions with dependency management.\n */\n\n// ---------------------------------------------------------------------------\n// Base Stub\n// ---------------------------------------------------------------------------\n\nexport abstract class Stub {\n readonly name: string;\n private _dependents: Stub[] = [];\n\n constructor(name: string) {\n this.name = name;\n }\n\n addDependent(stub: Stub): void {\n if (!this._dependents.includes(stub)) {\n this._dependents.push(stub);\n }\n }\n\n removeDependent(stub: Stub): void {\n const idx = this._dependents.indexOf(stub);\n if (idx >= 0) this._dependents.splice(idx, 1);\n }\n\n getDependents(): Stub[] {\n return [...this._dependents];\n }\n}\n\n// ---------------------------------------------------------------------------\n// ValueStub\n// ---------------------------------------------------------------------------\n\nexport class ValueStub extends Stub {\n private _value: unknown;\n private _dirty = false;\n\n constructor(name: string, value: unknown) {\n super(name);\n this._value = value;\n }\n\n getValue(): unknown {\n return this._value;\n }\n\n setValue(value: unknown): void {\n if (this._value !== value) {\n this._value = value;\n this._dirty = true;\n }\n }\n\n isDirty(): boolean {\n return this._dirty;\n }\n\n clearDirty(): void {\n this._dirty = false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// FormulaStub\n// ---------------------------------------------------------------------------\n\nexport class FormulaStub extends Stub {\n private _fn: () => unknown;\n private _dependencies: Stub[] = [];\n private _cachedValue: unknown = undefined;\n private _dirty = true;\n\n constructor(name: string, fn: () => unknown) {\n super(name);\n this._fn = fn;\n }\n\n compute(): unknown {\n this._cachedValue = this._fn();\n this._dirty = false;\n return this._cachedValue;\n }\n\n getCachedValue(): unknown {\n return this._cachedValue;\n }\n\n markDirty(): void {\n this._dirty = true;\n }\n\n isDirty(): boolean {\n return this._dirty;\n }\n\n addDependency(stub: Stub): void {\n if (!this._dependencies.includes(stub)) {\n this._dependencies.push(stub);\n stub.addDependent(this);\n }\n }\n\n getDependencies(): Stub[] {\n return [...this._dependencies];\n }\n\n clearDependencies(): void {\n for (const dep of this._dependencies) {\n dep.removeDependent(this);\n }\n this._dependencies = [];\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@framesquared/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Application architecture (MVC/MVVM)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@framesquared/core": "0.
|
|
18
|
+
"@framesquared/core": "0.2.0"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public",
|
|
23
|
+
"registry": "https://registry.npmjs.org"
|
|
19
24
|
},
|
|
20
25
|
"scripts": {
|
|
21
26
|
"build": "tsup",
|