@heshammesalam/heshjs 0.3.0 → 0.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/README.md +17 -18
- package/cli.js +8 -3
- package/dist/architecture/html.d.ts +2 -0
- package/dist/architecture/html.js +20 -2
- package/dist/architecture/html.js.map +1 -1
- package/dist/architecture/index.js +16 -6
- package/dist/architecture/index.js.map +1 -1
- package/dist/destinations/index.js +3 -2
- package/dist/destinations/index.js.map +1 -1
- package/dist/heshjs/index.d.ts +2 -0
- package/dist/heshjs/index.js +1 -0
- package/dist/heshjs/index.js.map +1 -1
- package/dist/hmvc/index.d.ts +2 -0
- package/dist/hmvc/index.js +11 -0
- package/dist/hmvc/index.js.map +1 -1
- package/dist/parser/index.js +1 -1
- package/dist/parser/index.js.map +1 -1
- package/dist/presentation/index.d.ts +3 -0
- package/dist/presentation/index.js +1 -0
- package/dist/presentation/index.js.map +1 -1
- package/dist/units/index.d.ts +13 -0
- package/dist/units/index.js +16 -0
- package/dist/units/index.js.map +1 -0
- package/docs/contracts.md +8 -1
- package/docs/units.md +71 -0
- package/package.json +4 -3
- package/scaffold/assets/hesh-icon.png +0 -0
- package/scaffold/create.js +78 -0
- package/scaffold/template.js +188 -0
- package/src/architecture/html.ts +15 -2
- package/src/architecture/index.ts +13 -5
- package/src/destinations/index.ts +3 -2
- package/src/heshjs/index.ts +2 -0
- package/src/hmvc/index.ts +7 -0
- package/src/parser/index.ts +1 -1
- package/src/presentation/index.ts +3 -1
- package/src/units/index.ts +23 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/destinations/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRouter } from '../router/index.js';\nimport { defineModule, useController, type RouteLocation } from '../hmvc/index.js';\nimport { createDomainGraph, ClientPolicyDenied, type DomainDefinition, type DomainOptions, type DomainGraph } from '../domains/index.js';\nimport { signal, effect, onCleanup, scope, type Disposer } from '../reactivity/index.js';\nimport { mount, element, text } from '../dom/index.js';\nimport type { PresentationState } from '../presentation/index.js';\nexport type InputType = 'string' | 'number' | 'boolean';\nexport interface TransitionOptions { query?: Record<string, string>; hash?: string; presentation?: 'page' }\nexport interface Destination<I extends object> {\n readonly name: string;\n href(input: I, options?: TransitionOptions): string;\n open(input: I, options?: TransitionOptions): void;\n replace(input: I, options?: TransitionOptions): void;\n /** Prefetch code/resources, not business data or authorization results. */\n prefetch(input: I): Promise<void>;\n}\nexport interface PresentationContext {\n domains: Record<string, unknown>;\n input: Record<string, string | number | boolean>;\n location: RouteLocation;\n signal: AbortSignal;\n}\nexport interface PresentationResources {\n create(context: PresentationContext): PresentationState;\n view(parent: Node, state: PresentationState, destinations: Record<string, Destination<Record<string, unknown>>>): void;\n}\nexport interface DestinationDefinition {\n name: string; url: string; input: Record<string, InputType>; owner: string; access?: string;\n load(): Promise<PresentationResources>;\n}\nexport interface DestinationEvent { type: 'loading' | 'ready' | 'blocked' | 'error' | 'cancelled' | 'disposed'; destination: string; reason?: string }\nexport interface ApplicationOptions extends DomainOptions { window?: Window; onError?: (error: unknown) => void; onDiagnostic?: (event: DestinationEvent) => void }\nexport interface GraphApplication<D = Record<string, Destination<Record<string, unknown>>>, G = Record<string, Record<string, unknown>>> {\n destinations: D;\n domains: G;\n status: { get(): { phase: 'idle' | 'loading' | 'ready' | 'error'; destination?: string; error?: unknown } };\n start(parent: Node): Disposer;\n stop(): void;\n}\nexport function validateInput(schema: Record<string, InputType>, input: object): Record<string, string | number | boolean> {\n if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Destination input must be an object');\n const values = input as Record<string, unknown>;\n for (const key of Object.keys(values)) if (!Object.hasOwn(schema, key)) throw new Error(`Unknown destination input ${key}`);\n const result: Record<string, string | number | boolean> = Object.create(null);\n for (const [key, type] of Object.entries(schema)) {\n const value = values[key];\n if (!Object.hasOwn(values, key) || typeof value !== type || (type === 'number' && !Number.isFinite(value)) || (type === 'string' && !(value as string).length)) throw new Error(`Destination input ${key} must be ${type}${type === 'string' ? ' (nonempty)' : ''}`);\n if (type === 'string' && (value === '.' || value === '..')) throw new Error(`Destination input ${key} cannot be a URL dot segment`);\n result[key] = value as string | number | boolean;\n }\n return result;\n}\nfunction decodeInput(definition: DestinationDefinition, params: Readonly<Record<string, string>>): Record<string, string | number | boolean> {\n const values: Record<string, unknown> = Object.create(null);\n for (const [key, type] of Object.entries(definition.input)) {\n const raw = params[key];\n if (raw === undefined) throw new Error(`Missing URL input ${key}`);\n if (type === 'boolean' && raw !== 'true' && raw !== 'false') throw new Error(`URL input ${key} must be true/false`);\n if (type === 'number' && !raw.trim()) throw new Error(`URL input ${key} must be numeric`);\n values[key] = type === 'number' ? Number(raw) : type === 'boolean' ? raw === 'true' : raw;\n }\n return validateInput(definition.input, values);\n}\nexport function createGraphApplication(definitions: readonly DomainDefinition[], pages: readonly DestinationDefinition[], options: ApplicationOptions = {}): GraphApplication {\n const graph = createDomainGraph(definitions, options);\n const status = signal<{ phase: 'idle' | 'loading' | 'ready' | 'error'; destination?: string; error?: unknown }>({ phase: 'idle' });\n const report = options.onError ?? (error => console.error(error));\n const emit = (type: DestinationEvent['type'], destination: string, error?: unknown) => {\n if (!options.onDiagnostic) return;\n try { options.onDiagnostic({ type, destination, ...(error === undefined ? {} : { reason: error instanceof Error ? error.message : String(error) }) }); }\n catch (failure) { report(failure); }\n };\n const destinations: Record<string, Destination<Record<string, unknown>>> = Object.create(null);\n const code = new Map<string, Promise<PresentationResources>>();\n let stopped = false;\n const load = (page: DestinationDefinition) => {\n let result = code.get(page.name);\n if (!result) { result = Promise.resolve().then(page.load).catch(error => { code.delete(page.name); throw error; }); code.set(page.name, result); }\n return result;\n };\n const authorize = (page: DestinationDefinition) => {\n if (page.access && options.authorize?.(page.access) !== true) throw new ClientPolicyDenied(page.access, page.name);\n };\n const routes = pages.map(page => ({ path: page.url, module: defineModule({\n model: context => context.route,\n controller: route => route,\n view(parent) {\n const route = useController<{ get(): RouteLocation }>();\n effect(() => {\n const location = route.get();\n const abort = new AbortController(); let dispose: Disposer | undefined, settled = false;\n onCleanup(() => { abort.abort(); dispose?.(); emit(settled ? 'disposed' : 'cancelled', page.name); });\n const message = element(parent, 'p'); message.setAttribute('role', 'status'); text(message, () => 'Loading…');\n status.set({ phase: 'loading', destination: page.name });\n emit('loading', page.name);\n const failed = (error: unknown) => {\n if (abort.signal.aborted) return;\n settled = true;\n message.textContent = 'Unable to open this destination.'; message.setAttribute('role', 'alert');\n status.set({ phase: 'error', destination: page.name, error }); emit(error instanceof ClientPolicyDenied ? 'blocked' : 'error', page.name, error); report(error);\n };\n let input: ReturnType<typeof validateInput>;\n try { authorize(page); input = decodeInput(page, location.params); } catch (error) { failed(error); return; }\n void load(page).then(resources => {\n if (abort.signal.aborted) return;\n const owned = scope(() => {\n const state = resources.create({ input, domains: graph.forDomain(page.owner), location, signal: abort.signal });\n if (state && typeof (state as unknown as { then?: unknown }).then === 'function') throw new Error('Presentation factories must be synchronous; use the provided AbortSignal for async work');\n mount(() => resources.view(parent, state, destinations), parent, { onError: report });\n });\n dispose = owned.dispose;\n if (abort.signal.aborted) { dispose(); return; }\n settled = true; message.remove(); status.set({ phase: 'ready', destination: page.name }); emit('ready', page.name);\n // Page-only focus management; opt-in target or the first heading.\n const target = (parent as Element).querySelector?.('[data-hesh-focus], h1, h2') as HTMLElement | null | undefined;\n if (target) { if (!target.hasAttribute('tabindex')) target.setAttribute('tabindex', '-1'); target.focus({ preventScroll: true }); }\n }).catch(failed);\n });\n }\n }) }));\n let router: ReturnType<typeof createRouter>;\n try { router = createRouter({ routes, window: options.window, onError: report }); }\n catch (error) { graph.dispose(); throw error; }\n for (const page of pages) {\n if (destinations[page.name]) { graph.dispose(); throw new Error(`Duplicate destination ${page.name}`); }\n const href = (input: object, transition: TransitionOptions = {}) => {\n if (stopped) throw new Error('Application is disposed');\n if (transition.presentation && transition.presentation !== 'page') throw new Error('Only page presentation is supported');\n const values = validateInput(page.input, input);\n const path = page.url.split('/').map(part => part.startsWith(':') ? encodeURIComponent(String(values[part.slice(1)])) : part).join('/');\n const query = new URLSearchParams(transition.query).toString();\n const hash = transition.hash ? '#' + encodeURIComponent(transition.hash) : '';\n return path + (query ? '?' + query : '') + hash;\n };\n destinations[page.name] = Object.freeze({ name: page.name, href,\n open(input: object, transition?: TransitionOptions) { authorize(page); router.navigate(href(input, transition)); },\n replace(input: object, transition?: TransitionOptions) { authorize(page); router.navigate(href(input, transition), { replace: true }); },\n async prefetch(input: object) { href(input); await load(page); }\n });\n }\n const stop = () => { if (stopped) return; stopped = true; try { router.stop(); } finally { try { graph.dispose(); } finally { code.clear(); status.set({ phase: 'idle' }); } } };\n return { destinations: Object.freeze(destinations), domains: graph.domains, status: { get: status.get },\n start(parent) { if (stopped) throw new Error('Application is disposed'); try { router.start(parent); return stop; } catch (error) { stop(); throw error; } }, stop };\n}\nexport { createDomainGraph };\nexport type { DomainDefinition, DomainGraph };\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/destinations/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRouter } from '../router/index.js';\nimport { defineModule, useController, useModule, withModuleContext, type RouteLocation } from '../hmvc/index.js';\nimport { createDomainGraph, ClientPolicyDenied, type DomainDefinition, type DomainOptions, type DomainGraph } from '../domains/index.js';\nimport { signal, effect, onCleanup, scope, type Disposer } from '../reactivity/index.js';\nimport { mount, element, text } from '../dom/index.js';\nimport type { PresentationState } from '../presentation/index.js';\nexport type InputType = 'string' | 'number' | 'boolean';\nexport interface TransitionOptions { query?: Record<string, string>; hash?: string; presentation?: 'page' }\nexport interface Destination<I extends object> {\n readonly name: string;\n href(input: I, options?: TransitionOptions): string;\n open(input: I, options?: TransitionOptions): void;\n replace(input: I, options?: TransitionOptions): void;\n /** Prefetch code/resources, not business data or authorization results. */\n prefetch(input: I): Promise<void>;\n}\nexport interface PresentationContext {\n domains: Record<string, unknown>;\n input: Record<string, string | number | boolean>;\n location: RouteLocation;\n signal: AbortSignal;\n}\nexport interface PresentationResources {\n create(context: PresentationContext): PresentationState;\n view(parent: Node, state: PresentationState, destinations: Record<string, Destination<Record<string, unknown>>>): void;\n}\nexport interface DestinationDefinition {\n name: string; url: string; input: Record<string, InputType>; owner: string; access?: string;\n load(): Promise<PresentationResources>;\n}\nexport interface DestinationEvent { type: 'loading' | 'ready' | 'blocked' | 'error' | 'cancelled' | 'disposed'; destination: string; reason?: string }\nexport interface ApplicationOptions extends DomainOptions { window?: Window; onError?: (error: unknown) => void; onDiagnostic?: (event: DestinationEvent) => void }\nexport interface GraphApplication<D = Record<string, Destination<Record<string, unknown>>>, G = Record<string, Record<string, unknown>>> {\n destinations: D;\n domains: G;\n status: { get(): { phase: 'idle' | 'loading' | 'ready' | 'error'; destination?: string; error?: unknown } };\n start(parent: Node): Disposer;\n stop(): void;\n}\nexport function validateInput(schema: Record<string, InputType>, input: object): Record<string, string | number | boolean> {\n if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Destination input must be an object');\n const values = input as Record<string, unknown>;\n for (const key of Object.keys(values)) if (!Object.hasOwn(schema, key)) throw new Error(`Unknown destination input ${key}`);\n const result: Record<string, string | number | boolean> = Object.create(null);\n for (const [key, type] of Object.entries(schema)) {\n const value = values[key];\n if (!Object.hasOwn(values, key) || typeof value !== type || (type === 'number' && !Number.isFinite(value)) || (type === 'string' && !(value as string).length)) throw new Error(`Destination input ${key} must be ${type}${type === 'string' ? ' (nonempty)' : ''}`);\n if (type === 'string' && (value === '.' || value === '..')) throw new Error(`Destination input ${key} cannot be a URL dot segment`);\n result[key] = value as string | number | boolean;\n }\n return result;\n}\nfunction decodeInput(definition: DestinationDefinition, params: Readonly<Record<string, string>>): Record<string, string | number | boolean> {\n const values: Record<string, unknown> = Object.create(null);\n for (const [key, type] of Object.entries(definition.input)) {\n const raw = params[key];\n if (raw === undefined) throw new Error(`Missing URL input ${key}`);\n if (type === 'boolean' && raw !== 'true' && raw !== 'false') throw new Error(`URL input ${key} must be true/false`);\n if (type === 'number' && !raw.trim()) throw new Error(`URL input ${key} must be numeric`);\n values[key] = type === 'number' ? Number(raw) : type === 'boolean' ? raw === 'true' : raw;\n }\n return validateInput(definition.input, values);\n}\nexport function createGraphApplication(definitions: readonly DomainDefinition[], pages: readonly DestinationDefinition[], options: ApplicationOptions = {}): GraphApplication {\n const graph = createDomainGraph(definitions, options);\n const status = signal<{ phase: 'idle' | 'loading' | 'ready' | 'error'; destination?: string; error?: unknown }>({ phase: 'idle' });\n const report = options.onError ?? (error => console.error(error));\n const emit = (type: DestinationEvent['type'], destination: string, error?: unknown) => {\n if (!options.onDiagnostic) return;\n try { options.onDiagnostic({ type, destination, ...(error === undefined ? {} : { reason: error instanceof Error ? error.message : String(error) }) }); }\n catch (failure) { report(failure); }\n };\n const destinations: Record<string, Destination<Record<string, unknown>>> = Object.create(null);\n const code = new Map<string, Promise<PresentationResources>>();\n let stopped = false;\n const load = (page: DestinationDefinition) => {\n let result = code.get(page.name);\n if (!result) { result = Promise.resolve().then(page.load).catch(error => { code.delete(page.name); throw error; }); code.set(page.name, result); }\n return result;\n };\n const authorize = (page: DestinationDefinition) => {\n if (page.access && options.authorize?.(page.access) !== true) throw new ClientPolicyDenied(page.access, page.name);\n };\n const routes = pages.map(page => ({ path: page.url, module: defineModule({\n model: context => context.route,\n controller: route => route,\n view(parent) {\n const parentContext = useModule();\n const route = useController<{ get(): RouteLocation }>();\n effect(() => {\n const location = route.get();\n const abort = new AbortController(); let dispose: Disposer | undefined, settled = false;\n onCleanup(() => { abort.abort(); dispose?.(); emit(settled ? 'disposed' : 'cancelled', page.name); });\n const message = element(parent, 'p'); message.setAttribute('role', 'status'); text(message, () => 'Loading…');\n status.set({ phase: 'loading', destination: page.name });\n emit('loading', page.name);\n const failed = (error: unknown) => {\n if (abort.signal.aborted) return;\n settled = true;\n message.textContent = 'Unable to open this destination.'; message.setAttribute('role', 'alert');\n status.set({ phase: 'error', destination: page.name, error }); emit(error instanceof ClientPolicyDenied ? 'blocked' : 'error', page.name, error); report(error);\n };\n let input: ReturnType<typeof validateInput>;\n try { authorize(page); input = decodeInput(page, location.params); } catch (error) { failed(error); return; }\n void load(page).then(resources => {\n if (abort.signal.aborted) return;\n const owned = scope(() => {\n const state = resources.create({ input, domains: graph.forDomain(page.owner), location, signal: abort.signal });\n if (state && typeof (state as unknown as { then?: unknown }).then === 'function') throw new Error('Presentation factories must be synchronous; use the provided AbortSignal for async work');\n mount(() => withModuleContext(parentContext, () => resources.view(parent, state, destinations)), parent, { onError: report });\n });\n dispose = owned.dispose;\n if (abort.signal.aborted) { dispose(); return; }\n settled = true; message.remove(); status.set({ phase: 'ready', destination: page.name }); emit('ready', page.name);\n // Page-only focus management; opt-in target or the first heading.\n const target = (parent as Element).querySelector?.('[data-hesh-focus], h1, h2') as HTMLElement | null | undefined;\n if (target) { if (!target.hasAttribute('tabindex')) target.setAttribute('tabindex', '-1'); target.focus({ preventScroll: true }); }\n }).catch(failed);\n });\n }\n }) }));\n let router: ReturnType<typeof createRouter>;\n try { router = createRouter({ routes, window: options.window, onError: report }); }\n catch (error) { graph.dispose(); throw error; }\n for (const page of pages) {\n if (destinations[page.name]) { graph.dispose(); throw new Error(`Duplicate destination ${page.name}`); }\n const href = (input: object, transition: TransitionOptions = {}) => {\n if (stopped) throw new Error('Application is disposed');\n if (transition.presentation && transition.presentation !== 'page') throw new Error('Only page presentation is supported');\n const values = validateInput(page.input, input);\n const path = page.url.split('/').map(part => part.startsWith(':') ? encodeURIComponent(String(values[part.slice(1)])) : part).join('/');\n const query = new URLSearchParams(transition.query).toString();\n const hash = transition.hash ? '#' + encodeURIComponent(transition.hash) : '';\n return path + (query ? '?' + query : '') + hash;\n };\n destinations[page.name] = Object.freeze({ name: page.name, href,\n open(input: object, transition?: TransitionOptions) { authorize(page); router.navigate(href(input, transition)); },\n replace(input: object, transition?: TransitionOptions) { authorize(page); router.navigate(href(input, transition), { replace: true }); },\n async prefetch(input: object) { href(input); await load(page); }\n });\n }\n const stop = () => { if (stopped) return; stopped = true; try { router.stop(); } finally { try { graph.dispose(); } finally { code.clear(); status.set({ phase: 'idle' }); } } };\n return { destinations: Object.freeze(destinations), domains: graph.domains, status: { get: status.get },\n start(parent) { if (stopped) throw new Error('Application is disposed'); try { router.start(parent); return stop; } catch (error) { stop(); throw error; } }, stop };\n}\nexport { createDomainGraph };\nexport type { DomainDefinition, DomainGraph };\n"]}
|
package/dist/heshjs/index.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ export { signal, effect, derived, batch, scope, onCleanup, untrack } from '../re
|
|
|
2
2
|
export type { Signal, Disposer } from '../reactivity/index.js';
|
|
3
3
|
export { mount, element, text, attribute, listen, input, component } from '../dom/index.js';
|
|
4
4
|
export type { Component, MountOptions } from '../dom/index.js';
|
|
5
|
+
export { defineUnit, useUnit, useUnitState, useUnitActions } from '../units/index.js';
|
|
6
|
+
export type { HeshUnit, UnitDefinition } from '../units/index.js';
|
package/dist/heshjs/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { signal, effect, derived, batch, scope, onCleanup, untrack } from '../reactivity/index.js';
|
|
2
2
|
export { mount, element, text, attribute, listen, input, component } from '../dom/index.js';
|
|
3
|
+
export { defineUnit, useUnit, useUnitState, useUnitActions } from '../units/index.js';
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
package/dist/heshjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/heshjs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEnG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export { signal, effect, derived, batch, scope, onCleanup, untrack } from '../reactivity/index.js';\nexport type { Signal, Disposer } from '../reactivity/index.js';\nexport { mount, element, text, attribute, listen, input, component } from '../dom/index.js';\nexport type { Component, MountOptions } from '../dom/index.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/heshjs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEnG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5F,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["export { signal, effect, derived, batch, scope, onCleanup, untrack } from '../reactivity/index.js';\nexport type { Signal, Disposer } from '../reactivity/index.js';\nexport { mount, element, text, attribute, listen, input, component } from '../dom/index.js';\nexport type { Component, MountOptions } from '../dom/index.js';\nexport { defineUnit, useUnit, useUnitState, useUnitActions } from '../units/index.js';\nexport type { HeshUnit, UnitDefinition } from '../units/index.js';\n"]}
|
package/dist/hmvc/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface MountedModule {
|
|
|
27
27
|
export interface AppModule {
|
|
28
28
|
attach(parent: Node, location: RouteLocation, parentContext?: ModuleContext, options?: MountOptions): MountedModule;
|
|
29
29
|
}
|
|
30
|
+
/** Restore a captured parent context while mounting an asynchronously loaded screen. */
|
|
31
|
+
export declare function withModuleContext<T>(context: ModuleContext, run: () => T): T;
|
|
30
32
|
export declare function useModule<M = unknown, C = unknown>(): ModuleContext<M, C>;
|
|
31
33
|
export declare function useController<C = unknown>(): C;
|
|
32
34
|
export declare function useModel<M = unknown>(): M;
|
package/dist/hmvc/index.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { mount, element } from '../dom/index.js';
|
|
2
2
|
import { signal } from '../reactivity/index.js';
|
|
3
3
|
let current;
|
|
4
|
+
/** Restore a captured parent context while mounting an asynchronously loaded screen. */
|
|
5
|
+
export function withModuleContext(context, run) {
|
|
6
|
+
const previous = current;
|
|
7
|
+
current = { context };
|
|
8
|
+
try {
|
|
9
|
+
return run();
|
|
10
|
+
}
|
|
11
|
+
finally {
|
|
12
|
+
current = previous;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
4
15
|
export function useModule() {
|
|
5
16
|
if (!current)
|
|
6
17
|
throw new Error('Module context is only available during a module view mount');
|
package/dist/hmvc/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hmvc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAqC,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,MAAM,EAA8B,MAAM,wBAAwB,CAAC;AA6B5E,IAAI,OAA8D,CAAC;AAEnE,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC7F,OAAO,OAAO,CAAC,OAA8B,CAAC;AAChD,CAAC;AACD,MAAM,UAAU,aAAa,KAAqB,OAAO,SAAS,EAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AAC9F,MAAM,UAAU,QAAQ,KAAqB,OAAO,SAAS,EAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAE3E,qFAAqF;AACrF,MAAM,UAAU,MAAM,CAAC,MAAY;IACjC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC3E,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO,CAAC,MAAsB,CAAC,YAAY,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,YAAY,CAAO,UAAkC;IACnE,OAAO;QACL,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO;YAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC/B,IAAI,KAA4D,CAAC;YACjE,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,EAAE;gBACzB,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;gBACrE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACxC,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBACzD,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;oBACxC,IAAI,KAAK,IAAI,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU;wBAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;gBAChJ,CAAC;gBACD,KAAK,GAAG,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;gBACvD,MAAM,QAAQ,GAAG,OAAO,CAAC;gBACzB,OAAO,GAAG,KAAK,CAAC;gBAChB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAY,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAChD,IAAI,MAAM,IAAI,OAAQ,MAA6B,CAAC,IAAI,KAAK,UAAU;wBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;gBAClI,CAAC;wBAAS,CAAC;oBAAC,OAAO,GAAG,QAAQ,CAAC;gBAAC,CAAC;YACnC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,KAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3G,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { mount, element, type Component, type MountOptions } from '../dom/index.js';\nimport { signal, type Signal, type Disposer } from '../reactivity/index.js';\n\nexport interface RouteLocation {\n readonly url: URL;\n readonly pathname: string;\n readonly params: Readonly<Record<string, string>>;\n readonly query: URLSearchParams;\n readonly hash: string;\n}\nexport interface ModuleContext<M = unknown, C = unknown> {\n readonly route: Pick<Signal<RouteLocation>, 'get'>;\n readonly parent?: ModuleContext;\n readonly model: M;\n readonly controller: C;\n}\nexport interface ModuleDefinition<M, C> {\n model: (context: Pick<ModuleContext, 'route' | 'parent'>) => M;\n controller: (model: M, context: Pick<ModuleContext, 'route' | 'parent'>) => C;\n view: Component;\n}\nexport interface MountedModule {\n readonly context: ModuleContext;\n readonly outlet?: Node;\n readonly dispose: Disposer;\n update(location: RouteLocation): void;\n}\nexport interface AppModule {\n attach(parent: Node, location: RouteLocation, parentContext?: ModuleContext, options?: MountOptions): MountedModule;\n}\nlet current: { context: ModuleContext; outlet?: Node } | undefined;\n\nexport function useModule<M = unknown, C = unknown>(): ModuleContext<M, C> {\n if (!current) throw new Error('Module context is only available during a module view mount');\n return current.context as ModuleContext<M, C>;\n}\nexport function useController<C = unknown>(): C { return useModule<unknown, C>().controller; }\nexport function useModel<M = unknown>(): M { return useModule<M>().model; }\n\n/** Child route outlet. Import this component in a .hesh layout and call Outlet(). */\nexport function Outlet(parent: Node): void {\n if (!current) throw new Error('Outlet requires a module view');\n if (current.outlet) throw new Error('A module may render only one Outlet');\n current.outlet = element(parent, 'div');\n (current.outlet as HTMLElement).setAttribute('data-hesh-outlet', '');\n}\n\nexport function defineModule<M, C>(definition: ModuleDefinition<M, C>): AppModule {\n return {\n attach(parent, location, parentContext, options) {\n const route = signal(location);\n let state: { context: ModuleContext; outlet?: Node } | undefined;\n const dispose = mount(() => {\n const context = { route: { get: route.get }, parent: parentContext };\n const model = definition.model(context);\n const controller = definition.controller(model, context);\n for (const value of [model, controller]) {\n if (value && typeof (value as { then?: unknown }).then === 'function') throw new Error('HMVC model/controller factories must be synchronous');\n }\n state = { context: { ...context, model, controller } };\n const previous = current;\n current = state;\n try {\n const result: unknown = definition.view(parent);\n if (result && typeof (result as { then?: unknown }).then === 'function') throw new Error('HMVC views must mount synchronously');\n } finally { current = previous; }\n }, parent, options);\n return { context: state!.context, outlet: state!.outlet, dispose, update: next => { route.set(next); } };\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hmvc/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { mount, element, type Component, type MountOptions } from '../dom/index.js';\nimport { signal, type Signal, type Disposer } from '../reactivity/index.js';\n\nexport interface RouteLocation {\n readonly url: URL;\n readonly pathname: string;\n readonly params: Readonly<Record<string, string>>;\n readonly query: URLSearchParams;\n readonly hash: string;\n}\nexport interface ModuleContext<M = unknown, C = unknown> {\n readonly route: Pick<Signal<RouteLocation>, 'get'>;\n readonly parent?: ModuleContext;\n readonly model: M;\n readonly controller: C;\n}\nexport interface ModuleDefinition<M, C> {\n model: (context: Pick<ModuleContext, 'route' | 'parent'>) => M;\n controller: (model: M, context: Pick<ModuleContext, 'route' | 'parent'>) => C;\n view: Component;\n}\nexport interface MountedModule {\n readonly context: ModuleContext;\n readonly outlet?: Node;\n readonly dispose: Disposer;\n update(location: RouteLocation): void;\n}\nexport interface AppModule {\n attach(parent: Node, location: RouteLocation, parentContext?: ModuleContext, options?: MountOptions): MountedModule;\n}\nlet current: { context: ModuleContext; outlet?: Node } | undefined;\n\n/** Restore a captured parent context while mounting an asynchronously loaded screen. */\nexport function withModuleContext<T>(context: ModuleContext, run: () => T): T {\n const previous = current;\n current = { context };\n try { return run(); } finally { current = previous; }\n}\n\nexport function useModule<M = unknown, C = unknown>(): ModuleContext<M, C> {\n if (!current) throw new Error('Module context is only available during a module view mount');\n return current.context as ModuleContext<M, C>;\n}\nexport function useController<C = unknown>(): C { return useModule<unknown, C>().controller; }\nexport function useModel<M = unknown>(): M { return useModule<M>().model; }\n\n/** Child route outlet. Import this component in a .hesh layout and call Outlet(). */\nexport function Outlet(parent: Node): void {\n if (!current) throw new Error('Outlet requires a module view');\n if (current.outlet) throw new Error('A module may render only one Outlet');\n current.outlet = element(parent, 'div');\n (current.outlet as HTMLElement).setAttribute('data-hesh-outlet', '');\n}\n\nexport function defineModule<M, C>(definition: ModuleDefinition<M, C>): AppModule {\n return {\n attach(parent, location, parentContext, options) {\n const route = signal(location);\n let state: { context: ModuleContext; outlet?: Node } | undefined;\n const dispose = mount(() => {\n const context = { route: { get: route.get }, parent: parentContext };\n const model = definition.model(context);\n const controller = definition.controller(model, context);\n for (const value of [model, controller]) {\n if (value && typeof (value as { then?: unknown }).then === 'function') throw new Error('HMVC model/controller factories must be synchronous');\n }\n state = { context: { ...context, model, controller } };\n const previous = current;\n current = state;\n try {\n const result: unknown = definition.view(parent);\n if (result && typeof (result as { then?: unknown }).then === 'function') throw new Error('HMVC views must mount synchronously');\n } finally { current = previous; }\n }, parent, options);\n return { context: state!.context, outlet: state!.outlet, dispose, update: next => { route.set(next); } };\n }\n };\n}\n"]}
|
package/dist/parser/index.js
CHANGED
|
@@ -176,7 +176,7 @@ export function parse(source, filename = 'component.hesh') {
|
|
|
176
176
|
const result = { kind: kind.text, name: name.text, start: kind.start, end: 0, fields: Object.create(null), blocks: Object.create(null) };
|
|
177
177
|
const schemas = {
|
|
178
178
|
domain: { implementation: 'string', owns: 'list', exposes: 'list', consumes: 'list', access: 'map' },
|
|
179
|
-
presentation: { html: 'string', logic: 'string', styles: 'string', bindings: 'list', actions: 'list' },
|
|
179
|
+
presentation: { html: 'string', logic: 'string', styles: 'string', bindings: 'list', actions: 'list', parts: 'list' },
|
|
180
180
|
destination: { url: 'string', input: 'map', presentation: 'identifier', access: 'string' },
|
|
181
181
|
application: { domains: 'list', destinations: 'list' }
|
|
182
182
|
};
|
package/dist/parser/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript';\nexport interface Location { start: number; end: number }\nexport interface Expression extends Location { source: string }\nexport interface State extends Location { kind: 'state' | 'const'; name: string; value: Expression }\nexport interface Element extends Location { kind: 'element'; name: string; value?: Expression; handler?: Expression; async: boolean; children: Element[] }\nexport interface View extends Location { name: string; exported: boolean; default: boolean; body: (State | Element)[] }\nexport interface ContractEntry extends Location { name: string; value?: string }\nexport interface Contract extends Location {\n kind: 'domain' | 'presentation' | 'destination' | 'application';\n name: string;\n fields: Record<string, ContractEntry>;\n blocks: Record<string, ContractEntry[]>;\n}\nexport interface Module { source: string; filename: string; imports: Expression[]; views: View[]; contracts?: Contract[] }\nexport interface ParsedModule extends Module { contracts: Contract[] }\nexport class HeshError extends Error {\n readonly line: number;\n readonly column: number;\n constructor(message: string, readonly source: string, readonly offset: number, readonly filename = 'component.hesh') {\n const lines = source.slice(0, offset).split('\\n');\n const line = lines.length, column = lines.at(-1)!.length + 1;\n super(`${filename}:${line}:${column}: ${message}`);\n this.name = 'HeshError'; this.line = line; this.column = column;\n }\n}\nexport interface Token extends Location { text: string; kind: ts.SyntaxKind }\nexport function tokenize(source: string, filename = 'component.hesh'): Token[] {\n const tokens: Token[] = [];\n const keywords = new Set('break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield let static await async'.split(' '));\n let at = 0;\n const fail = (message: string, offset: number): never => { throw new HeshError(message, source, offset, filename); };\n while (at < source.length) {\n const start = at;\n const ch = source[at]!;\n if (/\\s/.test(ch)) { at++; continue; }\n if (source.startsWith('//', at)) { while (at < source.length && source[at] !== '\\n') at++; continue; }\n if (source.startsWith('/*', at)) {\n const end = source.indexOf('*/', at + 2);\n if (end < 0) fail('Unterminated comment', at);\n at = end + 2; continue;\n }\n let kind = ts.SyntaxKind.Unknown;\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n const quote = ch;\n at++; let closed = false;\n while (at < source.length) {\n const current = source[at++]!;\n if (current === '\\\\') { at++; continue; }\n if (quote === '`' && current === '$' && source[at] === '{') fail('Template substitutions belong in imported JS/TS helpers in Milestone 1', at - 1);\n if (current === quote) { closed = true; break; }\n if (quote !== '`' && (current === '\\n' || current === '\\r')) fail('Unterminated string', start);\n }\n if (!closed) fail('Unterminated string', start);\n kind = quote === '`' ? ts.SyntaxKind.NoSubstitutionTemplateLiteral : ts.SyntaxKind.StringLiteral;\n } else if (/[$_\\p{ID_Start}]/u.test(ch)) {\n at++;\n while (at < source.length && /[$\\u200c\\u200d\\p{ID_Continue}]/u.test(source[at]!)) at++;\n kind = keywords.has(source.slice(start, at)) ? ts.SyntaxKind.Unknown : ts.SyntaxKind.Identifier;\n } else if (/\\d/.test(ch)) {\n at++;\n while (at < source.length && /[\\w.]/.test(source[at]!)) at++;\n kind = ts.SyntaxKind.NumericLiteral;\n } else {\n const operator = ['>>>=', '===', '!==', '**=', '&&=', '||=', '??=', '>>>', '<<=', '>>=', '=>', '==', '!=', '<=', '>=', '++', '--', '+=', '-=', '*=', '/=', '%=', '**', '&&', '||', '??', '?.', '<<', '>>', '&=', '|=', '^=', '...'].find(op => source.startsWith(op, at));\n at += operator?.length ?? 1;\n }\n tokens.push({ kind, text: source.slice(start, at), start, end: at });\n }\n return tokens;\n}\n\nexport function parse(source: string, filename = 'component.hesh'): ParsedModule {\n const tokens = tokenize(source, filename);\n let at = 0;\n const peek = () => tokens[at]?.text;\n const fail = (message: string, offset = tokens[at]?.start ?? source.length): never => { throw new HeshError(message, source, offset, filename); };\n const take = (text?: string): Token => {\n const token = tokens[at];\n if (!token || (text !== undefined && token.text !== text)) fail(`Expected ${text ?? 'token'}, received ${peek() ?? 'end of file'}`);\n at++; return token!;\n };\n const identifier = () => {\n const token = take();\n if (token.kind !== ts.SyntaxKind.Identifier) fail('Expected identifier', token.start);\n if (token.text.startsWith('__h')) fail('Identifiers beginning __h are reserved', token.start);\n return token;\n };\n const expression = (ends: string[]): Expression => {\n const start = tokens[at]?.start ?? source.length;\n const stack: string[] = [];\n const pairs: Record<string, string> = { '(': ')', '[': ']', '{': '}' };\n while (tokens[at]) {\n const token = tokens[at]!;\n if (!stack.length && ends.includes(token.text)) break;\n if (pairs[token.text]) stack.push(pairs[token.text]!);\n else if ([')', ']', '}'].includes(token.text)) {\n if (stack.pop() !== token.text) fail('Unbalanced expression', token.start);\n }\n at++;\n }\n if (stack.length) fail('Unterminated expression', start);\n const end = tokens[at]?.start ?? source.length;\n if (!source.slice(start, end).trim()) fail('Expected expression', start);\n return { source: source.slice(start, end).trimEnd(), start, end };\n };\n const element = (): Element => {\n const name = identifier(); take('(');\n let value: Expression | undefined, handler: Expression | undefined, async = false;\n if (peek() !== ')') value = expression([',', ')']);\n if (peek() === ',') {\n take(',');\n if (peek() === 'async') { take(); async = true; }\n const start = take('{').end;\n let depth = 1;\n while (tokens[at] && depth) {\n if (peek() === '{') depth++;\n if (peek() === '}') depth--;\n if (depth) at++;\n }\n if (!tokens[at]) fail('Unterminated event block', start);\n const end = take('}').start;\n handler = { source: source.slice(start, end), start, end };\n }\n take(')');\n const children: Element[] = [];\n if (peek() === '{') { take(); while (peek() && peek() !== '}') children.push(element()); take('}'); if (peek() === ';') take(); }\n else take(';');\n return { kind: 'element', name: name.text, start: name.start, end: tokens[at - 1]!.end, value, handler, async, children };\n };\n const contract = (): Contract => {\n const kind = take(); const name = identifier(); take('{');\n const result: Contract = { kind: kind.text as Contract['kind'], name: name.text, start: kind.start, end: 0, fields: Object.create(null), blocks: Object.create(null) };\n const schemas: Record<Contract['kind'], Record<string, string>> = {\n domain: { implementation: 'string', owns: 'list', exposes: 'list', consumes: 'list', access: 'map' },\n presentation: { html: 'string', logic: 'string', styles: 'string', bindings: 'list', actions: 'list' },\n destination: { url: 'string', input: 'map', presentation: 'identifier', access: 'string' },\n application: { domains: 'list', destinations: 'list' }\n };\n const path = (): ContractEntry => {\n const first = identifier(); let name = first.text;\n while (peek() === '.') { take(); name += '.' + identifier().text; }\n for (const part of name.split('.')) if (['__proto__', 'prototype', 'constructor'].includes(part)) fail('Unsafe contract identifier', first.start);\n return { name, start: first.start, end: tokens[at - 1]!.end };\n };\n const string = () => {\n const token = take();\n if (token.kind !== ts.SyntaxKind.StringLiteral) fail('Expected quoted string', token.start);\n const parsed = ts.createSourceFile('literal.js', token.text, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);\n return ((parsed.statements[0] as ts.ExpressionStatement).expression as ts.StringLiteral).text;\n };\n while (peek() && peek() !== '}') {\n const key = take(); const type = Object.hasOwn(schemas[result.kind], key.text) ? schemas[result.kind][key.text] : undefined;\n if (!type) fail(`Unknown ${result.kind} field ${key.text}`, key.start);\n if (result.fields[key.text] || result.blocks[key.text]) fail(`Duplicate field ${key.text}`, key.start);\n if (type === 'string' || type === 'identifier') {\n take(':'); const value = type === 'string' ? string() : identifier().text; const end = take(';').end;\n result.fields[key.text] = { name: key.text, value, start: key.start, end };\n } else {\n take('{'); const entries: ContractEntry[] = []; const seen = new Set<string>();\n while (peek() && peek() !== '}') {\n const entry = path();\n if (seen.has(entry.name)) fail(`Duplicate entry ${entry.name}`, entry.start); seen.add(entry.name);\n if (type === 'map') { take(':'); entry.value = key.text === 'input' ? identifier().text : string(); }\n entry.end = take(';').end; entries.push(entry);\n }\n take('}'); result.blocks[key.text] = entries;\n }\n }\n result.end = take('}').end;\n return result;\n };\n const module: ParsedModule = { source, filename, imports: [], views: [], contracts: [] };\n while (tokens[at]) {\n if (['domain', 'presentation', 'destination', 'application'].includes(peek() ?? '')) { module.contracts.push(contract()); continue; }\n if (peek() === 'import') {\n if (module.views.length) fail('Imports must precede views');\n const start = take().start;\n while (peek() && peek() !== ';') take();\n const end = take(';').end;\n module.imports.push({ source: source.slice(start, end), start, end }); continue;\n }\n let exported = false, isDefault = false;\n if (peek() === 'export') { take(); exported = true; }\n if (peek() === 'default') { take(); isDefault = true; if (!exported) fail('default requires export'); }\n const start = take('view').start;\n const name = identifier().text; take('{');\n const body: (State | Element)[] = [];\n while (peek() && peek() !== '}') {\n if (peek() === 'const' || tokens[at + 1]?.text === '=') {\n const kind = peek() === 'const' ? (take(), 'const' as const) : 'state' as const;\n const name = identifier(); take('='); const value = expression([';']); const end = take(';').end;\n body.push({ kind, name: name.text, value, start: name.start, end });\n } else body.push(element());\n }\n const end = take('}').end;\n module.views.push({ name, body, start, end, exported, default: isDefault });\n }\n if (!module.views.length && !module.contracts.length) fail('Expected at least one view or architecture declaration');\n return module;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript';\nexport interface Location { start: number; end: number }\nexport interface Expression extends Location { source: string }\nexport interface State extends Location { kind: 'state' | 'const'; name: string; value: Expression }\nexport interface Element extends Location { kind: 'element'; name: string; value?: Expression; handler?: Expression; async: boolean; children: Element[] }\nexport interface View extends Location { name: string; exported: boolean; default: boolean; body: (State | Element)[] }\nexport interface ContractEntry extends Location { name: string; value?: string }\nexport interface Contract extends Location {\n kind: 'domain' | 'presentation' | 'destination' | 'application';\n name: string;\n fields: Record<string, ContractEntry>;\n blocks: Record<string, ContractEntry[]>;\n}\nexport interface Module { source: string; filename: string; imports: Expression[]; views: View[]; contracts?: Contract[] }\nexport interface ParsedModule extends Module { contracts: Contract[] }\nexport class HeshError extends Error {\n readonly line: number;\n readonly column: number;\n constructor(message: string, readonly source: string, readonly offset: number, readonly filename = 'component.hesh') {\n const lines = source.slice(0, offset).split('\\n');\n const line = lines.length, column = lines.at(-1)!.length + 1;\n super(`${filename}:${line}:${column}: ${message}`);\n this.name = 'HeshError'; this.line = line; this.column = column;\n }\n}\nexport interface Token extends Location { text: string; kind: ts.SyntaxKind }\nexport function tokenize(source: string, filename = 'component.hesh'): Token[] {\n const tokens: Token[] = [];\n const keywords = new Set('break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield let static await async'.split(' '));\n let at = 0;\n const fail = (message: string, offset: number): never => { throw new HeshError(message, source, offset, filename); };\n while (at < source.length) {\n const start = at;\n const ch = source[at]!;\n if (/\\s/.test(ch)) { at++; continue; }\n if (source.startsWith('//', at)) { while (at < source.length && source[at] !== '\\n') at++; continue; }\n if (source.startsWith('/*', at)) {\n const end = source.indexOf('*/', at + 2);\n if (end < 0) fail('Unterminated comment', at);\n at = end + 2; continue;\n }\n let kind = ts.SyntaxKind.Unknown;\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n const quote = ch;\n at++; let closed = false;\n while (at < source.length) {\n const current = source[at++]!;\n if (current === '\\\\') { at++; continue; }\n if (quote === '`' && current === '$' && source[at] === '{') fail('Template substitutions belong in imported JS/TS helpers in Milestone 1', at - 1);\n if (current === quote) { closed = true; break; }\n if (quote !== '`' && (current === '\\n' || current === '\\r')) fail('Unterminated string', start);\n }\n if (!closed) fail('Unterminated string', start);\n kind = quote === '`' ? ts.SyntaxKind.NoSubstitutionTemplateLiteral : ts.SyntaxKind.StringLiteral;\n } else if (/[$_\\p{ID_Start}]/u.test(ch)) {\n at++;\n while (at < source.length && /[$\\u200c\\u200d\\p{ID_Continue}]/u.test(source[at]!)) at++;\n kind = keywords.has(source.slice(start, at)) ? ts.SyntaxKind.Unknown : ts.SyntaxKind.Identifier;\n } else if (/\\d/.test(ch)) {\n at++;\n while (at < source.length && /[\\w.]/.test(source[at]!)) at++;\n kind = ts.SyntaxKind.NumericLiteral;\n } else {\n const operator = ['>>>=', '===', '!==', '**=', '&&=', '||=', '??=', '>>>', '<<=', '>>=', '=>', '==', '!=', '<=', '>=', '++', '--', '+=', '-=', '*=', '/=', '%=', '**', '&&', '||', '??', '?.', '<<', '>>', '&=', '|=', '^=', '...'].find(op => source.startsWith(op, at));\n at += operator?.length ?? 1;\n }\n tokens.push({ kind, text: source.slice(start, at), start, end: at });\n }\n return tokens;\n}\n\nexport function parse(source: string, filename = 'component.hesh'): ParsedModule {\n const tokens = tokenize(source, filename);\n let at = 0;\n const peek = () => tokens[at]?.text;\n const fail = (message: string, offset = tokens[at]?.start ?? source.length): never => { throw new HeshError(message, source, offset, filename); };\n const take = (text?: string): Token => {\n const token = tokens[at];\n if (!token || (text !== undefined && token.text !== text)) fail(`Expected ${text ?? 'token'}, received ${peek() ?? 'end of file'}`);\n at++; return token!;\n };\n const identifier = () => {\n const token = take();\n if (token.kind !== ts.SyntaxKind.Identifier) fail('Expected identifier', token.start);\n if (token.text.startsWith('__h')) fail('Identifiers beginning __h are reserved', token.start);\n return token;\n };\n const expression = (ends: string[]): Expression => {\n const start = tokens[at]?.start ?? source.length;\n const stack: string[] = [];\n const pairs: Record<string, string> = { '(': ')', '[': ']', '{': '}' };\n while (tokens[at]) {\n const token = tokens[at]!;\n if (!stack.length && ends.includes(token.text)) break;\n if (pairs[token.text]) stack.push(pairs[token.text]!);\n else if ([')', ']', '}'].includes(token.text)) {\n if (stack.pop() !== token.text) fail('Unbalanced expression', token.start);\n }\n at++;\n }\n if (stack.length) fail('Unterminated expression', start);\n const end = tokens[at]?.start ?? source.length;\n if (!source.slice(start, end).trim()) fail('Expected expression', start);\n return { source: source.slice(start, end).trimEnd(), start, end };\n };\n const element = (): Element => {\n const name = identifier(); take('(');\n let value: Expression | undefined, handler: Expression | undefined, async = false;\n if (peek() !== ')') value = expression([',', ')']);\n if (peek() === ',') {\n take(',');\n if (peek() === 'async') { take(); async = true; }\n const start = take('{').end;\n let depth = 1;\n while (tokens[at] && depth) {\n if (peek() === '{') depth++;\n if (peek() === '}') depth--;\n if (depth) at++;\n }\n if (!tokens[at]) fail('Unterminated event block', start);\n const end = take('}').start;\n handler = { source: source.slice(start, end), start, end };\n }\n take(')');\n const children: Element[] = [];\n if (peek() === '{') { take(); while (peek() && peek() !== '}') children.push(element()); take('}'); if (peek() === ';') take(); }\n else take(';');\n return { kind: 'element', name: name.text, start: name.start, end: tokens[at - 1]!.end, value, handler, async, children };\n };\n const contract = (): Contract => {\n const kind = take(); const name = identifier(); take('{');\n const result: Contract = { kind: kind.text as Contract['kind'], name: name.text, start: kind.start, end: 0, fields: Object.create(null), blocks: Object.create(null) };\n const schemas: Record<Contract['kind'], Record<string, string>> = {\n domain: { implementation: 'string', owns: 'list', exposes: 'list', consumes: 'list', access: 'map' },\n presentation: { html: 'string', logic: 'string', styles: 'string', bindings: 'list', actions: 'list', parts: 'list' },\n destination: { url: 'string', input: 'map', presentation: 'identifier', access: 'string' },\n application: { domains: 'list', destinations: 'list' }\n };\n const path = (): ContractEntry => {\n const first = identifier(); let name = first.text;\n while (peek() === '.') { take(); name += '.' + identifier().text; }\n for (const part of name.split('.')) if (['__proto__', 'prototype', 'constructor'].includes(part)) fail('Unsafe contract identifier', first.start);\n return { name, start: first.start, end: tokens[at - 1]!.end };\n };\n const string = () => {\n const token = take();\n if (token.kind !== ts.SyntaxKind.StringLiteral) fail('Expected quoted string', token.start);\n const parsed = ts.createSourceFile('literal.js', token.text, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);\n return ((parsed.statements[0] as ts.ExpressionStatement).expression as ts.StringLiteral).text;\n };\n while (peek() && peek() !== '}') {\n const key = take(); const type = Object.hasOwn(schemas[result.kind], key.text) ? schemas[result.kind][key.text] : undefined;\n if (!type) fail(`Unknown ${result.kind} field ${key.text}`, key.start);\n if (result.fields[key.text] || result.blocks[key.text]) fail(`Duplicate field ${key.text}`, key.start);\n if (type === 'string' || type === 'identifier') {\n take(':'); const value = type === 'string' ? string() : identifier().text; const end = take(';').end;\n result.fields[key.text] = { name: key.text, value, start: key.start, end };\n } else {\n take('{'); const entries: ContractEntry[] = []; const seen = new Set<string>();\n while (peek() && peek() !== '}') {\n const entry = path();\n if (seen.has(entry.name)) fail(`Duplicate entry ${entry.name}`, entry.start); seen.add(entry.name);\n if (type === 'map') { take(':'); entry.value = key.text === 'input' ? identifier().text : string(); }\n entry.end = take(';').end; entries.push(entry);\n }\n take('}'); result.blocks[key.text] = entries;\n }\n }\n result.end = take('}').end;\n return result;\n };\n const module: ParsedModule = { source, filename, imports: [], views: [], contracts: [] };\n while (tokens[at]) {\n if (['domain', 'presentation', 'destination', 'application'].includes(peek() ?? '')) { module.contracts.push(contract()); continue; }\n if (peek() === 'import') {\n if (module.views.length) fail('Imports must precede views');\n const start = take().start;\n while (peek() && peek() !== ';') take();\n const end = take(';').end;\n module.imports.push({ source: source.slice(start, end), start, end }); continue;\n }\n let exported = false, isDefault = false;\n if (peek() === 'export') { take(); exported = true; }\n if (peek() === 'default') { take(); isDefault = true; if (!exported) fail('default requires export'); }\n const start = take('view').start;\n const name = identifier().text; take('{');\n const body: (State | Element)[] = [];\n while (peek() && peek() !== '}') {\n if (peek() === 'const' || tokens[at + 1]?.text === '=') {\n const kind = peek() === 'const' ? (take(), 'const' as const) : 'state' as const;\n const name = identifier(); take('='); const value = expression([';']); const end = take(';').end;\n body.push({ kind, name: name.text, value, start: name.start, end });\n } else body.push(element());\n }\n const end = take('}').end;\n module.views.push({ name, body, start, end, exported, default: isDefault });\n }\n if (!module.views.length && !module.contracts.length) fail('Expected at least one view or architecture declaration');\n return module;\n}\n"]}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { nativeElement as element, text, attribute, listen } from '../dom/index.js';
|
|
2
2
|
export { element, text, attribute, listen };
|
|
3
|
+
export { mountPart, unitOutlet } from '../units/index.js';
|
|
4
|
+
import type { HeshUnit } from '../units/index.js';
|
|
3
5
|
export interface PresentationState {
|
|
4
6
|
bindings: Record<string, unknown>;
|
|
5
7
|
actions: Record<string, (event: Event) => unknown>;
|
|
8
|
+
parts?: Record<string, HeshUnit>;
|
|
6
9
|
}
|
|
7
10
|
export declare function readBinding(bindings: Record<string, unknown>, path: string): unknown;
|
|
8
11
|
export declare function bindValue(node: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, bindings: Record<string, unknown>, name: string): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { effect } from '../reactivity/index.js';
|
|
2
2
|
import { nativeElement as element, text, attribute, listen } from '../dom/index.js';
|
|
3
3
|
export { element, text, attribute, listen };
|
|
4
|
+
export { mountPart, unitOutlet } from '../units/index.js';
|
|
4
5
|
export function readBinding(bindings, path) {
|
|
5
6
|
const unwrap = (value) => {
|
|
6
7
|
if (typeof value === 'function')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG1D,MAAM,UAAU,WAAW,CAAC,QAAiC,EAAE,IAAY;IACzE,MAAM,MAAM,GAAG,CAAC,KAAc,EAAW,EAAE;QACzC,IAAI,OAAO,KAAK,KAAK,UAAU;YAAE,OAAO,KAAK,EAAE,CAAC;QAChD,IAAI,KAAK,IAAI,OAAQ,KAA2B,CAAC,GAAG,KAAK,UAAU;YAAE,OAAQ,KAA4B,CAAC,GAAG,EAAE,CAAC;QAChH,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,IAAI,KAAK,GAAY,QAAQ,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrG,KAAK,GAAI,MAAM,CAAC,KAAK,CAAoC,EAAE,CAAC,IAAI,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,IAAgE,EAAE,QAAiC,EAAE,IAAY;IACzI,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAoD,CAAC;IAChF,IAAI,OAAO,KAAK,EAAE,GAAG,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,6BAA6B,CAAC,CAAC;IACvI,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;QAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1G,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACtD,CAAC;AACD,MAAM,UAAU,UAAU,CAAC,IAAiB,EAAE,KAAwB,EAAE,IAAY;IAClF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,OAAO,OAAO,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,EAAE,CAAC,CAAC;IAC1F,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;QACjE,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;YAAE,KAAK,CAAC,cAAc,EAAE,CAAC;QACpD,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { effect } from '../reactivity/index.js';\nimport { nativeElement as element, text, attribute, listen } from '../dom/index.js';\nexport { element, text, attribute, listen };\nexport { mountPart, unitOutlet } from '../units/index.js';\nimport type { HeshUnit } from '../units/index.js';\nexport interface PresentationState { bindings: Record<string, unknown>; actions: Record<string, (event: Event) => unknown>; parts?: Record<string, HeshUnit> }\nexport function readBinding(bindings: Record<string, unknown>, path: string): unknown {\n const unwrap = (value: unknown): unknown => {\n if (typeof value === 'function') return value();\n if (value && typeof (value as { get?: unknown }).get === 'function') return (value as { get(): unknown }).get();\n return value;\n };\n let value: unknown = bindings;\n for (const part of path.split('.')) {\n if (['__proto__', 'constructor', 'prototype'].includes(part)) throw new Error('Unsafe binding path');\n value = (unwrap(value) as Record<string, unknown> | null)?.[part];\n }\n return unwrap(value);\n}\nexport function bindValue(node: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, bindings: Record<string, unknown>, name: string): void {\n const state = bindings[name] as { get?(): unknown; set?(value: unknown): void };\n if (typeof state?.get !== 'function' || typeof state.set !== 'function') throw new Error(`h-value ${name} requires a writable signal`);\n effect(() => { const value = String(state.get!() ?? ''); if (node.value !== value) node.value = value; });\n listen(node, 'input', () => state.set!(node.value));\n}\nexport function bindAction(node: HTMLElement, state: PresentationState, name: string): void {\n const handler = state.actions[name];\n if (typeof handler !== 'function') throw new Error(`Missing presentation action ${name}`);\n listen(node, node.tagName === 'FORM' ? 'submit' : 'click', event => {\n if (node.tagName === 'FORM') event.preventDefault();\n return handler.call(state.actions, event);\n });\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AppModule, type ModuleContext } from '../hmvc/index.js';
|
|
2
|
+
import type { PresentationState } from '../presentation/index.js';
|
|
3
|
+
export type HeshUnit = AppModule;
|
|
4
|
+
export interface UnitDefinition<S, A extends PresentationState> {
|
|
5
|
+
state(context: Pick<ModuleContext, 'route' | 'parent'>): S;
|
|
6
|
+
actions(state: S, context: Pick<ModuleContext, 'route' | 'parent'>): A;
|
|
7
|
+
screen(parent: Node, state: A, destinations?: object): void;
|
|
8
|
+
destinations?: object;
|
|
9
|
+
}
|
|
10
|
+
/** Hesh naming over the hierarchical, scope-owned module lifecycle. */
|
|
11
|
+
export declare function defineUnit<S, A extends PresentationState>(definition: UnitDefinition<S, A>): HeshUnit;
|
|
12
|
+
export declare function mountPart(parent: Node, state: PresentationState, name: string): void;
|
|
13
|
+
export { Outlet as unitOutlet, useModule as useUnit, useModel as useUnitState, useController as useUnitActions } from '../hmvc/index.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineModule, useController, useModule } from '../hmvc/index.js';
|
|
2
|
+
/** Hesh naming over the hierarchical, scope-owned module lifecycle. */
|
|
3
|
+
export function defineUnit(definition) {
|
|
4
|
+
return defineModule({ model: definition.state, controller: definition.actions,
|
|
5
|
+
view(parent) { definition.screen(parent, useController(), definition.destinations); }
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
export function mountPart(parent, state, name) {
|
|
9
|
+
const part = state.parts?.[name];
|
|
10
|
+
if (!part || typeof part.attach !== 'function')
|
|
11
|
+
throw new Error(`Missing Hesh part ${name}`);
|
|
12
|
+
const context = useModule();
|
|
13
|
+
part.attach(parent, context.route.get(), context);
|
|
14
|
+
}
|
|
15
|
+
export { Outlet as unitOutlet, useModule as useUnit, useModel as useUnitState, useController as useUnitActions } from '../hmvc/index.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/units/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAA8C,MAAM,kBAAkB,CAAC;AAUtH,uEAAuE;AACvE,MAAM,UAAU,UAAU,CAAiC,UAAgC;IACzF,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,OAAO;QAC3E,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAK,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;KACzF,CAAC,CAAC;AACL,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,MAAY,EAAE,KAAwB,EAAE,IAAY;IAC5E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC;AACD,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,SAAS,IAAI,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,aAAa,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC","sourcesContent":["import { defineModule, useController, useModule, Outlet, type AppModule, type ModuleContext } from '../hmvc/index.js';\nimport type { PresentationState } from '../presentation/index.js';\n\nexport type HeshUnit = AppModule;\nexport interface UnitDefinition<S, A extends PresentationState> {\n state(context: Pick<ModuleContext, 'route' | 'parent'>): S;\n actions(state: S, context: Pick<ModuleContext, 'route' | 'parent'>): A;\n screen(parent: Node, state: A, destinations?: object): void;\n destinations?: object;\n}\n/** Hesh naming over the hierarchical, scope-owned module lifecycle. */\nexport function defineUnit<S, A extends PresentationState>(definition: UnitDefinition<S, A>): HeshUnit {\n return defineModule({ model: definition.state, controller: definition.actions,\n view(parent) { definition.screen(parent, useController<A>(), definition.destinations); }\n });\n}\nexport function mountPart(parent: Node, state: PresentationState, name: string): void {\n const part = state.parts?.[name];\n if (!part || typeof part.attach !== 'function') throw new Error(`Missing Hesh part ${name}`);\n const context = useModule();\n part.attach(parent, context.route.get(), context);\n}\nexport { Outlet as unitOutlet, useModule as useUnit, useModel as useUnitState, useController as useUnitActions } from '../hmvc/index.js';\n"]}
|
package/docs/contracts.md
CHANGED
|
@@ -15,7 +15,8 @@ presentation = "presentation", Identifier, "{",
|
|
|
15
15
|
"html", ":", String, ";", "logic", ":", String, ";",
|
|
16
16
|
[ "styles", ":", String, ";" ],
|
|
17
17
|
"bindings", "{", { Identifier, ";" }, "}",
|
|
18
|
-
"actions", "{", { Identifier, ";" }, "}",
|
|
18
|
+
"actions", "{", { Identifier, ";" }, "}",
|
|
19
|
+
[ "parts", "{", { Identifier, ";" }, "}" ], "}" ;
|
|
19
20
|
destination = "destination", Identifier, "{",
|
|
20
21
|
"url", ":", String, ";",
|
|
21
22
|
"input", "{", { Identifier, ":", ("string" | "number" | "boolean"), ";" }, "}",
|
|
@@ -51,6 +52,12 @@ No arbitrary JS expressions, raw HTML, inline event attributes, script elements,
|
|
|
51
52
|
h-each, h-key or unknown h-* directives are accepted in this first milestone.
|
|
52
53
|
Use normal CSS files; template scoping and keyed template lists remain deferred.
|
|
53
54
|
|
|
55
|
+
Standalone presentations also compile to reusable HTML screens. `h-outlet` on an
|
|
56
|
+
empty container creates the persistent shell's destination outlet (not permitted
|
|
57
|
+
inside destination screens). `h-part="Badge"` mounts a declared nested Hesh Unit
|
|
58
|
+
from the factory's `parts.Badge`. Parts inherit the parent context and disposal
|
|
59
|
+
scope. A container may have only one of h-bind, h-outlet or h-part and no children.
|
|
60
|
+
|
|
54
61
|
Destination URL params must exactly match input names. Values are encoded/decoded
|
|
55
62
|
once; number inputs must be finite and booleans serialize as true/false. Duplicate
|
|
56
63
|
or structurally conflicting URL destinations are errors. Generated declarations
|
package/docs/units.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Unified HeshJS 0.5
|
|
2
|
+
|
|
3
|
+
Use Node 22.12 or later:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx @heshammesalam/heshjs@latest create
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Choose your folder and JavaScript or TypeScript. JavaScript is the default.
|
|
10
|
+
For automation: `npx @heshammesalam/heshjs@latest create my-site --ts`.
|
|
11
|
+
Run `cd my-site`, `npm install`, then `npm run dev`.
|
|
12
|
+
|
|
13
|
+
Only `@heshammesalam/heshjs` is needed for Hesh runtime/compiler/CLI features.
|
|
14
|
+
Vite is the build tool; TypeScript is included in typed project development dependencies.
|
|
15
|
+
The former `create-heshjs` package is a legacy entry point. Do not use `npm create`:
|
|
16
|
+
that convention resolves a separate creator package. Use the unified npx command.
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
src/
|
|
20
|
+
app.hesh
|
|
21
|
+
hesh-units/
|
|
22
|
+
identity/
|
|
23
|
+
unit.hesh
|
|
24
|
+
state.js # .ts in typed projects
|
|
25
|
+
actions.js
|
|
26
|
+
parts/login/
|
|
27
|
+
state.js
|
|
28
|
+
actions.js
|
|
29
|
+
screen.html
|
|
30
|
+
workspace/
|
|
31
|
+
unit.hesh
|
|
32
|
+
state.js
|
|
33
|
+
actions.js
|
|
34
|
+
parts/home/...
|
|
35
|
+
parts/about/...
|
|
36
|
+
parts/counter/parts/detail/...
|
|
37
|
+
foundation/shell/
|
|
38
|
+
unit.hesh
|
|
39
|
+
unit.js
|
|
40
|
+
state.js
|
|
41
|
+
actions.js
|
|
42
|
+
screen.html
|
|
43
|
+
parts/badge/
|
|
44
|
+
unit.js
|
|
45
|
+
state.js
|
|
46
|
+
actions.js
|
|
47
|
+
screen.html
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Hesh Units preserve hierarchical MVC ownership with Hesh-specific names. State
|
|
51
|
+
corresponds to the model, actions to the controller, and screen to the view.
|
|
52
|
+
`defineUnit` composes these using the same scope/parent/lifetime machinery as
|
|
53
|
+
`defineModule`. `h-part="Badge"` mounts an explicitly declared child unit and
|
|
54
|
+
disposes its state effects, DOM and listeners with its parent. Instances have
|
|
55
|
+
independent state. `h-outlet` mounts the SPA destination outlet inside a persistent
|
|
56
|
+
shell; it is not permitted inside asynchronous destination screens.
|
|
57
|
+
|
|
58
|
+
Every starter UI screen is ordinary HTML, including shell and badge. `.hesh`
|
|
59
|
+
files declare Domain Graph contracts; generated `.hesh-generated` JS and type
|
|
60
|
+
declarations are compiler output. Existing brace views and `/hmvc` APIs remain
|
|
61
|
+
available for compatibility. Domain Graph controls business dependencies and
|
|
62
|
+
typed destinations; HTML units control hierarchy and ownership.
|
|
63
|
+
|
|
64
|
+
Use `npm run check` for architecture checks (plus strict tsc in typed projects),
|
|
65
|
+
`npm run graph` for dependencies, and `npm run build` for production. The supplied
|
|
66
|
+
logo is bundled locally and used as favicon. The session is an in-memory demo;
|
|
67
|
+
production authorization needs server enforcement. Configure the production host
|
|
68
|
+
to serve index.html for app URLs while serving real static assets normally.
|
|
69
|
+
|
|
70
|
+
Unsupported features remain unsupported: SSR, Journeys, deep reactivity and
|
|
71
|
+
keyed HTML template lists. Native HTML bindings accept data paths, not arbitrary JS.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heshammesalam/heshjs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Independent reactive UI framework with HTML screens, hierarchical Hesh Units, Domain Graph and an integrated project CLI",
|
|
5
5
|
"author": "Hesham",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"type": "module",
|
|
@@ -16,13 +16,14 @@
|
|
|
16
16
|
"./vite": { "types": "./dist/vite/index.d.ts", "import": "./dist/vite/index.js" },
|
|
17
17
|
"./router": { "types": "./dist/router/index.d.ts", "import": "./dist/router/index.js" },
|
|
18
18
|
"./hmvc": { "types": "./dist/hmvc/index.d.ts", "import": "./dist/hmvc/index.js" },
|
|
19
|
+
"./units": { "types": "./dist/units/index.d.ts", "import": "./dist/units/index.js" },
|
|
19
20
|
"./domains": { "types": "./dist/domains/index.d.ts", "import": "./dist/domains/index.js" },
|
|
20
21
|
"./destinations": { "types": "./dist/destinations/index.d.ts", "import": "./dist/destinations/index.js" },
|
|
21
22
|
"./presentation": { "types": "./dist/presentation/index.d.ts", "import": "./dist/presentation/index.js" },
|
|
22
23
|
"./architecture": { "types": "./dist/architecture/index.d.ts", "import": "./dist/architecture/index.js" },
|
|
23
24
|
"./package.json": "./package.json"
|
|
24
25
|
},
|
|
25
|
-
"files": ["dist", "src", "docs", "README.md", "cli.js"],
|
|
26
|
+
"files": ["dist", "src", "docs", "README.md", "cli.js", "scaffold"],
|
|
26
27
|
"bin": { "hesh": "./cli.js" },
|
|
27
28
|
"engines": { "node": ">=22.12.0" },
|
|
28
29
|
"dependencies": { "typescript": "~5.9.3", "parse5": "8.1.0" },
|
|
Binary file
|