mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-02 23:28:39 +08:00
refactor(backend): de-couple driver registration from DriverService
This commit is contained in:
parent
2d8e6240c6
commit
665b2d4e4e
@ -225,6 +225,9 @@ const install = async ({ services, app }) => {
|
|||||||
|
|
||||||
const { DevTODService } = require('./services/DevTODService');
|
const { DevTODService } = require('./services/DevTODService');
|
||||||
services.registerService('__dev-tod', DevTODService);
|
services.registerService('__dev-tod', DevTODService);
|
||||||
|
|
||||||
|
const { DriverService } = require("./services/drivers/DriverService");
|
||||||
|
services.registerService('driver', DriverService);
|
||||||
}
|
}
|
||||||
|
|
||||||
const install_legacy = async ({ services }) => {
|
const install_legacy = async ({ services }) => {
|
||||||
|
@ -5,6 +5,9 @@ class SelfHostedModule extends AdvancedBase {
|
|||||||
async install (context) {
|
async install (context) {
|
||||||
const services = context.get('services');
|
const services = context.get('services');
|
||||||
|
|
||||||
|
const { SelfhostedService } = require('./services/SelfhostedService');
|
||||||
|
services.registerService('__selfhosted', SelfhostedService);
|
||||||
|
|
||||||
const DefaultUserService = require('./services/DefaultUserService');
|
const DefaultUserService = require('./services/DefaultUserService');
|
||||||
services.registerService('__default-user', DefaultUserService);
|
services.registerService('__default-user', DefaultUserService);
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
const { AdvancedBase } = require("@heyputer/puter-js-common");
|
const { AdvancedBase } = require("@heyputer/puter-js-common");
|
||||||
const { Context } = require("../../../util/context");
|
const { Context } = require('../util/context')
|
||||||
const APIError = require("../../../api/APIError");
|
const APIError = require("../api/APIError");
|
||||||
const { AppUnderUserActorType, Actor, UserActorType } = require("../../auth/Actor");
|
const { AppUnderUserActorType, UserActorType } = require("../services/auth/Actor");
|
||||||
const { BaseOperation } = require("../../OperationTraceService");
|
const { BaseOperation } = require("../services/OperationTraceService");
|
||||||
const { CodeUtil } = require("../../../codex/CodeUtil");
|
const { CodeUtil } = require("../codex/CodeUtil");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all driver implementations.
|
* Base class for all driver implementations.
|
||||||
*/
|
*/
|
||||||
class BaseImplementation extends AdvancedBase {
|
class Driver extends AdvancedBase {
|
||||||
constructor (...a) {
|
constructor (...a) {
|
||||||
super(...a);
|
super(...a);
|
||||||
const methods = this._get_merged_static_object('METHODS');
|
const methods = this._get_merged_static_object('METHODS');
|
||||||
@ -184,5 +184,5 @@ class BaseImplementation extends AdvancedBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
BaseImplementation,
|
Driver,
|
||||||
};
|
};
|
@ -16,14 +16,12 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
const { AppUnderUserActorType } = require("../../auth/Actor");
|
const config = require("../config");
|
||||||
const { BaseImplementation } = require("./BaseImplementation");
|
const APIError = require("../api/APIError");
|
||||||
|
const { DB_READ, DB_WRITE } = require("../services/database/consts");
|
||||||
|
const { Driver } = require("../definitions/Driver");
|
||||||
|
|
||||||
const config = require("../../../config");
|
class DBKVStore extends Driver {
|
||||||
const APIError = require("../../../api/APIError");
|
|
||||||
const { DB_READ, DB_WRITE } = require("../../database/consts");
|
|
||||||
|
|
||||||
class DBKVStore extends BaseImplementation {
|
|
||||||
static ID = 'public-db-kvstore';
|
static ID = 'public-db-kvstore';
|
||||||
static VERSION = '0.0.0';
|
static VERSION = '0.0.0';
|
||||||
static INTERFACE = 'puter-kvstore';
|
static INTERFACE = 'puter-kvstore';
|
||||||
@ -32,6 +30,7 @@ class DBKVStore extends BaseImplementation {
|
|||||||
}
|
}
|
||||||
static METHODS = {
|
static METHODS = {
|
||||||
get: async function ({ key }) {
|
get: async function ({ key }) {
|
||||||
|
console.log('THIS WAS CALLED', { key });
|
||||||
const actor = this.context.get('actor');
|
const actor = this.context.get('actor');
|
||||||
|
|
||||||
// If the actor is an app then it gets its own KV store.
|
// If the actor is an app then it gets its own KV store.
|
||||||
@ -58,6 +57,7 @@ class DBKVStore extends BaseImplementation {
|
|||||||
return kv[0]?.value ?? null;
|
return kv[0]?.value ?? null;
|
||||||
},
|
},
|
||||||
set: async function ({ key, value }) {
|
set: async function ({ key, value }) {
|
||||||
|
console.log('THIS WAS CALLED (SET)', { key, value })
|
||||||
const actor = this.context.get('actor');
|
const actor = this.context.get('actor');
|
||||||
|
|
||||||
// Validate the key
|
// Validate the key
|
||||||
@ -98,12 +98,15 @@ class DBKVStore extends BaseImplementation {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// if ( e.code !== 'SQLITE_ERROR' && e.code !== 'SQLITE_CONSTRAINT_PRIMARYKEY' ) throw e;
|
// I discovered that my .sqlite file was corrupted and the update
|
||||||
// The "ON CONFLICT" clause isn't currently working.
|
// above didn't work. The current database initialization does not
|
||||||
await db.write(
|
// cause this issue so I'm adding this log as a safeguard.
|
||||||
`UPDATE kv SET value = ? WHERE user_id=? AND app=? AND kkey_hash=?`,
|
// - KernelDeimos / ED
|
||||||
[ value, user.id, app?.uid ?? 'global', key_hash ]
|
const svc_error = this.services.get('error-service');
|
||||||
);
|
svc_error.report('kvstore:sqlite_error', {
|
||||||
|
message: 'Broken database version - please contact maintainers',
|
||||||
|
source: e,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
@ -16,10 +16,10 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
const APIError = require("../../../api/APIError");
|
const APIError = require("../api/APIError");
|
||||||
const { Entity } = require("../../../om/entitystorage/Entity");
|
const { Driver } = require("../definitions/Driver");
|
||||||
const { Or, And, Eq } = require("../../../om/query/query");
|
const { Entity } = require("../om/entitystorage/Entity");
|
||||||
const { BaseImplementation } = require("./BaseImplementation");
|
const { Or, And, Eq } = require("../om/query/query");
|
||||||
|
|
||||||
const _fetch_based_on_complex_id = async (self, id) => {
|
const _fetch_based_on_complex_id = async (self, id) => {
|
||||||
// Ensure `id` is an object and get its keys
|
// Ensure `id` is an object and get its keys
|
||||||
@ -87,7 +87,7 @@ const _fetch_based_on_either_id = async (self, uid, id) => {
|
|||||||
return await _fetch_based_on_complex_id(self, id);
|
return await _fetch_based_on_complex_id(self, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntityStoreImplementation extends BaseImplementation {
|
class EntityStoreImplementation extends Driver {
|
||||||
constructor ({ service }) {
|
constructor ({ service }) {
|
||||||
super();
|
super();
|
||||||
this.service = service;
|
this.service = service;
|
@ -16,10 +16,9 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
const { Context } = require("../../../util/context");
|
const { Driver } = require("../definitions/Driver");
|
||||||
const { BaseImplementation } = require("./BaseImplementation");
|
|
||||||
|
|
||||||
class HelloWorld extends BaseImplementation {
|
class HelloWorld extends Driver {
|
||||||
static ID = 'public-helloworld';
|
static ID = 'public-helloworld';
|
||||||
static VERSION = '0.0.0';
|
static VERSION = '0.0.0';
|
||||||
static INTERFACE = 'helloworld';
|
static INTERFACE = 'helloworld';
|
@ -128,8 +128,6 @@ class PropType extends AdvancedBase {
|
|||||||
async is_set (value) {
|
async is_set (value) {
|
||||||
const is_setters = this.chains.is_set || [];
|
const is_setters = this.chains.is_set || [];
|
||||||
|
|
||||||
console.log('IS SETTERS', is_setters)
|
|
||||||
|
|
||||||
for ( const is_setter of is_setters ) {
|
for ( const is_setter of is_setters ) {
|
||||||
const result = await is_setter(value);
|
const result = await is_setter(value);
|
||||||
if ( ! result ) {
|
if ( ! result ) {
|
||||||
|
21
packages/backend/src/services/SelfhostedService.js
Normal file
21
packages/backend/src/services/SelfhostedService.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const { DBKVStore } = require("../drivers/DBKVStore");
|
||||||
|
const { EntityStoreImplementation } = require("../drivers/EntityStoreImplementation");
|
||||||
|
const { HelloWorld } = require("../drivers/HelloWorld");
|
||||||
|
const BaseService = require("./BaseService");
|
||||||
|
|
||||||
|
class SelfhostedService extends BaseService {
|
||||||
|
static description = `
|
||||||
|
Registers drivers for self-hosted Puter instances.
|
||||||
|
`
|
||||||
|
|
||||||
|
async _init () {
|
||||||
|
const svc_driver = this.services.get('driver');
|
||||||
|
|
||||||
|
svc_driver.register_driver('helloworld', new HelloWorld());
|
||||||
|
svc_driver.register_driver('puter-kvstore', new DBKVStore());
|
||||||
|
svc_driver.register_driver('puter-apps', new EntityStoreImplementation({ service: 'es:app' }));
|
||||||
|
svc_driver.register_driver('puter-subdomains', new EntityStoreImplementation({ service: 'es:subdomain' }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { SelfhostedService };
|
@ -168,22 +168,13 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
|
|||||||
query = this.sqlite_transform_query_(query);
|
query = this.sqlite_transform_query_(query);
|
||||||
params = this.sqlite_transform_params_(params);
|
params = this.sqlite_transform_params_(params);
|
||||||
|
|
||||||
try {
|
const stmt = this.db.prepare(query);
|
||||||
const stmt = this.db.prepare(query);
|
const info = stmt.run(...params);
|
||||||
const info = stmt.run(...params);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
insertId: info.lastInsertRowid,
|
insertId: info.lastInsertRowid,
|
||||||
anyRowsAffected: info.changes > 0,
|
anyRowsAffected: info.changes > 0,
|
||||||
};
|
};
|
||||||
} catch ( e ) {
|
|
||||||
console.error(e);
|
|
||||||
console.log('everything', {
|
|
||||||
query, params,
|
|
||||||
})
|
|
||||||
console.log(params.map(p => typeof p));
|
|
||||||
// throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _batch_write (entries) {
|
async _batch_write (entries) {
|
||||||
|
@ -16,37 +16,27 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
const { AdvancedBase } = require("@heyputer/puter-js-common");
|
|
||||||
const { Context } = require("../../util/context");
|
const { Context } = require("../../util/context");
|
||||||
const APIError = require("../../api/APIError");
|
const APIError = require("../../api/APIError");
|
||||||
const { DriverError } = require("./DriverError");
|
const { DriverError } = require("./DriverError");
|
||||||
const { Value, TypedValue } = require("./meta/Runtime");
|
const { TypedValue } = require("./meta/Runtime");
|
||||||
const { ServiceImplementation, EntityStoreImplementation } = require("./implementations/EntityStoreImplementation");
|
const BaseService = require("../BaseService");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DriverService provides the functionality of Puter drivers.
|
* DriverService provides the functionality of Puter drivers.
|
||||||
*/
|
*/
|
||||||
class DriverService extends AdvancedBase {
|
class DriverService extends BaseService {
|
||||||
static MODULES = {
|
static MODULES = {
|
||||||
types: require('./types'),
|
types: require('./types'),
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor ({ services }) {
|
_construct () {
|
||||||
super();
|
|
||||||
this.services = services;
|
|
||||||
|
|
||||||
// TODO: move this to an init method
|
|
||||||
this.log = services.get('log-service').create(this.constructor.name);
|
|
||||||
this.errors = services.get('error-service').create(this.log);
|
|
||||||
|
|
||||||
this.interfaces = require('./interfaces');
|
this.interfaces = require('./interfaces');
|
||||||
|
this.interface_to_implementation = {};
|
||||||
|
}
|
||||||
|
|
||||||
this.interface_to_implementation = {
|
register_driver (interface_name, implementation) {
|
||||||
'helloworld': new (require('./implementations/HelloWorld').HelloWorld)(),
|
this.interface_to_implementation[interface_name] = implementation;
|
||||||
'puter-kvstore': new (require('./implementations/DBKVStore').DBKVStore)(),
|
|
||||||
'puter-apps': new EntityStoreImplementation({ service: 'es:app' }),
|
|
||||||
'puter-subdomains': new EntityStoreImplementation({ service: 'es:subdomain' }),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_interface (interface_name) {
|
get_interface (interface_name) {
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2024 Puter Technologies Inc.
|
|
||||||
*
|
|
||||||
* This file is part of Puter.
|
|
||||||
*
|
|
||||||
* Puter is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* 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 { AdvancedBase } = require("@heyputer/puter-js-common");
|
|
||||||
|
|
||||||
const ENDPOINT = 'https://api.puter.com/drivers/call';
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Fetch example:
|
|
||||||
|
|
||||||
await fetch("https://api.puter.local/drivers/call", {
|
|
||||||
"headers": {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Authorization": "Bearer <actor token>",
|
|
||||||
},
|
|
||||||
"body": JSON.stringify({ interface: '...', method: '...', args: { ... } }),
|
|
||||||
"method": "POST",
|
|
||||||
});
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PuterDriverProxy extends AdvancedBase {
|
|
||||||
static MODULES = {
|
|
||||||
axios: require('axios'),
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor ({ target }) {
|
|
||||||
super();
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
async call (method, args) {
|
|
||||||
const require = this.require;
|
|
||||||
const axios = require('axios');
|
|
||||||
|
|
||||||
// TODO: We need the BYOK feature before we can implement this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = PuterDriverProxy;
|
|
@ -57,7 +57,6 @@ const main = async () => {
|
|||||||
Kernel,
|
Kernel,
|
||||||
CoreModule,
|
CoreModule,
|
||||||
DatabaseModule,
|
DatabaseModule,
|
||||||
PuterDriversModule,
|
|
||||||
LocalDiskStorageModule,
|
LocalDiskStorageModule,
|
||||||
SelfHostedModule
|
SelfHostedModule
|
||||||
} = (await import('@heyputer/backend')).default;
|
} = (await import('@heyputer/backend')).default;
|
||||||
@ -66,7 +65,6 @@ const main = async () => {
|
|||||||
const k = new Kernel();
|
const k = new Kernel();
|
||||||
k.add_module(new CoreModule());
|
k.add_module(new CoreModule());
|
||||||
k.add_module(new DatabaseModule());
|
k.add_module(new DatabaseModule());
|
||||||
k.add_module(new PuterDriversModule());
|
|
||||||
k.add_module(new LocalDiskStorageModule());
|
k.add_module(new LocalDiskStorageModule());
|
||||||
k.add_module(new SelfHostedModule());
|
k.add_module(new SelfHostedModule());
|
||||||
k.boot();
|
k.boot();
|
||||||
|
Loading…
Reference in New Issue
Block a user