@webmate-studio/builder 0.2.21 → 0.2.22

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.
Files changed (2) hide show
  1. package/build-service.js +89 -2
  2. package/package.json +1 -1
package/build-service.js CHANGED
@@ -62,13 +62,72 @@ async function installDependencies(componentDir, packageJson) {
62
62
  }
63
63
  }
64
64
 
65
+ /**
66
+ * Auto-inject <svelte:options> for Web Component registration
67
+ * Converts filename to kebab-case tag name (e.g., SwiperTest.svelte → swiper-test)
68
+ * Generates props definition from component.json metadata
69
+ */
70
+ function injectSvelteOptions(filename, content, componentMetadata) {
71
+ // Convert filename to kebab-case tag name
72
+ // SwiperTest.svelte → swiper-test
73
+ // MyAwesomeComponent.svelte → my-awesome-component
74
+ const componentName = filename.replace('.svelte', '');
75
+ const tagName = componentName
76
+ .replace(/([A-Z])/g, '-$1') // Insert hyphen before capital letters
77
+ .toLowerCase()
78
+ .replace(/^-/, ''); // Remove leading hyphen
79
+
80
+ // Generate props definition from component.json
81
+ const props = {};
82
+ if (componentMetadata.props) {
83
+ // Props can be either an object or an array
84
+ const propsData = Array.isArray(componentMetadata.props)
85
+ ? componentMetadata.props
86
+ : Object.entries(componentMetadata.props).map(([name, config]) => ({ name, ...config }));
87
+
88
+ for (const prop of propsData) {
89
+ // Map prop types to Svelte types
90
+ const typeMap = {
91
+ 'text': 'String',
92
+ 'string': 'String',
93
+ 'number': 'Number',
94
+ 'boolean': 'Boolean',
95
+ 'array': 'Array',
96
+ 'object': 'Object'
97
+ };
98
+ const svelteType = typeMap[prop.type?.toLowerCase()] || 'String';
99
+ props[prop.name] = { type: svelteType };
100
+ }
101
+ }
102
+
103
+ // Generate <svelte:options> block
104
+ const propsJson = JSON.stringify(props, null, 3).replace(/^/gm, '\t\t\t'); // Indent props
105
+ const svelteOptions = `<svelte:options
106
+ customElement={{
107
+ tag: "${tagName}",
108
+ shadow: "none",
109
+ props: ${propsJson}
110
+ }}
111
+ />\n\n`;
112
+
113
+ // Check if <svelte:options> already exists
114
+ if (content.includes('<svelte:options')) {
115
+ console.log(`[Build Service] ℹ️ ${filename} already has <svelte:options>, skipping auto-inject`);
116
+ return content;
117
+ }
118
+
119
+ // Inject at the top of the file (before <script> or template)
120
+ console.log(`[Build Service] ✓ Auto-injected <svelte:options> for ${tagName}`);
121
+ return svelteOptions + content;
122
+ }
123
+
65
124
  /**
66
125
  * Build a component (islands + CSS)
67
126
  * @param {Object} payload - Build request payload
68
127
  * @returns {Object} Build result
69
128
  */
70
129
  async function buildComponent(payload) {
71
- const { packageJson, islands, html, componentName = 'component' } = payload;
130
+ const { packageJson, islands, html, assets, componentMetadata, componentName = 'component' } = payload;
72
131
 
73
132
  // Create temporary directory
74
133
  const tmpDir = await mkdtemp(join(tmpdir(), 'wm-build-'));
@@ -81,6 +140,28 @@ async function buildComponent(payload) {
81
140
  await installDependencies(tmpDir, packageJson);
82
141
  }
83
142
 
143
+ // Write assets to disk BEFORE building islands (islands may reference them)
144
+ if (assets && assets.length > 0) {
145
+ const assetsDir = join(tmpDir, 'assets');
146
+ await mkdir(assetsDir, { recursive: true });
147
+
148
+ for (const asset of assets) {
149
+ const assetPath = join(assetsDir, asset.file);
150
+
151
+ // Convert base64 back to Buffer for binary files
152
+ // Text files can be written directly as UTF-8
153
+ let content;
154
+ if (asset.encoding === 'base64') {
155
+ content = Buffer.from(asset.content, 'base64');
156
+ } else {
157
+ content = asset.content; // UTF-8 string
158
+ }
159
+
160
+ await writeFile(assetPath, content);
161
+ }
162
+ console.log(`[Build Service] Wrote ${assets.length} asset(s)`);
163
+ }
164
+
84
165
  // Build islands
85
166
  const bundledIslands = [];
86
167
  if (islands && islands.length > 0) {
@@ -91,8 +172,14 @@ async function buildComponent(payload) {
91
172
  const inputPath = join(islandsDir, island.file);
92
173
  const outputPath = join(islandsDir, island.file.replace(/\.(jsx?|tsx?|svelte|vue)$/, '.js'));
93
174
 
175
+ // Auto-inject <svelte:options> for Svelte islands
176
+ let content = island.content;
177
+ if (island.file.endsWith('.svelte') && componentMetadata && componentMetadata.props) {
178
+ content = injectSvelteOptions(island.file, content, componentMetadata);
179
+ }
180
+
94
181
  // Write source file
95
- await writeFile(inputPath, island.content);
182
+ await writeFile(inputPath, content);
96
183
 
97
184
  console.log(`[Build Service] Bundling ${island.file}...`);
98
185
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webmate-studio/builder",
3
- "version": "0.2.21",
3
+ "version": "0.2.22",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [