coralite 0.37.1 → 0.37.2

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.
@@ -0,0 +1,147 @@
1
+ // lib/plugin.js
2
+ import { basename, dirname } from "path";
3
+
4
+ // lib/utils/errors.js
5
+ var CoraliteError = class extends Error {
6
+ /**
7
+ * @param {string} message - The error message.
8
+ * @param {Object} [options] - Additional options for the error.
9
+ * @param {string} [options.componentId] - The ID of the component where the error occurred.
10
+ * @param {string} [options.filePath] - The path to the file where the error occurred.
11
+ * @param {string} [options.instanceId] - The unique ID of the component instance.
12
+ * @param {string} [options.pagePath] - The path to the page being rendered.
13
+ * @param {number} [options.line] - The line number where the error occurred.
14
+ * @param {number} [options.column] - The column number where the error occurred.
15
+ * @param {string} [options.stackFile] - The file name from the stack trace.
16
+ * @param {Error} [options.cause] - The original error that caused this error.
17
+ */
18
+ constructor(message, options = {}) {
19
+ super(message, options);
20
+ this.name = "CoraliteError";
21
+ this.isCoraliteError = true;
22
+ this.componentId = options.componentId;
23
+ this.filePath = options.filePath;
24
+ this.instanceId = options.instanceId;
25
+ this.pagePath = options.pagePath;
26
+ this.line = options.line;
27
+ this.column = options.column;
28
+ this.stackFile = options.stackFile;
29
+ if (options.cause && !this.cause) {
30
+ this.cause = options.cause;
31
+ }
32
+ }
33
+ };
34
+
35
+ // lib/plugin.js
36
+ function validateNonEmptyString(value, paramName) {
37
+ if (typeof value !== "string" || value.trim().length === 0) {
38
+ throw new CoraliteError(
39
+ `Coralite plugin validation failed: "${paramName}" must be a non-empty string, received ${typeof value}`
40
+ );
41
+ }
42
+ }
43
+ function validateStringArray(value, paramName) {
44
+ if (!Array.isArray(value)) {
45
+ throw new CoraliteError(
46
+ `Coralite plugin validation failed: "${paramName}" must be an array, received ${typeof value}`
47
+ );
48
+ }
49
+ for (let i = 0; i < value.length; i++) {
50
+ if (typeof value[i] !== "string") {
51
+ throw new CoraliteError(
52
+ `Coralite plugin validation failed: "${paramName}[${i}]" must be a string, received ${typeof value[i]}`
53
+ );
54
+ }
55
+ }
56
+ }
57
+ function processComponents(path) {
58
+ try {
59
+ const componentData = {
60
+ path: {
61
+ pathname: path,
62
+ dirname: dirname(path),
63
+ filename: basename(path)
64
+ }
65
+ };
66
+ return componentData;
67
+ } catch (error) {
68
+ throw new CoraliteError(
69
+ `Coralite plugin component processing failed for "${path}": ${error.message}`,
70
+ {
71
+ cause: error,
72
+ filePath: path
73
+ }
74
+ );
75
+ }
76
+ }
77
+ function definePlugin({
78
+ name,
79
+ server,
80
+ client
81
+ }) {
82
+ validateNonEmptyString(name, "name");
83
+ let callerDir;
84
+ if (client != null && client.rootDir == null) {
85
+ const stack = new Error().stack;
86
+ if (stack) {
87
+ const callerLine = stack.split("\n")[2];
88
+ if (callerLine) {
89
+ const match = callerLine.match(/file:\/\/(.+?):/);
90
+ if (match) {
91
+ callerDir = dirname(match[1]);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ if (server != null) {
97
+ if (typeof server !== "object") {
98
+ throw new CoraliteError(
99
+ `Coralite plugin validation failed: "server" must be an object, received ${typeof server}`
100
+ );
101
+ }
102
+ server = { ...server };
103
+ if (server.components) {
104
+ validateStringArray(server.components, "server.components");
105
+ const componentHTMLData = [];
106
+ try {
107
+ for (const path of server.components) {
108
+ componentHTMLData.push(processComponents(path));
109
+ }
110
+ server.components = componentHTMLData;
111
+ } catch (error) {
112
+ throw new CoraliteError(
113
+ `Coralite plugin "${name}" failed to load components: ${error.message}`,
114
+ { cause: error }
115
+ );
116
+ }
117
+ }
118
+ }
119
+ if (client != null) {
120
+ if (typeof client !== "object") {
121
+ throw new CoraliteError(
122
+ `Coralite plugin validation failed: "client" must be an object, received ${typeof client}`
123
+ );
124
+ }
125
+ if (client.setup != null && typeof client.setup !== "function") {
126
+ throw new CoraliteError(
127
+ `Coralite plugin validation failed: "client.setup" must be a function, received ${typeof client.setup}`
128
+ );
129
+ }
130
+ if (client.config != null && typeof client.config !== "object") {
131
+ throw new CoraliteError(
132
+ `Coralite plugin validation failed: "client.config" must be an object, received ${typeof client.config}`
133
+ );
134
+ }
135
+ client.rootDir = client.rootDir || callerDir;
136
+ client.name = client.name || name;
137
+ }
138
+ return {
139
+ name,
140
+ server,
141
+ client
142
+ };
143
+ }
144
+ export {
145
+ definePlugin
146
+ };
147
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../lib/plugin.js", "../../lib/utils/errors.js"],
4
+ "sourcesContent": ["/**\n * @import { CoralitePlugin, HTMLData } from '../types/index.js'\n */\n\nimport { basename, dirname } from 'path'\nimport { CoraliteError } from './utils/errors.js'\n\n/**\n * Validates that a value is a non-empty string\n * @param {*} value - Value to validate\n * @param {string} paramName - Parameter name for error messages\n * @throws {Error} If value is not a valid non-empty string\n */\nfunction validateNonEmptyString (value, paramName) {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"${paramName}\" must be a non-empty string, received ${typeof value}`\n )\n }\n}\n\n/**\n * Validates that a value is an array of strings (or empty array)\n * @param {*} value - Value to validate\n * @param {string} paramName - Parameter name for error messages\n * @throws {Error} If value is defined but not an array of strings\n */\nfunction validateStringArray (value, paramName) {\n if (!Array.isArray(value)) {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"${paramName}\" must be an array, received ${typeof value}`\n )\n }\n\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== 'string') {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"${paramName}[${i}]\" must be a string, received ${typeof value[i]}`\n )\n }\n }\n}\n\n/**\n * Processes a single components file with optional caching\n * @param {string} path - Template file path\n * @returns {HTMLData} Template data\n * @throws {Error} If components file cannot be read or is invalid\n */\nfunction processComponents (path) {\n try {\n const componentData = {\n path: {\n pathname: path,\n dirname: dirname(path),\n filename: basename(path)\n }\n }\n\n return componentData\n } catch (error) {\n throw new CoraliteError(\n `Coralite plugin component processing failed for \"${path}\": ${error.message}`,\n {\n cause: error,\n filePath: path\n }\n )\n }\n}\n\n/**\n * Creates a new Coralite plugin instance based on provided configuration options.\n * @param {CoralitePlugin & { server?: { components?: string[] } }} options - Plugin configuration object\n * @returns {CoralitePlugin} A configured plugin instance ready to be registered with Coralite\n * @example\n * // Basic plugin\n * const myPlugin = definePlugin({\n * name: 'my-plugin',\n * server: {\n * exports: {\n * getData: (context) => (options) => {\n * // Plugin logic implementation\n * return { ...context.state, custom: 'data', ...options }\n * }\n * }\n * }\n * })\n *\n * @example\n * // Plugin with components and metadata\n * const advancedPlugin = definePlugin({\n * name: 'advanced-plugin',\n * server: {\n * exports: {\n * process: (context) => async (options) => {\n * // Async plugin logic\n * return { ...context.state, processed: true, ...options }\n * }\n * },\n * components: ['src/components/header.html', 'src/components/footer.html'],\n * onPageSet: async (data) => {\n * console.log('Page created:', data.path.pathname)\n * }\n * }\n * })\n */\nexport function definePlugin ({\n name,\n server,\n client\n}) {\n validateNonEmptyString(name, 'name')\n\n let callerDir\n if (client != null && client.rootDir == null) {\n const stack = new Error().stack\n if (stack) {\n const callerLine = stack.split('\\n')[2]\n if (callerLine) {\n const match = callerLine.match(/file:\\/\\/(.+?):/)\n if (match) {\n callerDir = dirname(match[1])\n }\n }\n }\n }\n\n // Validate server plugin if provided\n if (server != null) {\n if (typeof server !== 'object') {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"server\" must be an object, received ${typeof server}`\n )\n }\n\n server = { ...server }\n\n // Process component files with error handling\n if (server.components) {\n validateStringArray(server.components, 'server.components')\n\n const componentHTMLData = []\n try {\n // Process all components\n for (const path of server.components) {\n componentHTMLData.push(processComponents(path))\n }\n // @ts-ignore\n server.components = componentHTMLData\n } catch (error) {\n // Enhance error message with plugin context\n throw new CoraliteError(\n `Coralite plugin \"${name}\" failed to load components: ${error.message}`,\n { cause: error }\n )\n }\n }\n }\n\n // Validate client plugin if provided\n if (client != null) {\n if (typeof client !== 'object') {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"client\" must be an object, received ${typeof client}`\n )\n }\n\n // Validate optional client state\n if (client.setup != null && typeof client.setup !== 'function') {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"client.setup\" must be a function, received ${typeof client.setup}`\n )\n }\n\n if (client.config != null && typeof client.config !== 'object') {\n throw new CoraliteError(\n `Coralite plugin validation failed: \"client.config\" must be an object, received ${typeof client.config}`\n )\n }\n\n // append rootDir\n client.rootDir = client.rootDir || callerDir\n client.name = client.name || name\n }\n\n // Create the plugin object with all configured state\n return {\n name,\n server,\n client\n }\n}\n", "\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"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,467 @@
1
+ // lib/utils/errors.js
2
+ var CoraliteError = class extends Error {
3
+ /**
4
+ * @param {string} message - The error message.
5
+ * @param {Object} [options] - Additional options for the error.
6
+ * @param {string} [options.componentId] - The ID of the component where the error occurred.
7
+ * @param {string} [options.filePath] - The path to the file where the error occurred.
8
+ * @param {string} [options.instanceId] - The unique ID of the component instance.
9
+ * @param {string} [options.pagePath] - The path to the page being rendered.
10
+ * @param {number} [options.line] - The line number where the error occurred.
11
+ * @param {number} [options.column] - The column number where the error occurred.
12
+ * @param {string} [options.stackFile] - The file name from the stack trace.
13
+ * @param {Error} [options.cause] - The original error that caused this error.
14
+ */
15
+ constructor(message, options = {}) {
16
+ super(message, options);
17
+ this.name = "CoraliteError";
18
+ this.isCoraliteError = true;
19
+ this.componentId = options.componentId;
20
+ this.filePath = options.filePath;
21
+ this.instanceId = options.instanceId;
22
+ this.pagePath = options.pagePath;
23
+ this.line = options.line;
24
+ this.column = options.column;
25
+ this.stackFile = options.stackFile;
26
+ if (options.cause && !this.cause) {
27
+ this.cause = options.cause;
28
+ }
29
+ }
30
+ };
31
+
32
+ // lib/utils/core.js
33
+ var KEBAB_REGEX = /[-|:]([a-z])/g;
34
+ function kebabToCamel(str) {
35
+ return str.replace(KEBAB_REGEX, function(match, letter) {
36
+ return letter.toUpperCase();
37
+ });
38
+ }
39
+ function cleanKeys(object) {
40
+ const result = {};
41
+ for (const [key, value] of Object.entries(object)) {
42
+ result[key] = value;
43
+ const camelKey = kebabToCamel(key);
44
+ if (camelKey !== key) {
45
+ result[camelKey] = value;
46
+ }
47
+ }
48
+ return result;
49
+ }
50
+ function normalizeObjectFunctions(target, transform = null, seen = /* @__PURE__ */ new WeakMap()) {
51
+ if (typeof transform === "function") {
52
+ const transformed = transform(target);
53
+ if (transformed !== target) {
54
+ return transformed;
55
+ }
56
+ }
57
+ if (typeof target !== "object" || target === null) {
58
+ return target;
59
+ }
60
+ if (seen.has(target)) {
61
+ return seen.get(target);
62
+ }
63
+ if (Array.isArray(target)) {
64
+ const arr = [];
65
+ seen.set(target, arr);
66
+ for (let i = 0; i < target.length; i++) {
67
+ arr.push(normalizeObjectFunctions(target[i], transform, seen));
68
+ }
69
+ return arr;
70
+ }
71
+ const obj = {};
72
+ seen.set(target, obj);
73
+ for (const key in target) {
74
+ if (Object.hasOwn(target, key)) {
75
+ if (typeof target[key] === "function") {
76
+ const normalizedString = normalizeFunction(target[key]);
77
+ const originalFunction = target[key];
78
+ const wrapper = function() {
79
+ return originalFunction.apply(this, arguments);
80
+ };
81
+ wrapper.toString = () => normalizedString;
82
+ obj[key] = wrapper;
83
+ } else {
84
+ obj[key] = normalizeObjectFunctions(target[key], transform, seen);
85
+ }
86
+ }
87
+ }
88
+ return obj;
89
+ }
90
+ function hasObjectKeys(obj) {
91
+ return obj && typeof obj === "object" && Object.keys(obj).length > 0;
92
+ }
93
+ function mergeUniqueObjects(arr1, arr2) {
94
+ const all = [...arr1 || [], ...arr2 || []];
95
+ const seen = /* @__PURE__ */ new Set();
96
+ return all.filter((item) => {
97
+ const key = typeof item === "object" ? JSON.stringify(item) : item;
98
+ if (seen.has(key)) {
99
+ return false;
100
+ }
101
+ seen.add(key);
102
+ return true;
103
+ });
104
+ }
105
+ function normalizeFunction(func) {
106
+ const original = func.toString().trim();
107
+ const firstBrace = original.indexOf("{");
108
+ const firstArrow = original.indexOf("=>");
109
+ const isArrow = firstArrow !== -1 && (firstBrace === -1 || firstArrow < firstBrace);
110
+ if (isArrow) {
111
+ return original;
112
+ }
113
+ const header = firstBrace !== -1 ? original.slice(0, firstBrace).trim() : original;
114
+ const isStandard = header.startsWith("function") || header.startsWith("async function");
115
+ if (isStandard) {
116
+ return original;
117
+ }
118
+ if (header.startsWith("async ")) {
119
+ if (header.startsWith("async get ") || header.startsWith("async set ")) {
120
+ return original;
121
+ }
122
+ return original.replace(/^async\s+([$\w]+)\s*\(/, "async function(");
123
+ } else {
124
+ if (header.startsWith("get ") || header.startsWith("set ")) {
125
+ return original;
126
+ }
127
+ return original.replace(/^([$\w]+)\s*\(/, "function(");
128
+ }
129
+ }
130
+ function cloneNode(nodeMap, node, parent) {
131
+ const newNode = Object.create(Object.getPrototypeOf(node));
132
+ Object.assign(newNode, node);
133
+ if (parent) {
134
+ newNode.parent = parent;
135
+ }
136
+ if (newNode.attribs) {
137
+ newNode.attribs = { ...newNode.attribs };
138
+ }
139
+ nodeMap.set(node, newNode);
140
+ if (node.children) {
141
+ const children = node.children;
142
+ const length = children.length;
143
+ const clonedChildren = new Array(length);
144
+ newNode.children = clonedChildren;
145
+ for (let i = 0; i < length; i++) {
146
+ const clonedChild = cloneNode(nodeMap, children[i], newNode);
147
+ clonedChildren[i] = clonedChild;
148
+ if (i > 0) {
149
+ clonedChild.prev = clonedChildren[i - 1];
150
+ clonedChildren[i - 1].next = clonedChild;
151
+ }
152
+ }
153
+ }
154
+ if (node.slots) {
155
+ const slots = node.slots;
156
+ const length = slots.length;
157
+ const clonedSlots = new Array(length);
158
+ for (let i = 0; i < length; i++) {
159
+ const slot = slots[i];
160
+ const clonedSlot = { ...slot };
161
+ if (slot.node) {
162
+ const clonedNode = nodeMap.get(slot.node);
163
+ if (clonedNode) {
164
+ clonedSlot.node = clonedNode;
165
+ }
166
+ }
167
+ clonedSlots[i] = clonedSlot;
168
+ }
169
+ newNode.slots = clonedSlots;
170
+ }
171
+ Object.defineProperty(newNode, "__coralite_enhanced__", {
172
+ value: true,
173
+ enumerable: false,
174
+ configurable: true
175
+ });
176
+ return newNode;
177
+ }
178
+ function cloneModuleInstance(originalModule) {
179
+ const nodeMap = /* @__PURE__ */ new Map();
180
+ const newTemplate = cloneNode(nodeMap, originalModule.template, null);
181
+ const newValues = {
182
+ attributes: originalModule.values.attributes.map((item) => ({
183
+ ...item,
184
+ element: nodeMap.get(item.element)
185
+ })),
186
+ textNodes: originalModule.values.textNodes.map((item) => ({
187
+ ...item,
188
+ textNode: nodeMap.get(item.textNode)
189
+ })),
190
+ refs: originalModule.values.refs.map((item) => ({
191
+ ...item,
192
+ element: nodeMap.get(item.element)
193
+ }))
194
+ };
195
+ const newCustomElements = originalModule.customElements.map((el) => nodeMap.get(el));
196
+ const newSlotElements = {};
197
+ if (originalModule.slotElements) {
198
+ for (const modId in originalModule.slotElements) {
199
+ newSlotElements[modId] = {};
200
+ const slotGroup = originalModule.slotElements[modId];
201
+ for (const slotName in slotGroup) {
202
+ const slotItem = slotGroup[slotName];
203
+ newSlotElements[modId][slotName] = {
204
+ ...slotItem,
205
+ element: nodeMap.get(slotItem.element)
206
+ };
207
+ }
208
+ }
209
+ }
210
+ return {
211
+ ...originalModule,
212
+ template: newTemplate,
213
+ values: newValues,
214
+ customElements: newCustomElements,
215
+ // @ts-ignore
216
+ slotElements: newSlotElements
217
+ };
218
+ }
219
+ function cloneComponentInstance(originalDocument) {
220
+ const nodeMap = /* @__PURE__ */ new Map();
221
+ const newRoot = cloneNode(nodeMap, originalDocument.root, null);
222
+ const newCustomElements = originalDocument.customElements.map((el) => nodeMap.get(el));
223
+ const newTempElements = originalDocument.tempElements ? originalDocument.tempElements.map((el) => nodeMap.get(el)) : [];
224
+ const newSkipRenderElements = originalDocument.skipRenderElements ? originalDocument.skipRenderElements.map((el) => nodeMap.get(el)) : [];
225
+ return {
226
+ ...originalDocument,
227
+ state: { ...originalDocument.state },
228
+ root: newRoot,
229
+ customElements: newCustomElements,
230
+ tempElements: newTempElements,
231
+ skipRenderElements: newSkipRenderElements
232
+ };
233
+ }
234
+ function getNodePath(node, root) {
235
+ const path = [];
236
+ let current = node;
237
+ while (current && current !== root) {
238
+ const parent = current.parent;
239
+ if (!parent) {
240
+ break;
241
+ }
242
+ const index = parent.children.indexOf(current);
243
+ if (index === -1) {
244
+ break;
245
+ }
246
+ path.unshift(index);
247
+ current = parent;
248
+ }
249
+ return path;
250
+ }
251
+ function generateHydrationMap(templateNodes, templateValues) {
252
+ const map = {
253
+ texts: [],
254
+ attributes: [],
255
+ refs: []
256
+ };
257
+ if (!templateNodes || !templateValues) {
258
+ return map;
259
+ }
260
+ const root = templateNodes.length > 0 ? templateNodes[0].parent : { children: templateNodes };
261
+ if (templateValues.textNodes) {
262
+ for (const item of templateValues.textNodes) {
263
+ if (item.textNode) {
264
+ const isHtml = item.type === "html";
265
+ const targetNode = isHtml ? item.textNode.parent : item.textNode;
266
+ map.texts.push({
267
+ path: getNodePath(targetNode, root),
268
+ template: item.textNode.data,
269
+ type: isHtml ? "html" : "text"
270
+ });
271
+ }
272
+ }
273
+ }
274
+ if (templateValues.attributes) {
275
+ for (const item of templateValues.attributes) {
276
+ if (item.element && item.element.attribs) {
277
+ const originalValue = item.element.attribs[item.name];
278
+ map.attributes.push({
279
+ path: getNodePath(item.element, root),
280
+ name: item.name,
281
+ template: originalValue
282
+ });
283
+ }
284
+ }
285
+ }
286
+ if (templateValues.refs) {
287
+ for (const item of templateValues.refs) {
288
+ if (item.element) {
289
+ map.refs.push({
290
+ path: getNodePath(item.element, root),
291
+ name: item.name
292
+ });
293
+ }
294
+ }
295
+ }
296
+ return map;
297
+ }
298
+ function addComponentAndDependencies(componentId, processed, sharedFunctions) {
299
+ if (!processed[componentId] && sharedFunctions[componentId]) {
300
+ processed[componentId] = true;
301
+ const dependencies = sharedFunctions[componentId].components || [];
302
+ for (const depId of dependencies) {
303
+ addComponentAndDependencies(depId, processed, sharedFunctions);
304
+ }
305
+ }
306
+ }
307
+ function cleanAST(nodes, nodeMap, state) {
308
+ if (!nodes) {
309
+ return null;
310
+ }
311
+ return nodes.map((node) => {
312
+ const cloned = { ...node };
313
+ const id = state.counter++;
314
+ nodeMap.set(node, id);
315
+ cloned._id = id;
316
+ delete cloned.parent;
317
+ delete cloned.prev;
318
+ delete cloned.next;
319
+ delete cloned.slots;
320
+ if (cloned.children) {
321
+ cloned.children = cleanAST(cloned.children, nodeMap, state);
322
+ }
323
+ return cloned;
324
+ });
325
+ }
326
+ function cleanValues(values, nodeMap) {
327
+ if (!values) {
328
+ return null;
329
+ }
330
+ const result = { ...values };
331
+ if (result.attributes) {
332
+ result.attributes = result.attributes.map((item) => {
333
+ const cloned = { ...item };
334
+ cloned.elementId = nodeMap.get(item.element);
335
+ delete cloned.element;
336
+ return cloned;
337
+ });
338
+ }
339
+ if (result.textNodes) {
340
+ result.textNodes = result.textNodes.map((item) => {
341
+ const cloned = { ...item };
342
+ cloned.textNodeId = nodeMap.get(item.textNode);
343
+ delete cloned.textNode;
344
+ return cloned;
345
+ });
346
+ }
347
+ if (result.refs) {
348
+ result.refs = result.refs.map((item) => {
349
+ const cloned = { ...item };
350
+ cloned.elementId = nodeMap.get(item.element);
351
+ delete cloned.element;
352
+ return cloned;
353
+ });
354
+ }
355
+ return result;
356
+ }
357
+ function mergePluginState(current, patch) {
358
+ if (!patch || typeof patch !== "object") {
359
+ return current;
360
+ }
361
+ const result = { ...current };
362
+ for (const key of Object.keys(patch)) {
363
+ const patchValue = patch[key];
364
+ const currentValue = result[key];
365
+ if (patchValue && typeof patchValue === "object" && !Array.isArray(patchValue) && currentValue && typeof currentValue === "object" && !Array.isArray(currentValue)) {
366
+ result[key] = mergePluginState(currentValue, patchValue);
367
+ } else {
368
+ result[key] = patchValue;
369
+ }
370
+ }
371
+ return result;
372
+ }
373
+ function createReactiveProxy(target, onChange, proxies = /* @__PURE__ */ new WeakMap()) {
374
+ if (proxies.has(target)) {
375
+ return proxies.get(target);
376
+ }
377
+ const handler = {
378
+ get(target2, property, receiver) {
379
+ const value = Reflect.get(target2, property, receiver);
380
+ if (value !== null && typeof value === "object" && !(typeof Node !== "undefined" && value instanceof Node)) {
381
+ return createReactiveProxy(value, onChange, proxies);
382
+ }
383
+ return value;
384
+ },
385
+ set(target2, property, value, receiver) {
386
+ const oldValue = target2[property];
387
+ if (oldValue === value && property in target2) {
388
+ return true;
389
+ }
390
+ const result = Reflect.set(target2, property, value, receiver);
391
+ if (result) {
392
+ onChange({
393
+ property,
394
+ value,
395
+ oldValue,
396
+ target: target2
397
+ });
398
+ }
399
+ return result;
400
+ },
401
+ deleteProperty(target2, property) {
402
+ const hadProperty = Object.prototype.hasOwnProperty.call(target2, property);
403
+ const oldValue = target2[property];
404
+ const result = Reflect.deleteProperty(target2, property);
405
+ if (result && hadProperty) {
406
+ onChange({
407
+ property,
408
+ value: void 0,
409
+ oldValue,
410
+ target: target2,
411
+ deleted: true
412
+ });
413
+ }
414
+ return result;
415
+ }
416
+ };
417
+ const proxy = new Proxy(target, handler);
418
+ proxies.set(target, proxy);
419
+ return proxy;
420
+ }
421
+ function createReadOnlyProxy(target, proxies = /* @__PURE__ */ new WeakMap()) {
422
+ if (proxies.has(target)) {
423
+ return proxies.get(target);
424
+ }
425
+ const handler = {
426
+ get(target2, property, receiver) {
427
+ const value = Reflect.get(target2, property, receiver);
428
+ if (value !== null && typeof value === "object" && !(typeof Node !== "undefined" && value instanceof Node)) {
429
+ return createReadOnlyProxy(value, proxies);
430
+ }
431
+ return value;
432
+ },
433
+ set() {
434
+ throw new CoraliteError("Cannot mutate state inside a getter. State is read-only here.");
435
+ },
436
+ deleteProperty() {
437
+ throw new CoraliteError("Cannot delete state inside a getter. State is read-only here.");
438
+ }
439
+ };
440
+ const proxy = new Proxy(target, handler);
441
+ proxies.set(target, proxy);
442
+ return proxy;
443
+ }
444
+ function defineComponent(options) {
445
+ return options;
446
+ }
447
+ export {
448
+ addComponentAndDependencies,
449
+ cleanAST,
450
+ cleanKeys,
451
+ cleanValues,
452
+ cloneComponentInstance,
453
+ cloneModuleInstance,
454
+ cloneNode,
455
+ createReactiveProxy,
456
+ createReadOnlyProxy,
457
+ defineComponent,
458
+ generateHydrationMap,
459
+ getNodePath,
460
+ hasObjectKeys,
461
+ kebabToCamel,
462
+ mergePluginState,
463
+ mergeUniqueObjects,
464
+ normalizeFunction,
465
+ normalizeObjectFunctions
466
+ };
467
+ //# sourceMappingURL=core.js.map