invoket 0.1.2 → 0.1.3

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/package.json +1 -1
  2. package/src/cli.ts +49 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "invoket",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "TypeScript task runner for Bun - uses type annotations to parse CLI arguments",
6
6
  "bin": {
package/src/cli.ts CHANGED
@@ -152,7 +152,7 @@ function parseParams(paramsStr: string | undefined): ParamMeta[] {
152
152
  return params;
153
153
  }
154
154
 
155
- // Discover all tasks including namespaced ones
155
+ // Discover all tasks including namespaced ones (source parsing only)
156
156
  function discoverAllTasks(source: string): DiscoveredTasks {
157
157
  const root = extractMethodsFromClass(source, "Tasks");
158
158
  const namespaced = new Map<string, Map<string, TaskMeta>>();
@@ -177,6 +177,48 @@ function discoverAllTasks(source: string): DiscoveredTasks {
177
177
  return { root, namespaced, classDoc };
178
178
  }
179
179
 
180
+ // Discover methods from runtime instance (for imported namespaces)
181
+ function discoverRuntimeNamespaces(
182
+ instance: any,
183
+ discovered: DiscoveredTasks,
184
+ ): void {
185
+ // Find namespace properties on the instance
186
+ for (const propName of Object.getOwnPropertyNames(instance)) {
187
+ // Skip private, already discovered, or non-objects
188
+ if (propName.startsWith("_")) continue;
189
+ if (discovered.namespaced.has(propName)) continue;
190
+
191
+ const prop = instance[propName];
192
+ if (!prop || typeof prop !== "object" || Array.isArray(prop)) continue;
193
+
194
+ // Discover methods from this namespace at runtime
195
+ const methods = new Map<string, TaskMeta>();
196
+ let proto = Object.getPrototypeOf(prop);
197
+
198
+ while (proto && proto !== Object.prototype) {
199
+ for (const methodName of Object.getOwnPropertyNames(proto)) {
200
+ if (
201
+ methodName === "constructor" ||
202
+ methodName.startsWith("_") ||
203
+ typeof prop[methodName] !== "function"
204
+ ) {
205
+ continue;
206
+ }
207
+
208
+ // No type info for imported methods - treat args as strings
209
+ if (!methods.has(methodName)) {
210
+ methods.set(methodName, { description: "", params: [] });
211
+ }
212
+ }
213
+ proto = Object.getPrototypeOf(proto);
214
+ }
215
+
216
+ if (methods.size > 0) {
217
+ discovered.namespaced.set(propName, methods);
218
+ }
219
+ }
220
+ }
221
+
180
222
  // Parse TypeScript source to extract method signatures and types (legacy, for compatibility)
181
223
  async function extractTaskMeta(source: string): Promise<Map<string, TaskMeta>> {
182
224
  const { root, namespaced } = discoverAllTasks(source);
@@ -285,14 +327,17 @@ async function main() {
285
327
  const tasksPath = Bun.resolveSync("./tasks.ts", process.cwd());
286
328
  const source = await Bun.file(tasksPath).text();
287
329
 
288
- // Discover all tasks including namespaced
289
- const discovered = discoverAllTasks(source);
290
-
291
330
  // Import and instantiate Tasks class
292
331
  const { Tasks } = await import(tasksPath);
293
332
  const instance = new Tasks();
294
333
  const context = new Context();
295
334
 
335
+ // Discover all tasks including namespaced
336
+ const discovered = discoverAllTasks(source);
337
+
338
+ // Also discover imported namespaces from runtime
339
+ discoverRuntimeNamespaces(instance, discovered);
340
+
296
341
  // No args or just help flag -> show general help
297
342
  if (
298
343
  args.length === 0 ||