Skip to content

Commit

Permalink
Expose instantiated resources from ComponentsManager
Browse files Browse the repository at this point in the history
  • Loading branch information
Falx authored May 10, 2022
1 parent 4c14d40 commit 19c8d66
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 9 deletions.
11 changes: 11 additions & 0 deletions lib/ComponentsManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from 'fs';
import type { Resource, RdfObjectLoader } from 'rdf-object';
import { stringToTerm } from 'rdf-string';
import type { Logger } from 'winston';
import type { IConfigConstructorPool } from './construction/IConfigConstructorPool';
import type { IConstructionSettings } from './construction/IConstructionSettings';
Expand Down Expand Up @@ -61,6 +62,16 @@ export class ComponentsManager<Instance> {
}
}

/**
* Retrieve a list of all instantiated Resources.
*/
public getInstantiatedResources(): Resource[] {
const instances = this.configConstructorPool.getInstanceRegistry();
return Object.keys(instances)
.map(key => stringToTerm(key))
.map(term => this.configRegistry.getInstantiatedResource(term));
}

/**
* Create an `componentsjs-error-state.json` file to represent the application state in the current working directory.
* @param error The error that causes this error state to be created.
Expand Down
23 changes: 16 additions & 7 deletions lib/construction/ConfigConstructorPool.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Resource, RdfObjectLoader } from 'rdf-object';
import { termToString } from 'rdf-string';
import type { IModuleState } from '../loading/ModuleStateBuilder';
import type { IConfigPreprocessor } from '../preprocess/IConfigPreprocessor';
import { ErrorResourcesContext } from '../util/ErrorResourcesContext';
Expand Down Expand Up @@ -40,7 +41,8 @@ export class ConfigConstructorPool<Instance> implements IConfigConstructorPool<I
// Check if this resource is required as argument in its own chain,
// if so, return a dummy value, to avoid infinite recursion.
const resourceBlacklist = settings.resourceBlacklist || {};
if (resourceBlacklist[configResource.value]) {
const configResourceId = termToString(configResource.term);
if (resourceBlacklist[configResourceId]) {
return Promise.reject(new ErrorResourcesContext(`Circular dependency was detected on ${configResource.value}`, { config: configResource }));
}

Expand All @@ -51,28 +53,28 @@ export class ConfigConstructorPool<Instance> implements IConfigConstructorPool<I
}

// Instantiate only once
if (!(configResource.value in this.instances)) {
if (!(configResourceId in this.instances)) {
// The blacklist avoids infinite recursion for self-referencing configs
const subBlackList: Record<string, boolean> = { ...resourceBlacklist };
subBlackList[configResource.value] = true;
subBlackList[configResourceId] = true;

// Prepare instance parameters
let rawConfig: Resource;
try {
rawConfig = this.getRawConfig(configResource);
} catch (syncError: unknown) {
this.instances[configResource.value] = Promise.reject(syncError);
return this.instances[configResource.value];
this.instances[configResourceId] = Promise.reject(syncError);
return this.instances[configResourceId];
}
const subSettings = { ...settings, resourceBlacklist: subBlackList };

// Invoke instance creation
this.instances[configResource.value] = this.configConstructor.createInstance(
this.instances[configResourceId] = this.configConstructor.createInstance(
rawConfig,
subSettings,
);
}
return this.instances[configResource.value];
return this.instances[configResourceId];
}

/**
Expand Down Expand Up @@ -128,6 +130,13 @@ export class ConfigConstructorPool<Instance> implements IConfigConstructorPool<I
throw new ErrorResourcesContext(`Invalid config: ${field} "${config.property[field].value}" must be a ${type}, but got ${config.property[field].type}`, { config });
}
}

/**
* Returns the instance registry.
*/
public getInstanceRegistry(): Record<string, Promise<any>> {
return this.instances;
}
}

export interface IInstancePoolOptions<Instance> {
Expand Down
6 changes: 6 additions & 0 deletions lib/construction/IConfigConstructorPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ export interface IConfigConstructorPool<Instance> {
settings: IConstructionSettings,
) => Promise<Instance>;

/**
* Return the instance regsitry.
* This is a hash from registered id to a Promise of the Instance.
*/
getInstanceRegistry: () => Record<string, Promise<Instance>>;

}
11 changes: 10 additions & 1 deletion lib/loading/ConfigRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Readable } from 'stream';
import type * as RDF from '@rdfjs/types';
import type { RdfObjectLoader } from 'rdf-object';
import type { RdfObjectLoader, Resource } from 'rdf-object';
import { termToString } from 'rdf-string';
import type { Logger } from 'winston';
import { RdfParser } from '../rdf/RdfParser';
import type { IModuleState } from './ModuleStateBuilder';
Expand Down Expand Up @@ -65,6 +66,14 @@ export class ConfigRegistry {
configResource.property[key] = this.objectLoader.createCompactedResource(`"${params[key]}"`);
}
}

/**
* Get the instantiated Resource that was registered to the given term.
* @param term The term of the Resource that was instantiated
*/
public getInstantiatedResource(term: RDF.Term): Resource {
return this.objectLoader.resources[termToString(term)];
}
}

export interface IConfigLoaderRegistryOptions {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@
"rdf-object": "^1.13.1",
"rdf-parse": "^2.0.0",
"rdf-quad": "^1.5.0",
"rdf-string": "^1.6.0",
"rdf-terms": "^1.7.0",
"semver": "^7.3.2",
"winston": "^3.3.3"
},
"devDependencies": {
"@rubensworks/eslint-config": "^1.0.1",
"@types/jest": "^27.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"@types/jest": "^27.0.0",
"eslint": "^7.12.1",
"eslint-config-es": "3.25.3",
"eslint-import-resolver-typescript": "^2.3.0",
Expand Down
3 changes: 3 additions & 0 deletions test/unit/construction/ConfigConstructorPool-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ describe('ConfigConstructorPool', () => {
'ex:myComponentInstance': true,
},
});
await expect(pool.getInstanceRegistry()['ex:myComponentInstance']).resolves.toBe('INSTANCE0');
});

it('should create different instances by different id', async() => {
Expand All @@ -285,6 +286,8 @@ describe('ConfigConstructorPool', () => {
types: 'ex:Component',
}), creationSettings);
expect(instance1).not.toBe(instance2);
await expect(pool.getInstanceRegistry()['ex:myComponentInstance1']).resolves.toBe('INSTANCE0');
await expect(pool.getInstanceRegistry()['ex:myComponentInstance2']).resolves.toBe('INSTANCE1');
});

it('should return the same instances by equal id', async() => {
Expand Down
10 changes: 10 additions & 0 deletions test/unit/loading/ComponentsManager-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ describe('ComponentsManager', () => {
dumpErrorState = false;
configConstructorPool = <any> {
instantiate: jest.fn(() => 'INSTANCE'),
getInstanceRegistry: jest.fn(() => ({
'http://example.org/myconfig': 'INSTANCE',
})),
};
componentsManager = new ComponentsManager({
moduleState,
Expand Down Expand Up @@ -133,6 +136,13 @@ describe('ComponentsManager', () => {
});
});

describe('getInstantiatedResources', () => {
it('should return an array of instantiated Resources', async() => {
await componentsManager.configRegistry.register(`${__dirname}/../../assets/config.jsonld`);
expect(componentsManager.getInstantiatedResources()).toHaveLength(1);
});
});

describe('generateErrorLog', () => {
it('should export the context for an ErrorResourcesContext', () => {
componentsManager = new ComponentsManager({
Expand Down
9 changes: 9 additions & 0 deletions test/unit/loading/ConfigRegistry-test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from 'fs';
import { RdfObjectLoader } from 'rdf-object';
import { stringToTerm } from 'rdf-string';
import type { Logger } from 'winston';
import { ConfigRegistry } from '../../../lib/loading/ConfigRegistry';
import type { IModuleState } from '../../../lib/loading/ModuleStateBuilder';
Expand Down Expand Up @@ -62,4 +63,12 @@ describe('ConfigRegistry', () => {
});
});
});

describe('getInstantiatedResource', () => {
it('can return an instantiated Resource', async() => {
await configRegistry.register(`${__dirname}/../../assets/config.jsonld`);
expect(configRegistry.getInstantiatedResource(stringToTerm('http://example.org/myconfig')).property.type.value)
.toBe('http://example.org/HelloWorldModule#SayHelloComponent');
});
});
});

0 comments on commit 19c8d66

Please sign in to comment.