-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from zazuko/env-combine
Improve Environment extensibility
- Loading branch information
Showing
13 changed files
with
354 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--- | ||
"@zazuko/env": major | ||
"@zazuko/env-node": major | ||
--- | ||
|
||
Change the method of creating derived environments: | ||
|
||
1. The additional factories have been removed from the `create` function. | ||
2. To create a derived environment, use the constructor overload which takes a parent environment as the second argument in addition to the array of additional factories. | ||
|
||
For example, | ||
|
||
```js | ||
import env from '@zazuko/env'; | ||
import Environment from '@zazuko/env/Environment.js'; | ||
import MyFactory from './my-factory.js'; | ||
|
||
const myEnv = new Environment([MyFactory], { parent: env }); | ||
``` |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { Environment, FactoryConstructor } from '@rdfjs/environment/Environment.js' | ||
import { DerivedEnvironment } from './lib/extend.js' | ||
|
||
type Narrow<T> = | ||
| (T extends infer U ? U : never) | ||
| Extract<T, number | string | boolean | bigint | symbol | null | undefined | []> | ||
| ([T] extends [[]] ? [] : { [K in keyof T]: Narrow<T[K]> }); | ||
|
||
type ReturnFactory<C> = C extends FactoryConstructor<infer X> ? X : C; | ||
type Distribute<U> = U extends any ? ReturnFactory<U> : never; | ||
|
||
interface EnvironmentCtor { | ||
new<F extends ReadonlyArray<FactoryConstructor<any>>>( | ||
factories: Narrow<F>, | ||
options?: { bind: boolean }, | ||
): Environment<Distribute<F[number]>> | ||
|
||
new<F extends ReadonlyArray<FactoryConstructor<any>>, E extends Environment<any>>( | ||
factories: Narrow<F>, | ||
options: { parent?: E; bind?: boolean }, | ||
): DerivedEnvironment<E, Environment<Distribute<F[number]>>> | ||
} | ||
|
||
declare const environment: EnvironmentCtor | ||
|
||
export default environment |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { extend } from './lib/extend.js' | ||
|
||
export default class Environment { | ||
constructor(factories, { parent, bind = false } = {}) { | ||
this._parent = parent | ||
this._factories = factories.slice() | ||
|
||
const extended = parent ? extend(parent, this) : this | ||
|
||
for (const factory of this._factories) { | ||
if (typeof factory.prototype.init === 'function') { | ||
factory.prototype.init.call(extended) | ||
} | ||
|
||
for (const method of factory.exports || []) { | ||
if (bind) { | ||
this[method] = factory.prototype[method].bind(extended) | ||
} else { | ||
this[method] = factory.prototype[method] | ||
} | ||
} | ||
} | ||
|
||
return extended | ||
} | ||
|
||
clone() { | ||
const env = new Environment(this._factories, this._parent) | ||
|
||
for (const factory of env._factories) { | ||
if (typeof factory.prototype.clone === 'function') { | ||
factory.prototype.clone.call(env, this) | ||
} | ||
} | ||
|
||
return env | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import type { Environment } from '@rdfjs/environment/Environment.js' | ||
|
||
type Factories<E> = E extends Environment<infer F> ? F : never; | ||
type Distribute<U> = U extends any ? Factories<U> : never; | ||
|
||
type CombinedEnvironment<E extends ReadonlyArray<Environment<any>>> = Environment<Distribute<E[number]>> | ||
export type DerivedEnvironment<Env extends Environment<unknown>, Ex extends Environment<unknown>> = CombinedEnvironment<[Env, Ex]> | ||
|
||
export function extend<E extends Environment<any>, P extends Environment<any>>(self: E, parent: P) { | ||
const envs = [self, parent] | ||
|
||
return new Proxy({}, { | ||
get(target, prop) { | ||
const value = envs.find(env => prop in env) | ||
if (value) { | ||
return value[prop as keyof E] | ||
} | ||
}, | ||
set(target, prop, value) { | ||
envs[0][prop as keyof E] = value | ||
|
||
return true | ||
}, | ||
has(target, prop) { | ||
return envs.some(env => prop in env) | ||
}, | ||
}) as any as DerivedEnvironment<P, E> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import DataFactory from '@rdfjs/data-model/Factory.js' | ||
import DatasetFactory from '@rdfjs/dataset/Factory.js' | ||
import { expect } from 'chai' | ||
import { schema } from '@tpluscode/rdf-ns-builders' | ||
import Environment from '../Environment.js' | ||
import { TestFactory } from './TestFactory.js' | ||
|
||
describe('Environment with parent', () => { | ||
it('merges all factories', () => { | ||
// given | ||
const dataEnv = new Environment([DataFactory]) | ||
|
||
// when | ||
const env = new Environment([DatasetFactory], { parent: dataEnv }) | ||
|
||
// then | ||
expect(env).to.have.property('dataset') | ||
expect(env).to.have.property('namedNode') | ||
expect(env.namedNode('http://schema.org/Person')).to.deep.eq(schema.Person) | ||
}) | ||
|
||
it('merge multiple levels', () => { | ||
// given | ||
const dataEnv = new Environment([DataFactory]) | ||
const datasetEnv = new Environment([DatasetFactory], { parent: dataEnv }) | ||
|
||
// when | ||
const env = new Environment([TestFactory], { parent: datasetEnv }) | ||
|
||
// then | ||
const test = env.test() | ||
expect(test.size).to.eq(1) | ||
}) | ||
}) |
Oops, something went wrong.