mirror of
https://github.com/HeyPuter/puter.git
synced 2026-08-23 14:36:44 +00:00
dev: add command to list extensions
This commit adds the `extension:list` command for listing extensions. This command is itself defined in an extension. To make this possible, an event called 'create.commands' is emitted form CommandService with the event object holding a function that can be used to add commands.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
//@extension name extension
|
||||
const { Context } = extension.import('core');
|
||||
|
||||
// The 'create.commands' event is fired by CommandService
|
||||
extension.on('create.commands', event => {
|
||||
|
||||
// Add command to list available extensions
|
||||
event.createCommand('list', {
|
||||
description: 'list available extensions',
|
||||
handler: async (_, console) => {
|
||||
|
||||
// Get extnsion information from context
|
||||
const extensionInfos = Context.get('extensionInfo');
|
||||
|
||||
// Iterate over extension infos
|
||||
for ( const info of Object.values(extensionInfos) ) {
|
||||
|
||||
// Construct a string
|
||||
const moduleType = info.type === 'module'
|
||||
? '\x1B[32;1m(ESM)\x1B[0m'
|
||||
: '\x1B[33;1m(CJS)\x1B[0m';
|
||||
let str = `- ${info.name} ${moduleType}`;
|
||||
if ( info.priority !== 0 ) {
|
||||
str += ` (priority ${info.priority})`;
|
||||
}
|
||||
|
||||
// Print a string
|
||||
console.log(str);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -95,19 +95,19 @@ class ExtensionService extends BaseService {
|
||||
svc_event.on_all(async (key, data, meta = {}) => {
|
||||
meta.from_outside_of_extension = true;
|
||||
|
||||
const promises = [];
|
||||
|
||||
// push event to the extension's event bus
|
||||
promises.push(
|
||||
this.state.extension.emit(key, data, meta));
|
||||
|
||||
// legacy: older extensions prefix "core." to events from Puter
|
||||
promises.push(
|
||||
this.state.extension.emit(`core.${key}`, data, meta));
|
||||
|
||||
// future: going to remove 'boot.' prefix from lifecycle events
|
||||
|
||||
await Promise.all(promises);
|
||||
await Context.sub({
|
||||
extension_name: this.state.extension.name,
|
||||
}).arun(async () => {
|
||||
const promises = [
|
||||
// push event to the extension's event bus
|
||||
this.state.extension.emit(key, data, meta),
|
||||
// legacy: older extensions prefix "core." to events from Puter
|
||||
this.state.extension.emit(`core.${key}`, data, meta),
|
||||
];
|
||||
// await this.state.extension.emit(key, data, meta);
|
||||
await Promise.all(promises);
|
||||
});
|
||||
// await Promise.all(promises);
|
||||
});
|
||||
|
||||
// Propagate all events from extension to Puter's event bus
|
||||
|
||||
@@ -51,6 +51,7 @@ class Kernel extends AdvancedBase {
|
||||
|
||||
this.entry_path = entry_path;
|
||||
this.extensionExports = {};
|
||||
this.extensionInfo = {};
|
||||
this.registry = {};
|
||||
|
||||
this.runtimeModuleRegistry = new RuntimeModuleRegistry();
|
||||
@@ -126,6 +127,7 @@ class Kernel extends AdvancedBase {
|
||||
config,
|
||||
logger: this.bootLogger,
|
||||
extensionExports: this.extensionExports,
|
||||
extensionInfo: this.extensionInfo,
|
||||
registry: this.registry,
|
||||
args,
|
||||
['runtime-modules']: this.runtimeModuleRegistry,
|
||||
@@ -447,6 +449,11 @@ class Kernel extends AdvancedBase {
|
||||
|
||||
const extension_name = exportObject?.name ?? packageJSON.name;
|
||||
this.extensionExports[extension_name] = exportObject;
|
||||
this.extensionInfo[extension_name] = {
|
||||
name: extension_name,
|
||||
priority: mod_entry.priority,
|
||||
type: packageJSON?.type ?? 'commonjs',
|
||||
};
|
||||
mod.extension.registry = this.registry;
|
||||
mod.extension.name = extension_name;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const { Context } = require("../util/context");
|
||||
const BaseService = require("./BaseService");
|
||||
|
||||
|
||||
@@ -100,6 +101,30 @@ class CommandService extends BaseService {
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
async ['__on_boot.consolidation'] () {
|
||||
const svc_event = this.services.get('event');
|
||||
const svc_command = this;
|
||||
const event = {
|
||||
createCommand (name, command) {
|
||||
const serviceName = Context.get('extension_name') ?? '%missing%';
|
||||
const commandSpec = typeof command === 'function'
|
||||
? { handler: command }
|
||||
: command;
|
||||
if ( typeof commandSpec !== 'object' ) {
|
||||
throw new Error('command must be either a function or an object');
|
||||
}
|
||||
if ( ! (typeof command.handler === 'function') ) {
|
||||
throw new Error('command should have a handler function');
|
||||
}
|
||||
svc_command.registerCommands(serviceName, [{
|
||||
id: name,
|
||||
...commandSpec,
|
||||
}]);
|
||||
},
|
||||
};
|
||||
svc_event.emit('create.commands', event);
|
||||
}
|
||||
|
||||
registerCommands(serviceName, commands) {
|
||||
if ( ! this.log ) process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user