diff --git a/packages/caching/src/building/SegmentCacheWriter.ts b/packages/caching/src/building/SegmentCacheWriter.ts index 724c0de1..f6c71bd5 100644 --- a/packages/caching/src/building/SegmentCacheWriter.ts +++ b/packages/caching/src/building/SegmentCacheWriter.ts @@ -25,10 +25,10 @@ export default class SegmentCacheWriter async #writeWorkerCache(cache: SegmentCache): Promise { - const importCode = this.#createImportCode(cache.imports); - const segmentCode = this.#createSegmentCode(cache.name, cache.procedures); - const filename = createWorkerFilename(cache.name); + const importCode = this.#createImportCode(cache.imports, filename); + const segmentCode = this.#createSegmentCode(cache.name, cache.procedures, filename); + const code = `${importCode}\n${segmentCode}`; return this.#fileManager.write(filename, code); @@ -37,28 +37,29 @@ export default class SegmentCacheWriter async #writeRepositoryCache(cache: SegmentCache): Promise { const filename = createRepositoryFilename(cache.name); - const code = `export const files = [\n\t"${[...cache.files].join('",\n\t"')}"\n];`; + const files = cache.files.map(file => `./${file}`); + const code = `export const files = [\n\t"${[...files].join('",\n\t"')}"\n];`; return this.#fileManager.write(filename, code); } - #createImportCode(imports: SegmentImport[]): string + #createImportCode(imports: SegmentImport[], filename: string): string { const codes: string[] = []; for (const { members, from } of imports) { - codes.push(`const { ${members.join(', ')} } = await __import("./${from}", "application", false);`); + codes.push(`const { ${members.join(', ')} } = await __import("${filename}", "./${from}", "application", false);`); } return codes.join('\n'); } - #createSegmentCode(name: string, procedures: SegmentProcedure[]): string + #createSegmentCode(name: string, procedures: SegmentProcedure[], filename: string): string { const codes: string[] = []; - codes.push('const { Segment, Procedure, Implementation, Version, NamedParameter, ArrayParameter, ObjectParameter } = await __import("jitar", "runtime", false);'); + codes.push(`const { Segment, Procedure, Implementation, Version, NamedParameter, ArrayParameter, ObjectParameter } = await __import("${filename}", "jitar", "runtime", false);`); codes.push(`export const segment = new Segment("${name}")`); for (const procedure of procedures) diff --git a/packages/caching/src/building/utils/ImportRewriter.ts b/packages/caching/src/building/utils/ImportRewriter.ts index 952ae846..889f0ca2 100644 --- a/packages/caching/src/building/utils/ImportRewriter.ts +++ b/packages/caching/src/building/utils/ImportRewriter.ts @@ -43,17 +43,18 @@ export default class ImportRewriter #rewriteImport(dependency: ReflectionImport, scope: string, filename: string): string { + const caller = this.#ensureRoot(filename); const from = this.#rewriteImportFrom(dependency, filename); if (dependency.members.length === 0) { - return `await __import("${from}", "${scope}", true, "${filename}");`; + return `await __import("${caller}", "${from}", "${scope}", true);`; } const members = this.#rewriteImportMembers(dependency); const extractDefault = this.#mustUseAs(dependency) ? 'true' : 'false'; - return `const ${members} = await __import("${from}", "${scope}", ${extractDefault}, "${filename}");`; + return `const ${members} = await __import("${caller}", "${from}", "${scope}", ${extractDefault});`; } #rewriteImportFrom(dependency: ReflectionImport, filename: string): string diff --git a/packages/jitar/src/client.ts b/packages/jitar/src/client.ts index efdad152..402bf5c8 100644 --- a/packages/jitar/src/client.ts +++ b/packages/jitar/src/client.ts @@ -13,6 +13,7 @@ export NamedParameter, ArrayParameter, ObjectParameter, + Import, BadRequest, Forbidden, NotFound, diff --git a/packages/plugin-vite/src/index.ts b/packages/plugin-vite/src/index.ts index e514608a..aecbcca4 100644 --- a/packages/plugin-vite/src/index.ts +++ b/packages/plugin-vite/src/index.ts @@ -76,8 +76,8 @@ async function createImportCode(code: string, id: string, jitarFullPath: string, exportCode += `export { ${functionKeys.join(', ')} };\n`; } - return 'import { getClient } from "/jitar/client.js";\n' - + `const module = await (await getClient()).import("./${jitarPath}${relativeId}");\n` + return 'import { getClient, Import } from "/jitar/client.js";\n' + + `const module = await (await getClient()).import(new Import("", "./${jitarPath}${relativeId}", "application", false));\n` + importCode + exportCode; } @@ -105,11 +105,11 @@ export default function viteJitar(sourcePath: string, jitarPath: string, jitarUr jitarFullPath = path.join(resolvedConfig.root, sourcePath, jitarPath); }, - resolveId(source: string) + resolveId(id: string) { - if (source === '/jitar/client.js') + if (id === '/jitar/client.js') { - return { id: source, external: 'absolute' }; + return { id, external: 'absolute' }; } return null; @@ -117,11 +117,17 @@ export default function viteJitar(sourcePath: string, jitarPath: string, jitarUr async transform(code: string, id: string) { - if (jitarFullPath === undefined || id.includes(jitarFullPath) === false) + if (jitarFullPath === undefined) { return code; } + if (id.includes(jitarFullPath)) + { + return undefined; + } + + // TODO: refactor createImportCode to rewrite all the jitar (domain) related imports return createImportCode(code, id, jitarFullPath, jitarPath); }, diff --git a/packages/runtime/src/hooks.ts b/packages/runtime/src/hooks.ts index d76f5f7e..7e32a0b5 100644 --- a/packages/runtime/src/hooks.ts +++ b/packages/runtime/src/hooks.ts @@ -24,7 +24,7 @@ export function getRuntime(): ProcedureRuntime return _runtime; } -export async function importModule(specifier: string, executionScope: ExecutionScope, extractDefault: boolean, source?: string): Promise +export async function importModule(caller: string, specifier: string, executionScope: ExecutionScope, extractDefault: boolean): Promise { const runtime = getRuntime(); @@ -33,9 +33,7 @@ export async function importModule(specifier: string, executionScope: ExecutionS specifier = 'RUNTIME_HOOKS_LOCATION'; } - console.log('importModule', specifier, source); - - const importModel = new Import(specifier, executionScope, extractDefault, source); + const importModel = new Import(caller, specifier, executionScope, extractDefault); const module = await runtime.import(importModel); return importModel.extractDefault && module.default !== undefined ? module.default : module; diff --git a/packages/runtime/src/models/Import.ts b/packages/runtime/src/models/Import.ts index d4697da8..e293540a 100644 --- a/packages/runtime/src/models/Import.ts +++ b/packages/runtime/src/models/Import.ts @@ -3,24 +3,24 @@ import { ExecutionScope } from '../definitions/ExecutionScope.js'; export default class Import { + #caller: string; #specifier: string; #scope: ExecutionScope; #extractDefault: boolean; - #source?: string; - constructor(specifier: string, scope: ExecutionScope, extractDefault: boolean = true, source?: string) + constructor(caller: string, specifier: string, scope: ExecutionScope, extractDefault: boolean = true) { + this.#caller = caller; this.#specifier = specifier; this.#scope = scope; this.#extractDefault = extractDefault; - this.#source = source; } + get caller() { return this.#caller; } + get specifier() { return this.#specifier; } get scope() { return this.#scope; } get extractDefault() { return this.#extractDefault; } - - get source() { return this.#source; } } diff --git a/packages/runtime/src/services/LocalRepository.ts b/packages/runtime/src/services/LocalRepository.ts index d3d5f15f..448ea46e 100644 --- a/packages/runtime/src/services/LocalRepository.ts +++ b/packages/runtime/src/services/LocalRepository.ts @@ -123,7 +123,7 @@ export default class LocalRepository extends Repository return this.#readFile(filename); } - readModule(source: string, specifier: string): Promise + readModule(caller: string, specifier: string): Promise { if (isSegmentFilename(specifier)) { @@ -132,10 +132,13 @@ export default class LocalRepository extends Repository if (this.#isSegmented(specifier) === false) { + console.log('NOT SEGMENTED', specifier); return this.#readWorkerModule(specifier); } - return this.#bbb(source, specifier) + console.log('IS SEGMENTED', specifier); + + return this.#inSameSegment(caller, specifier) ? this.#readWorkerModule(specifier) : this.#readRemoteModule(specifier); } @@ -147,26 +150,22 @@ export default class LocalRepository extends Repository return ModuleLoader.load(filename); } - #bbb(source: string, specifier: string): boolean + async #readWorkerModule(specifier: string): Promise { - const sourceSegments = this.#aaa(source); - const specifierSegments = this.#aaa(specifier); - - return sourceSegments.some(segmentName => specifierSegments.includes(segmentName)); - } + console.log('WORKER MODULE', specifier); - async #readWorkerModule(name: string): Promise - { - const filename = this.#getModuleFilename(name); + const filename = this.#getModuleFilename(specifier); const file = await this.#readFile(filename); const code = file.content.toString(); return new File(filename, 'application/javascript', code); } - #readRemoteModule(name: string): Promise + #readRemoteModule(specifier: string): Promise { - const remoteFilename = convertToRemoteFilename(name); + console.log('REMOTE MODULE', specifier); + + const remoteFilename = convertToRemoteFilename(specifier); return this.#readFile(remoteFilename); } @@ -196,7 +195,15 @@ export default class LocalRepository extends Repository return this.#fileManager.read(filename); } - #aaa(filename: string): string[] + #inSameSegment(firstFilename: string, secondFilename: string): boolean + { + const firstSegments = this.#filterSegments(firstFilename); + const secondSegments = this.#filterSegments(secondFilename); + + return firstSegments.some(segmentName => secondSegments.includes(segmentName)); + } + + #filterSegments(filename: string): string[] { const segmentNames = [...this.#segments.keys()]; diff --git a/packages/runtime/src/services/LocalWorker.ts b/packages/runtime/src/services/LocalWorker.ts index 89c0b5d7..1275798a 100644 --- a/packages/runtime/src/services/LocalWorker.ts +++ b/packages/runtime/src/services/LocalWorker.ts @@ -122,7 +122,7 @@ export default class LocalWorker extends Worker async #loadSegment(name: string): Promise { const filename = createWorkerFilename(name); - const importModel = new Import(filename, ExecutionScopes.APPLICATION); + const importModel = new Import('', filename, ExecutionScopes.APPLICATION); const module = await this.import(importModel); const segment = module.segment as Segment; diff --git a/packages/runtime/src/services/ProcedureRuntime.ts b/packages/runtime/src/services/ProcedureRuntime.ts index 25be1fc6..d1483e2d 100644 --- a/packages/runtime/src/services/ProcedureRuntime.ts +++ b/packages/runtime/src/services/ProcedureRuntime.ts @@ -112,15 +112,15 @@ export default abstract class ProcedureRuntime extends Runtime implements Runner } } - async #importMiddleware(url: string): Promise + async #importMiddleware(specifier: string): Promise { - const importModel = new Import(url, ExecutionScopes.APPLICATION); + const importModel = new Import('', specifier, ExecutionScopes.APPLICATION); const module = await this.import(importModel); const middleware = module.default as Middleware; if (middleware?.handle === undefined) { - throw new InvalidMiddleware(url); + throw new InvalidMiddleware(specifier); } this.addMiddleware(middleware); diff --git a/packages/runtime/src/services/Remote.ts b/packages/runtime/src/services/Remote.ts index 5f452635..d02d1190 100644 --- a/packages/runtime/src/services/Remote.ts +++ b/packages/runtime/src/services/Remote.ts @@ -28,7 +28,6 @@ export default class Remote async loadFile(filename: string): Promise { const url = `${this.#url}/${filename}`; - console.log('load file', url); const options = { method: 'GET' }; const response = await this.#callRemote(url, options); diff --git a/packages/runtime/src/services/RemoteRepository.ts b/packages/runtime/src/services/RemoteRepository.ts index da3703a7..d7a21c07 100644 --- a/packages/runtime/src/services/RemoteRepository.ts +++ b/packages/runtime/src/services/RemoteRepository.ts @@ -36,9 +36,9 @@ export default class RemoteRepository extends Repository return this.#remote.loadFile(filename); } - readModule(source: string, specifier: string): Promise + readModule(caller: string, specifier: string): Promise { - return this.#remote.loadFile(`modules/${specifier}?source=${source}`); + return this.#remote.loadFile(`modules/${specifier}?caller=${caller}`); } loadModule(specifier: string): Promise diff --git a/packages/runtime/src/services/Repository.ts b/packages/runtime/src/services/Repository.ts index b476dca6..d7ad8ef5 100644 --- a/packages/runtime/src/services/Repository.ts +++ b/packages/runtime/src/services/Repository.ts @@ -22,7 +22,7 @@ export default abstract class Repository extends Runtime abstract readAsset(filename: string): Promise; - abstract readModule(source: string, specifier: string): Promise; + abstract readModule(caller: string, specifier: string): Promise; abstract loadModule(specifier: string): Promise; } diff --git a/packages/runtime/src/services/Runtime.ts b/packages/runtime/src/services/Runtime.ts index 15b443b8..023b39c3 100644 --- a/packages/runtime/src/services/Runtime.ts +++ b/packages/runtime/src/services/Runtime.ts @@ -89,15 +89,15 @@ export default abstract class Runtime } } - async #importHealthCheck(url: string): Promise + async #importHealthCheck(specifier: string): Promise { - const importModel = new Import(url, ExecutionScopes.APPLICATION); + const importModel = new Import('', specifier, ExecutionScopes.APPLICATION); const module = await this.import(importModel); const healthCheck = module.default as HealthCheck; if (healthCheck?.isHealthy === undefined) { - throw new InvalidHealthCheck(url); + throw new InvalidHealthCheck(specifier); } this.addHealthCheck(healthCheck as HealthCheck); diff --git a/packages/runtime/test/_fixtures/services/LocalRepository.fixture.ts b/packages/runtime/test/_fixtures/services/LocalRepository.fixture.ts index c50a5f97..2344f353 100644 --- a/packages/runtime/test/_fixtures/services/LocalRepository.fixture.ts +++ b/packages/runtime/test/_fixtures/services/LocalRepository.fixture.ts @@ -5,14 +5,11 @@ import LocalRepository from '../../../src/services/LocalRepository'; import { TestFileManager } from '../interfaces/FileManager.fixture'; import { SEGMENT_FILES } from '../models/Segment.fixture'; -const CLIENT = { id: '' }; - const defaultRepository = new LocalRepository(new TestFileManager()); defaultRepository.assets = new Set(['index.html']); await defaultRepository.registerSegment('first', SEGMENT_FILES.FIRST); await defaultRepository.registerSegment('second', SEGMENT_FILES.SECOND); -await defaultRepository.registerClient(['first']).then(clientId => CLIENT.id = clientId); const dummyRepository = new DummyRepository(); @@ -33,4 +30,4 @@ const REPOSITORY_FILES = Object.freeze(REPOSITORY_FILES); -export { REPOSITORIES, REPOSITORY_FILES, CLIENT }; +export { REPOSITORIES, REPOSITORY_FILES }; diff --git a/packages/runtime/test/services/LocalRepository.spec.ts b/packages/runtime/test/services/LocalRepository.spec.ts index 8d1b8929..4274ec64 100644 --- a/packages/runtime/test/services/LocalRepository.spec.ts +++ b/packages/runtime/test/services/LocalRepository.spec.ts @@ -1,11 +1,8 @@ import { describe, expect, it } from 'vitest'; -import InvalidClientId from '../../src/errors/InvalidClientId'; -import ClientNotFound from '../../src/errors/ClientNotFound'; - import FileNotFound from '../../src/errors/FileNotFound'; -import { REPOSITORIES, REPOSITORY_FILES, CLIENT } from '../_fixtures/services/LocalRepository.fixture'; +import { REPOSITORIES, REPOSITORY_FILES } from '../_fixtures/services/LocalRepository.fixture'; const repository = REPOSITORIES.DEFAULT; @@ -13,20 +10,6 @@ describe('services/LocalRepository', () => { describe('.readModule(clientId, filename)', () => { - it('should not accept an invalid client id', () => - { - const run = async () => repository.readModule('/some/file', 'INVALID'); - - expect(run).rejects.toEqual(new InvalidClientId('INVALID')); - }); - - it('should not accept an unknown client id', () => - { - const run = async () => repository.readModule('/some/file', 'CLIENT_9999'); - - expect(run).rejects.toEqual(new ClientNotFound('CLIENT_9999')); - }); - it('should return an unsegmented module file', async () => { const result = await repository.readModule(REPOSITORY_FILES.UNSEGMENTED, CLIENT.id); diff --git a/packages/server-nodejs/src/JitarServer.ts b/packages/server-nodejs/src/JitarServer.ts index 08a9c1de..34b64cc0 100644 --- a/packages/server-nodejs/src/JitarServer.ts +++ b/packages/server-nodejs/src/JitarServer.ts @@ -222,7 +222,7 @@ export default class JitarServer for (const setUpScript of setUpScripts) { - const importModel = new Import(setUpScript, ExecutionScopes.APPLICATION); + const importModel = new Import('', setUpScript, ExecutionScopes.APPLICATION); await runtime.import(importModel); } @@ -243,7 +243,7 @@ export default class JitarServer for (const tearDownScript of tearDownScripts) { - const importModel = new Import(tearDownScript, ExecutionScopes.APPLICATION); + const importModel = new Import('', tearDownScript, ExecutionScopes.APPLICATION); await runtime.import(importModel); } diff --git a/packages/server-nodejs/src/controllers/ModulesController.ts b/packages/server-nodejs/src/controllers/ModulesController.ts index e8213eb8..107db1fe 100644 --- a/packages/server-nodejs/src/controllers/ModulesController.ts +++ b/packages/server-nodejs/src/controllers/ModulesController.ts @@ -25,23 +25,23 @@ export default class ModulesController async getModule(request: Request, response: Response): Promise { - const source = request.query.source ?? ""; + const caller = request.query.caller ?? ''; - if (typeof source !== 'string') + if (typeof caller !== 'string') { - return response.status(400).send('Invalid source.'); + return response.status(400).send('Invalid caller.'); } - this.#logger.info(`Get module for -> '${source}'`); + this.#logger.info(`Get module for -> '${caller}'`); const pathKey = '/modules/'; const specifier = request.path.substring(pathKey.length); try { - const file = await this.#repository.readModule(source, specifier); + const file = await this.#repository.readModule(caller, specifier); - this.#logger.info(`Got module -> '${specifier}' (${source})`); + this.#logger.info(`Got module -> '${specifier}' (${caller})`); response.setHeader(Headers.CONTENT_TYPE, file.type); @@ -51,7 +51,7 @@ export default class ModulesController { const message = error instanceof Error ? error.message : String(error); - this.#logger.error(`Failed to get module -> '${specifier}' (${source}) | ${message}`); + this.#logger.error(`Failed to get module -> '${specifier}' (${caller}) | ${message}`); const data = this.#serializer.serialize(error);