mirror of
https://github.com/HeyPuter/puter.git
synced 2026-09-23 21:56:57 +00:00
dev: add runtime modules for imports and exports
RuntimeModule is a new construct which represents the import/export
mechanism for Puter extensions. This can be thought of as analogous
to node's Module class. These are called "runtime modules" because
extensions have less control of what they're consuming than a typical
npm module; i.e. `runtime.import('database')` will provide a version
of 'database' that's compatible with the importing extension, but the
version used can't be locked or otherwise determined by the extension.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
//@puter priority -1
|
||||
console.log('exporting something...');
|
||||
runtime.exports = {
|
||||
testval: 5
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
console.log('importing something...');
|
||||
const { testval } = runtime.import('exports_something');
|
||||
console.log(testval);
|
||||
@@ -32,6 +32,8 @@ const { prependToJSFiles } = require("./kernel/modutil");
|
||||
|
||||
const uuid = require('uuid');
|
||||
const readline = require("node:readline/promises");
|
||||
const { RuntimeModuleRegistry } = require("./extension/RuntimeModuleRegistry");
|
||||
const { RuntimeModule } = require("./extension/RuntimeModule");
|
||||
|
||||
const { quot } = libs.string;
|
||||
|
||||
@@ -50,6 +52,8 @@ class Kernel extends AdvancedBase {
|
||||
this.entry_path = entry_path;
|
||||
this.extensionExports = {};
|
||||
this.registry = {};
|
||||
|
||||
this.runtimeModuleRegistry = new RuntimeModuleRegistry();
|
||||
}
|
||||
|
||||
add_module (module) {
|
||||
@@ -380,6 +384,7 @@ class Kernel extends AdvancedBase {
|
||||
`const { use: puter } = globalThis.__puter_extension_globals__.useapi;`,
|
||||
`const extension = globalThis.__puter_extension_globals__` +
|
||||
`.extensionObjectRegistry[${JSON.stringify(extension_id)}];`,
|
||||
`const runtime = extension.runtime;`,
|
||||
`const config = extension.config;`,
|
||||
`const registry = extension.registry;`,
|
||||
`const register = registry.register;`,
|
||||
@@ -392,6 +397,10 @@ class Kernel extends AdvancedBase {
|
||||
|
||||
const mod = new ExtensionModule();
|
||||
mod.extension = new Extension();
|
||||
|
||||
const runtimeModule = new RuntimeModule({ name: mod_name });
|
||||
this.runtimeModuleRegistry.register(runtimeModule);
|
||||
mod.extension.runtime = runtimeModule;
|
||||
|
||||
mod_entry.module = mod;
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
const { AdvancedBase } = require("@heyputer/putility");
|
||||
|
||||
class RuntimeModule extends AdvancedBase {
|
||||
constructor (options = {}) {
|
||||
super();
|
||||
this.exports_ = undefined;
|
||||
this.exports_is_set_ = false;
|
||||
this.remappings = options.remappings ?? {};
|
||||
|
||||
this.name = options.name ?? undefined;
|
||||
}
|
||||
set exports (value) {
|
||||
this.exports_is_set_ = true;
|
||||
this.exports_ = value;
|
||||
}
|
||||
get exports () {
|
||||
if ( this.exports_is_set_ === false && this.defer ) {
|
||||
this.exports = this.defer();
|
||||
}
|
||||
return this.exports_;
|
||||
}
|
||||
import (name) {
|
||||
if ( this.remappings.hasOwnProperty(name) ) {
|
||||
name = this.remappings[name];
|
||||
}
|
||||
return this.runtimeModuleRegistry.exportsOf(name);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { RuntimeModule };
|
||||
@@ -0,0 +1,34 @@
|
||||
const { AdvancedBase } = require("@heyputer/putility");
|
||||
const { RuntimeModule } = require("./RuntimeModule");
|
||||
|
||||
class RuntimeModuleRegistry extends AdvancedBase {
|
||||
constructor () {
|
||||
super();
|
||||
this.modules_ = {};
|
||||
}
|
||||
|
||||
register (extensionModule, options = {}) {
|
||||
if ( ! (extensionModule instanceof RuntimeModule) ) {
|
||||
throw new Error(`expected a RuntimeModule, but got: ${
|
||||
extensionModule?.constructor?.name ?? typeof extensionModule})`);
|
||||
}
|
||||
const uniqueName = options.as ?? extensionModule.name ?? require('uuid').v4();
|
||||
if ( this.modules_.hasOwnProperty(uniqueName) ) {
|
||||
throw new Error(`duplicate runtime module: ${uniqueName}`);
|
||||
}
|
||||
console.log(`registering with name... ${uniqueName}`);
|
||||
this.modules_[uniqueName] = extensionModule;
|
||||
extensionModule.runtimeModuleRegistry = this;
|
||||
}
|
||||
|
||||
exportsOf (name) {
|
||||
if ( ! this.modules_[name] ) {
|
||||
throw new Error(`could not find runtime module: ${name}`);
|
||||
}
|
||||
return this.modules_[name].exports;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
RuntimeModuleRegistry
|
||||
};
|
||||
Reference in New Issue
Block a user