bun_plugins 1.2.4 → 1.2.6

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 (155) hide show
  1. package/README.md +2 -2
  2. package/dist/{src/PluginManager.d.ts → PluginManager.d.ts} +9 -16
  3. package/dist/PluginManager.d.ts.map +1 -0
  4. package/dist/{src/PluginManager.js → PluginManager.js} +188 -187
  5. package/dist/PluginManager.js.map +1 -0
  6. package/dist/{src/index.d.ts → index.d.ts} +1 -2
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/{src/index.js → index.js} +0 -2
  9. package/dist/index.js.map +1 -0
  10. package/dist/{src/managers → managers}/ContextFactory.d.ts +1 -1
  11. package/dist/managers/ContextFactory.d.ts.map +1 -0
  12. package/dist/{src/managers → managers}/ContextFactory.js +29 -52
  13. package/dist/managers/ContextFactory.js.map +1 -0
  14. package/dist/managers/DependencyManager.d.ts.map +1 -0
  15. package/dist/{src/managers → managers}/DependencyManager.js +5 -7
  16. package/dist/managers/DependencyManager.js.map +1 -0
  17. package/dist/{src/managers → managers}/HooksManager.d.ts +1 -4
  18. package/dist/managers/HooksManager.d.ts.map +1 -0
  19. package/dist/{src/managers → managers}/HooksManager.js +8 -36
  20. package/dist/managers/HooksManager.js.map +1 -0
  21. package/dist/managers/ResourceManager.d.ts.map +1 -0
  22. package/dist/{src/managers → managers}/ResourceManager.js +3 -3
  23. package/dist/managers/ResourceManager.js.map +1 -0
  24. package/dist/{src/storage → storage}/JsonPluginStorage.d.ts +1 -2
  25. package/dist/storage/JsonPluginStorage.d.ts.map +1 -0
  26. package/dist/storage/JsonPluginStorage.js +63 -0
  27. package/dist/storage/JsonPluginStorage.js.map +1 -0
  28. package/dist/{src/types.d.ts → types.d.ts} +19 -60
  29. package/dist/types.d.ts.map +1 -0
  30. package/dist/{src/types.js → types.js} +0 -7
  31. package/dist/types.js.map +1 -0
  32. package/dist/utils/errorParser.d.ts.map +1 -0
  33. package/dist/{src/utils → utils}/errorParser.js +5 -2
  34. package/dist/utils/errorParser.js.map +1 -0
  35. package/dist/utils/pluginValidator.d.ts +93 -0
  36. package/dist/utils/pluginValidator.d.ts.map +1 -0
  37. package/dist/{src/utils → utils}/pluginValidator.js +14 -12
  38. package/dist/utils/pluginValidator.js.map +1 -0
  39. package/dist/utils/security.d.ts.map +1 -0
  40. package/dist/utils/security.js.map +1 -0
  41. package/dist/worker/WorkerRunner.d.ts.map +1 -0
  42. package/dist/{src/worker → worker}/WorkerRunner.js +13 -33
  43. package/dist/worker/WorkerRunner.js.map +1 -0
  44. package/package.json +7 -18
  45. package/LICENSE +0 -9
  46. package/dist/plugins/ActionRegistryPlugin.d.ts +0 -23
  47. package/dist/plugins/ActionRegistryPlugin.d.ts.map +0 -1
  48. package/dist/plugins/ActionRegistryPlugin.js +0 -56
  49. package/dist/plugins/ActionRegistryPlugin.js.map +0 -1
  50. package/dist/plugins/DynamicJSActionsPlugin.d.ts +0 -21
  51. package/dist/plugins/DynamicJSActionsPlugin.d.ts.map +0 -1
  52. package/dist/plugins/DynamicJSActionsPlugin.js +0 -57
  53. package/dist/plugins/DynamicJSActionsPlugin.js.map +0 -1
  54. package/dist/plugins/DynamicMathActionsPlugin.d.ts +0 -22
  55. package/dist/plugins/DynamicMathActionsPlugin.d.ts.map +0 -1
  56. package/dist/plugins/DynamicMathActionsPlugin.js +0 -64
  57. package/dist/plugins/DynamicMathActionsPlugin.js.map +0 -1
  58. package/dist/plugins/DynamicTextActionsPlugin.d.ts +0 -22
  59. package/dist/plugins/DynamicTextActionsPlugin.d.ts.map +0 -1
  60. package/dist/plugins/DynamicTextActionsPlugin.js +0 -58
  61. package/dist/plugins/DynamicTextActionsPlugin.js.map +0 -1
  62. package/dist/plugins/DynamicUtilityActionsPlugin.d.ts +0 -22
  63. package/dist/plugins/DynamicUtilityActionsPlugin.d.ts.map +0 -1
  64. package/dist/plugins/DynamicUtilityActionsPlugin.js +0 -75
  65. package/dist/plugins/DynamicUtilityActionsPlugin.js.map +0 -1
  66. package/dist/plugins/LifecycleDemoPlugin.d.ts +0 -20
  67. package/dist/plugins/LifecycleDemoPlugin.d.ts.map +0 -1
  68. package/dist/plugins/LifecycleDemoPlugin.js +0 -34
  69. package/dist/plugins/LifecycleDemoPlugin.js.map +0 -1
  70. package/dist/plugins/MathPlugin.d.ts +0 -16
  71. package/dist/plugins/MathPlugin.d.ts.map +0 -1
  72. package/dist/plugins/MathPlugin.js +0 -25
  73. package/dist/plugins/MathPlugin.js.map +0 -1
  74. package/dist/plugins/MyJSPlugin.d.ts +0 -7
  75. package/dist/plugins/MyJSPlugin.d.ts.map +0 -1
  76. package/dist/plugins/MyJSPlugin.js +0 -12
  77. package/dist/plugins/MyJSPlugin.js.map +0 -1
  78. package/dist/plugins/arktype/index.d.ts +0 -8
  79. package/dist/plugins/arktype/index.d.ts.map +0 -1
  80. package/dist/plugins/arktype/index.js +0 -25
  81. package/dist/plugins/arktype/index.js.map +0 -1
  82. package/dist/src/Plugin.d.ts +0 -28
  83. package/dist/src/Plugin.d.ts.map +0 -1
  84. package/dist/src/Plugin.js +0 -36
  85. package/dist/src/Plugin.js.map +0 -1
  86. package/dist/src/PluginManager.d.ts.map +0 -1
  87. package/dist/src/PluginManager.js.map +0 -1
  88. package/dist/src/index.d.ts.map +0 -1
  89. package/dist/src/index.js.map +0 -1
  90. package/dist/src/logger/LoggerAdapter.d.ts +0 -77
  91. package/dist/src/logger/LoggerAdapter.d.ts.map +0 -1
  92. package/dist/src/logger/LoggerAdapter.js +0 -242
  93. package/dist/src/logger/LoggerAdapter.js.map +0 -1
  94. package/dist/src/logger/LoggerFactory.d.ts +0 -73
  95. package/dist/src/logger/LoggerFactory.d.ts.map +0 -1
  96. package/dist/src/logger/LoggerFactory.js +0 -99
  97. package/dist/src/logger/LoggerFactory.js.map +0 -1
  98. package/dist/src/logger/index.d.ts +0 -3
  99. package/dist/src/logger/index.d.ts.map +0 -1
  100. package/dist/src/logger/index.js +0 -3
  101. package/dist/src/logger/index.js.map +0 -1
  102. package/dist/src/managers/ContextFactory.d.ts.map +0 -1
  103. package/dist/src/managers/ContextFactory.js.map +0 -1
  104. package/dist/src/managers/DependencyManager.d.ts.map +0 -1
  105. package/dist/src/managers/DependencyManager.js.map +0 -1
  106. package/dist/src/managers/HooksManager.d.ts.map +0 -1
  107. package/dist/src/managers/HooksManager.js.map +0 -1
  108. package/dist/src/managers/ResourceManager.d.ts.map +0 -1
  109. package/dist/src/managers/ResourceManager.js.map +0 -1
  110. package/dist/src/storage/JsonPluginStorage.d.ts.map +0 -1
  111. package/dist/src/storage/JsonPluginStorage.js +0 -75
  112. package/dist/src/storage/JsonPluginStorage.js.map +0 -1
  113. package/dist/src/types/arktype_converter.d.ts +0 -19
  114. package/dist/src/types/arktype_converter.d.ts.map +0 -1
  115. package/dist/src/types/arktype_converter.js +0 -73
  116. package/dist/src/types/arktype_converter.js.map +0 -1
  117. package/dist/src/types/generator.d.ts +0 -9
  118. package/dist/src/types/generator.d.ts.map +0 -1
  119. package/dist/src/types/generator.js +0 -9
  120. package/dist/src/types/generator.js.map +0 -1
  121. package/dist/src/types/interfaces.d.ts +0 -55
  122. package/dist/src/types/interfaces.d.ts.map +0 -1
  123. package/dist/src/types/interfaces.js +0 -5
  124. package/dist/src/types/interfaces.js.map +0 -1
  125. package/dist/src/types/plugin-registry-base.d.ts +0 -78
  126. package/dist/src/types/plugin-registry-base.d.ts.map +0 -1
  127. package/dist/src/types/plugin-registry-base.js +0 -6
  128. package/dist/src/types/plugin-registry-base.js.map +0 -1
  129. package/dist/src/types/plugin-registry.d.ts +0 -2
  130. package/dist/src/types/plugin-registry.d.ts.map +0 -1
  131. package/dist/src/types/plugin-registry.js +0 -4
  132. package/dist/src/types/plugin-registry.js.map +0 -1
  133. package/dist/src/types/plugin_generator.d.ts +0 -62
  134. package/dist/src/types/plugin_generator.d.ts.map +0 -1
  135. package/dist/src/types/plugin_generator.js +0 -700
  136. package/dist/src/types/plugin_generator.js.map +0 -1
  137. package/dist/src/types.d.ts.map +0 -1
  138. package/dist/src/types.js.map +0 -1
  139. package/dist/src/utils/errorParser.d.ts.map +0 -1
  140. package/dist/src/utils/errorParser.js.map +0 -1
  141. package/dist/src/utils/pluginValidator.d.ts +0 -17
  142. package/dist/src/utils/pluginValidator.d.ts.map +0 -1
  143. package/dist/src/utils/pluginValidator.js.map +0 -1
  144. package/dist/src/utils/security.d.ts.map +0 -1
  145. package/dist/src/utils/security.js.map +0 -1
  146. package/dist/src/worker/WorkerRunner.d.ts.map +0 -1
  147. package/dist/src/worker/WorkerRunner.js.map +0 -1
  148. package/plugin-types/index.d.ts +0 -20
  149. package/plugin-types/plugin-registry.d.ts +0 -148
  150. /package/dist/{src/managers → managers}/DependencyManager.d.ts +0 -0
  151. /package/dist/{src/managers → managers}/ResourceManager.d.ts +0 -0
  152. /package/dist/{src/utils → utils}/errorParser.d.ts +0 -0
  153. /package/dist/{src/utils → utils}/security.d.ts +0 -0
  154. /package/dist/{src/utils → utils}/security.js +0 -0
  155. /package/dist/{src/worker → worker}/WorkerRunner.d.ts +0 -0
@@ -1,700 +0,0 @@
1
- import { readdir, readFile, writeFile, mkdir } from "node:fs/promises";
2
- import { join, extname } from "node:path";
3
- import ts from "typescript";
4
- import { ArkTypeConverter } from "./arktype_converter";
5
- /**
6
- * Main generator for handling conversion between classes and arktype schemas.
7
- * Provides dynamic typing and autocomplete without static KnownPluginNames.
8
- */
9
- export class PluginTypeGenerator {
10
- pluginsDir;
11
- outputDir;
12
- packageName;
13
- compilerOptions;
14
- constructor(options) {
15
- this.pluginsDir = options.pluginsDir;
16
- this.outputDir = options.outputDir;
17
- this.packageName = options.packageName || "bun_plugins";
18
- this.compilerOptions = this.getCompilerOptions();
19
- }
20
- getCompilerOptions() {
21
- const configPath = join(process.cwd(), "tsconfig.json");
22
- try {
23
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
24
- if (configFile.error) {
25
- return this.getDefaultOptions();
26
- }
27
- const { options } = ts.parseJsonConfigFileContent(configFile.config, ts.sys, process.cwd());
28
- return options;
29
- }
30
- catch {
31
- return this.getDefaultOptions();
32
- }
33
- }
34
- getDefaultOptions() {
35
- return {
36
- target: ts.ScriptTarget.ESNext,
37
- module: ts.ModuleKind.ESNext,
38
- strict: true,
39
- esModuleInterop: true,
40
- skipLibCheck: true,
41
- noEmit: true
42
- };
43
- }
44
- async scanPlugins() {
45
- const pluginFiles = await this.scanDirectory(this.pluginsDir);
46
- const plugins = [];
47
- const seenClasses = new Set();
48
- for (const filePath of pluginFiles) {
49
- try {
50
- const content = await readFile(filePath, "utf-8");
51
- const pluginInfo = this.parsePlugin(filePath, content);
52
- if (pluginInfo && pluginInfo.className && !seenClasses.has(pluginInfo.className)) {
53
- seenClasses.add(pluginInfo.className);
54
- plugins.push(pluginInfo);
55
- }
56
- }
57
- catch (err) {
58
- console.warn(`Warning: Failed to parse ${filePath}: ${err}`);
59
- }
60
- }
61
- return plugins;
62
- }
63
- async scanDirectory(dir) {
64
- const files = [];
65
- try {
66
- const entries = await readdir(dir, { withFileTypes: true });
67
- for (const entry of entries) {
68
- const fullPath = join(dir, entry.name);
69
- if (entry.isDirectory()) {
70
- if (entry.name !== "node_modules" &&
71
- entry.name !== "dist" &&
72
- entry.name !== "build" &&
73
- entry.name !== ".git" &&
74
- !entry.name.startsWith(".")) {
75
- files.push(...(await this.scanDirectory(fullPath)));
76
- }
77
- }
78
- else if (entry.isFile()) {
79
- const ext = extname(entry.name);
80
- if (ext === ".ts" || ext === ".js") {
81
- files.push(fullPath);
82
- }
83
- }
84
- }
85
- }
86
- catch {
87
- console.warn(`Warning: Could not read directory ${dir}`);
88
- }
89
- return files;
90
- }
91
- /**
92
- * Extracts the properties and methods from a TypeScript class.
93
- */
94
- extractClassProperties(sourceFile) {
95
- const properties = [];
96
- const visit = (node) => {
97
- if (ts.isClassDeclaration(node)) {
98
- node.members.forEach(member => {
99
- if (ts.isPropertyDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
100
- const propName = member.name.text;
101
- const propInfo = this.extractPropertyType(member, sourceFile);
102
- if (propInfo) {
103
- properties.push(propInfo);
104
- }
105
- }
106
- if (ts.isMethodDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
107
- const methodInfo = this.extractMethodInfo(member, sourceFile);
108
- if (methodInfo) {
109
- properties.push(methodInfo);
110
- }
111
- }
112
- if (ts.isConstructorDeclaration(member)) {
113
- member.parameters.forEach(param => {
114
- if (ts.isIdentifier(param.name) && param.type) {
115
- const propInfo = {
116
- name: param.name.text,
117
- type: param.type.getText(sourceFile),
118
- isOptional: param.questionToken !== undefined,
119
- isArray: this.isArrayType(param.type, sourceFile),
120
- nestedType: this.extractNestedType(param.type, sourceFile)
121
- };
122
- properties.push(propInfo);
123
- }
124
- });
125
- }
126
- });
127
- }
128
- ts.forEachChild(node, visit);
129
- };
130
- ts.forEachChild(sourceFile, visit);
131
- return properties;
132
- }
133
- extractMethodInfo(node, sourceFile) {
134
- const name = node.name.getText(sourceFile);
135
- if (name.startsWith("_") || name.startsWith("#")) {
136
- return null;
137
- }
138
- // Filter out lifecycle methods and getApi (internal plugin methods)
139
- const lifecycleMethods = ["onLoad", "onUnload", "onEnable", "onDisable", "onReload", "getApi"];
140
- if (lifecycleMethods.includes(name)) {
141
- return null;
142
- }
143
- const params = [];
144
- node.parameters.forEach(param => {
145
- if (ts.isIdentifier(param.name)) {
146
- params.push({
147
- name: param.name.text,
148
- type: param.type ? param.type.getText(sourceFile) : "any",
149
- isOptional: param.questionToken !== undefined
150
- });
151
- }
152
- });
153
- const returnType = node.type ? node.type.getText(sourceFile) : "void";
154
- return {
155
- name,
156
- type: returnType,
157
- isOptional: false,
158
- isArray: false,
159
- isMethod: true,
160
- params
161
- };
162
- }
163
- extractPropertyType(node, sourceFile) {
164
- if (!node.name || !ts.isIdentifier(node.name)) {
165
- return null;
166
- }
167
- const name = node.name.text;
168
- if (name.startsWith("_") || name.startsWith("#")) {
169
- return null;
170
- }
171
- let type = "any";
172
- let isOptional = node.questionToken !== undefined || node.initializer !== undefined;
173
- let isArray = false;
174
- let nestedType;
175
- if (node.type) {
176
- type = node.type.getText(sourceFile);
177
- isArray = this.isArrayType(node.type, sourceFile);
178
- nestedType = this.extractNestedType(node.type, sourceFile);
179
- }
180
- else if (node.initializer) {
181
- type = this.inferTypeFromInitializer(node.initializer, sourceFile);
182
- }
183
- return {
184
- name,
185
- type: this.mapTypeName(type),
186
- isOptional,
187
- isArray,
188
- nestedType
189
- };
190
- }
191
- isArrayType(typeNode, sourceFile) {
192
- if (ts.isArrayTypeNode(typeNode)) {
193
- return true;
194
- }
195
- if (ts.isUnionTypeNode(typeNode)) {
196
- return typeNode.types.some(t => this.isArrayType(t, sourceFile));
197
- }
198
- return false;
199
- }
200
- extractNestedType(typeNode, sourceFile) {
201
- if (ts.isTypeReferenceNode(typeNode)) {
202
- const typeName = typeNode.typeName.getText(sourceFile);
203
- const nestedProperties = this.findTypeProperties(typeName, sourceFile);
204
- if (nestedProperties.length > 0) {
205
- return {
206
- schemaName: typeName,
207
- schemaDefinition: "",
208
- typeDefinition: "",
209
- properties: nestedProperties
210
- };
211
- }
212
- }
213
- if (ts.isTypeLiteralNode(typeNode)) {
214
- const properties = [];
215
- typeNode.members.forEach(member => {
216
- if (ts.isPropertySignature(member) && member.name && ts.isIdentifier(member.name)) {
217
- const propInfo = {
218
- name: member.name.text,
219
- type: member.type ? member.type.getText(sourceFile) : "any",
220
- isOptional: member.questionToken !== undefined,
221
- isArray: member.type ? this.isArrayType(member.type, sourceFile) : false
222
- };
223
- properties.push(propInfo);
224
- }
225
- });
226
- return {
227
- schemaName: "InlineType",
228
- schemaDefinition: "",
229
- typeDefinition: "",
230
- properties
231
- };
232
- }
233
- return undefined;
234
- }
235
- /**
236
- * Generate a type string for public methods of a plugin class.
237
- */
238
- generatePublicMethodsType(p) {
239
- if (p.arkTypeSchema && p.arkTypeSchema.properties.length > 0) {
240
- const props = p.arkTypeSchema.properties
241
- .filter(prop => !prop.name.startsWith("_") && !prop.name.startsWith("#"))
242
- .map(prop => {
243
- if (prop.isMethod) {
244
- const params = prop.params?.map(param => `${param.name}: ${param.type}`).join(", ") || "";
245
- return ` ${prop.name}(${params}): ${prop.type};`;
246
- }
247
- return ` ${prop.name}${prop.isOptional ? "?" : ""}: ${prop.type};`;
248
- })
249
- .join("\n");
250
- return `{\n${props}\n }`;
251
- }
252
- return p.className;
253
- }
254
- /**
255
- * Generate an inline type definition for a plugin's API.
256
- * If the plugin has an API interface defined, it extracts the interface definition.
257
- * Otherwise, it generates the type from public methods.
258
- */
259
- generateInlineApiType(p, fallbackType) {
260
- // If the plugin has an API interface, try to extract its definition
261
- if (p.apiInterface && p.arkTypeSchema) {
262
- const props = p.arkTypeSchema.properties
263
- .filter(prop => !prop.name.startsWith("_") && !prop.name.startsWith("#"))
264
- .map(prop => {
265
- if (prop.isMethod) {
266
- const params = prop.params?.map(param => `${param.name}: ${param.type}`).join(", ") || "";
267
- return ` ${prop.name}(${params}): ${prop.type};`;
268
- }
269
- return ` ${prop.name}${prop.isOptional ? "?" : ""}: ${prop.type};`;
270
- })
271
- .join("\n");
272
- if (props) {
273
- return `{\n${props}\n }`;
274
- }
275
- }
276
- // Fallback: use the provided type (either interface name or public methods)
277
- return fallbackType;
278
- }
279
- findTypeProperties(typeName, sourceFile) {
280
- const properties = [];
281
- const visit = (node) => {
282
- if (ts.isInterfaceDeclaration(node) && node.name.text === typeName) {
283
- node.members.forEach(member => {
284
- if (ts.isPropertySignature(member) && member.name && ts.isIdentifier(member.name)) {
285
- const propInfo = {
286
- name: member.name.text,
287
- type: member.type ? this.mapTypeName(member.type.getText(sourceFile)) : "any",
288
- isOptional: member.questionToken !== undefined,
289
- isArray: member.type ? this.isArrayType(member.type, sourceFile) : false
290
- };
291
- properties.push(propInfo);
292
- }
293
- });
294
- }
295
- if (ts.isTypeAliasDeclaration(node) && node.name.text === typeName) {
296
- if (ts.isTypeLiteralNode(node.type)) {
297
- node.type.members.forEach(member => {
298
- if (ts.isPropertySignature(member) && member.name && ts.isIdentifier(member.name)) {
299
- const propInfo = {
300
- name: member.name.text,
301
- type: member.type ? this.mapTypeName(member.type.getText(sourceFile)) : "any",
302
- isOptional: member.questionToken !== undefined,
303
- isArray: member.type ? this.isArrayType(member.type, sourceFile) : false
304
- };
305
- properties.push(propInfo);
306
- }
307
- });
308
- }
309
- }
310
- ts.forEachChild(node, visit);
311
- };
312
- ts.forEachChild(sourceFile, visit);
313
- return properties;
314
- }
315
- mapTypeName(type) {
316
- const typeMap = {
317
- "string": "string",
318
- "String": "string",
319
- "number": "number",
320
- "Number": "number",
321
- "boolean": "boolean",
322
- "Boolean": "boolean",
323
- "any": "any",
324
- "unknown": "unknown",
325
- "void": "void",
326
- "null": "null",
327
- "Date": "Date",
328
- "Promise": "Promise",
329
- "Array": "Array",
330
- "Record": "Record"
331
- };
332
- const baseType = type.split("<")[0]?.split("|")[0]?.trim() || type;
333
- return typeMap[baseType] || baseType;
334
- }
335
- inferTypeFromInitializer(initializer, sourceFile) {
336
- if (ts.isStringLiteral(initializer)) {
337
- return "string";
338
- }
339
- if (ts.isNumericLiteral(initializer)) {
340
- return "number";
341
- }
342
- if (ts.isIdentifier(initializer)) {
343
- const symbol = this.getSymbolAtLocation(initializer, sourceFile);
344
- if (symbol) {
345
- return symbol;
346
- }
347
- }
348
- return "any";
349
- }
350
- getSymbolAtLocation(node, sourceFile) {
351
- const typeChecker = this.getTypeChecker();
352
- const symbol = typeChecker.getSymbolAtLocation(node);
353
- if (symbol && symbol.declarations && symbol.declarations.length > 0) {
354
- const decl = symbol.declarations[0];
355
- if (decl && (ts.isTypeAliasDeclaration(decl) || ts.isInterfaceDeclaration(decl))) {
356
- return decl.name.text;
357
- }
358
- }
359
- return undefined;
360
- }
361
- getTypeChecker() {
362
- const program = ts.createProgram([join(process.cwd(), "src/types/plugin_generator.ts")], this.compilerOptions);
363
- return program.getTypeChecker();
364
- }
365
- parseTypeScriptPlugin(filePath, source) {
366
- const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);
367
- let pluginName = "";
368
- let pluginVersion = "1.0.0";
369
- let className = "";
370
- let apiInterface;
371
- let dependencies;
372
- let arkTypeSchema;
373
- // Store interface definitions for later lookup
374
- const interfaceDefinitions = new Map();
375
- const self = this;
376
- function visit(node) {
377
- // Extract interface definitions
378
- if (ts.isInterfaceDeclaration(node)) {
379
- const interfaceName = node.name.text;
380
- const properties = [];
381
- node.members.forEach(member => {
382
- if (ts.isPropertySignature(member) && member.name && ts.isIdentifier(member.name)) {
383
- const propName = member.name.text;
384
- if (!propName.startsWith("_") && !propName.startsWith("#")) {
385
- const propInfo = {
386
- name: propName,
387
- type: member.type ? member.type.getText(sourceFile) : "any",
388
- isOptional: member.questionToken !== undefined,
389
- isArray: member.type ? self.isArrayType(member.type, sourceFile) : false
390
- };
391
- properties.push(propInfo);
392
- }
393
- }
394
- else if (ts.isMethodSignature(member) && member.name && ts.isIdentifier(member.name)) {
395
- const methodName = member.name.getText(sourceFile);
396
- if (!methodName.startsWith("_") && !methodName.startsWith("#")) {
397
- const params = [];
398
- member.parameters.forEach(param => {
399
- if (ts.isIdentifier(param.name)) {
400
- params.push({
401
- name: param.name.text,
402
- type: param.type ? param.type.getText(sourceFile) : "any",
403
- isOptional: param.questionToken !== undefined
404
- });
405
- }
406
- });
407
- const returnType = member.type ? member.type.getText(sourceFile) : "void";
408
- properties.push({
409
- name: methodName,
410
- type: returnType,
411
- isOptional: false,
412
- isArray: false,
413
- isMethod: true,
414
- params
415
- });
416
- }
417
- }
418
- });
419
- if (properties.length > 0) {
420
- interfaceDefinitions.set(interfaceName, properties);
421
- }
422
- }
423
- if (ts.isClassDeclaration(node)) {
424
- if (node.name) {
425
- className = node.name.text;
426
- const converter = new PluginTypeGenerator({
427
- pluginsDir: "",
428
- outputDir: ""
429
- });
430
- const properties = converter.extractClassProperties(sourceFile);
431
- if (properties.length > 0) {
432
- const schemaName = className + "Schema";
433
- arkTypeSchema = {
434
- schemaName,
435
- schemaDefinition: ArkTypeConverter.classToArkType(className, properties),
436
- typeDefinition: "",
437
- properties
438
- };
439
- }
440
- }
441
- }
442
- if (ts.isPropertyDeclaration(node)) {
443
- const name = node.name.getText(sourceFile);
444
- if (name === "name" && node.initializer) {
445
- pluginName = node.initializer.getText(sourceFile).replace(/['"]/g, "");
446
- }
447
- if (name === "version" && node.initializer) {
448
- pluginVersion = node.initializer.getText(sourceFile).replace(/['"]/g, "");
449
- }
450
- if (name === "dependencies" && node.initializer) {
451
- try {
452
- const depsText = node.initializer.getText(sourceFile);
453
- dependencies = eval(`(${depsText})`);
454
- }
455
- catch {
456
- }
457
- }
458
- }
459
- if (ts.isMethodDeclaration(node)) {
460
- const name = node.name.getText(sourceFile);
461
- if (name === "getApi" && node.type) {
462
- const returnType = node.type.getText(sourceFile);
463
- const match = returnType.match(/:\s*(\w+Api)/);
464
- if (match) {
465
- apiInterface = match[1];
466
- // If we found an API interface, use its properties for the schema
467
- if (apiInterface) {
468
- const apiProperties = interfaceDefinitions.get(apiInterface);
469
- if (apiProperties) {
470
- arkTypeSchema = {
471
- schemaName: apiInterface + "Schema",
472
- schemaDefinition: ArkTypeConverter.classToArkType(apiInterface, apiProperties),
473
- typeDefinition: "",
474
- properties: apiProperties
475
- };
476
- }
477
- }
478
- }
479
- }
480
- }
481
- ts.forEachChild(node, visit);
482
- }
483
- ts.forEachChild(sourceFile, visit);
484
- const fileName = filePath.split(/[/\\]/).pop()?.replace(/\.(ts|js)$/, "") || "";
485
- const name = pluginName || fileName.toLowerCase().replace(/plugin$/i, "");
486
- if (!name)
487
- return null;
488
- return {
489
- name,
490
- version: pluginVersion,
491
- className,
492
- filePath,
493
- isTypeScript: true,
494
- apiInterface,
495
- dependencies,
496
- arkTypeSchema
497
- };
498
- }
499
- parseJavaScriptPlugin(filePath, source) {
500
- const fileName = filePath.split(/[/\\]/).pop()?.replace(/\.(ts|js)$/, "") || "";
501
- const classMatch = source.match(/export\s+class\s+(\w+)/);
502
- const className = classMatch?.[1] || fileName;
503
- const nameMatch = source.match(/this\.name\s*=\s*["']([^"']+)["']/) ||
504
- source.match(/name\s*=\s*["']([^"']+)["']/);
505
- const name = nameMatch?.[1] || fileName.toLowerCase().replace(/plugin$/i, "");
506
- const versionMatch = source.match(/version\s*=\s*["']([^"']+)["']/);
507
- const version = versionMatch?.[1] || "1.0.0";
508
- const hasSharedApi = /getApi\s*\(/.test(source);
509
- if (!name)
510
- return null;
511
- return {
512
- name,
513
- version,
514
- className,
515
- filePath,
516
- isTypeScript: false,
517
- apiInterface: hasSharedApi ? `${className}Api` : undefined
518
- };
519
- }
520
- parsePlugin(filePath, content) {
521
- const ext = extname(filePath);
522
- if (ext === ".ts") {
523
- return this.parseTypeScriptPlugin(filePath, content);
524
- }
525
- else if (ext === ".js") {
526
- return this.parseJavaScriptPlugin(filePath, content);
527
- }
528
- return null;
529
- }
530
- /**
531
- * Generates dynamic type declarations using a factory pattern.
532
- * No static KnownPluginNames - types are computed at compile time.
533
- *
534
- * The API type includes:
535
- * - Base plugin properties (name, version)
536
- * - Public methods from the class
537
- * - Shared API methods if getApi is defined
538
- */
539
- generateDeclarations(plugins, baseApiInterface = "BasePluginApi") {
540
- // Note: We don't import plugin classes here because they are not distributed with the package
541
- // The class names are used only for type information
542
- // Dynamic plugin factory map - each plugin is indexed by name
543
- const pluginFactoryEntries = plugins.map(p => {
544
- // Generate public methods type from the class
545
- const publicMethodsType = this.generatePublicMethodsType(p);
546
- // Use the shared API interface if available, otherwise use the public methods
547
- const apiType = p.apiInterface ? p.apiInterface : publicMethodsType;
548
- // Generate inline type definition for the API
549
- // This ensures that the API type is fully defined without external dependencies
550
- const inlineApiType = this.generateInlineApiType(p, apiType);
551
- // Fix relative imports for distributed types
552
- const sanitizedApiType = inlineApiType
553
- .replace(/PluginContext/g, 'any')
554
- .replace(/EngineActionHandler/g, 'any')
555
- .replace(/ActionRegistry/g, 'any')
556
- .replace(/import\("\.\.\/\.\.\/src"\)\./g, 'import("bun_plugins/src").')
557
- .replace(/import\("\.\.\/src"\)\./g, 'import("bun_plugins/src").');
558
- return ` "${p.name}": {
559
- name: "${p.name}";
560
- version: "${p.version}";
561
- class: ${p.className};
562
- api: ${sanitizedApiType};
563
- dependencies?: ${p.dependencies ? `Record<${JSON.stringify(Object.keys(p.dependencies))}, string>` : "undefined"};
564
- }`;
565
- }).join(",\n");
566
- return `import type { PluginFactory as BasePluginFactory, BasePluginApi } from "${this.packageName}/src/types/plugin-registry-base";
567
-
568
- /**
569
- * Extend the PluginFactory interface with discovered plugins.
570
- * Users can also extend this interface with their own plugins using declaration merging.
571
- *
572
- * Example:
573
- * \`\`\`typescript
574
- * declare module "bun_plugins" {
575
- * export interface PluginFactory {
576
- * "my-plugin": {
577
- * name: "my-plugin";
578
- * version: "1.0.0";
579
- * class: MyPlugin;
580
- * api: MyPluginApi;
581
- * };
582
- * }
583
- * }
584
- * \`\`\`
585
- */
586
- export interface PluginFactory extends BasePluginFactory {
587
- ${pluginFactoryEntries}
588
- }
589
-
590
- /**
591
- * Re-export base types for convenience.
592
- * These types support dynamic plugin discovery and user extension.
593
- */
594
- export type {
595
- PluginClassType,
596
- GetPluginApi,
597
- GetPluginClass,
598
- IsValidPlugin,
599
- PluginFromFactory,
600
- PluginInstanceType
601
- } from "${this.packageName}/src/types/plugin-registry-base";
602
-
603
- // Re-export BasePluginApi (already imported at the top)
604
- export type { BasePluginApi };
605
-
606
- // Define PluginNames directly from the extended PluginFactory
607
- // For development, we allow any string to be used as plugin name
608
- export type PluginNames = keyof PluginFactory | string;
609
-
610
- // Define PluginApiType directly from the extended PluginFactory
611
- export type PluginApiType<T extends string> =
612
- T extends keyof PluginFactory
613
- ? PluginFactory[T]["api"]
614
- : BasePluginApi;
615
- `;
616
- }
617
- generateModuleExports(plugins, baseApiInterface = "BasePluginApi") {
618
- // Note: We don't export plugin classes here because they are not distributed with the package
619
- return `
620
-
621
- export type {
622
- PluginNames,
623
- PluginApiType,
624
- PluginClassType,
625
- GetPluginApi,
626
- GetPluginClass,
627
- IsValidPlugin,
628
- PluginFromFactory,
629
- PluginFactory
630
- } from "${this.packageName}/plugin-types/plugin-registry";
631
-
632
- export interface ${baseApiInterface} {
633
- name: string;
634
- version: string;
635
- actions?: string[];
636
- type?: string;
637
- loaded?: string;
638
- }
639
- `;
640
- }
641
- async generate() {
642
- await mkdir(this.outputDir, { recursive: true });
643
- const plugins = await this.scanPlugins();
644
- const baseApiInterface = "BasePluginApi";
645
- const declarations = this.generateDeclarations(plugins, baseApiInterface);
646
- const moduleExports = this.generateModuleExports(plugins);
647
- const dtsPath = join(this.outputDir, "plugin-registry.d.ts");
648
- const indexPath = join(this.outputDir, "index.d.ts");
649
- await writeFile(dtsPath, declarations, "utf-8");
650
- await writeFile(indexPath, moduleExports, "utf-8");
651
- console.log(`Generated ${dtsPath} with ${plugins.length} plugins`);
652
- console.log(`Generated ${indexPath}`);
653
- return plugins;
654
- }
655
- async getPlugins() {
656
- return this.scanPlugins();
657
- }
658
- static async convertClassToArkType(classFilePath) {
659
- try {
660
- const content = await readFile(classFilePath, "utf-8");
661
- const sourceFile = ts.createSourceFile(classFilePath, content, ts.ScriptTarget.Latest, true);
662
- let className = "";
663
- let properties = [];
664
- const visit = (node) => {
665
- if (ts.isClassDeclaration(node) && node.name) {
666
- className = node.name.text;
667
- const tempGenerator = new PluginTypeGenerator({
668
- pluginsDir: "",
669
- outputDir: ""
670
- });
671
- properties = tempGenerator.extractClassProperties(sourceFile);
672
- }
673
- ts.forEachChild(node, visit);
674
- };
675
- ts.forEachChild(sourceFile, visit);
676
- if (!className || properties.length === 0) {
677
- return null;
678
- }
679
- const schemaName = className + "Schema";
680
- return {
681
- schemaName,
682
- schemaDefinition: ArkTypeConverter.classToArkType(className, properties),
683
- typeDefinition: "",
684
- properties
685
- };
686
- }
687
- catch (error) {
688
- console.error(`Error converting class to ArkType: ${error}`);
689
- return null;
690
- }
691
- }
692
- }
693
- /**
694
- * Generates plugin types from a plugins directory.
695
- */
696
- export async function generatePluginTypes(pluginsDir = join(process.cwd(), "plugins"), outputDir = join(process.cwd(), "plugin-types"), packageName = "bun_plugins") {
697
- const generator = new PluginTypeGenerator({ pluginsDir, outputDir, packageName });
698
- return generator.generate();
699
- }
700
- //# sourceMappingURL=plugin_generator.js.map