@sprlab/wccompiler 0.11.3 → 0.11.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/wcc.js CHANGED
@@ -35,6 +35,7 @@ async function build(config, cwd) {
35
35
 
36
36
  const { code, usesSharedRuntime } = await compile(file, {
37
37
  standalone: config.standalone,
38
+ minify: config.minify,
38
39
  runtimeImportPath,
39
40
  });
40
41
 
@@ -209,6 +210,9 @@ async function main() {
209
210
  const cwd = process.cwd();
210
211
  const config = await loadConfig(cwd);
211
212
 
213
+ // CLI flags override config
214
+ if (process.argv.includes('--minify')) config.minify = true;
215
+
212
216
  if (command === 'build') {
213
217
  const errors = await build(config, cwd);
214
218
  if (errors > 0) process.exit(1);
@@ -236,6 +240,7 @@ async function main() {
236
240
 
237
241
  const { code, usesSharedRuntime } = await compile(filePath, {
238
242
  standalone: config.standalone,
243
+ minify: config.minify,
239
244
  runtimeImportPath,
240
245
  });
241
246
 
package/lib/codegen.js CHANGED
@@ -864,6 +864,7 @@ export function generateComponent(parseResult, options = {}) {
864
864
  forBlocks = [],
865
865
  onMountHooks = [],
866
866
  onDestroyHooks = [],
867
+ onAdoptHooks = [],
867
868
  modelBindings = [],
868
869
  modelPropBindings = [],
869
870
  attrBindings = [],
@@ -1698,6 +1699,31 @@ export function generateComponent(parseResult, options = {}) {
1698
1699
  lines.push(' }');
1699
1700
  lines.push('');
1700
1701
 
1702
+ // adoptedCallback (if onAdopt hooks exist)
1703
+ if (onAdoptHooks.length > 0) {
1704
+ lines.push(' adoptedCallback() {');
1705
+ for (const hook of onAdoptHooks) {
1706
+ const body = transformMethodBody(hook.body, signalNames, computedNames, propsObjectName, propNames, emitsObjectName, refVarNames, constantNames, modelVarMap);
1707
+ if (hook.async) {
1708
+ lines.push(' ;(async () => {');
1709
+ const bodyLines = body.split('\n');
1710
+ for (const line of bodyLines) {
1711
+ lines.push(` ${line}`);
1712
+ }
1713
+ lines.push(' })();');
1714
+ } else {
1715
+ const bodyLines = body.split('\n');
1716
+ for (const line of bodyLines) {
1717
+ const trimmed = line.trimEnd();
1718
+ const needsSemi = trimmed && !trimmed.endsWith(';') && !trimmed.endsWith('{') && !trimmed.endsWith('}');
1719
+ lines.push(` ${trimmed}${needsSemi ? ';' : ''}`);
1720
+ }
1721
+ }
1722
+ }
1723
+ lines.push(' }');
1724
+ lines.push('');
1725
+ }
1726
+
1701
1727
  // attributeChangedCallback (if props or model props exist)
1702
1728
  if (propDefs.length > 0 || modelDefs.length > 0) {
1703
1729
  lines.push(' attributeChangedCallback(name, oldVal, newVal) {');
package/lib/compiler.js CHANGED
@@ -485,5 +485,21 @@ export function resolveStandalone(componentValue, globalValue) {
485
485
  */
486
486
  export async function compile(filePath, config) {
487
487
  const result = await compileSFC(filePath, config);
488
+
489
+ if (config?.minify) {
490
+ const { transform } = await import('esbuild');
491
+ try {
492
+ const minified = await transform(result.code, {
493
+ minify: true,
494
+ loader: 'js',
495
+ target: 'esnext',
496
+ });
497
+ result.code = minified.code;
498
+ } catch {
499
+ // If minification fails (e.g., edge-case syntax), return unminified code
500
+ // This is a graceful fallback — the code still works at runtime
501
+ }
502
+ }
503
+
488
504
  return result;
489
505
  }
package/lib/config.js CHANGED
@@ -19,7 +19,7 @@ import { pathToFileURL } from 'node:url';
19
19
  * @returns {Promise<WccConfig>}
20
20
  */
21
21
  export async function loadConfig(projectRoot) {
22
- const defaults = { port: 4100, input: 'src', output: 'dist', standalone: false };
22
+ const defaults = { port: 4100, input: 'src', output: 'dist', standalone: false, minify: false };
23
23
  const configPath = resolve(projectRoot, 'wcc.config.js');
24
24
 
25
25
  if (!existsSync(configPath)) return defaults;
@@ -56,6 +56,11 @@ export async function loadConfig(projectRoot) {
56
56
  error.code = 'INVALID_CONFIG';
57
57
  throw error;
58
58
  }
59
+ if (typeof config.minify !== 'boolean') {
60
+ const error = new Error(`Error en wcc.config.js: minify debe ser un booleano`);
61
+ error.code = 'INVALID_CONFIG';
62
+ throw error;
63
+ }
59
64
 
60
65
  return config;
61
66
  }
@@ -890,6 +890,14 @@ export function extractFunctions(source) {
890
890
  if (j === i) {
891
891
  // First line: capture everything after the opening brace
892
892
  const afterBrace = l.substring(l.indexOf('{') + 1);
893
+ // Single-line function: depth already closed on first line
894
+ if (depth <= 0) {
895
+ const lastBraceIdx = afterBrace.lastIndexOf('}');
896
+ const inner = lastBraceIdx >= 0 ? afterBrace.substring(0, lastBraceIdx) : afterBrace;
897
+ if (inner.trim()) bodyLines.push(inner);
898
+ i = j;
899
+ break;
900
+ }
893
901
  if (afterBrace.trim()) bodyLines.push(afterBrace);
894
902
  } else if (depth <= 0) {
895
903
  // Last line: capture everything before the closing brace
@@ -925,13 +933,15 @@ export function extractFunctions(source) {
925
933
  * Only extracts top-level calls (brace depth === 0 when the call is encountered).
926
934
  *
927
935
  * @param {string} script - The script content (after type stripping)
928
- * @returns {{ onMountHooks: LifecycleHook[], onDestroyHooks: LifecycleHook[] }}
936
+ * @returns {{ onMountHooks: LifecycleHook[], onDestroyHooks: LifecycleHook[], onAdoptHooks: LifecycleHook[] }}
929
937
  */
930
938
  export function extractLifecycleHooks(script) {
931
939
  /** @type {LifecycleHook[]} */
932
940
  const onMountHooks = [];
933
941
  /** @type {LifecycleHook[]} */
934
942
  const onDestroyHooks = [];
943
+ /** @type {LifecycleHook[]} */
944
+ const onAdoptHooks = [];
935
945
  const lines = script.split('\n');
936
946
  let i = 0;
937
947
 
@@ -939,8 +949,9 @@ export function extractLifecycleHooks(script) {
939
949
  const line = lines[i];
940
950
  const mountMatch = line.match(/\bonMount\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{/);
941
951
  const destroyMatch = line.match(/\bonDestroy\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{/);
952
+ const adoptMatch = line.match(/\bonAdopt\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{/);
942
953
 
943
- if (mountMatch || destroyMatch) {
954
+ if (mountMatch || destroyMatch || adoptMatch) {
944
955
  // Detect if the callback is async
945
956
  const isAsync = /\basync\s*\(/.test(line);
946
957
 
@@ -998,14 +1009,16 @@ export function extractLifecycleHooks(script) {
998
1009
 
999
1010
  if (mountMatch) {
1000
1011
  onMountHooks.push({ body, async: isAsync });
1001
- } else {
1012
+ } else if (destroyMatch) {
1002
1013
  onDestroyHooks.push({ body, async: isAsync });
1014
+ } else {
1015
+ onAdoptHooks.push({ body, async: isAsync });
1003
1016
  }
1004
1017
  }
1005
1018
  i++;
1006
1019
  }
1007
1020
 
1008
- return { onMountHooks, onDestroyHooks };
1021
+ return { onMountHooks, onDestroyHooks, onAdoptHooks };
1009
1022
  }
1010
1023
 
1011
1024
  // ── Ref extraction ───────────────────────────────────────────────────
package/lib/parser.js CHANGED
@@ -153,12 +153,12 @@ export async function parse(filePath) {
153
153
  }
154
154
 
155
155
  // 8. Extract lifecycle hooks (before other extractions to avoid misidentification)
156
- const { onMountHooks, onDestroyHooks } = extractLifecycleHooks(source);
156
+ const { onMountHooks, onDestroyHooks, onAdoptHooks } = extractLifecycleHooks(source);
157
157
 
158
158
  // 8b. Strip lifecycle hook blocks from source to prevent signal/computed/effect/function
159
159
  // extractors from misidentifying code inside hook bodies
160
160
  let sourceForExtraction = source;
161
- const hookLinePattern = /\bonMount\s*\(|\bonDestroy\s*\(|\bwatch\s*\(/;
161
+ const hookLinePattern = /\bonMount\s*\(|\bonDestroy\s*\(|\bonAdopt\s*\(|\bwatch\s*\(/;
162
162
  const sourceLines = sourceForExtraction.split('\n');
163
163
  const filteredLines = [];
164
164
  let skipDepth = 0;
@@ -263,6 +263,7 @@ export async function parse(filePath) {
263
263
  processedTemplate: null,
264
264
  onMountHooks,
265
265
  onDestroyHooks,
266
+ onAdoptHooks,
266
267
  refs,
267
268
  };
268
269
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprlab/wccompiler",
3
- "version": "0.11.3",
3
+ "version": "0.11.5",
4
4
  "description": "Zero-runtime compiler that transforms .wcc single-file components into native web components with signals-based reactivity",
5
5
  "type": "module",
6
6
  "exports": {
package/types/wcc.d.ts CHANGED
@@ -23,5 +23,6 @@ declare module 'wcc' {
23
23
 
24
24
  export function onMount(fn: () => void | Promise<void>): void;
25
25
  export function onDestroy(fn: () => void | Promise<void>): void;
26
+ export function onAdopt(fn: () => void | Promise<void>): void;
26
27
  export function defineExpose(bindings: Record<string, any>): void;
27
28
  }