@openwebf/webf 0.23.10 → 0.24.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.
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readJsonFile = readJsonFile;
7
+ exports.getPackageTypesFileFromDir = getPackageTypesFileFromDir;
8
+ exports.isPackageTypesReady = isPackageTypesReady;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ function readJsonFile(jsonPath) {
12
+ return JSON.parse(fs_1.default.readFileSync(jsonPath, 'utf-8'));
13
+ }
14
+ function getPackageTypesFileFromDir(pkgDir) {
15
+ const pkgJsonPath = path_1.default.join(pkgDir, 'package.json');
16
+ if (!fs_1.default.existsSync(pkgJsonPath))
17
+ return null;
18
+ const pkgJson = readJsonFile(pkgJsonPath);
19
+ const typesRel = pkgJson.types;
20
+ if (!typesRel)
21
+ return null;
22
+ return path_1.default.join(pkgDir, typesRel);
23
+ }
24
+ function isPackageTypesReady(pkgDir) {
25
+ const typesFile = getPackageTypesFileFromDir(pkgDir);
26
+ return typesFile ? fs_1.default.existsSync(typesFile) : true;
27
+ }
package/dist/react.js CHANGED
@@ -55,14 +55,13 @@ function generateReturnType(type) {
55
55
  return pointerType;
56
56
  }
57
57
  if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
58
- const elemType = (0, utils_1.getPointerType)(type.value);
59
- // Map arrays of Dart `Type` to `any[]` in TS; parenthesize typeof
60
- if (elemType === 'Type')
58
+ const elemType = generateReturnType(type.value);
59
+ if (!elemType)
61
60
  return 'any[]';
62
- if (typeof elemType === 'string' && elemType.startsWith('typeof ')) {
63
- return `(${elemType})[]`;
61
+ if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
62
+ return `${elemType}[]`;
64
63
  }
65
- return `${elemType}[]`;
64
+ return `(${elemType})[]`;
66
65
  }
67
66
  switch (type.value) {
68
67
  case declaration_1.FunctionArgumentType.int:
@@ -348,20 +347,13 @@ function generateReactComponent(blob, packageName, relativeDir) {
348
347
  return pointerType;
349
348
  }
350
349
  if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
351
- const elemType = (0, utils_1.getPointerType)(type.value);
352
- if (elemType === 'Type')
350
+ const elemType = genRT(type.value);
351
+ if (!elemType)
353
352
  return 'any[]';
354
- if (typeof elemType === 'string' && elemType.startsWith('typeof ')) {
355
- const ident = elemType.substring('typeof '.length).trim();
356
- return `(typeof __webfTypes.${ident})[]`;
357
- }
358
- if (typeof elemType === 'string' && /^(?:[A-Za-z_][A-Za-z0-9_]*)(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
359
- const base = elemType.split('.')[0];
360
- if (!localTypeNames.has(base)) {
361
- return `__webfTypes.${elemType}[]`;
362
- }
353
+ if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
354
+ return `${elemType}[]`;
363
355
  }
364
- return `${elemType}[]`;
356
+ return `(${elemType})[]`;
365
357
  }
366
358
  switch (type.value) {
367
359
  case declaration_1.FunctionArgumentType.int:
package/dist/vue.js CHANGED
@@ -8,7 +8,6 @@ const lodash_1 = __importDefault(require("lodash"));
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const declaration_1 = require("./declaration");
11
- const logger_1 = require("./logger");
12
11
  const utils_1 = require("./utils");
13
12
  function readTemplate(name) {
14
13
  return fs_1.default.readFileSync(path_1.default.join(__dirname, '../templates/' + name + '.tpl'), { encoding: 'utf-8' });
@@ -50,19 +49,18 @@ function generateReturnType(type) {
50
49
  return 'any';
51
50
  if (typeof pointerType === 'string' && pointerType.startsWith('typeof ')) {
52
51
  const ident = pointerType.substring('typeof '.length).trim();
53
- return `typeof __webfTypes.${ident}`;
52
+ return `typeof ${ident}`;
54
53
  }
55
54
  return pointerType;
56
55
  }
57
56
  if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
58
- const elemType = (0, utils_1.getPointerType)(type.value);
59
- if (elemType === 'Type')
57
+ const elemType = generateReturnType(type.value);
58
+ if (!elemType)
60
59
  return 'any[]';
61
- if (typeof elemType === 'string' && elemType.startsWith('typeof ')) {
62
- const ident = elemType.substring('typeof '.length).trim();
63
- return `(typeof __webfTypes.${ident})[]`;
60
+ if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
61
+ return `${elemType}[]`;
64
62
  }
65
- return `${elemType}[]`;
63
+ return `(${elemType})[]`;
66
64
  }
67
65
  switch (type.value) {
68
66
  case declaration_1.FunctionArgumentType.int:
@@ -111,125 +109,111 @@ function generateMethodDeclaration(method) {
111
109
  var returnType = generateReturnType(method.returnType);
112
110
  return `${methodName}(${args}): ${returnType};`;
113
111
  }
114
- function generateVueComponent(blob) {
115
- const classObjects = blob.objects;
116
- // Skip if no class objects
117
- if (!classObjects || classObjects.length === 0) {
118
- return '';
119
- }
120
- const classObjectDictionary = Object.fromEntries(classObjects.map(object => {
121
- return [object.name, object];
122
- }));
123
- const properties = classObjects.filter(object => {
124
- return object.name.endsWith('Properties');
112
+ function getVueComponentSpecs(blob) {
113
+ const classObjects = blob.objects.filter(obj => obj instanceof declaration_1.ClassObject);
114
+ if (classObjects.length === 0)
115
+ return [];
116
+ const properties = classObjects.filter(object => object.name.endsWith('Properties'));
117
+ const events = classObjects.filter(object => object.name.endsWith('Events'));
118
+ const methods = classObjects.filter(object => object.name.endsWith('Methods'));
119
+ const componentMap = new Map();
120
+ properties.forEach(prop => {
121
+ const className = prop.name.replace(/Properties$/, '');
122
+ if (!componentMap.has(className))
123
+ componentMap.set(className, { className });
124
+ componentMap.get(className).properties = prop;
125
125
  });
126
- const events = classObjects.filter(object => {
127
- return object.name.endsWith('Events');
126
+ events.forEach(ev => {
127
+ const className = ev.name.replace(/Events$/, '');
128
+ if (!componentMap.has(className))
129
+ componentMap.set(className, { className });
130
+ componentMap.get(className).events = ev;
128
131
  });
129
- const others = classObjects.filter(object => {
130
- return !object.name.endsWith('Properties')
131
- && !object.name.endsWith('Events');
132
+ methods.forEach(m => {
133
+ const className = m.name.replace(/Methods$/, '');
134
+ if (!componentMap.has(className))
135
+ componentMap.set(className, { className });
136
+ componentMap.get(className).methods = m;
132
137
  });
133
- const dependencies = others.map(object => {
134
- if (!object || !object.props || object.props.length === 0) {
135
- return '';
136
- }
137
- const interfaceLines = [];
138
- if (object.documentation && object.documentation.trim().length > 0) {
139
- interfaceLines.push('/**');
140
- object.documentation.split('\n').forEach(line => {
141
- interfaceLines.push(` * ${line}`);
138
+ return Array.from(componentMap.values())
139
+ .filter(spec => spec.className.trim().length > 0)
140
+ .sort((a, b) => a.className.localeCompare(b.className));
141
+ }
142
+ function renderSupportingInterface(object) {
143
+ const hasProps = !!object.props && object.props.length > 0;
144
+ const hasMethods = !!object.methods && object.methods.length > 0;
145
+ if (!hasProps && !hasMethods) {
146
+ return '';
147
+ }
148
+ const interfaceLines = [];
149
+ if (object.documentation && object.documentation.trim().length > 0) {
150
+ interfaceLines.push('/**');
151
+ object.documentation.split('\n').forEach(line => {
152
+ interfaceLines.push(` * ${line}`);
153
+ });
154
+ interfaceLines.push(' */');
155
+ }
156
+ interfaceLines.push(`export interface ${object.name} {`);
157
+ const propLines = (object.props || []).map(prop => {
158
+ const lines = [];
159
+ if (prop.documentation && prop.documentation.trim().length > 0) {
160
+ lines.push(' /**');
161
+ prop.documentation.split('\n').forEach(line => {
162
+ lines.push(` * ${line}`);
142
163
  });
143
- interfaceLines.push(' */');
164
+ lines.push(' */');
144
165
  }
145
- interfaceLines.push(`interface ${object.name} {`);
146
- const propLines = object.props.map(prop => {
147
- const lines = [];
148
- if (prop.documentation && prop.documentation.trim().length > 0) {
149
- lines.push(' /**');
150
- prop.documentation.split('\n').forEach(line => {
151
- lines.push(` * ${line}`);
152
- });
153
- lines.push(' */');
154
- }
155
- const optionalToken = prop.optional ? '?' : '';
156
- lines.push(` ${prop.name}${optionalToken}: ${generateReturnType(prop.type)};`);
157
- return lines.join('\n');
166
+ const optionalToken = prop.optional ? '?' : '';
167
+ lines.push(` ${prop.name}${optionalToken}: ${generateReturnType(prop.type)};`);
168
+ return lines.join('\n');
169
+ });
170
+ interfaceLines.push(propLines.join('\n'));
171
+ if (object.methods && object.methods.length > 0) {
172
+ const methodLines = object.methods.map(method => {
173
+ return ` ${generateMethodDeclaration(method)}`;
158
174
  });
159
- interfaceLines.push(propLines.join('\n'));
160
- interfaceLines.push('}');
161
- return interfaceLines.join('\n');
162
- }).filter(dep => dep.trim() !== '').join('\n\n');
163
- const componentProperties = properties.length > 0 ? properties[0] : undefined;
164
- const componentEvents = events.length > 0 ? events[0] : undefined;
165
- const className = (() => {
166
- if (componentProperties) {
167
- return componentProperties.name.replace(/Properties$/, '');
168
- }
169
- if (componentEvents) {
170
- return componentEvents.name.replace(/Events$/, '');
171
- }
172
- return '';
173
- })();
174
- if (!className) {
175
- return '';
175
+ interfaceLines.push(methodLines.join('\n'));
176
176
  }
177
- const content = lodash_1.default.template(readTemplate('vue.component.partial'))({
178
- className: className,
179
- properties: componentProperties,
180
- events: componentEvents,
181
- classObjectDictionary,
182
- dependencies,
183
- blob,
184
- generateReturnType,
185
- generateMethodDeclaration,
186
- generateEventHandlerType,
187
- });
188
- const result = content.split('\n').filter(str => {
189
- return str.trim().length > 0;
190
- }).join('\n');
191
- return result;
177
+ interfaceLines.push('}');
178
+ return interfaceLines.join('\n');
192
179
  }
193
- function toVueTagName(className) {
180
+ function toVueTagName(rawClassName) {
181
+ const className = rawClassName.trim();
194
182
  if (className.startsWith('WebF')) {
195
183
  const withoutPrefix = className.substring(4);
196
- return 'web-f-' + lodash_1.default.kebabCase(withoutPrefix);
184
+ const suffix = lodash_1.default.kebabCase(withoutPrefix);
185
+ return suffix.length > 0 ? 'webf-' + suffix : 'webf';
197
186
  }
198
- else if (className.startsWith('Flutter')) {
187
+ if (className.startsWith('Flutter')) {
199
188
  const withoutPrefix = className.substring(7);
200
- return 'flutter-' + lodash_1.default.kebabCase(withoutPrefix);
189
+ const suffix = lodash_1.default.kebabCase(withoutPrefix);
190
+ return suffix.length > 0 ? 'flutter-' + suffix : 'flutter';
201
191
  }
202
- return lodash_1.default.kebabCase(className);
192
+ const kebab = lodash_1.default.kebabCase(className);
193
+ return kebab.replace(/^web-f-/, 'webf-');
203
194
  }
204
195
  function generateVueTypings(blobs) {
205
- const componentNames = blobs.map(blob => {
206
- const classObjects = blob.objects;
207
- const properties = classObjects.filter(object => {
208
- return object.name.endsWith('Properties');
209
- });
210
- const events = classObjects.filter(object => {
211
- return object.name.endsWith('Events');
212
- });
213
- const componentProperties = properties.length > 0 ? properties[0] : undefined;
214
- const componentEvents = events.length > 0 ? events[0] : undefined;
215
- const className = (() => {
216
- if (componentProperties) {
217
- return componentProperties.name.replace(/Properties$/, '');
218
- }
219
- if (componentEvents) {
220
- return componentEvents.name.replace(/Events$/, '');
221
- }
222
- return '';
223
- })();
224
- return className;
225
- }).filter(name => {
226
- return name.length > 0;
196
+ const componentSpecMap = new Map();
197
+ blobs
198
+ .flatMap(blob => getVueComponentSpecs(blob))
199
+ .forEach(spec => {
200
+ if (!componentSpecMap.has(spec.className))
201
+ componentSpecMap.set(spec.className, spec);
227
202
  });
228
- const components = blobs.map(blob => {
229
- return generateVueComponent(blob);
230
- }).filter(component => {
231
- return component.length > 0;
232
- }).join('\n\n');
203
+ const componentSpecs = Array.from(componentSpecMap.values()).sort((a, b) => a.className.localeCompare(b.className));
204
+ const componentNames = componentSpecs.map(spec => spec.className);
205
+ const components = componentSpecs.map(spec => {
206
+ const content = lodash_1.default.template(readTemplate('vue.component.partial'))({
207
+ className: spec.className,
208
+ properties: spec.properties,
209
+ events: spec.events,
210
+ methods: spec.methods,
211
+ generateReturnType,
212
+ generateMethodDeclaration,
213
+ generateEventHandlerType,
214
+ });
215
+ return content.split('\n').filter(str => str.trim().length > 0).join('\n');
216
+ }).filter(Boolean).join('\n\n');
233
217
  // Collect declare consts across blobs and render as exported ambient declarations
234
218
  const consts = blobs
235
219
  .flatMap(blob => blob.objects)
@@ -241,34 +225,55 @@ function generateVueTypings(blobs) {
241
225
  uniqueConsts.set(c.name, c);
242
226
  });
243
227
  const constDeclarations = Array.from(uniqueConsts.values())
228
+ .sort((a, b) => a.name.localeCompare(b.name))
244
229
  .map(c => `export declare const ${c.name}: ${c.type};`)
245
230
  .join('\n');
246
231
  // Collect declare enums across blobs
247
232
  const enums = blobs
248
233
  .flatMap(blob => blob.objects)
249
234
  .filter(obj => obj instanceof declaration_1.EnumObject);
250
- const enumDeclarations = enums.map(e => {
235
+ const uniqueEnums = new Map();
236
+ enums.forEach(e => {
237
+ if (!uniqueEnums.has(e.name))
238
+ uniqueEnums.set(e.name, e);
239
+ });
240
+ const enumDeclarations = Array.from(uniqueEnums.values())
241
+ .sort((a, b) => a.name.localeCompare(b.name))
242
+ .map(e => {
251
243
  const members = e.members.map(m => m.initializer ? `${m.name} = ${m.initializer}` : `${m.name}`).join(', ');
252
244
  return `export declare enum ${e.name} { ${members} }`;
253
- }).join('\n');
254
- // Compute relative import path from the generated typings file (index.d.ts at dist root)
255
- // to the aggregated React types module (src/types.ts) when present.
256
- let typesImportPath = './src/types';
257
- try {
258
- if (blobs.length > 0) {
259
- const distRoot = blobs[0].dist;
260
- const typingsDir = distRoot; // index.d.ts is written directly under distRoot
261
- const typesFilePath = path_1.default.join(distRoot, 'src', 'types');
262
- const rel = path_1.default.relative(typingsDir, typesFilePath).replace(/\\/g, '/');
263
- typesImportPath = rel.startsWith('.') ? rel : `./${rel}`;
264
- }
265
- }
266
- catch (_a) {
267
- typesImportPath = './src/types';
268
- }
269
- // Always import the types namespace to support typeof references
270
- const typesImport = `import * as __webfTypes from '${typesImportPath}';`;
271
- (0, logger_1.debug)(`[vue] Generating typings; importing types from ${typesImportPath}`);
245
+ })
246
+ .join('\n');
247
+ // Collect type aliases across blobs and render as exported declarations.
248
+ const typeAliases = blobs
249
+ .flatMap(blob => blob.objects)
250
+ .filter(obj => obj instanceof declaration_1.TypeAliasObject);
251
+ const uniqueTypeAliases = new Map();
252
+ typeAliases.forEach(t => {
253
+ if (!uniqueTypeAliases.has(t.name))
254
+ uniqueTypeAliases.set(t.name, t);
255
+ });
256
+ const typeAliasDeclarations = Array.from(uniqueTypeAliases.values())
257
+ .sort((a, b) => a.name.localeCompare(b.name))
258
+ .map(t => `export type ${t.name} = ${t.type};`)
259
+ .join('\n');
260
+ // Collect supporting interfaces (non-component interfaces) so referenced types exist.
261
+ const supportingInterfaces = blobs
262
+ .flatMap(blob => blob.objects)
263
+ .filter(obj => obj instanceof declaration_1.ClassObject);
264
+ const supporting = supportingInterfaces.filter(obj => {
265
+ return !obj.name.endsWith('Properties') && !obj.name.endsWith('Events') && !obj.name.endsWith('Methods');
266
+ });
267
+ const uniqueSupporting = new Map();
268
+ supporting.forEach(obj => {
269
+ if (!uniqueSupporting.has(obj.name))
270
+ uniqueSupporting.set(obj.name, obj);
271
+ });
272
+ const supportingDeclarations = Array.from(uniqueSupporting.values())
273
+ .sort((a, b) => a.name.localeCompare(b.name))
274
+ .map(obj => renderSupportingInterface(obj))
275
+ .filter(Boolean)
276
+ .join('\n\n');
272
277
  // Build mapping of template tag names to class names for GlobalComponents
273
278
  const componentMetas = componentNames.map(className => ({
274
279
  className,
@@ -284,7 +289,8 @@ function generateVueTypings(blobs) {
284
289
  components,
285
290
  consts: constDeclarations,
286
291
  enums: enumDeclarations,
287
- typesImport,
292
+ typeAliases: typeAliasDeclarations,
293
+ dependencies: supportingDeclarations,
288
294
  });
289
295
  return content.split('\n').filter(str => {
290
296
  return str.trim().length > 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwebf/webf",
3
- "version": "0.23.10",
3
+ "version": "0.24.1",
4
4
  "description": "Command line tools for WebF",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -39,6 +39,7 @@
39
39
  "dependencies": {
40
40
  "@microsoft/tsdoc": "^0.15.1",
41
41
  "@microsoft/tsdoc-config": "^0.17.1",
42
+ "@openwebf/claude-code-skills": "^1.0.1",
42
43
  "commander": "^14.0.0",
43
44
  "glob": "^10.4.5",
44
45
  "inquirer": "^8.2.6",