coralite 0.37.2 → 0.38.1
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 +18 -14
- package/bin/coralite.js +5 -2
- package/dist/lib/compiler.d.ts +1 -3
- package/dist/lib/compiler.d.ts.map +1 -1
- package/dist/lib/component-setup.d.ts.map +1 -1
- package/dist/lib/coralite-element.d.ts +2 -2
- package/dist/lib/coralite-element.d.ts.map +1 -1
- package/dist/lib/coralite-element.js +4 -5
- package/dist/lib/coralite-element.js.map +2 -2
- package/dist/lib/hooks.d.ts +8 -10
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/index.js +862 -580
- package/dist/lib/index.js.map +3 -3
- package/dist/lib/parser.d.ts.map +1 -1
- package/dist/lib/plugin-setup.d.ts.map +1 -1
- package/dist/lib/plugin.d.ts +16 -10
- package/dist/lib/plugin.d.ts.map +1 -1
- package/dist/lib/plugin.js +8 -2
- package/dist/lib/plugin.js.map +2 -2
- package/dist/lib/renderer.d.ts.map +1 -1
- package/dist/lib/script-manager.d.ts +11 -13
- package/dist/lib/script-manager.d.ts.map +1 -1
- package/dist/lib/utils/client/inject.js +173 -0
- package/dist/lib/utils/client/inject.js.map +7 -0
- package/dist/lib/utils/client/runtime.d.ts.map +1 -1
- package/dist/lib/utils/server/html.d.ts +6 -2
- package/dist/lib/utils/server/html.d.ts.map +1 -1
- package/dist/lib/utils/server/server.d.ts +1 -4
- package/dist/lib/utils/server/server.d.ts.map +1 -1
- package/dist/plugins/metadata.d.ts.map +1 -1
- package/dist/plugins/testing.d.ts.map +1 -1
- package/dist/types/core.d.ts +9 -1
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/plugin.d.ts +14 -5
- package/dist/types/plugin.d.ts.map +1 -1
- package/dist/types/script.d.ts +7 -11
- package/dist/types/script.d.ts.map +1 -1
- package/llms.txt +35 -32
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
Coralite is a **Native-First**, strictly Server-Side Rendered (SSR) framework for building fast, accessible, and future-proof websites.
|
|
10
10
|
|
|
11
11
|
- **True Native Web Components with a "Flat" API**
|
|
12
|
-
No vanilla boilerplate. Use a clean `defineComponent` flat-options API (`attributes`, `
|
|
12
|
+
No vanilla boilerplate. Use a clean `defineComponent` flat-options API (`attributes`, `server`, `getters`, `client`) to build powerful Custom Elements without the `class extends HTMLElement` friction.
|
|
13
13
|
- **The "Smart State, Dumb Template" Paradigm**
|
|
14
14
|
Templates are strictly declarative and "dumb"—no logic loops or dot-notation in HTML. All logic lives in pure JavaScript `getters` which receive a safe, Read-Only Proxy.
|
|
15
15
|
- **Scoped CSS without Shadow DOM**
|
|
16
16
|
Enjoy perfect style encapsulation using standard CSS. The Coralite compiler automatically injects unique instance identifiers and nests rules, avoiding the accessibility and global styling headaches of Shadow DOM.
|
|
17
17
|
- **Native Async Race-Condition Immunity**
|
|
18
|
-
Coralite's reactive engine handles asynchronous `
|
|
18
|
+
Coralite's reactive engine handles asynchronous `server()` and `getters` with built-in version locks, ensuring your DOM never renders stale data from out-of-order Promise resolutions.
|
|
19
19
|
- **Isomorphic, Two-Phase Curried Plugins**
|
|
20
20
|
Extend the engine with a strict, typed boundary. Plugins use a two-phase currying pattern to inject heavy context during initialization, leaving you with a clean, scoped API at runtime.
|
|
21
21
|
|
|
@@ -147,8 +147,8 @@ Styles defined in the `<style>` block are automatically **scoped** to the compon
|
|
|
147
147
|
role: { type: String, default: 'Guest' }
|
|
148
148
|
},
|
|
149
149
|
|
|
150
|
-
//
|
|
151
|
-
async
|
|
150
|
+
// SERVER: Async server-side fetching (Stripped from client bundle)
|
|
151
|
+
async server({ state }) {
|
|
152
152
|
const user = await userService.getById(state.userId)
|
|
153
153
|
return {
|
|
154
154
|
firstName: user.firstName,
|
|
@@ -163,8 +163,8 @@ Styles defined in the `<style>` block are automatically **scoped** to the compon
|
|
|
163
163
|
userMeta: (state) => `Role: ${state.role} | ID: ${state.userId}`
|
|
164
164
|
},
|
|
165
165
|
|
|
166
|
-
//
|
|
167
|
-
|
|
166
|
+
// CLIENT: Client-side controller (Read/Write Proxy)
|
|
167
|
+
client({ state, refs, signal }) {
|
|
168
168
|
// Use the 'refs' utility to get the unique DOM element
|
|
169
169
|
const titleEl = refs('title')
|
|
170
170
|
|
|
@@ -193,10 +193,12 @@ export default function myPlugin(options = {}) {
|
|
|
193
193
|
name: 'my-plugin',
|
|
194
194
|
|
|
195
195
|
server: {
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
196
|
+
// Symmetrical context: available in defineComponent server block
|
|
197
|
+
context: (pluginContext) => {
|
|
198
|
+
return {
|
|
199
|
+
getData: (query) => {
|
|
200
|
+
return { custom: 'data' }
|
|
201
|
+
}
|
|
200
202
|
}
|
|
201
203
|
},
|
|
202
204
|
onBeforeComponentRender: ({ state }) => {
|
|
@@ -205,10 +207,12 @@ export default function myPlugin(options = {}) {
|
|
|
205
207
|
},
|
|
206
208
|
|
|
207
209
|
client: {
|
|
208
|
-
// Injects
|
|
209
|
-
context: {
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
// Injects context helpers directly into the component's client block
|
|
211
|
+
context: (pluginContext) => (instanceContext) => {
|
|
212
|
+
return {
|
|
213
|
+
myHelper: () => {
|
|
214
|
+
console.log('Hello from component', instanceContext.instanceId)
|
|
215
|
+
}
|
|
212
216
|
}
|
|
213
217
|
}
|
|
214
218
|
}
|
package/bin/coralite.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --experimental-vm-modules --experimental-import-meta-resolve
|
|
2
2
|
|
|
3
|
-
import { createCoralite } from '../lib/index.js'
|
|
3
|
+
import { createCoralite } from '../dist/lib/index.js'
|
|
4
4
|
import { Command } from 'commander'
|
|
5
5
|
import kleur from 'kleur'
|
|
6
6
|
import { pathToFileURL } from 'node:url'
|
|
7
7
|
import { join } from 'node:path'
|
|
8
8
|
import { existsSync } from 'node:fs'
|
|
9
|
+
import pkg from '../package.json' with { type: 'json' }
|
|
9
10
|
|
|
10
11
|
// remove all Node warnings before doing anything else
|
|
11
12
|
process.removeAllListeners('warning')
|
|
@@ -15,7 +16,7 @@ const program = new Command()
|
|
|
15
16
|
program
|
|
16
17
|
.name('Coralite')
|
|
17
18
|
.description('HTML modules static site generator CLI tool')
|
|
18
|
-
.version(
|
|
19
|
+
.version(pkg.version)
|
|
19
20
|
.requiredOption('-c, --components <path>', 'Path to components directory')
|
|
20
21
|
.requiredOption('-p, --pages <path>', 'Path to pages directory')
|
|
21
22
|
.requiredOption('-o, --output <path>', 'Output directory for the generated site')
|
|
@@ -137,3 +138,5 @@ if (options.dryRun) {
|
|
|
137
138
|
// save the generated documents to output directory
|
|
138
139
|
await coralite.save()
|
|
139
140
|
}
|
|
141
|
+
|
|
142
|
+
await coralite.clearCache(true)
|
package/dist/lib/compiler.d.ts
CHANGED
|
@@ -5,15 +5,13 @@
|
|
|
5
5
|
* @param {CoraliteFilePath} options.path - The file path metadata of the component
|
|
6
6
|
* @param {CoralitePluginContext} options.context - Contextual rendering data
|
|
7
7
|
* @param {Object} options.source - Framework source context
|
|
8
|
-
* @param {Object} options.plugins - Bound plugins
|
|
9
8
|
* @param {Function} options.importModuleDynamically - The dynamic import callback
|
|
10
9
|
* @returns {(specifier: string, referencingModule: Module, extra: { attributes: any }) => Promise<Module>}
|
|
11
10
|
*/
|
|
12
|
-
export function createModuleLinker({ path, context, source,
|
|
11
|
+
export function createModuleLinker({ path, context, source, importModuleDynamically }: {
|
|
13
12
|
path: CoraliteFilePath;
|
|
14
13
|
context: CoralitePluginContext;
|
|
15
14
|
source: any;
|
|
16
|
-
plugins: any;
|
|
17
15
|
importModuleDynamically: Function;
|
|
18
16
|
}): (specifier: string, referencingModule: Module, extra: {
|
|
19
17
|
attributes: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../lib/compiler.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../lib/compiler.js"],"names":[],"mappings":"AAiBA;;;;;;;;;GASG;AACH,uFANG;IAAkC,IAAI,EAA9B,gBAAgB;IACe,OAAO,EAAtC,qBAAqB;IACL,MAAM;IACJ,uBAAuB;CACjD,GAAU,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,UAAU,EAAE,GAAG,CAAA;CAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAwFzG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,mLAhBG;IAAgC,MAAM,EAA9B,cAAc;IACqB,KAAK,EAAxC,yBAAyB;IACH,IAAI,EAA1B,YAAY;IACC,IAAI,EAAjB,GAAG;IACa,SAAS,EAAzB,MAAM;IACmB,OAAO,EAAhC,eAAe;IACE,WAAW,EAA5B,OAAO;IACS,GAAG;IACH,MAAM;IACJ,WAAW;IACX,eAAe;IACf,oBAAoB;IACpB,YAAY;CAEtC,GAAU,OAAO,CAAC,yBAAyB,CAAC,CAmI9C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,kLAhBG;IAAgC,MAAM,EAA9B,cAAc;IACqB,KAAK,EAAxC,yBAAyB;IACH,IAAI,EAA1B,YAAY;IACC,IAAI,EAAjB,GAAG;IACa,SAAS,EAAzB,MAAM;IACmB,OAAO,EAAhC,eAAe;IACE,WAAW,EAA5B,OAAO;IACS,GAAG;IACH,MAAM;IACJ,WAAW;IACX,eAAe;IACf,oBAAoB;IACpB,YAAY;CAEtC,GAAU,OAAO,CAAC,yBAAyB,CAAC,CA8H9C;AAED;;;GAGG;AACH,kCAFW,GAAG,sCAOb;sCA5ZqI,mBAAmB;2CAAnB,mBAAmB;4BAC9H,SAAS;oCADkG,mBAAmB;+CAAnB,mBAAmB;kCAAnB,mBAAmB;qCAAnB,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-setup.d.ts","sourceRoot":"","sources":["../../lib/component-setup.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,mDAHG;IAAuC,GAAG,EAAlC,gBAAgB;CACxB,YA2MF;AAED;;;;;;;;;;;GAWG;AACH,mGAPG;IAAqB,SAAS,EAAtB,GAAG;IACe,QAAQ;IACb,aAAa,EAA1B,GAAG;IACe,aAAa;IACf,IAAI,EAApB,MAAM;CACd,GAAU,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"component-setup.d.ts","sourceRoot":"","sources":["../../lib/component-setup.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,mDAHG;IAAuC,GAAG,EAAlC,gBAAgB;CACxB,YA2MF;AAED;;;;;;;;;;;GAWG;AACH,mGAPG;IAAqB,SAAS,EAAtB,GAAG;IACe,QAAQ;IACb,aAAa,EAA1B,GAAG;IACe,aAAa;IACf,IAAI,EAApB,MAAM;CACd,GAAU,OAAO,CAAC,IAAI,CAAC,CA2HzB;sCA1VS,mBAAmB"}
|
|
@@ -30,7 +30,7 @@ export function createCoraliteClass(options: CoraliteComponentOptions, contextGe
|
|
|
30
30
|
* @property {Object} [attributes] - Schema for coercing HTML attributes into typed primitives.
|
|
31
31
|
* @property {Object.<string, Function>} [getters] - Pure functions for derived state, supporting Promises.
|
|
32
32
|
* @property {Object.<string, Function>} [slots] - Transformation functions for projected Light DOM.
|
|
33
|
-
* @property {Function} [
|
|
33
|
+
* @property {Function} [client] - The client-side controller logic.
|
|
34
34
|
* @property {Object} [hydrationMap] - AST mapping for reactive text nodes, attributes, and refs.
|
|
35
35
|
*/
|
|
36
36
|
/**
|
|
@@ -231,7 +231,7 @@ export type CoraliteComponentOptions = {
|
|
|
231
231
|
/**
|
|
232
232
|
* - The client-side controller logic.
|
|
233
233
|
*/
|
|
234
|
-
|
|
234
|
+
client?: Function;
|
|
235
235
|
/**
|
|
236
236
|
* - AST mapping for reactive text nodes, attributes, and refs.
|
|
237
237
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coralite-element.d.ts","sourceRoot":"","sources":["../../lib/coralite-element.js"],"names":[],"mappings":"AAuCA;;;;;;GAMG;AACH,8BAJW,GAAG,QACH,WAAS,MAAM,GACb,GAAG,CAmBf;
|
|
1
|
+
{"version":3,"file":"coralite-element.d.ts","sourceRoot":"","sources":["../../lib/coralite-element.js"],"names":[],"mappings":"AAuCA;;;;;;GAMG;AACH,8BAJW,GAAG,QACH,WAAS,MAAM,GACb,GAAG,CAmBf;AAkmBD;;;;;;;;;;GAUG;AACH,6CARW,wBAAwB,kBACxB,WAAS,IAAI,UAErB;IAAyE,uBAAuB,GAAxF,KAAK,CAAC,iDAAiD,CAAC;IACQ,sBAAsB,GAAtF,KAAK,CAAC,gDAAgD,CAAC;IACC,cAAc,GAAtE,KAAK,CAAC,wCAAwC,CAAC;CACvD,GAAU,OAAO,eAAe,CA8BlC;AAvoBD;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH;IAOI;;;;OAIG;IACH,4BAHU,eAAe,GAAC,IAAI,CAGF;IAE5B;;;;OAIG;IACH,uBAHU,MAAM,GAAC,IAAI,CAGE;IAEvB;;;;OAIG;IACH,kBAHU,MAAO,IAAI,CAGH;IAElB;;;;OAIG;IACH,qBAHU,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAG1D;IAEnB;;;;OAIG;IACH,4BAHU,OAAO,CAGY;IAE7B;;;;OAIG;IACH,iCAHU,MAAM,GAAC,IAAI,CAGY;IAEjC;;;OAGG;IACH,qBAHU,gBAAgB,GAAC,IAAI,CAGV;IAErB;;;;OAIG;IACH,gCAHU,WAAS,IAAI,CAGS;IAEhC;;;;OAIG;IACH,mCAHU;YAAQ,MAAM,GAAE,eAAe;KAAC,GAAC,IAAI,CAGZ;IAEnC;;;;;;;;OAQG;IACH,kBAPU;QACL,uBAAuB,EAAE,KAAK,CAAC,iDAAiD,CAAC,CAAC;QAClF,sBAAsB,EAAE,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChF,cAAc,EAAE,KAAK,CAAC,wCAAwC,CAAC,CAAA;KAChE,CAOH;IAED;;;OAGG;IACH,kBAFU,wBAAwB,GAAC,IAAI,CAEX;IAG9B;;;;OAIG;IACH,0BAsDC;IAED;;;;;OAKG;IACH,sCAkBC;IAED;;;;;;;OAOG;IACH,+BAJW,MAAM,UACN,MAAM,GAAC,IAAI,UACX,MAAM,GAAC,IAAI,QAWrB;IAED;;;;;;OAMG;IACH,oBAkFC;IAED;;;;;;OAMG;IACH,6BAYC;IAED;;;;;OAKG;IACH,oBAHW,MAAM,EAAE,GACN,IAAI,GAAC,IAAI,CAYrB;IAED;;;;OAIG;IACH,uBAiCC;IAED;;;;OAIG;IACH,wBASC;IAED;;;;;;;OAOG;IACH,mBA2GC;IAED;;;;OAIG;IACH,sBAqCC;IAED;;;;;;OAMG;IACH,cAqCC;CACF;;;;;iBA5lBa,MAAM;;;;mBACN,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uEA/DV,oBAAoB;sEAApB,oBAAoB;8DAApB,oBAAoB"}
|
|
@@ -505,7 +505,7 @@ var CoraliteElement = class extends HTMLElement {
|
|
|
505
505
|
*/
|
|
506
506
|
async _init(isImperative = false) {
|
|
507
507
|
const self = this;
|
|
508
|
-
|
|
508
|
+
let localContext = {
|
|
509
509
|
instanceId: this._instanceId,
|
|
510
510
|
state: this._state,
|
|
511
511
|
root: this,
|
|
@@ -519,17 +519,16 @@ var CoraliteElement = class extends HTMLElement {
|
|
|
519
519
|
}
|
|
520
520
|
};
|
|
521
521
|
if (typeof this._clientContextGetter === "function") {
|
|
522
|
-
|
|
523
|
-
Object.assign(localContext, pluginContext);
|
|
522
|
+
localContext = await this._clientContextGetter(localContext);
|
|
524
523
|
}
|
|
525
524
|
if (isImperative) {
|
|
526
525
|
this._updateDOM();
|
|
527
526
|
} else {
|
|
528
527
|
this._scheduleUpdate();
|
|
529
528
|
}
|
|
530
|
-
if (this.componentOptions.
|
|
529
|
+
if (this.componentOptions.client) {
|
|
531
530
|
try {
|
|
532
|
-
this.componentOptions.
|
|
531
|
+
this.componentOptions.client(localContext);
|
|
533
532
|
} catch (error) {
|
|
534
533
|
console.error(`Coralite Error: Component "${this.componentOptions.componentId}" script failed:`, error);
|
|
535
534
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../lib/utils/errors.js", "../../lib/utils/core.js", "../../lib/coralite-element.js"],
|
|
4
|
-
"sourcesContent": ["\n/**\n * @import { CoraliteErrorData } from '../../types/index.js'\n */\n\n/**\n * Base error class for all Coralite-related errors.\n */\nexport class CoraliteError extends Error {\n /**\n * @param {string} message - The error message.\n * @param {Object} [options] - Additional options for the error.\n * @param {string} [options.componentId] - The ID of the component where the error occurred.\n * @param {string} [options.filePath] - The path to the file where the error occurred.\n * @param {string} [options.instanceId] - The unique ID of the component instance.\n * @param {string} [options.pagePath] - The path to the page being rendered.\n * @param {number} [options.line] - The line number where the error occurred.\n * @param {number} [options.column] - The column number where the error occurred.\n * @param {string} [options.stackFile] - The file name from the stack trace.\n * @param {Error} [options.cause] - The original error that caused this error.\n */\n constructor (message, options = {}) {\n super(message, options)\n this.name = 'CoraliteError'\n this.isCoraliteError = true\n this.componentId = options.componentId\n this.filePath = options.filePath\n this.instanceId = options.instanceId\n this.pagePath = options.pagePath\n this.line = options.line\n this.column = options.column\n this.stackFile = options.stackFile\n\n // Polyfill cause if necessary (node version differences)\n if (options.cause && !this.cause) {\n this.cause = options.cause\n }\n }\n}\n\n/**\n * Default error handler.\n * @param {CoraliteErrorData} data - The data object containing error details.\n */\nexport function defaultOnError ({ level, message, error }) {\n if (level === 'ERR') {\n if (error) {\n throw error\n }\n throw new CoraliteError(message)\n } else if (level === 'WARN') {\n console.warn(message)\n } else {\n console.log(message)\n }\n}\n\n/**\n * Handles errors using an optional callback or the default handler.\n * @param {Object} options - The options for handling the error.\n * @param {Function} [options.onErrorCallback] - The optional custom error callback function.\n * @param {CoraliteErrorData} options.data - The error data to be handled.\n */\nexport function handleError ({ onErrorCallback, data }) {\n const error = data.error\n if (error && 'isCoraliteError' in error && error.isCoraliteError) {\n const coraliteError = error\n // @ts-ignore\n data.componentId = data.componentId || coraliteError.componentId\n // @ts-ignore\n data.filePath = data.filePath || coraliteError.filePath\n // @ts-ignore\n data.instanceId = data.instanceId || coraliteError.instanceId\n // @ts-ignore\n data.pagePath = data.pagePath || coraliteError.pagePath\n // @ts-ignore\n data.line = data.line || coraliteError.line\n // @ts-ignore\n data.column = data.column || coraliteError.column\n // @ts-ignore\n data.stackFile = data.stackFile || coraliteError.stackFile\n }\n\n if (onErrorCallback) {\n onErrorCallback(data)\n } else {\n defaultOnError(data)\n }\n}\n", "import { CoraliteError } from './errors.js'\n\n/**\n * @import {\n * CoraliteModule,\n * CoraliteComponent,\n * CoraliteComponentResult,\n * } from '../../types/index.js'\n */\n\nconst KEBAB_REGEX = /[-|:]([a-z])/g\n\n/**\n * Converts a kebab-case string to camelCase\n * @param {string} str - The kebab-case string to convert\n * @returns {string} - The camelCase version of the string\n */\nexport function kebabToCamel (str) {\n // replace each dash followed by a letter with the uppercase version of the letter\n return str.replace(KEBAB_REGEX, function (match, letter) {\n return letter.toUpperCase()\n })\n}\n\n/**\n * Converts all keys in an object from kebab-case to camelCase\n * @template T\n * @param {Record<string, T>} object - The object with kebab-case keys\n * @returns {Record<string, T>} - A new object with camelCase keys\n */\nexport function cleanKeys (object) {\n /** @type {Record<string, T>} */\n const result = {}\n\n for (const [key, value] of Object.entries(object)) {\n result[key] = value\n\n const camelKey = kebabToCamel(key)\n if (camelKey !== key) {\n result[camelKey] = value\n }\n }\n\n return result\n}\n\n/**\n * Recursively clones an object or array and normalizes any function state\n * it finds into a string representation that preserves standard function syntax,\n * bypassing ES6 shorthand method serialization issues.\n * @param {any} target - The object or array to normalize.\n * @param {Function} [transform] - Optional transform function for each node.\n * @param {WeakMap} [seen=new WeakMap()] - Map of seen objects to handle circular references.\n * @returns {any} A deeply cloned object with normalized functions.\n */\nexport function normalizeObjectFunctions (target, transform = null, seen = new WeakMap()) {\n if (typeof transform === 'function') {\n const transformed = transform(target)\n if (transformed !== target) {\n return transformed\n }\n }\n\n if (typeof target !== 'object' || target === null) {\n return target\n }\n\n if (seen.has(target)) {\n return seen.get(target)\n }\n\n if (Array.isArray(target)) {\n const arr = []\n seen.set(target, arr)\n for (let i = 0; i < target.length; i++) {\n arr.push(normalizeObjectFunctions(target[i], transform, seen))\n }\n return arr\n }\n\n const obj = {}\n seen.set(target, obj)\n for (const key in target) {\n if (Object.hasOwn(target, key)) {\n if (typeof target[key] === 'function') {\n const normalizedString = normalizeFunction(target[key])\n const originalFunction = target[key]\n\n const wrapper = function () {\n return originalFunction.apply(this, arguments)\n }\n wrapper.toString = () => normalizedString\n obj[key] = wrapper\n } else {\n obj[key] = normalizeObjectFunctions(target[key], transform, seen)\n }\n }\n }\n\n return obj\n}\n\n/**\n * Checks whether the given object is an object and has at least one own key.\n * @param {any} obj - The object to check.\n * @returns {boolean} True if the object is truthy and has keys, otherwise false.\n */\nexport function hasObjectKeys (obj) {\n return obj && typeof obj === 'object' && Object.keys(obj).length > 0\n}\n\n/**\n * Merges two arrays, returning a new array with unique items.\n * Uses JSON.stringify for deep comparison of object elements, preserving object uniqueness correctly.\n * @param {Array<any>} [arr1] - The first array.\n * @param {Array<any>} [arr2] - The second array.\n * @returns {Array<any>} A new array with unique values from both input arrays.\n */\nexport function mergeUniqueObjects (arr1, arr2) {\n const all = [...(arr1 || []), ...(arr2 || [])]\n const seen = new Set()\n return all.filter(item => {\n const key = typeof item === 'object' ? JSON.stringify(item) : item\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\n/**\n * Normalizes function declarations to ensure consistent formatting.\n * Converts shorthand method syntax to full function declarations where needed,\n * while preserving arrow functions and existing full declarations.\n *\n * @param {Function} func - The function to normalize\n * @returns {string} The normalized function string representation\n */\nexport function normalizeFunction (func) {\n const original = func.toString().trim()\n\n const firstBrace = original.indexOf('{')\n const firstArrow = original.indexOf('=>')\n\n const isArrow = firstArrow !== -1 && (firstBrace === -1 || firstArrow < firstBrace)\n\n if (isArrow) {\n return original\n }\n\n // For non-arrows, extract header to check for shorthand\n const header = firstBrace !== -1 ? original.slice(0, firstBrace).trim() : original\n\n const isStandard = header.startsWith('function') || header.startsWith('async function')\n\n if (isStandard) {\n return original\n }\n\n // Handle Method Shorthand\n if (header.startsWith('async ')) {\n if (header.startsWith('async get ') || header.startsWith('async set ')) {\n return original\n }\n\n return original.replace(/^async\\s+([$\\w]+)\\s*\\(/, 'async function(')\n } else {\n if (header.startsWith('get ') || header.startsWith('set ')) {\n return original\n }\n\n return original.replace(/^([$\\w]+)\\s*\\(/, 'function(')\n }\n}\n\n\n/**\n * Recursively clones an AST node and its children, ensuring that\n * inner references (like parents and slots) point to the newly cloned nodes.\n *\n * @param {Map<Object, Object>} nodeMap - A map tracking original nodes to their newly cloned counterparts.\n * @param {Object} node - The current AST node being cloned.\n * @param {Object} [parent] - The parent node reference to assign to the clone.\n * @returns {Object} The newly cloned node.\n */\nexport function cloneNode (nodeMap, node, parent) {\n const newNode = Object.create(Object.getPrototypeOf(node))\n\n // Copy all own enumerable properties\n Object.assign(newNode, node)\n\n if (parent) {\n newNode.parent = parent\n }\n\n if (newNode.attribs) {\n newNode.attribs = { ...newNode.attribs }\n }\n\n // Register in map\n nodeMap.set(node, newNode)\n\n // Recursively clone children\n if (node.children) {\n const children = node.children\n const length = children.length\n const clonedChildren = new Array(length)\n newNode.children = clonedChildren\n\n for (let i = 0; i < length; i++) {\n const clonedChild = cloneNode(nodeMap, children[i], newNode)\n clonedChildren[i] = clonedChild\n if (i > 0) {\n clonedChild.prev = clonedChildren[i - 1]\n clonedChildren[i - 1].next = clonedChild\n }\n }\n }\n\n // Update slot references to point to new cloned nodes\n if (node.slots) {\n const slots = node.slots\n const length = slots.length\n const clonedSlots = new Array(length)\n for (let i = 0; i < length; i++) {\n const slot = slots[i]\n const clonedSlot = { ...slot }\n if (slot.node) {\n const clonedNode = nodeMap.get(slot.node)\n if (clonedNode) {\n clonedSlot.node = clonedNode\n }\n }\n clonedSlots[i] = clonedSlot\n }\n newNode.slots = clonedSlots\n }\n\n // Preserve the enhanced flag without re-running enhanceNode\n Object.defineProperty(newNode, '__coralite_enhanced__', {\n value: true,\n enumerable: false,\n configurable: true\n })\n\n return newNode\n}\n\n/**\n * Creates a shallow copy of a CoraliteModule with a deep clone of its DOM tree (template) and re-linked internal references to enable safe independent mutation.\n *\n * Top-level non-DOM state (id, path, script, isTemplate, lineOffset) are shallow copied. Nested objects within these state (e.g., path) remain shared references. Only DOM-related structures undergo deep cloning and reference re-linking to isolate mutations from the original module.\n *\n * @param {CoraliteModule} originalModule - Module to clone.\n * @returns {CoraliteModule}\n */\nexport function cloneModuleInstance (originalModule) {\n const nodeMap = new Map()\n\n // Clone the main template tree\n const newTemplate = cloneNode(nodeMap, originalModule.template, null)\n\n // Reconstruct the 'values' object\n const newValues = {\n attributes: originalModule.values.attributes.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n })),\n textNodes: originalModule.values.textNodes.map(item => ({\n ...item,\n textNode: nodeMap.get(item.textNode)\n })),\n refs: originalModule.values.refs.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n }))\n }\n\n // Reconstruct customElements list\n const newCustomElements = originalModule.customElements.map(el => nodeMap.get(el))\n\n // Reconstruct slotElements\n const newSlotElements = {}\n if (originalModule.slotElements) {\n for (const modId in originalModule.slotElements) {\n newSlotElements[modId] = {}\n const slotGroup = originalModule.slotElements[modId]\n\n for (const slotName in slotGroup) {\n const slotItem = slotGroup[slotName]\n newSlotElements[modId][slotName] = {\n ...slotItem,\n element: nodeMap.get(slotItem.element)\n }\n }\n }\n }\n\n // Return the new module structure\n return {\n ...originalModule,\n template: newTemplate,\n values: newValues,\n customElements: newCustomElements,\n // @ts-ignore\n slotElements: newSlotElements\n }\n}\n\n/**\n * Creates a deep copy of a CoraliteComponent with re-linked internal references to enable safe independent mutation.\n *\n * @param {CoraliteComponent & CoraliteComponentResult} originalDocument - Document to clone.\n * @returns {CoraliteComponent & CoraliteComponentResult}\n */\nexport function cloneComponentInstance (originalDocument) {\n const nodeMap = new Map()\n const newRoot = cloneNode(nodeMap, originalDocument.root, null)\n\n const newCustomElements = originalDocument.customElements.map(el => nodeMap.get(el))\n const newTempElements = originalDocument.tempElements ? originalDocument.tempElements.map(el => nodeMap.get(el)) : []\n const newSkipRenderElements = originalDocument.skipRenderElements ? originalDocument.skipRenderElements.map(el => nodeMap.get(el)) : []\n\n return {\n ...originalDocument,\n state: { ...originalDocument.state },\n root: newRoot,\n customElements: newCustomElements,\n tempElements: newTempElements,\n skipRenderElements: newSkipRenderElements\n }\n}\n\n/**\n * Calculates the DOM path from a node to the root.\n * @param {Object} node - The node to calculate the path for.\n * @param {Object} root - The root node.\n * @returns {Array<number>} An array of indices representing the path.\n */\nexport function getNodePath (node, root) {\n const path = []\n let current = node\n while (current && current !== root) {\n const parent = current.parent\n if (!parent) {\n break\n }\n const index = parent.children.indexOf(current)\n if (index === -1) {\n break\n }\n path.unshift(index)\n current = parent\n }\n return path\n}\n\n/**\n * Generates a hydration map for the client.\n * @param {Array<Object>} templateNodes - The component's template nodes.\n * @param {Object} templateValues - The component's template values.\n * @returns {Object} The hydration map.\n */\nexport function generateHydrationMap (templateNodes, templateValues) {\n const map = {\n texts: [],\n attributes: [],\n refs: []\n }\n\n if (!templateNodes || !templateValues) {\n return map\n }\n\n const root = templateNodes.length > 0 ? templateNodes[0].parent : { children: templateNodes }\n\n if (templateValues.textNodes) {\n for (const item of templateValues.textNodes) {\n if (item.textNode) {\n const isHtml = item.type === 'html'\n const targetNode = isHtml ? item.textNode.parent : item.textNode\n\n map.texts.push({\n path: getNodePath(targetNode, root),\n template: item.textNode.data,\n type: isHtml ? 'html' : 'text'\n })\n }\n }\n }\n\n if (templateValues.attributes) {\n for (const item of templateValues.attributes) {\n if (item.element && item.element.attribs) {\n const originalValue = item.element.attribs[item.name]\n map.attributes.push({\n path: getNodePath(item.element, root),\n name: item.name,\n template: originalValue\n })\n }\n }\n }\n\n if (templateValues.refs) {\n for (const item of templateValues.refs) {\n if (item.element) {\n map.refs.push({\n path: getNodePath(item.element, root),\n name: item.name\n })\n }\n }\n }\n\n return map\n}\n\n/**\n * Recursively adds a component and its dependencies to a tracking object.\n *\n * @param {string} componentId - The ID of the component to add.\n * @param {Object.<string, boolean>} processed - The object tracking processed components.\n * @param {Object.<string, any>} sharedFunctions - The map of shared component functions.\n */\nexport function addComponentAndDependencies (componentId, processed, sharedFunctions) {\n if (!processed[componentId] && sharedFunctions[componentId]) {\n processed[componentId] = true\n\n // Add all dependencies of this component\n const dependencies = sharedFunctions[componentId].components || []\n for (const depId of dependencies) {\n addComponentAndDependencies(depId, processed, sharedFunctions)\n }\n }\n}\n\n/**\n * Recursively clones an AST node and its children, stripping circular references\n * and assigning unique IDs for client-side hydration.\n *\n * @param {Array<Object>} nodes - The nodes to clean.\n * @param {WeakMap} nodeMap - Map to track original nodes to their unique IDs.\n * @param {Object} state - Object containing the current node counter.\n * @returns {Array<Object>|null} The cleaned AST nodes.\n */\nexport function cleanAST (nodes, nodeMap, state) {\n if (!nodes) {\n return null\n }\n\n return nodes.map((node) => {\n const cloned = { ...node }\n // Assign unique ID for token mapping\n const id = state.counter++\n nodeMap.set(node, id)\n cloned._id = id\n\n // Remove circular references\n delete cloned.parent\n delete cloned.prev\n delete cloned.next\n delete cloned.slots\n\n if (cloned.children) {\n cloned.children = cleanAST(cloned.children, nodeMap, state)\n }\n return cloned\n })\n}\n\n/**\n * Cleans the template values object, mapping original node references to unique IDs.\n *\n * @param {Object} values - The values object to clean.\n * @param {WeakMap} nodeMap - Map of original nodes to their unique IDs.\n * @returns {Object|null} The cleaned values object.\n */\nexport function cleanValues (values, nodeMap) {\n if (!values) {\n return null\n }\n\n const result = { ...values }\n\n if (result.attributes) {\n result.attributes = result.attributes.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n\n if (result.textNodes) {\n result.textNodes = result.textNodes.map(item => {\n const cloned = { ...item }\n cloned.textNodeId = nodeMap.get(item.textNode)\n delete cloned.textNode\n return cloned\n })\n }\n\n if (result.refs) {\n result.refs = result.refs.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n return result\n}\n\n/**\n * Safely merges partial plugin updates into the main context object.\n * Deeply merges plain objects and overwrites other types (arrays, primitives, etc.).\n *\n * @param {any} current - The current state object.\n * @param {any} patch - The patch object containing updates.\n * @returns {any} The newly merged state object.\n */\nexport function mergePluginState (current, patch) {\n if (!patch || typeof patch !== 'object') {\n return current\n }\n\n const result = { ...current }\n\n for (const key of Object.keys(patch)) {\n const patchValue = patch[key]\n const currentValue = result[key]\n\n // If both are plain objects, merge them deeply\n if (\n patchValue && typeof patchValue === 'object' && !Array.isArray(patchValue) &&\n currentValue && typeof currentValue === 'object' && !Array.isArray(currentValue)\n ) {\n result[key] = mergePluginState(currentValue, patchValue)\n } else {\n // Otherwise, overwrite (Arrays, strings, numbers, etc.)\n result[key] = patchValue\n }\n }\n\n return result\n}\n\n/**\n * Creates a reactive proxy that triggers a callback on changes.\n * Supports deep reactivity via lazy proxying of nested objects.\n *\n * @param {Object} target - The object to proxy.\n * @param {Function} onChange - Callback triggered when a property is set or deleted.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies to handle circular references and identity.\n * @returns {Proxy} The reactive proxy.\n */\nexport function createReactiveProxy (target, onChange, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReactiveProxy(value, onChange, proxies)\n }\n return value\n },\n set (target, property, value, receiver) {\n const oldValue = target[property]\n if (oldValue === value && property in target) {\n return true\n }\n\n const result = Reflect.set(target, property, value, receiver)\n if (result) {\n onChange({\n property,\n value,\n oldValue,\n target\n })\n }\n return result\n },\n deleteProperty (target, property) {\n const hadProperty = Object.prototype.hasOwnProperty.call(target, property)\n const oldValue = target[property]\n const result = Reflect.deleteProperty(target, property)\n if (result && hadProperty) {\n onChange({\n property,\n value: undefined,\n oldValue,\n target,\n deleted: true\n })\n }\n return result\n }\n }\n\n const proxy = new Proxy(target, handler)\n proxies.set(target, proxy)\n return proxy\n}\n\n/**\n * Creates a read-only proxy that throws on mutation attempts.\n * @param {Object} target - The object to proxy.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies.\n * @returns {Proxy} The read-only proxy.\n */\nexport function createReadOnlyProxy (target, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReadOnlyProxy(value, proxies)\n }\n return value\n },\n set () {\n throw new CoraliteError('Cannot mutate state inside a getter. State is read-only here.')\n },\n deleteProperty () {\n throw new CoraliteError('Cannot delete state inside a getter. State is read-only here.')\n }\n }\n\n const proxy = new Proxy(target, handler)\n\n proxies.set(target, proxy)\n\n return proxy\n}\n\n/**\n * Defines a Coralite component.\n * On the client, this acts as an identity function for type safety and HRM.\n * @param {Object} options - Component options\n * @returns {Object} The component options\n */\nexport function defineComponent (options) {\n return options\n}\n", "/**\n * @import {\n * CoraliteClientPluginDisconnectedCallback,\n * CoraliteClientPluginAfterComponentRenderCallback,\n * CoraliteClientPluginBeforeComponentRenderCallback\n * } from '../types/plugin.js'\n */\n\nimport { createReadOnlyProxy } from './utils/core.js'\n\nconst BOOLEAN_ATTRIBUTES = new Set([\n 'allowfullscreen',\n 'async',\n 'autofocus',\n 'autoplay',\n 'checked',\n 'controls',\n 'default',\n 'defer',\n 'disabled',\n 'formnovalidate',\n 'hidden',\n 'inert',\n 'ismap',\n 'itemscope',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'readonly',\n 'required',\n 'reversed',\n 'selected',\n 'truespeed'\n])\n\n/**\n * Coerces a value to a specified type.\n * Supports Number, Boolean, and String.\n * @param {any} value - The value to coerce.\n * @param {Function|string} type - The target type (Constructor or string name).\n * @returns {any} The coerced value.\n */\nexport function coerce (value, type) {\n if (value === null || value === undefined) {\n return value\n }\n if (type === Number || type === 'Number') {\n return Number(value)\n }\n if (type === Boolean || type === 'Boolean') {\n if (value === '') {\n return true\n }\n return value !== 'false' && value !== null\n }\n if (type === String || type === 'String') {\n return String(value)\n }\n return value\n}\n\n/**\n * @typedef {Object} CoraliteComponentOptions\n * @property {string} componentId - The unique identifier for the component.\n * @property {string} [templateHTML] - The raw HTML string for imperative mounting.\n * @property {Object} [defaultValues] - The initial state values extracted from the server data block.\n * @property {Object} [attributes] - Schema for coercing HTML attributes into typed primitives.\n * @property {Object.<string, Function>} [getters] - Pure functions for derived state, supporting Promises.\n * @property {Object.<string, Function>} [slots] - Transformation functions for projected Light DOM.\n * @property {Function} [script] - The client-side controller logic.\n * @property {Object} [hydrationMap] - AST mapping for reactive text nodes, attributes, and refs.\n */\n\n/**\n * Base class for all Coralite custom elements.\n *\n * @augments HTMLElement\n */\nexport class CoraliteElement extends HTMLElement {\n /**\n * Initializes a new instance of the CoraliteElement.\n * Sets up internal state trackers, binding collections, and hook registries.\n */\n constructor () {\n super()\n /**\n * Controls native teardown of event listeners and async fetches upon disconnection.\n * @type {AbortController|null}\n * @protected\n */\n this._abortController = null\n\n /**\n * A globally unique, deterministic identifier (e.g., `my-comp-0`).\n * @type {string|null}\n * @protected\n */\n this._instanceId = null\n\n /**\n * The unified, deeply reactive proxy holding attributes, data, and getters.\n * @type {Object|null}\n * @protected\n */\n this._state = null\n\n /**\n * The collection of DOM nodes mapped to template tokens and attributes.\n * @type {Array<{type: string, node: Node, template?: string, name?: string}>}\n * @protected\n */\n this._bindings = []\n\n /**\n * Flag to prevent multiple synchronous state mutations from triggering multiple DOM paints.\n * @type {boolean}\n * @protected\n */\n this._isUpdatePending = false\n\n /**\n * A unique Symbol generated per render cycle to prevent async getter race conditions.\n * @type {symbol|null}\n * @protected\n */\n this._currentRenderVersion = null\n\n /**\n * @type {MutationObserver|null}\n * @protected\n */\n this._observer = null\n\n /**\n * Hook to fetch globally registered Phase-2 plugin contexts.\n * @type {Function|null}\n * @protected\n */\n this._clientContextGetter = null\n\n /**\n * Tracks AbortControllers specifically for cancelling stale async getters.\n * @type {Object.<string, AbortController>|null}\n * @protected\n */\n this._getterAbortControllers = null\n\n /**\n * Internal lifecycle hooks injected by registered Coralite plugins.\n * @type {{\n * onBeforeComponentRender: Array<CoraliteClientPluginBeforeComponentRenderCallback>,\n * onAfterComponentRender: Array<CoraliteClientPluginAfterComponentRenderCallback>,\n * onDisconnected: Array<CoraliteClientPluginDisconnectedCallback>\n * }}\n * @protected\n */\n this._hooks = {\n onBeforeComponentRender: [],\n onAfterComponentRender: [],\n onDisconnected: []\n }\n\n /**\n * The definition and schema of the component generated by the compiler.\n * @type {CoraliteComponentOptions|null}\n */\n this.componentOptions = null\n }\n\n /**\n * Invoked natively when the element is added to the document.\n * Handles the architectural split between Declarative (SSR) and Imperative (JS) components.\n * Orchestrates template injection, instance ID generation, and state/binding setup.\n */\n connectedCallback () {\n this._abortController = new AbortController()\n\n if (!this.componentOptions) {\n return\n }\n\n // Declarative components receive a data-cid from the server.\n // Imperative components (created via document.createElement) do not.\n const isImperative = !this.hasAttribute('data-cid')\n\n // Imperative Flow: Manually stamp the template and project the Light DOM.\n if (isImperative && this.componentOptions.templateHTML) {\n const originalLightDOM = Array.from(this.childNodes)\n this.innerHTML = this.componentOptions.templateHTML\n\n if (originalLightDOM.length > 0) {\n const slots = this.querySelectorAll('slot')\n slots.forEach(slot => {\n const slotName = slot.getAttribute('name') || 'default'\n const matchingNodes = originalLightDOM.filter(node => {\n // @ts-ignore\n const nodeSlot = (node.getAttribute && node.getAttribute('slot')) || 'default'\n return nodeSlot === slotName\n })\n matchingNodes.forEach(n => slot.appendChild(n))\n })\n }\n }\n\n // Establish the Deterministic Instance ID\n if (this.hasAttribute('data-cid')) {\n this._instanceId = this.getAttribute('data-cid')\n } else {\n // Fallback counter for imperatively created components\n // @ts-ignore\n window.__coralite_instanceCounters = window.__coralite_instanceCounters || {}\n const prefix = this.componentOptions.componentId\n // @ts-ignore\n if (window.__coralite_instanceCounters[prefix] === undefined) {\n // @ts-ignore\n window.__coralite_instanceCounters[prefix] = 0\n }\n // @ts-ignore\n this._instanceId = `${prefix}-${window.__coralite_instanceCounters[prefix]++}`\n }\n\n if (isImperative) {\n this.setAttribute('data-cid', this._instanceId)\n }\n\n this._setupState()\n this._setupBindings()\n this._init(isImperative)\n }\n\n /**\n * Invoked natively when the element is removed from the document.\n * Aborts pending requests and triggers `onDisconnected` plugin hooks\n * to ensure external libraries (e.g., Observers) do not cause memory leaks.\n * @this {any}\n */\n disconnectedCallback () {\n if (this._abortController) {\n this._abortController.abort()\n }\n\n if (!this.componentOptions) {\n return\n }\n\n for (const hook of this._hooks.onDisconnected) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n /**\n * Invoked natively when an observed HTML attribute changes.\n * Coerces the raw string value based on the component's attribute schema\n * and synchronizes it into the reactive state proxy.\n * @param {string} name - The kebab-case name of the attribute.\n * @param {string|null} oldVal - The previous value.\n * @param {string|null} newVal - The new value.\n */\n attributeChangedCallback (name, oldVal, newVal) {\n if (!this._state || oldVal === newVal || name === 'data-cid') {\n return\n }\n const camelName = name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = this.componentOptions.attributes?.[camelName] || this.componentOptions.attributes?.[name]\n const value = schema ? coerce(newVal, schema.type) : newVal\n\n this._state[camelName] = value\n }\n\n /**\n * Constructs the unified state object.\n * Merges `defaultValues`, JSON hydration payloads, and DOM attributes.\n * Defines getters (wrapping state in a Read-Only proxy) and applies the final Read/Write Proxy.\n * @this {any}\n * @private\n */\n _setupState () {\n const options = this.componentOptions\n const target = { ...options.defaultValues }\n\n /** @type {Array<{name: string, element: HTMLElement}>} */\n const refs = []\n if (options.hydrationMap && options.hydrationMap.refs) {\n for (const ref of options.hydrationMap.refs) {\n const uniqueRefValue = `${this._instanceId}__${ref.name}`\n\n if (!target[`ref_${ref.name}`]) {\n target[`ref_${ref.name}`] = uniqueRefValue\n }\n\n const node = this.getNodeByPath(ref.path)\n if (node) {\n if (node.setAttribute) {\n node.setAttribute('ref', uniqueRefValue)\n }\n refs.push({\n name: ref.name,\n element: node\n })\n }\n }\n }\n\n // Trigger Before-Render hooks BEFORE state is proxied, allowing plugins to inject reactive data\n for (const hook of this._hooks.onBeforeComponentRender) {\n hook({\n state: target,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n refs,\n element: this,\n options: this.componentOptions\n })\n }\n\n // Hydrate data() block results from the SSR JSON payload\n const hydrationTag = document.getElementById('__CORALITE_HYDRATION__')\n if (hydrationTag) {\n try {\n const allData = JSON.parse(hydrationTag.textContent)\n if (allData[this._instanceId]) {\n Object.assign(target, allData[this._instanceId])\n }\n } catch {\n console.error('Coralite Element hydration failed:', this._instanceId)\n }\n }\n\n // Process initial attributes mapping\n for (const attr of this.attributes) {\n if (attr.name === 'data-cid') {\n continue\n }\n const camelName = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = options.attributes?.[camelName] || options.attributes?.[attr.name]\n target[camelName] = schema ? coerce(attr.value, schema.type) : attr.value\n }\n\n // Define derived state getters with isolation controllers\n this._getterAbortControllers = {}\n for (const [key, getter] of Object.entries(options.getters || {})) {\n Object.defineProperty(target, key, {\n get: () => {\n if (this._getterAbortControllers[key]) {\n this._getterAbortControllers[key].abort()\n }\n this._getterAbortControllers[key] = new AbortController()\n\n // Enforce \"Dual-Proxy\" safety: Getters cannot mutate state\n const roState = createReadOnlyProxy(this._state)\n return getter(roState, { signal: this._getterAbortControllers[key].signal })\n },\n enumerable: true,\n configurable: true\n })\n }\n\n this._state = this._createReactiveProxy(target)\n }\n\n /**\n * Wraps the state target in a reactive Proxy.\n * Intercepts property setters to automatically batch and schedule DOM updates.\n * @param {Object} target - The state dictionary.\n * @returns {Proxy} The reactive state proxy.\n * @private\n */\n _createReactiveProxy (target) {\n const self = this\n return new Proxy(target, {\n set (t, p, v) {\n if (t[p] === v) {\n return true\n }\n t[p] = v\n self._scheduleUpdate()\n return true\n }\n })\n }\n\n /**\n * Traverses the DOM tree using an AST-generated path index array.\n * Allows O(1) element lookups without relying on querySelectors or classes.\n * @param {number[]} path - Array of childNode indices (e.g., `[0, 1, 2]`).\n * @returns {Node|null} The physical DOM node, or null if traversal fails.\n */\n getNodeByPath (path) {\n let node = this\n for (const index of path) {\n if (!node) {\n return null\n }\n // @ts-ignore\n node = node.childNodes[index]\n }\n return node\n }\n\n /**\n * Initializes DOM bindings based on the compiler's hydration map.\n * Caches physical DOM references to text nodes and attributes that contain template tokens.\n * @private\n */\n _setupBindings () {\n this._bindings = []\n const map = this.componentOptions.hydrationMap\n if (!map) {\n return\n }\n\n if (map.texts) {\n for (const item of map.texts) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: item.type || 'text',\n node,\n template: item.template\n })\n }\n }\n }\n\n if (map.attributes) {\n for (const item of map.attributes) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: 'attribute',\n node,\n name: item.name,\n template: item.template\n })\n }\n }\n }\n }\n\n /**\n * Schedules a DOM update in the next microtask queue.\n * This guarantees that multiple synchronous state mutations result in only one render pass.\n * @private\n */\n _scheduleUpdate () {\n if (this._isUpdatePending) {\n return\n }\n this._isUpdatePending = true\n queueMicrotask(() => {\n this._updateDOM()\n this._isUpdatePending = false\n })\n }\n\n /**\n * Performs the physical DOM update and resolves template tokens.\n * **Async Safety:** Implements a Symbol-based locking mechanism (`renderVersion`)\n * to guarantee that if state mutates while an async getter is pending, the stale\n * Promise will be discarded, preventing DOM race conditions.\n * @this {any}\n * @private\n */\n _updateDOM () {\n // Create a unique lock for this specific render cycle\n const renderVersion = Symbol()\n this._currentRenderVersion = renderVersion\n\n // Extract unique tokens to prevent double-reading and accidental aborts\n /** @type {Set<string>} */\n const requiredTokens = new Set()\n for (const binding of this._bindings) {\n binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n requiredTokens.add(key)\n return ''\n })\n }\n\n const evaluatedTokens = {}\n let hasPromise = false\n\n // Evaluate getters exactly once per render cycle\n for (const key of requiredTokens) {\n let val = this._state[key]\n if (typeof val === 'function') {\n val = val(this._state)\n }\n evaluatedTokens[key] = val\n if (val instanceof Promise) {\n hasPromise = true\n }\n }\n\n // The DOM Mutator Function\n const applyBindings = (tokenValues) => {\n // Race Condition Lock: Abort if a newer render cycle has already begun\n if (this._currentRenderVersion !== renderVersion) {\n return\n }\n\n for (const binding of this._bindings) {\n const hydratedValue = binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n return tokenValues[key] ?? ''\n })\n\n if (binding.type === 'text') {\n if (binding.node.textContent !== hydratedValue) {\n binding.node.textContent = hydratedValue\n }\n } else if (binding.type === 'html') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (element.innerHTML !== hydratedValue) {\n element.innerHTML = hydratedValue\n }\n } else if (binding.type === 'attribute') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (BOOLEAN_ATTRIBUTES.has(binding.name)) {\n const isFalsy = hydratedValue === '' || hydratedValue === 'false' || hydratedValue === 'null' || hydratedValue === '0' || hydratedValue === 'undefined'\n if (isFalsy) {\n element.removeAttribute(binding.name)\n } else {\n element.setAttribute(binding.name, '')\n }\n } else {\n if (element.getAttribute(binding.name) !== hydratedValue) {\n element.setAttribute(binding.name, hydratedValue)\n }\n }\n }\n }\n\n this._processSlots()\n\n // Trigger After-Render hooks ONLY after the physical DOM is stable\n for (const hook of this._hooks.onAfterComponentRender) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n // Await Promises or Apply Synchronously\n if (hasPromise) {\n const keys = Object.keys(evaluatedTokens)\n const promises = keys.map(k => Promise.resolve(evaluatedTokens[k]))\n\n Promise.all(promises).then(resolvedValues => {\n const resolvedMap = {}\n keys.forEach((k, i) => {\n resolvedMap[k] = resolvedValues[i]\n })\n applyBindings(resolvedMap)\n }).catch(e => {\n if (e.name !== 'AbortError') {\n console.error('Coralite Async Getter Error:', e)\n }\n })\n } else {\n applyBindings(evaluatedTokens)\n }\n }\n\n /**\n * Evaluates and projects Light DOM elements into their respective `<slot>` nodes.\n * Invokes component-specific slot transformation functions.\n * @private\n */\n _processSlots () {\n const slots = this.componentOptions.slots\n if (!slots || Object.keys(slots).length === 0) {\n return\n }\n\n const slotElements = this.querySelectorAll('slot')\n slotElements.forEach(slotEl => {\n const slotName = slotEl.getAttribute('name') || 'default'\n const slotFn = slots[slotName]\n\n if (slotFn) {\n // @ts-ignore\n if (!slotEl._originalNodes) {\n // @ts-ignore\n slotEl._originalNodes = Array.from(slotEl.childNodes).map(n => n.cloneNode(true))\n }\n\n // @ts-ignore\n const result = slotFn(slotEl._originalNodes, this._state)\n\n if (result === undefined) {\n return\n }\n\n if (result === null || result === '' || (Array.isArray(result) && result.length === 0)) {\n slotEl.innerHTML = ''\n return\n }\n\n if (typeof result === 'string') {\n slotEl.innerHTML = result\n } else if (Array.isArray(result)) {\n slotEl.replaceChildren(...result)\n }\n }\n })\n }\n\n /**\n * The final initialization pipeline.\n * Injects globally registered client plugins into the local context payload,\n * triggers the initial DOM render, and invokes the user's `script()` logic.\n * @param {boolean} [isImperative=false] - If true, initial render runs synchronously.\n * @private\n */\n async _init (isImperative = false) {\n const self = this\n /**\n * The context payload injected into the user's script block.\n * @type {Object}\n */\n const localContext = {\n instanceId: this._instanceId,\n state: this._state,\n root: this,\n signal: this._abortController.signal,\n refs (id) {\n const refId = self._state[`ref_${id}`]\n if (!refId && typeof refId !== 'string') {\n return null\n }\n return self.querySelector(`[ref=\"${refId}\"]`)\n }\n }\n\n if (typeof this._clientContextGetter === 'function') {\n const pluginContext = await this._clientContextGetter(localContext)\n Object.assign(localContext, pluginContext)\n }\n\n if (isImperative) {\n this._updateDOM()\n } else {\n this._scheduleUpdate()\n }\n\n if (this.componentOptions.script) {\n try {\n this.componentOptions.script(localContext)\n } catch (error) {\n console.error(`Coralite Error: Component \"${this.componentOptions.componentId}\" script failed:`, error)\n }\n }\n }\n}\n\n/**\n * Factory function to create a Coralite element class.\n * It dynamically defines the class, including observed attributes and hook initialization.\n * @param {CoraliteComponentOptions} options - Component options and metadata.\n * @param {Function|null} [contextGetter=null] - Optional function to retrieve client-side plugin context.\n * @param {Object} [hooks={}] - Lifecycle hooks to register.\n * @param {Array<CoraliteClientPluginBeforeComponentRenderCallback>} [hooks.onBeforeComponentRender] - Hooks to run before render.\n * @param {Array<CoraliteClientPluginAfterComponentRenderCallback>} [hooks.onAfterComponentRender] - Hooks to run after render.\n * @param {Array<CoraliteClientPluginDisconnectedCallback>} [hooks.onDisconnected] - Hooks to run after render.\n * @returns {typeof CoraliteElement} A new CoraliteElement subclass.\n */\nexport function createCoraliteClass (options, contextGetter = null, hooks = {}) {\n return class extends CoraliteElement {\n /**\n * The attributes to observe for changes.\n * @returns {string[]} Array of attribute names.\n */\n static get observedAttributes () {\n if (!options.attributes) {\n return []\n }\n return Object.keys(options.attributes).map(key => key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n )\n }\n\n /**\n * Initializes the dynamic Coralite element.\n */\n constructor () {\n super()\n this.componentOptions = options\n this._clientContextGetter = contextGetter\n this._hooks = {\n onBeforeComponentRender: hooks.onBeforeComponentRender || [],\n onAfterComponentRender: hooks.onAfterComponentRender || [],\n onDisconnected: hooks.onDisconnected || []\n }\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\n/**\n * @import { CoraliteErrorData } from '../../types/index.js'\n */\n\n/**\n * Base error class for all Coralite-related errors.\n */\nexport class CoraliteError extends Error {\n /**\n * @param {string} message - The error message.\n * @param {Object} [options] - Additional options for the error.\n * @param {string} [options.componentId] - The ID of the component where the error occurred.\n * @param {string} [options.filePath] - The path to the file where the error occurred.\n * @param {string} [options.instanceId] - The unique ID of the component instance.\n * @param {string} [options.pagePath] - The path to the page being rendered.\n * @param {number} [options.line] - The line number where the error occurred.\n * @param {number} [options.column] - The column number where the error occurred.\n * @param {string} [options.stackFile] - The file name from the stack trace.\n * @param {Error} [options.cause] - The original error that caused this error.\n */\n constructor (message, options = {}) {\n super(message, options)\n this.name = 'CoraliteError'\n this.isCoraliteError = true\n this.componentId = options.componentId\n this.filePath = options.filePath\n this.instanceId = options.instanceId\n this.pagePath = options.pagePath\n this.line = options.line\n this.column = options.column\n this.stackFile = options.stackFile\n\n // Polyfill cause if necessary (node version differences)\n if (options.cause && !this.cause) {\n this.cause = options.cause\n }\n }\n}\n\n/**\n * Default error handler.\n * @param {CoraliteErrorData} data - The data object containing error details.\n */\nexport function defaultOnError ({ level, message, error }) {\n if (level === 'ERR') {\n if (error) {\n throw error\n }\n throw new CoraliteError(message)\n } else if (level === 'WARN') {\n console.warn(message)\n } else {\n console.log(message)\n }\n}\n\n/**\n * Handles errors using an optional callback or the default handler.\n * @param {Object} options - The options for handling the error.\n * @param {Function} [options.onErrorCallback] - The optional custom error callback function.\n * @param {CoraliteErrorData} options.data - The error data to be handled.\n */\nexport function handleError ({ onErrorCallback, data }) {\n const error = data.error\n if (error && 'isCoraliteError' in error && error.isCoraliteError) {\n const coraliteError = error\n // @ts-ignore\n data.componentId = data.componentId || coraliteError.componentId\n // @ts-ignore\n data.filePath = data.filePath || coraliteError.filePath\n // @ts-ignore\n data.instanceId = data.instanceId || coraliteError.instanceId\n // @ts-ignore\n data.pagePath = data.pagePath || coraliteError.pagePath\n // @ts-ignore\n data.line = data.line || coraliteError.line\n // @ts-ignore\n data.column = data.column || coraliteError.column\n // @ts-ignore\n data.stackFile = data.stackFile || coraliteError.stackFile\n }\n\n if (onErrorCallback) {\n onErrorCallback(data)\n } else {\n defaultOnError(data)\n }\n}\n", "import { CoraliteError } from './errors.js'\n\n/**\n * @import {\n * CoraliteModule,\n * CoraliteComponent,\n * CoraliteComponentResult,\n * } from '../../types/index.js'\n */\n\nconst KEBAB_REGEX = /[-|:]([a-z])/g\n\n/**\n * Converts a kebab-case string to camelCase\n * @param {string} str - The kebab-case string to convert\n * @returns {string} - The camelCase version of the string\n */\nexport function kebabToCamel (str) {\n // replace each dash followed by a letter with the uppercase version of the letter\n return str.replace(KEBAB_REGEX, function (match, letter) {\n return letter.toUpperCase()\n })\n}\n\n/**\n * Converts all keys in an object from kebab-case to camelCase\n * @template T\n * @param {Record<string, T>} object - The object with kebab-case keys\n * @returns {Record<string, T>} - A new object with camelCase keys\n */\nexport function cleanKeys (object) {\n /** @type {Record<string, T>} */\n const result = {}\n\n for (const [key, value] of Object.entries(object)) {\n result[key] = value\n\n const camelKey = kebabToCamel(key)\n if (camelKey !== key) {\n result[camelKey] = value\n }\n }\n\n return result\n}\n\n/**\n * Recursively clones an object or array and normalizes any function state\n * it finds into a string representation that preserves standard function syntax,\n * bypassing ES6 shorthand method serialization issues.\n * @param {any} target - The object or array to normalize.\n * @param {Function} [transform] - Optional transform function for each node.\n * @param {WeakMap} [seen=new WeakMap()] - Map of seen objects to handle circular references.\n * @returns {any} A deeply cloned object with normalized functions.\n */\nexport function normalizeObjectFunctions (target, transform = null, seen = new WeakMap()) {\n if (typeof transform === 'function') {\n const transformed = transform(target)\n if (transformed !== target) {\n return transformed\n }\n }\n\n if (typeof target !== 'object' || target === null) {\n return target\n }\n\n if (seen.has(target)) {\n return seen.get(target)\n }\n\n if (Array.isArray(target)) {\n const arr = []\n seen.set(target, arr)\n for (let i = 0; i < target.length; i++) {\n arr.push(normalizeObjectFunctions(target[i], transform, seen))\n }\n return arr\n }\n\n const obj = {}\n seen.set(target, obj)\n for (const key in target) {\n if (Object.hasOwn(target, key)) {\n if (typeof target[key] === 'function') {\n const normalizedString = normalizeFunction(target[key])\n const originalFunction = target[key]\n\n const wrapper = function () {\n return originalFunction.apply(this, arguments)\n }\n wrapper.toString = () => normalizedString\n obj[key] = wrapper\n } else {\n obj[key] = normalizeObjectFunctions(target[key], transform, seen)\n }\n }\n }\n\n return obj\n}\n\n/**\n * Checks whether the given object is an object and has at least one own key.\n * @param {any} obj - The object to check.\n * @returns {boolean} True if the object is truthy and has keys, otherwise false.\n */\nexport function hasObjectKeys (obj) {\n return obj && typeof obj === 'object' && Object.keys(obj).length > 0\n}\n\n/**\n * Merges two arrays, returning a new array with unique items.\n * Uses JSON.stringify for deep comparison of object elements, preserving object uniqueness correctly.\n * @param {Array<any>} [arr1] - The first array.\n * @param {Array<any>} [arr2] - The second array.\n * @returns {Array<any>} A new array with unique values from both input arrays.\n */\nexport function mergeUniqueObjects (arr1, arr2) {\n const all = [...(arr1 || []), ...(arr2 || [])]\n const seen = new Set()\n return all.filter(item => {\n const key = typeof item === 'object' ? JSON.stringify(item) : item\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\n/**\n * Normalizes function declarations to ensure consistent formatting.\n * Converts shorthand method syntax to full function declarations where needed,\n * while preserving arrow functions and existing full declarations.\n *\n * @param {Function} func - The function to normalize\n * @returns {string} The normalized function string representation\n */\nexport function normalizeFunction (func) {\n const original = func.toString().trim()\n\n const firstBrace = original.indexOf('{')\n const firstArrow = original.indexOf('=>')\n\n const isArrow = firstArrow !== -1 && (firstBrace === -1 || firstArrow < firstBrace)\n\n if (isArrow) {\n return original\n }\n\n // For non-arrows, extract header to check for shorthand\n const header = firstBrace !== -1 ? original.slice(0, firstBrace).trim() : original\n\n const isStandard = header.startsWith('function') || header.startsWith('async function')\n\n if (isStandard) {\n return original\n }\n\n // Handle Method Shorthand\n if (header.startsWith('async ')) {\n if (header.startsWith('async get ') || header.startsWith('async set ')) {\n return original\n }\n\n return original.replace(/^async\\s+([$\\w]+)\\s*\\(/, 'async function(')\n } else {\n if (header.startsWith('get ') || header.startsWith('set ')) {\n return original\n }\n\n return original.replace(/^([$\\w]+)\\s*\\(/, 'function(')\n }\n}\n\n\n/**\n * Recursively clones an AST node and its children, ensuring that\n * inner references (like parents and slots) point to the newly cloned nodes.\n *\n * @param {Map<Object, Object>} nodeMap - A map tracking original nodes to their newly cloned counterparts.\n * @param {Object} node - The current AST node being cloned.\n * @param {Object} [parent] - The parent node reference to assign to the clone.\n * @returns {Object} The newly cloned node.\n */\nexport function cloneNode (nodeMap, node, parent) {\n const newNode = Object.create(Object.getPrototypeOf(node))\n\n // Copy all own enumerable properties\n Object.assign(newNode, node)\n\n if (parent) {\n newNode.parent = parent\n }\n\n if (newNode.attribs) {\n newNode.attribs = { ...newNode.attribs }\n }\n\n // Register in map\n nodeMap.set(node, newNode)\n\n // Recursively clone children\n if (node.children) {\n const children = node.children\n const length = children.length\n const clonedChildren = new Array(length)\n newNode.children = clonedChildren\n\n for (let i = 0; i < length; i++) {\n const clonedChild = cloneNode(nodeMap, children[i], newNode)\n clonedChildren[i] = clonedChild\n if (i > 0) {\n clonedChild.prev = clonedChildren[i - 1]\n clonedChildren[i - 1].next = clonedChild\n }\n }\n }\n\n // Update slot references to point to new cloned nodes\n if (node.slots) {\n const slots = node.slots\n const length = slots.length\n const clonedSlots = new Array(length)\n for (let i = 0; i < length; i++) {\n const slot = slots[i]\n const clonedSlot = { ...slot }\n if (slot.node) {\n const clonedNode = nodeMap.get(slot.node)\n if (clonedNode) {\n clonedSlot.node = clonedNode\n }\n }\n clonedSlots[i] = clonedSlot\n }\n newNode.slots = clonedSlots\n }\n\n // Preserve the enhanced flag without re-running enhanceNode\n Object.defineProperty(newNode, '__coralite_enhanced__', {\n value: true,\n enumerable: false,\n configurable: true\n })\n\n return newNode\n}\n\n/**\n * Creates a shallow copy of a CoraliteModule with a deep clone of its DOM tree (template) and re-linked internal references to enable safe independent mutation.\n *\n * Top-level non-DOM state (id, path, script, isTemplate, lineOffset) are shallow copied. Nested objects within these state (e.g., path) remain shared references. Only DOM-related structures undergo deep cloning and reference re-linking to isolate mutations from the original module.\n *\n * @param {CoraliteModule} originalModule - Module to clone.\n * @returns {CoraliteModule}\n */\nexport function cloneModuleInstance (originalModule) {\n const nodeMap = new Map()\n\n // Clone the main template tree\n const newTemplate = cloneNode(nodeMap, originalModule.template, null)\n\n // Reconstruct the 'values' object\n const newValues = {\n attributes: originalModule.values.attributes.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n })),\n textNodes: originalModule.values.textNodes.map(item => ({\n ...item,\n textNode: nodeMap.get(item.textNode)\n })),\n refs: originalModule.values.refs.map(item => ({\n ...item,\n element: nodeMap.get(item.element)\n }))\n }\n\n // Reconstruct customElements list\n const newCustomElements = originalModule.customElements.map(el => nodeMap.get(el))\n\n // Reconstruct slotElements\n const newSlotElements = {}\n if (originalModule.slotElements) {\n for (const modId in originalModule.slotElements) {\n newSlotElements[modId] = {}\n const slotGroup = originalModule.slotElements[modId]\n\n for (const slotName in slotGroup) {\n const slotItem = slotGroup[slotName]\n newSlotElements[modId][slotName] = {\n ...slotItem,\n element: nodeMap.get(slotItem.element)\n }\n }\n }\n }\n\n // Return the new module structure\n return {\n ...originalModule,\n template: newTemplate,\n values: newValues,\n customElements: newCustomElements,\n // @ts-ignore\n slotElements: newSlotElements\n }\n}\n\n/**\n * Creates a deep copy of a CoraliteComponent with re-linked internal references to enable safe independent mutation.\n *\n * @param {CoraliteComponent & CoraliteComponentResult} originalDocument - Document to clone.\n * @returns {CoraliteComponent & CoraliteComponentResult}\n */\nexport function cloneComponentInstance (originalDocument) {\n const nodeMap = new Map()\n const newRoot = cloneNode(nodeMap, originalDocument.root, null)\n\n const newCustomElements = originalDocument.customElements.map(el => nodeMap.get(el))\n const newTempElements = originalDocument.tempElements ? originalDocument.tempElements.map(el => nodeMap.get(el)) : []\n const newSkipRenderElements = originalDocument.skipRenderElements ? originalDocument.skipRenderElements.map(el => nodeMap.get(el)) : []\n\n return {\n ...originalDocument,\n state: { ...originalDocument.state },\n root: newRoot,\n customElements: newCustomElements,\n tempElements: newTempElements,\n skipRenderElements: newSkipRenderElements\n }\n}\n\n/**\n * Calculates the DOM path from a node to the root.\n * @param {Object} node - The node to calculate the path for.\n * @param {Object} root - The root node.\n * @returns {Array<number>} An array of indices representing the path.\n */\nexport function getNodePath (node, root) {\n const path = []\n let current = node\n while (current && current !== root) {\n const parent = current.parent\n if (!parent) {\n break\n }\n const index = parent.children.indexOf(current)\n if (index === -1) {\n break\n }\n path.unshift(index)\n current = parent\n }\n return path\n}\n\n/**\n * Generates a hydration map for the client.\n * @param {Array<Object>} templateNodes - The component's template nodes.\n * @param {Object} templateValues - The component's template values.\n * @returns {Object} The hydration map.\n */\nexport function generateHydrationMap (templateNodes, templateValues) {\n const map = {\n texts: [],\n attributes: [],\n refs: []\n }\n\n if (!templateNodes || !templateValues) {\n return map\n }\n\n const root = templateNodes.length > 0 ? templateNodes[0].parent : { children: templateNodes }\n\n if (templateValues.textNodes) {\n for (const item of templateValues.textNodes) {\n if (item.textNode) {\n const isHtml = item.type === 'html'\n const targetNode = isHtml ? item.textNode.parent : item.textNode\n\n map.texts.push({\n path: getNodePath(targetNode, root),\n template: item.textNode.data,\n type: isHtml ? 'html' : 'text'\n })\n }\n }\n }\n\n if (templateValues.attributes) {\n for (const item of templateValues.attributes) {\n if (item.element && item.element.attribs) {\n const originalValue = item.element.attribs[item.name]\n map.attributes.push({\n path: getNodePath(item.element, root),\n name: item.name,\n template: originalValue\n })\n }\n }\n }\n\n if (templateValues.refs) {\n for (const item of templateValues.refs) {\n if (item.element) {\n map.refs.push({\n path: getNodePath(item.element, root),\n name: item.name\n })\n }\n }\n }\n\n return map\n}\n\n/**\n * Recursively adds a component and its dependencies to a tracking object.\n *\n * @param {string} componentId - The ID of the component to add.\n * @param {Object.<string, boolean>} processed - The object tracking processed components.\n * @param {Object.<string, any>} sharedFunctions - The map of shared component functions.\n */\nexport function addComponentAndDependencies (componentId, processed, sharedFunctions) {\n if (!processed[componentId] && sharedFunctions[componentId]) {\n processed[componentId] = true\n\n // Add all dependencies of this component\n const dependencies = sharedFunctions[componentId].components || []\n for (const depId of dependencies) {\n addComponentAndDependencies(depId, processed, sharedFunctions)\n }\n }\n}\n\n/**\n * Recursively clones an AST node and its children, stripping circular references\n * and assigning unique IDs for client-side hydration.\n *\n * @param {Array<Object>} nodes - The nodes to clean.\n * @param {WeakMap} nodeMap - Map to track original nodes to their unique IDs.\n * @param {Object} state - Object containing the current node counter.\n * @returns {Array<Object>|null} The cleaned AST nodes.\n */\nexport function cleanAST (nodes, nodeMap, state) {\n if (!nodes) {\n return null\n }\n\n return nodes.map((node) => {\n const cloned = { ...node }\n // Assign unique ID for token mapping\n const id = state.counter++\n nodeMap.set(node, id)\n cloned._id = id\n\n // Remove circular references\n delete cloned.parent\n delete cloned.prev\n delete cloned.next\n delete cloned.slots\n\n if (cloned.children) {\n cloned.children = cleanAST(cloned.children, nodeMap, state)\n }\n return cloned\n })\n}\n\n/**\n * Cleans the template values object, mapping original node references to unique IDs.\n *\n * @param {Object} values - The values object to clean.\n * @param {WeakMap} nodeMap - Map of original nodes to their unique IDs.\n * @returns {Object|null} The cleaned values object.\n */\nexport function cleanValues (values, nodeMap) {\n if (!values) {\n return null\n }\n\n const result = { ...values }\n\n if (result.attributes) {\n result.attributes = result.attributes.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n\n if (result.textNodes) {\n result.textNodes = result.textNodes.map(item => {\n const cloned = { ...item }\n cloned.textNodeId = nodeMap.get(item.textNode)\n delete cloned.textNode\n return cloned\n })\n }\n\n if (result.refs) {\n result.refs = result.refs.map(item => {\n const cloned = { ...item }\n cloned.elementId = nodeMap.get(item.element)\n delete cloned.element\n return cloned\n })\n }\n return result\n}\n\n/**\n * Safely merges partial plugin updates into the main context object.\n * Deeply merges plain objects and overwrites other types (arrays, primitives, etc.).\n *\n * @param {any} current - The current state object.\n * @param {any} patch - The patch object containing updates.\n * @returns {any} The newly merged state object.\n */\nexport function mergePluginState (current, patch) {\n if (!patch || typeof patch !== 'object') {\n return current\n }\n\n const result = { ...current }\n\n for (const key of Object.keys(patch)) {\n const patchValue = patch[key]\n const currentValue = result[key]\n\n // If both are plain objects, merge them deeply\n if (\n patchValue && typeof patchValue === 'object' && !Array.isArray(patchValue) &&\n currentValue && typeof currentValue === 'object' && !Array.isArray(currentValue)\n ) {\n result[key] = mergePluginState(currentValue, patchValue)\n } else {\n // Otherwise, overwrite (Arrays, strings, numbers, etc.)\n result[key] = patchValue\n }\n }\n\n return result\n}\n\n/**\n * Creates a reactive proxy that triggers a callback on changes.\n * Supports deep reactivity via lazy proxying of nested objects.\n *\n * @param {Object} target - The object to proxy.\n * @param {Function} onChange - Callback triggered when a property is set or deleted.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies to handle circular references and identity.\n * @returns {Proxy} The reactive proxy.\n */\nexport function createReactiveProxy (target, onChange, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReactiveProxy(value, onChange, proxies)\n }\n return value\n },\n set (target, property, value, receiver) {\n const oldValue = target[property]\n if (oldValue === value && property in target) {\n return true\n }\n\n const result = Reflect.set(target, property, value, receiver)\n if (result) {\n onChange({\n property,\n value,\n oldValue,\n target\n })\n }\n return result\n },\n deleteProperty (target, property) {\n const hadProperty = Object.prototype.hasOwnProperty.call(target, property)\n const oldValue = target[property]\n const result = Reflect.deleteProperty(target, property)\n if (result && hadProperty) {\n onChange({\n property,\n value: undefined,\n oldValue,\n target,\n deleted: true\n })\n }\n return result\n }\n }\n\n const proxy = new Proxy(target, handler)\n proxies.set(target, proxy)\n return proxy\n}\n\n/**\n * Creates a read-only proxy that throws on mutation attempts.\n * @param {Object} target - The object to proxy.\n * @param {WeakMap} [proxies=new WeakMap()] - Cache for existing proxies.\n * @returns {Proxy} The read-only proxy.\n */\nexport function createReadOnlyProxy (target, proxies = new WeakMap()) {\n if (proxies.has(target)) {\n return proxies.get(target)\n }\n\n const handler = {\n get (target, property, receiver) {\n const value = Reflect.get(target, property, receiver)\n if (value !== null && typeof value === 'object' && !(typeof Node !== 'undefined' && value instanceof Node)) {\n return createReadOnlyProxy(value, proxies)\n }\n return value\n },\n set () {\n throw new CoraliteError('Cannot mutate state inside a getter. State is read-only here.')\n },\n deleteProperty () {\n throw new CoraliteError('Cannot delete state inside a getter. State is read-only here.')\n }\n }\n\n const proxy = new Proxy(target, handler)\n\n proxies.set(target, proxy)\n\n return proxy\n}\n\n/**\n * Defines a Coralite component.\n * On the client, this acts as an identity function for type safety and HRM.\n * @param {Object} options - Component options\n * @returns {Object} The component options\n */\nexport function defineComponent (options) {\n return options\n}\n", "/**\n * @import {\n * CoraliteClientPluginDisconnectedCallback,\n * CoraliteClientPluginAfterComponentRenderCallback,\n * CoraliteClientPluginBeforeComponentRenderCallback\n * } from '../types/plugin.js'\n */\n\nimport { createReadOnlyProxy } from './utils/core.js'\n\nconst BOOLEAN_ATTRIBUTES = new Set([\n 'allowfullscreen',\n 'async',\n 'autofocus',\n 'autoplay',\n 'checked',\n 'controls',\n 'default',\n 'defer',\n 'disabled',\n 'formnovalidate',\n 'hidden',\n 'inert',\n 'ismap',\n 'itemscope',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'readonly',\n 'required',\n 'reversed',\n 'selected',\n 'truespeed'\n])\n\n/**\n * Coerces a value to a specified type.\n * Supports Number, Boolean, and String.\n * @param {any} value - The value to coerce.\n * @param {Function|string} type - The target type (Constructor or string name).\n * @returns {any} The coerced value.\n */\nexport function coerce (value, type) {\n if (value === null || value === undefined) {\n return value\n }\n if (type === Number || type === 'Number') {\n return Number(value)\n }\n if (type === Boolean || type === 'Boolean') {\n if (value === '') {\n return true\n }\n return value !== 'false' && value !== null\n }\n if (type === String || type === 'String') {\n return String(value)\n }\n return value\n}\n\n/**\n * @typedef {Object} CoraliteComponentOptions\n * @property {string} componentId - The unique identifier for the component.\n * @property {string} [templateHTML] - The raw HTML string for imperative mounting.\n * @property {Object} [defaultValues] - The initial state values extracted from the server data block.\n * @property {Object} [attributes] - Schema for coercing HTML attributes into typed primitives.\n * @property {Object.<string, Function>} [getters] - Pure functions for derived state, supporting Promises.\n * @property {Object.<string, Function>} [slots] - Transformation functions for projected Light DOM.\n * @property {Function} [client] - The client-side controller logic.\n * @property {Object} [hydrationMap] - AST mapping for reactive text nodes, attributes, and refs.\n */\n\n/**\n * Base class for all Coralite custom elements.\n *\n * @augments HTMLElement\n */\nexport class CoraliteElement extends HTMLElement {\n /**\n * Initializes a new instance of the CoraliteElement.\n * Sets up internal state trackers, binding collections, and hook registries.\n */\n constructor () {\n super()\n /**\n * Controls native teardown of event listeners and async fetches upon disconnection.\n * @type {AbortController|null}\n * @protected\n */\n this._abortController = null\n\n /**\n * A globally unique, deterministic identifier (e.g., `my-comp-0`).\n * @type {string|null}\n * @protected\n */\n this._instanceId = null\n\n /**\n * The unified, deeply reactive proxy holding attributes, data, and getters.\n * @type {Object|null}\n * @protected\n */\n this._state = null\n\n /**\n * The collection of DOM nodes mapped to template tokens and attributes.\n * @type {Array<{type: string, node: Node, template?: string, name?: string}>}\n * @protected\n */\n this._bindings = []\n\n /**\n * Flag to prevent multiple synchronous state mutations from triggering multiple DOM paints.\n * @type {boolean}\n * @protected\n */\n this._isUpdatePending = false\n\n /**\n * A unique Symbol generated per render cycle to prevent async getter race conditions.\n * @type {symbol|null}\n * @protected\n */\n this._currentRenderVersion = null\n\n /**\n * @type {MutationObserver|null}\n * @protected\n */\n this._observer = null\n\n /**\n * Hook to fetch globally registered Phase-2 plugin contexts.\n * @type {Function|null}\n * @protected\n */\n this._clientContextGetter = null\n\n /**\n * Tracks AbortControllers specifically for cancelling stale async getters.\n * @type {Object.<string, AbortController>|null}\n * @protected\n */\n this._getterAbortControllers = null\n\n /**\n * Internal lifecycle hooks injected by registered Coralite plugins.\n * @type {{\n * onBeforeComponentRender: Array<CoraliteClientPluginBeforeComponentRenderCallback>,\n * onAfterComponentRender: Array<CoraliteClientPluginAfterComponentRenderCallback>,\n * onDisconnected: Array<CoraliteClientPluginDisconnectedCallback>\n * }}\n * @protected\n */\n this._hooks = {\n onBeforeComponentRender: [],\n onAfterComponentRender: [],\n onDisconnected: []\n }\n\n /**\n * The definition and schema of the component generated by the compiler.\n * @type {CoraliteComponentOptions|null}\n */\n this.componentOptions = null\n }\n\n /**\n * Invoked natively when the element is added to the document.\n * Handles the architectural split between Declarative (SSR) and Imperative (JS) components.\n * Orchestrates template injection, instance ID generation, and state/binding setup.\n */\n connectedCallback () {\n this._abortController = new AbortController()\n\n if (!this.componentOptions) {\n return\n }\n\n // Declarative components receive a data-cid from the server.\n // Imperative components (created via document.createElement) do not.\n const isImperative = !this.hasAttribute('data-cid')\n\n // Imperative Flow: Manually stamp the template and project the Light DOM.\n if (isImperative && this.componentOptions.templateHTML) {\n const originalLightDOM = Array.from(this.childNodes)\n this.innerHTML = this.componentOptions.templateHTML\n\n if (originalLightDOM.length > 0) {\n const slots = this.querySelectorAll('slot')\n slots.forEach(slot => {\n const slotName = slot.getAttribute('name') || 'default'\n const matchingNodes = originalLightDOM.filter(node => {\n // @ts-ignore\n const nodeSlot = (node.getAttribute && node.getAttribute('slot')) || 'default'\n return nodeSlot === slotName\n })\n matchingNodes.forEach(n => slot.appendChild(n))\n })\n }\n }\n\n // Establish the Deterministic Instance ID\n if (this.hasAttribute('data-cid')) {\n this._instanceId = this.getAttribute('data-cid')\n } else {\n // Fallback counter for imperatively created components\n // @ts-ignore\n window.__coralite_instanceCounters = window.__coralite_instanceCounters || {}\n const prefix = this.componentOptions.componentId\n // @ts-ignore\n if (window.__coralite_instanceCounters[prefix] === undefined) {\n // @ts-ignore\n window.__coralite_instanceCounters[prefix] = 0\n }\n // @ts-ignore\n this._instanceId = `${prefix}-${window.__coralite_instanceCounters[prefix]++}`\n }\n\n if (isImperative) {\n this.setAttribute('data-cid', this._instanceId)\n }\n\n this._setupState()\n this._setupBindings()\n this._init(isImperative)\n }\n\n /**\n * Invoked natively when the element is removed from the document.\n * Aborts pending requests and triggers `onDisconnected` plugin hooks\n * to ensure external libraries (e.g., Observers) do not cause memory leaks.\n * @this {any}\n */\n disconnectedCallback () {\n if (this._abortController) {\n this._abortController.abort()\n }\n\n if (!this.componentOptions) {\n return\n }\n\n for (const hook of this._hooks.onDisconnected) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n /**\n * Invoked natively when an observed HTML attribute changes.\n * Coerces the raw string value based on the component's attribute schema\n * and synchronizes it into the reactive state proxy.\n * @param {string} name - The kebab-case name of the attribute.\n * @param {string|null} oldVal - The previous value.\n * @param {string|null} newVal - The new value.\n */\n attributeChangedCallback (name, oldVal, newVal) {\n if (!this._state || oldVal === newVal || name === 'data-cid') {\n return\n }\n const camelName = name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = this.componentOptions.attributes?.[camelName] || this.componentOptions.attributes?.[name]\n const value = schema ? coerce(newVal, schema.type) : newVal\n\n this._state[camelName] = value\n }\n\n /**\n * Constructs the unified state object.\n * Merges `defaultValues`, JSON hydration payloads, and DOM attributes.\n * Defines getters (wrapping state in a Read-Only proxy) and applies the final Read/Write Proxy.\n * @this {any}\n * @private\n */\n _setupState () {\n const options = this.componentOptions\n const target = { ...options.defaultValues }\n\n /** @type {Array<{name: string, element: HTMLElement}>} */\n const refs = []\n if (options.hydrationMap && options.hydrationMap.refs) {\n for (const ref of options.hydrationMap.refs) {\n const uniqueRefValue = `${this._instanceId}__${ref.name}`\n\n if (!target[`ref_${ref.name}`]) {\n target[`ref_${ref.name}`] = uniqueRefValue\n }\n\n const node = this.getNodeByPath(ref.path)\n if (node) {\n if (node.setAttribute) {\n node.setAttribute('ref', uniqueRefValue)\n }\n refs.push({\n name: ref.name,\n element: node\n })\n }\n }\n }\n\n // Trigger Before-Render hooks BEFORE state is proxied, allowing plugins to inject reactive data\n for (const hook of this._hooks.onBeforeComponentRender) {\n hook({\n state: target,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n refs,\n element: this,\n options: this.componentOptions\n })\n }\n\n // Hydrate data() block results from the SSR JSON payload\n const hydrationTag = document.getElementById('__CORALITE_HYDRATION__')\n if (hydrationTag) {\n try {\n const allData = JSON.parse(hydrationTag.textContent)\n if (allData[this._instanceId]) {\n Object.assign(target, allData[this._instanceId])\n }\n } catch {\n console.error('Coralite Element hydration failed:', this._instanceId)\n }\n }\n\n // Process initial attributes mapping\n for (const attr of this.attributes) {\n if (attr.name === 'data-cid') {\n continue\n }\n const camelName = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase())\n const schema = options.attributes?.[camelName] || options.attributes?.[attr.name]\n target[camelName] = schema ? coerce(attr.value, schema.type) : attr.value\n }\n\n // Define derived state getters with isolation controllers\n this._getterAbortControllers = {}\n for (const [key, getter] of Object.entries(options.getters || {})) {\n Object.defineProperty(target, key, {\n get: () => {\n if (this._getterAbortControllers[key]) {\n this._getterAbortControllers[key].abort()\n }\n this._getterAbortControllers[key] = new AbortController()\n\n // Enforce \"Dual-Proxy\" safety: Getters cannot mutate state\n const roState = createReadOnlyProxy(this._state)\n return getter(roState, { signal: this._getterAbortControllers[key].signal })\n },\n enumerable: true,\n configurable: true\n })\n }\n\n this._state = this._createReactiveProxy(target)\n }\n\n /**\n * Wraps the state target in a reactive Proxy.\n * Intercepts property setters to automatically batch and schedule DOM updates.\n * @param {Object} target - The state dictionary.\n * @returns {Proxy} The reactive state proxy.\n * @private\n */\n _createReactiveProxy (target) {\n const self = this\n return new Proxy(target, {\n set (t, p, v) {\n if (t[p] === v) {\n return true\n }\n t[p] = v\n self._scheduleUpdate()\n return true\n }\n })\n }\n\n /**\n * Traverses the DOM tree using an AST-generated path index array.\n * Allows O(1) element lookups without relying on querySelectors or classes.\n * @param {number[]} path - Array of childNode indices (e.g., `[0, 1, 2]`).\n * @returns {Node|null} The physical DOM node, or null if traversal fails.\n */\n getNodeByPath (path) {\n let node = this\n for (const index of path) {\n if (!node) {\n return null\n }\n // @ts-ignore\n node = node.childNodes[index]\n }\n return node\n }\n\n /**\n * Initializes DOM bindings based on the compiler's hydration map.\n * Caches physical DOM references to text nodes and attributes that contain template tokens.\n * @private\n */\n _setupBindings () {\n this._bindings = []\n const map = this.componentOptions.hydrationMap\n if (!map) {\n return\n }\n\n if (map.texts) {\n for (const item of map.texts) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: item.type || 'text',\n node,\n template: item.template\n })\n }\n }\n }\n\n if (map.attributes) {\n for (const item of map.attributes) {\n const node = this.getNodeByPath(item.path)\n if (node) {\n this._bindings.push({\n type: 'attribute',\n node,\n name: item.name,\n template: item.template\n })\n }\n }\n }\n }\n\n /**\n * Schedules a DOM update in the next microtask queue.\n * This guarantees that multiple synchronous state mutations result in only one render pass.\n * @private\n */\n _scheduleUpdate () {\n if (this._isUpdatePending) {\n return\n }\n this._isUpdatePending = true\n queueMicrotask(() => {\n this._updateDOM()\n this._isUpdatePending = false\n })\n }\n\n /**\n * Performs the physical DOM update and resolves template tokens.\n * **Async Safety:** Implements a Symbol-based locking mechanism (`renderVersion`)\n * to guarantee that if state mutates while an async getter is pending, the stale\n * Promise will be discarded, preventing DOM race conditions.\n * @this {any}\n * @private\n */\n _updateDOM () {\n // Create a unique lock for this specific render cycle\n const renderVersion = Symbol()\n this._currentRenderVersion = renderVersion\n\n // Extract unique tokens to prevent double-reading and accidental aborts\n /** @type {Set<string>} */\n const requiredTokens = new Set()\n for (const binding of this._bindings) {\n binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n requiredTokens.add(key)\n return ''\n })\n }\n\n const evaluatedTokens = {}\n let hasPromise = false\n\n // Evaluate getters exactly once per render cycle\n for (const key of requiredTokens) {\n let val = this._state[key]\n if (typeof val === 'function') {\n val = val(this._state)\n }\n evaluatedTokens[key] = val\n if (val instanceof Promise) {\n hasPromise = true\n }\n }\n\n // The DOM Mutator Function\n const applyBindings = (tokenValues) => {\n // Race Condition Lock: Abort if a newer render cycle has already begun\n if (this._currentRenderVersion !== renderVersion) {\n return\n }\n\n for (const binding of this._bindings) {\n const hydratedValue = binding.template.replace(/\\{\\{\\s*(.+?)\\s*\\}\\}/g, (_, key) => {\n return tokenValues[key] ?? ''\n })\n\n if (binding.type === 'text') {\n if (binding.node.textContent !== hydratedValue) {\n binding.node.textContent = hydratedValue\n }\n } else if (binding.type === 'html') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (element.innerHTML !== hydratedValue) {\n element.innerHTML = hydratedValue\n }\n } else if (binding.type === 'attribute') {\n /** @type {HTMLElement} */\n // @ts-ignore\n const element = binding.node\n\n if (BOOLEAN_ATTRIBUTES.has(binding.name)) {\n const isFalsy = hydratedValue === '' || hydratedValue === 'false' || hydratedValue === 'null' || hydratedValue === '0' || hydratedValue === 'undefined'\n if (isFalsy) {\n element.removeAttribute(binding.name)\n } else {\n element.setAttribute(binding.name, '')\n }\n } else {\n if (element.getAttribute(binding.name) !== hydratedValue) {\n element.setAttribute(binding.name, hydratedValue)\n }\n }\n }\n }\n\n this._processSlots()\n\n // Trigger After-Render hooks ONLY after the physical DOM is stable\n for (const hook of this._hooks.onAfterComponentRender) {\n hook({\n state: this._state,\n instanceId: this._instanceId,\n componentId: this.componentOptions.componentId,\n element: this,\n options: this.componentOptions\n })\n }\n }\n\n // Await Promises or Apply Synchronously\n if (hasPromise) {\n const keys = Object.keys(evaluatedTokens)\n const promises = keys.map(k => Promise.resolve(evaluatedTokens[k]))\n\n Promise.all(promises).then(resolvedValues => {\n const resolvedMap = {}\n keys.forEach((k, i) => {\n resolvedMap[k] = resolvedValues[i]\n })\n applyBindings(resolvedMap)\n }).catch(e => {\n if (e.name !== 'AbortError') {\n console.error('Coralite Async Getter Error:', e)\n }\n })\n } else {\n applyBindings(evaluatedTokens)\n }\n }\n\n /**\n * Evaluates and projects Light DOM elements into their respective `<slot>` nodes.\n * Invokes component-specific slot transformation functions.\n * @private\n */\n _processSlots () {\n const slots = this.componentOptions.slots\n if (!slots || Object.keys(slots).length === 0) {\n return\n }\n\n const slotElements = this.querySelectorAll('slot')\n slotElements.forEach(slotEl => {\n const slotName = slotEl.getAttribute('name') || 'default'\n const slotFn = slots[slotName]\n\n if (slotFn) {\n // @ts-ignore\n if (!slotEl._originalNodes) {\n // @ts-ignore\n slotEl._originalNodes = Array.from(slotEl.childNodes).map(n => n.cloneNode(true))\n }\n\n // @ts-ignore\n const result = slotFn(slotEl._originalNodes, this._state)\n\n if (result === undefined) {\n return\n }\n\n if (result === null || result === '' || (Array.isArray(result) && result.length === 0)) {\n slotEl.innerHTML = ''\n return\n }\n\n if (typeof result === 'string') {\n slotEl.innerHTML = result\n } else if (Array.isArray(result)) {\n slotEl.replaceChildren(...result)\n }\n }\n })\n }\n\n /**\n * The final initialization pipeline.\n * Injects globally registered client plugins into the local context payload,\n * triggers the initial DOM render, and invokes the user's `script()` logic.\n * @param {boolean} [isImperative=false] - If true, initial render runs synchronously.\n * @private\n */\n async _init (isImperative = false) {\n const self = this\n /**\n * The context payload injected into the user's script block.\n * @type {Object}\n */\n let localContext = {\n instanceId: this._instanceId,\n state: this._state,\n root: this,\n signal: this._abortController.signal,\n refs (id) {\n const refId = self._state[`ref_${id}`]\n if (!refId && typeof refId !== 'string') {\n return null\n }\n return self.querySelector(`[ref=\"${refId}\"]`)\n }\n }\n\n if (typeof this._clientContextGetter === 'function') {\n localContext = await this._clientContextGetter(localContext)\n }\n\n if (isImperative) {\n this._updateDOM()\n } else {\n this._scheduleUpdate()\n }\n\n if (this.componentOptions.client) {\n try {\n this.componentOptions.client(localContext)\n } catch (error) {\n console.error(`Coralite Error: Component \"${this.componentOptions.componentId}\" script failed:`, error)\n }\n }\n }\n}\n\n/**\n * Factory function to create a Coralite element class.\n * It dynamically defines the class, including observed attributes and hook initialization.\n * @param {CoraliteComponentOptions} options - Component options and metadata.\n * @param {Function|null} [contextGetter=null] - Optional function to retrieve client-side plugin context.\n * @param {Object} [hooks={}] - Lifecycle hooks to register.\n * @param {Array<CoraliteClientPluginBeforeComponentRenderCallback>} [hooks.onBeforeComponentRender] - Hooks to run before render.\n * @param {Array<CoraliteClientPluginAfterComponentRenderCallback>} [hooks.onAfterComponentRender] - Hooks to run after render.\n * @param {Array<CoraliteClientPluginDisconnectedCallback>} [hooks.onDisconnected] - Hooks to run after render.\n * @returns {typeof CoraliteElement} A new CoraliteElement subclass.\n */\nexport function createCoraliteClass (options, contextGetter = null, hooks = {}) {\n return class extends CoraliteElement {\n /**\n * The attributes to observe for changes.\n * @returns {string[]} Array of attribute names.\n */\n static get observedAttributes () {\n if (!options.attributes) {\n return []\n }\n return Object.keys(options.attributes).map(key => key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n )\n }\n\n /**\n * Initializes the dynamic Coralite element.\n */\n constructor () {\n super()\n this.componentOptions = options\n this._clientContextGetter = contextGetter\n this._hooks = {\n onBeforeComponentRender: hooks.onBeforeComponentRender || [],\n onAfterComponentRender: hooks.onAfterComponentRender || [],\n onDisconnected: hooks.onDisconnected || []\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAQO,IAAM,gBAAN,cAA4B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAavC,YAAa,SAAS,UAAU,CAAC,GAAG;AAClC,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AACZ,SAAK,kBAAkB;AACvB,SAAK,cAAc,QAAQ;AAC3B,SAAK,WAAW,QAAQ;AACxB,SAAK,aAAa,QAAQ;AAC1B,SAAK,WAAW,QAAQ;AACxB,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ;AAGzB,QAAI,QAAQ,SAAS,CAAC,KAAK,OAAO;AAChC,WAAK,QAAQ,QAAQ;AAAA,IACvB;AAAA,EACF;AACF;;;ACkkBO,SAAS,oBAAqB,QAAQ,UAAU,oBAAI,QAAQ,GAAG;AACpE,MAAI,QAAQ,IAAI,MAAM,GAAG;AACvB,WAAO,QAAQ,IAAI,MAAM;AAAA,EAC3B;AAEA,QAAM,UAAU;AAAA,IACd,IAAKA,SAAQ,UAAU,UAAU;AAC/B,YAAM,QAAQ,QAAQ,IAAIA,SAAQ,UAAU,QAAQ;AACpD,UAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,EAAE,OAAO,SAAS,eAAe,iBAAiB,OAAO;AAC1G,eAAO,oBAAoB,OAAO,OAAO;AAAA,MAC3C;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAO;AACL,YAAM,IAAI,cAAc,+DAA+D;AAAA,IACzF;AAAA,IACA,iBAAkB;AAChB,YAAM,IAAI,cAAc,+DAA+D;AAAA,IACzF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,MAAM,QAAQ,OAAO;AAEvC,UAAQ,IAAI,QAAQ,KAAK;AAEzB,SAAO;AACT;;;ACxnBA,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,SAAS,OAAQ,OAAO,MAAM;AACnC,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AACA,MAAI,SAAS,UAAU,SAAS,UAAU;AACxC,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,MAAI,SAAS,WAAW,SAAS,WAAW;AAC1C,QAAI,UAAU,IAAI;AAChB,aAAO;AAAA,IACT;AACA,WAAO,UAAU,WAAW,UAAU;AAAA,EACxC;AACA,MAAI,SAAS,UAAU,SAAS,UAAU;AACxC,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,SAAO;AACT;AAmBO,IAAM,kBAAN,cAA8B,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAK/C,cAAe;AACb,UAAM;AAMN,SAAK,mBAAmB;AAOxB,SAAK,cAAc;AAOnB,SAAK,SAAS;AAOd,SAAK,YAAY,CAAC;AAOlB,SAAK,mBAAmB;AAOxB,SAAK,wBAAwB;AAM7B,SAAK,YAAY;AAOjB,SAAK,uBAAuB;AAO5B,SAAK,0BAA0B;AAW/B,SAAK,SAAS;AAAA,MACZ,yBAAyB,CAAC;AAAA,MAC1B,wBAAwB,CAAC;AAAA,MACzB,gBAAgB,CAAC;AAAA,IACnB;AAMA,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAqB;AACnB,SAAK,mBAAmB,IAAI,gBAAgB;AAE5C,QAAI,CAAC,KAAK,kBAAkB;AAC1B;AAAA,IACF;AAIA,UAAM,eAAe,CAAC,KAAK,aAAa,UAAU;AAGlD,QAAI,gBAAgB,KAAK,iBAAiB,cAAc;AACtD,YAAM,mBAAmB,MAAM,KAAK,KAAK,UAAU;AACnD,WAAK,YAAY,KAAK,iBAAiB;AAEvC,UAAI,iBAAiB,SAAS,GAAG;AAC/B,cAAM,QAAQ,KAAK,iBAAiB,MAAM;AAC1C,cAAM,QAAQ,UAAQ;AACpB,gBAAM,WAAW,KAAK,aAAa,MAAM,KAAK;AAC9C,gBAAM,gBAAgB,iBAAiB,OAAO,UAAQ;AAEpD,kBAAM,WAAY,KAAK,gBAAgB,KAAK,aAAa,MAAM,KAAM;AACrE,mBAAO,aAAa;AAAA,UACtB,CAAC;AACD,wBAAc,QAAQ,OAAK,KAAK,YAAY,CAAC,CAAC;AAAA,QAChD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,KAAK,aAAa,UAAU,GAAG;AACjC,WAAK,cAAc,KAAK,aAAa,UAAU;AAAA,IACjD,OAAO;AAGL,aAAO,8BAA8B,OAAO,+BAA+B,CAAC;AAC5E,YAAM,SAAS,KAAK,iBAAiB;AAErC,UAAI,OAAO,4BAA4B,MAAM,MAAM,QAAW;AAE5D,eAAO,4BAA4B,MAAM,IAAI;AAAA,MAC/C;AAEA,WAAK,cAAc,GAAG,MAAM,IAAI,OAAO,4BAA4B,MAAM,GAAG;AAAA,IAC9E;AAEA,QAAI,cAAc;AAChB,WAAK,aAAa,YAAY,KAAK,WAAW;AAAA,IAChD;AAEA,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,MAAM,YAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAwB;AACtB,QAAI,KAAK,kBAAkB;AACzB,WAAK,iBAAiB,MAAM;AAAA,IAC9B;AAEA,QAAI,CAAC,KAAK,kBAAkB;AAC1B;AAAA,IACF;AAEA,eAAW,QAAQ,KAAK,OAAO,gBAAgB;AAC7C,WAAK;AAAA,QACH,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,QACjB,aAAa,KAAK,iBAAiB;AAAA,QACnC,SAAS;AAAA,QACT,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,yBAA0B,MAAM,QAAQ,QAAQ;AAC9C,QAAI,CAAC,KAAK,UAAU,WAAW,UAAU,SAAS,YAAY;AAC5D;AAAA,IACF;AACA,UAAM,YAAY,KAAK,QAAQ,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,YAAY,CAAC;AACrE,UAAM,SAAS,KAAK,iBAAiB,aAAa,SAAS,KAAK,KAAK,iBAAiB,aAAa,IAAI;AACvG,UAAM,QAAQ,SAAS,OAAO,QAAQ,OAAO,IAAI,IAAI;AAErD,SAAK,OAAO,SAAS,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAe;AACb,UAAM,UAAU,KAAK;AACrB,UAAM,SAAS,EAAE,GAAG,QAAQ,cAAc;AAG1C,UAAM,OAAO,CAAC;AACd,QAAI,QAAQ,gBAAgB,QAAQ,aAAa,MAAM;AACrD,iBAAW,OAAO,QAAQ,aAAa,MAAM;AAC3C,cAAM,iBAAiB,GAAG,KAAK,WAAW,KAAK,IAAI,IAAI;AAEvD,YAAI,CAAC,OAAO,OAAO,IAAI,IAAI,EAAE,GAAG;AAC9B,iBAAO,OAAO,IAAI,IAAI,EAAE,IAAI;AAAA,QAC9B;AAEA,cAAM,OAAO,KAAK,cAAc,IAAI,IAAI;AACxC,YAAI,MAAM;AACR,cAAI,KAAK,cAAc;AACrB,iBAAK,aAAa,OAAO,cAAc;AAAA,UACzC;AACA,eAAK,KAAK;AAAA,YACR,MAAM,IAAI;AAAA,YACV,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,eAAW,QAAQ,KAAK,OAAO,yBAAyB;AACtD,WAAK;AAAA,QACH,OAAO;AAAA,QACP,YAAY,KAAK;AAAA,QACjB,aAAa,KAAK,iBAAiB;AAAA,QACnC;AAAA,QACA,SAAS;AAAA,QACT,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAGA,UAAM,eAAe,SAAS,eAAe,wBAAwB;AACrE,QAAI,cAAc;AAChB,UAAI;AACF,cAAM,UAAU,KAAK,MAAM,aAAa,WAAW;AACnD,YAAI,QAAQ,KAAK,WAAW,GAAG;AAC7B,iBAAO,OAAO,QAAQ,QAAQ,KAAK,WAAW,CAAC;AAAA,QACjD;AAAA,MACF,QAAQ;AACN,gBAAQ,MAAM,sCAAsC,KAAK,WAAW;AAAA,MACtE;AAAA,IACF;AAGA,eAAW,QAAQ,KAAK,YAAY;AAClC,UAAI,KAAK,SAAS,YAAY;AAC5B;AAAA,MACF;AACA,YAAM,YAAY,KAAK,KAAK,QAAQ,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,YAAY,CAAC;AAC1E,YAAM,SAAS,QAAQ,aAAa,SAAS,KAAK,QAAQ,aAAa,KAAK,IAAI;AAChF,aAAO,SAAS,IAAI,SAAS,OAAO,KAAK,OAAO,OAAO,IAAI,IAAI,KAAK;AAAA,IACtE;AAGA,SAAK,0BAA0B,CAAC;AAChC,eAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,QAAQ,WAAW,CAAC,CAAC,GAAG;AACjE,aAAO,eAAe,QAAQ,KAAK;AAAA,QACjC,KAAK,MAAM;AACT,cAAI,KAAK,wBAAwB,GAAG,GAAG;AACrC,iBAAK,wBAAwB,GAAG,EAAE,MAAM;AAAA,UAC1C;AACA,eAAK,wBAAwB,GAAG,IAAI,IAAI,gBAAgB;AAGxD,gBAAM,UAAU,oBAAoB,KAAK,MAAM;AAC/C,iBAAO,OAAO,SAAS,EAAE,QAAQ,KAAK,wBAAwB,GAAG,EAAE,OAAO,CAAC;AAAA,QAC7E;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAEA,SAAK,SAAS,KAAK,qBAAqB,MAAM;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,qBAAsB,QAAQ;AAC5B,UAAM,OAAO;AACb,WAAO,IAAI,MAAM,QAAQ;AAAA,MACvB,IAAK,GAAG,GAAG,GAAG;AACZ,YAAI,EAAE,CAAC,MAAM,GAAG;AACd,iBAAO;AAAA,QACT;AACA,UAAE,CAAC,IAAI;AACP,aAAK,gBAAgB;AACrB,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAe,MAAM;AACnB,QAAI,OAAO;AACX,eAAW,SAAS,MAAM;AACxB,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,MACT;AAEA,aAAO,KAAK,WAAW,KAAK;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAkB;AAChB,SAAK,YAAY,CAAC;AAClB,UAAM,MAAM,KAAK,iBAAiB;AAClC,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,QAAI,IAAI,OAAO;AACb,iBAAW,QAAQ,IAAI,OAAO;AAC5B,cAAM,OAAO,KAAK,cAAc,KAAK,IAAI;AACzC,YAAI,MAAM;AACR,eAAK,UAAU,KAAK;AAAA,YAClB,MAAM,KAAK,QAAQ;AAAA,YACnB;AAAA,YACA,UAAU,KAAK;AAAA,UACjB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,QAAI,IAAI,YAAY;AAClB,iBAAW,QAAQ,IAAI,YAAY;AACjC,cAAM,OAAO,KAAK,cAAc,KAAK,IAAI;AACzC,YAAI,MAAM;AACR,eAAK,UAAU,KAAK;AAAA,YAClB,MAAM;AAAA,YACN;AAAA,YACA,MAAM,KAAK;AAAA,YACX,UAAU,KAAK;AAAA,UACjB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAmB;AACjB,QAAI,KAAK,kBAAkB;AACzB;AAAA,IACF;AACA,SAAK,mBAAmB;AACxB,mBAAe,MAAM;AACnB,WAAK,WAAW;AAChB,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAc;AAEZ,UAAM,gBAAgB,OAAO;AAC7B,SAAK,wBAAwB;AAI7B,UAAM,iBAAiB,oBAAI,IAAI;AAC/B,eAAW,WAAW,KAAK,WAAW;AACpC,cAAQ,SAAS,QAAQ,wBAAwB,CAAC,GAAG,QAAQ;AAC3D,uBAAe,IAAI,GAAG;AACtB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,UAAM,kBAAkB,CAAC;AACzB,QAAI,aAAa;AAGjB,eAAW,OAAO,gBAAgB;AAChC,UAAI,MAAM,KAAK,OAAO,GAAG;AACzB,UAAI,OAAO,QAAQ,YAAY;AAC7B,cAAM,IAAI,KAAK,MAAM;AAAA,MACvB;AACA,sBAAgB,GAAG,IAAI;AACvB,UAAI,eAAe,SAAS;AAC1B,qBAAa;AAAA,MACf;AAAA,IACF;AAGA,UAAM,gBAAgB,CAAC,gBAAgB;AAErC,UAAI,KAAK,0BAA0B,eAAe;AAChD;AAAA,MACF;AAEA,iBAAW,WAAW,KAAK,WAAW;AACpC,cAAM,gBAAgB,QAAQ,SAAS,QAAQ,wBAAwB,CAAC,GAAG,QAAQ;AACjF,iBAAO,YAAY,GAAG,KAAK;AAAA,QAC7B,CAAC;AAED,YAAI,QAAQ,SAAS,QAAQ;AAC3B,cAAI,QAAQ,KAAK,gBAAgB,eAAe;AAC9C,oBAAQ,KAAK,cAAc;AAAA,UAC7B;AAAA,QACF,WAAW,QAAQ,SAAS,QAAQ;AAGlC,gBAAM,UAAU,QAAQ;AAExB,cAAI,QAAQ,cAAc,eAAe;AACvC,oBAAQ,YAAY;AAAA,UACtB;AAAA,QACF,WAAW,QAAQ,SAAS,aAAa;AAGvC,gBAAM,UAAU,QAAQ;AAExB,cAAI,mBAAmB,IAAI,QAAQ,IAAI,GAAG;AACxC,kBAAM,UAAU,kBAAkB,MAAM,kBAAkB,WAAW,kBAAkB,UAAU,kBAAkB,OAAO,kBAAkB;AAC5I,gBAAI,SAAS;AACX,sBAAQ,gBAAgB,QAAQ,IAAI;AAAA,YACtC,OAAO;AACL,sBAAQ,aAAa,QAAQ,MAAM,EAAE;AAAA,YACvC;AAAA,UACF,OAAO;AACL,gBAAI,QAAQ,aAAa,QAAQ,IAAI,MAAM,eAAe;AACxD,sBAAQ,aAAa,QAAQ,MAAM,aAAa;AAAA,YAClD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,WAAK,cAAc;AAGnB,iBAAW,QAAQ,KAAK,OAAO,wBAAwB;AACrD,aAAK;AAAA,UACH,OAAO,KAAK;AAAA,UACZ,YAAY,KAAK;AAAA,UACjB,aAAa,KAAK,iBAAiB;AAAA,UACnC,SAAS;AAAA,UACT,SAAS,KAAK;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,YAAY;AACd,YAAM,OAAO,OAAO,KAAK,eAAe;AACxC,YAAM,WAAW,KAAK,IAAI,OAAK,QAAQ,QAAQ,gBAAgB,CAAC,CAAC,CAAC;AAElE,cAAQ,IAAI,QAAQ,EAAE,KAAK,oBAAkB;AAC3C,cAAM,cAAc,CAAC;AACrB,aAAK,QAAQ,CAAC,GAAG,MAAM;AACrB,sBAAY,CAAC,IAAI,eAAe,CAAC;AAAA,QACnC,CAAC;AACD,sBAAc,WAAW;AAAA,MAC3B,CAAC,EAAE,MAAM,OAAK;AACZ,YAAI,EAAE,SAAS,cAAc;AAC3B,kBAAQ,MAAM,gCAAgC,CAAC;AAAA,QACjD;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,oBAAc,eAAe;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAiB;AACf,UAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAI,CAAC,SAAS,OAAO,KAAK,KAAK,EAAE,WAAW,GAAG;AAC7C;AAAA,IACF;AAEA,UAAM,eAAe,KAAK,iBAAiB,MAAM;AACjD,iBAAa,QAAQ,YAAU;AAC7B,YAAM,WAAW,OAAO,aAAa,MAAM,KAAK;AAChD,YAAM,SAAS,MAAM,QAAQ;AAE7B,UAAI,QAAQ;AAEV,YAAI,CAAC,OAAO,gBAAgB;AAE1B,iBAAO,iBAAiB,MAAM,KAAK,OAAO,UAAU,EAAE,IAAI,OAAK,EAAE,UAAU,IAAI,CAAC;AAAA,QAClF;AAGA,cAAM,SAAS,OAAO,OAAO,gBAAgB,KAAK,MAAM;AAExD,YAAI,WAAW,QAAW;AACxB;AAAA,QACF;AAEA,YAAI,WAAW,QAAQ,WAAW,MAAO,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAI;AACtF,iBAAO,YAAY;AACnB;AAAA,QACF;AAEA,YAAI,OAAO,WAAW,UAAU;AAC9B,iBAAO,YAAY;AAAA,QACrB,WAAW,MAAM,QAAQ,MAAM,GAAG;AAChC,iBAAO,gBAAgB,GAAG,MAAM;AAAA,QAClC;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAO,eAAe,OAAO;AACjC,UAAM,OAAO;AAKb,QAAI,eAAe;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,QAAQ,KAAK,iBAAiB;AAAA,MAC9B,KAAM,IAAI;AACR,cAAM,QAAQ,KAAK,OAAO,OAAO,EAAE,EAAE;AACrC,YAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,iBAAO;AAAA,QACT;AACA,eAAO,KAAK,cAAc,SAAS,KAAK,IAAI;AAAA,MAC9C;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,yBAAyB,YAAY;AACnD,qBAAe,MAAM,KAAK,qBAAqB,YAAY;AAAA,IAC7D;AAEA,QAAI,cAAc;AAChB,WAAK,WAAW;AAAA,IAClB,OAAO;AACL,WAAK,gBAAgB;AAAA,IACvB;AAEA,QAAI,KAAK,iBAAiB,QAAQ;AAChC,UAAI;AACF,aAAK,iBAAiB,OAAO,YAAY;AAAA,MAC3C,SAAS,OAAO;AACd,gBAAQ,MAAM,8BAA8B,KAAK,iBAAiB,WAAW,oBAAoB,KAAK;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AACF;AAaO,SAAS,oBAAqB,SAAS,gBAAgB,MAAM,QAAQ,CAAC,GAAG;AAC9E,SAAO,cAAc,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKnC,WAAW,qBAAsB;AAC/B,UAAI,CAAC,QAAQ,YAAY;AACvB,eAAO,CAAC;AAAA,MACV;AACA,aAAO,OAAO,KAAK,QAAQ,UAAU,EAAE;AAAA,QAAI,SAAO,IAAI,QAAQ,mBAAmB,OAAO,EAAE,YAAY;AAAA,MACtG;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,cAAe;AACb,YAAM;AACN,WAAK,mBAAmB;AACxB,WAAK,uBAAuB;AAC5B,WAAK,SAAS;AAAA,QACZ,yBAAyB,MAAM,2BAA2B,CAAC;AAAA,QAC3D,wBAAwB,MAAM,0BAA0B,CAAC;AAAA,QACzD,gBAAgB,MAAM,kBAAkB,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": ["target"]
|
|
7
7
|
}
|
package/dist/lib/hooks.d.ts
CHANGED
|
@@ -43,17 +43,15 @@ export function triggerPluginHook({ app, hooks, serverGlobalContext, name, initi
|
|
|
43
43
|
initialData: any;
|
|
44
44
|
}): Promise<any>;
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* Binds plugins to the instance context using a lazy, cached Proxy.
|
|
47
47
|
*
|
|
48
48
|
* @param {Object} options - The options used to bind plugins.
|
|
49
|
-
* @param {Object} options.
|
|
50
|
-
* @param {Object} options.
|
|
51
|
-
* @
|
|
52
|
-
* @returns {Promise<Object>} Bound plugins
|
|
49
|
+
* @param {Object} options.pluginFactories - The map of Phase 2 factory functions.
|
|
50
|
+
* @param {Object} [options.instanceContext] - The specific instance context.
|
|
51
|
+
* @returns {Object} A Proxy that resolves plugins lazily.
|
|
53
52
|
*/
|
|
54
|
-
export function bindPlugins({
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}): Promise<any>;
|
|
53
|
+
export function bindPlugins({ pluginFactories, instanceContext }: {
|
|
54
|
+
pluginFactories: any;
|
|
55
|
+
instanceContext?: any;
|
|
56
|
+
}): any;
|
|
59
57
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/lib/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../lib/hooks.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,gDAHW,WAAW,GAAC,cAAc,GAAC,cAAc,GAAC,gBAAgB,GAAC,mBAAmB,GAAC,mBAAmB,GAAC,oBAAoB,GAAC,mBAAmB,GAAC,yBAAyB,GAAC,wBAAwB,GAAC,eAAe,GAAC,cAAc,4BAWvO;AAED;;;;;;;;;;GAUG;AACH,mGAPG;IAAwB,GAAG;IACH,KAAK;IACL,mBAAmB;IACnB,IAAI,EAApB,MAAM;IACO,WAAW,EAAxB,GAAG;CACX,GAAU,OAAO,CAAC,GAAG,EAAE,CAAC,CA2B1B;AAED;;;;;;;;;;GAUG;AACH,0FAPG;IAAwB,GAAG;IACH,KAAK;IACL,mBAAmB;IACnB,IAAI,EAApB,MAAM;IACO,WAAW,EAAxB,GAAG;CACX,GAAU,OAAO,CAAC,GAAG,CAAC,CA0BxB;AAED
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../lib/hooks.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,gDAHW,WAAW,GAAC,cAAc,GAAC,cAAc,GAAC,gBAAgB,GAAC,mBAAmB,GAAC,mBAAmB,GAAC,oBAAoB,GAAC,mBAAmB,GAAC,yBAAyB,GAAC,wBAAwB,GAAC,eAAe,GAAC,cAAc,4BAWvO;AAED;;;;;;;;;;GAUG;AACH,mGAPG;IAAwB,GAAG;IACH,KAAK;IACL,mBAAmB;IACnB,IAAI,EAApB,MAAM;IACO,WAAW,EAAxB,GAAG;CACX,GAAU,OAAO,CAAC,GAAG,EAAE,CAAC,CA2B1B;AAED;;;;;;;;;;GAUG;AACH,0FAPG;IAAwB,GAAG;IACH,KAAK;IACL,mBAAmB;IACnB,IAAI,EAApB,MAAM;IACO,WAAW,EAAxB,GAAG;CACX,GAAU,OAAO,CAAC,GAAG,CAAC,CA0BxB;AAED;;;;;;;GAOG;AACH,kEAJG;IAAwB,eAAe;IACd,eAAe;CACxC,OAyDF"}
|