This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CompilerSupplier support in compile-common
- Loading branch information
g. nicholas d'andrea
committed
Aug 13, 2021
1 parent
d52234e
commit f88640d
Showing
6 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
packages/compile-common/src/compilerSupplier/constructor.ts
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,35 @@ | ||
export namespace Constructor { | ||
/** | ||
* Type-level description for a particular constructor | ||
*/ | ||
export type Specification = { | ||
/** | ||
* Options argument for specified constructor | ||
*/ | ||
options: any; | ||
|
||
/** | ||
* Output object created by specified constructor | ||
*/ | ||
result: any; | ||
}; | ||
|
||
/** | ||
* Getter type for constructor arg | ||
*/ | ||
export type Options<S extends Specification> = S["options"]; | ||
|
||
/** | ||
* Getter type for constructed object | ||
*/ | ||
export type Result<S extends Specification> = S["result"]; | ||
} | ||
|
||
/** | ||
* An object of type Constructor<S> is a JS constructor (or "class") that | ||
* takes a sole argument (of the specified "options" type), and instantiates | ||
* a new object in memory (of the specified "result" type). | ||
*/ | ||
export type Constructor<S extends Constructor.Specification> = new ( | ||
options: Constructor.Options<S> | ||
) => Constructor.Result<S>; |
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,3 @@ | ||
export { Results } from "./results"; | ||
export { Strategy, BaseStrategy } from "./strategy"; | ||
export { Supplier, forDefinition } from "./supplier"; |
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,9 @@ | ||
export namespace Results { | ||
export type Specification = { | ||
load: any; | ||
list: any; | ||
}; | ||
|
||
export type Load<S extends Specification> = S["load"]; | ||
export type List<S extends Specification> = S["list"]; | ||
} |
106 changes: 106 additions & 0 deletions
106
packages/compile-common/src/compilerSupplier/strategy.ts
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,106 @@ | ||
import type { Constructor as FreeConstructor } from "./constructor"; | ||
import type { Results as FreeResults } from "./results"; | ||
|
||
export namespace Strategy { | ||
/** | ||
* Type-level description of a compiler supplier strategy | ||
*/ | ||
export type Specification = { | ||
constructor: Omit<FreeConstructor.Specification, "result">; | ||
results: FreeResults.Specification; | ||
allowsLoadingSpecificVersion: boolean; | ||
allowsListingVersions: boolean; | ||
}; | ||
|
||
/** | ||
* Scoped re-exports of Constructor, using Strategy.Specification as | ||
* generic param | ||
*/ | ||
export namespace Constructor { | ||
/** | ||
* Getter for the specified constructor, intersected with fixed result | ||
* type of Strategy<S> | ||
*/ | ||
export type Specification<S extends Strategy.Specification> = | ||
S["constructor"] & { result: Strategy<S>; }; | ||
|
||
/** | ||
* Constructor options argument for a specified strategy | ||
*/ | ||
export type Options<S extends Strategy.Specification> = FreeConstructor.Options< | ||
Strategy.Constructor.Specification<S> | ||
>; | ||
} | ||
|
||
/** | ||
* Type representing a constructor for specified strategy | ||
*/ | ||
export type Constructor<S extends Strategy.Specification> = FreeConstructor< | ||
Strategy.Constructor.Specification<S> | ||
>; | ||
|
||
/** | ||
* Results types for a particular strategy | ||
*/ | ||
export namespace Results { | ||
export type Specification<S extends Strategy.Specification> = | ||
S["results"]; | ||
|
||
export type Load<S extends Strategy.Specification> = FreeResults.Load< | ||
Strategy.Results.Specification<S> | ||
>; | ||
|
||
export type List<S extends Strategy.Specification> = FreeResults.List< | ||
Strategy.Results.Specification<S> | ||
>; | ||
} | ||
|
||
/** | ||
* Getter type for whether specified strategy allows argument to load() | ||
*/ | ||
export type AllowsLoadingSpecificVersion< | ||
S extends Strategy.Specification | ||
> = S["allowsLoadingSpecificVersion"]; | ||
|
||
/** | ||
* Getter type for whether specified strategy provides version listing | ||
*/ | ||
export type AllowsListingVersions< | ||
S extends Strategy.Specification | ||
> = S["allowsListingVersions"]; | ||
|
||
} | ||
|
||
/** | ||
* An object of type Strategy<S> provides version loading and possibly version | ||
* listing functionality | ||
*/ | ||
export type Strategy<S extends Strategy.Specification> = BaseStrategy<S> & | ||
(true extends Strategy.AllowsLoadingSpecificVersion<S> | ||
? { | ||
load(version?: string): Strategy.Results.Load<S>; | ||
} | ||
: { | ||
load(): Strategy.Results.Load<S>; | ||
}) & | ||
(true extends Strategy.AllowsListingVersions<S> | ||
? { | ||
list(): Strategy.Results.List<S>; | ||
} | ||
: {}); | ||
|
||
/** | ||
* An object of BaseStrategy<S> allows loading an unspecified version, plus | ||
* type guards to determine additional functionality | ||
*/ | ||
export interface BaseStrategy<S extends Strategy.Specification> { | ||
load(): Strategy.Results.Load<S>; | ||
|
||
allowsLoadingSpecificVersion(): this is this & { | ||
load(version?: string): Strategy.Results.Load<S>; | ||
}; | ||
|
||
allowsListingVersions(): this is { | ||
list(): Strategy.Results.List<S>; | ||
}; | ||
} |
139 changes: 139 additions & 0 deletions
139
packages/compile-common/src/compilerSupplier/supplier.ts
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,139 @@ | ||
import type { Strategy as FreeStrategy, BaseStrategy } from "./strategy"; | ||
import type { Results as FreeResults } from "./results"; | ||
|
||
export namespace Supplier { | ||
/** | ||
* Type-level description of a supplier | ||
*/ | ||
export type Specification = { | ||
options: any; | ||
results: FreeResults.Specification; | ||
strategies: { | ||
[strategyName: string]: Omit<FreeStrategy.Specification, "results">; | ||
}; | ||
}; | ||
|
||
/** | ||
* Getter type for the options argument passed to the constructor for one of | ||
* the named strategies for a specified supplier | ||
*/ | ||
export type Options< | ||
S extends Supplier.Specification, | ||
N extends Supplier.StrategyName<S> | ||
> = S["options"] & Supplier.Strategy.Constructor.Options<S, N>; | ||
|
||
export namespace Results { | ||
/** | ||
* Type-level specification of method results for specified supplier; | ||
* used in conjunction with each strategy individually | ||
*/ | ||
export type Specification<S extends Supplier.Specification> = S["results"]; | ||
} | ||
|
||
export namespace Strategies { | ||
export type Specification<S extends Supplier.Specification> = S["strategies"]; | ||
} | ||
|
||
/** | ||
* A type representing one of the strategy names for specified supplier | ||
*/ | ||
export type StrategyName<S extends Supplier.Specification> = string & | ||
keyof Supplier.Strategies.Specification<S>; | ||
|
||
export namespace Strategy { | ||
/** | ||
* Type-level specification of one of the named strategies for specified | ||
* supplier; joins specified supplier results type | ||
*/ | ||
export type Specification< | ||
S extends Supplier.Specification, | ||
N extends Supplier.StrategyName<S> | ||
> = Supplier.Strategies.Specification<S>[N] & { | ||
results: Supplier.Results.Specification<S> | ||
}; | ||
|
||
export namespace Constructor { | ||
/** | ||
* Type-level specification of the constructor for one of the named | ||
* strategies for a specified supplier | ||
*/ | ||
export type Specification< | ||
S extends Supplier.Specification, | ||
N extends Supplier.StrategyName<S> | ||
> = FreeStrategy.Constructor<Supplier.Strategy.Specification<S, N>>; | ||
|
||
/** | ||
* Getter type for options argument passed to the constructor for one of | ||
* the named strategies for a specified supplier | ||
*/ | ||
export type Options< | ||
S extends Supplier.Specification, | ||
N extends Supplier.StrategyName<S> | ||
> = { | ||
[K in N]: FreeStrategy.Constructor.Options< | ||
Supplier.Strategy.Specification<S, K> | ||
> | ||
}[N]; | ||
} | ||
|
||
/** | ||
* An object of Constructor<S, N> is a JS constructor (or "class") for one | ||
* of the named strategies for specified supplier | ||
*/ | ||
export type Constructor< | ||
S extends Supplier.Specification, | ||
N extends Supplier.StrategyName<S> | ||
> = FreeStrategy.Constructor<Supplier.Strategy.Specification<S, N>>; | ||
} | ||
|
||
/** | ||
* An object of type Definition<S> comprises constructors for each of the | ||
* specified strategies, as well as a method to determine the name of which | ||
* strategy to use for a given set of input options | ||
*/ | ||
export type Definition<S extends Supplier.Specification> = { | ||
determineStrategy( | ||
options: Options<S, Supplier.StrategyName<S>> | ||
): Supplier.StrategyName<S>; | ||
|
||
strategyConstructors: { | ||
[N in Supplier.StrategyName<S>]: Supplier.Strategy.Constructor<S, N>; | ||
}; | ||
}; | ||
} | ||
|
||
/** | ||
* An object of type Supplier<S, N> provides an interface for loading and | ||
* possibly listing versions of the compiler | ||
* | ||
* @dev for known strategy names, this computes the method signature of | ||
* `load()` according to the corresponding strategy specification; | ||
* | ||
* for the default of "any strategy name", this type will resolve to an | ||
* interface that may require the use of defined type guards | ||
* (e.g. `if(supplier.allowsListingVersions()) { supplier.list(); }`) | ||
*/ | ||
export type Supplier< | ||
S extends Supplier.Specification, | ||
N extends Supplier.StrategyName<S> = Supplier.StrategyName<S> | ||
> = Supplier.StrategyName<S> extends N | ||
? BaseStrategy<Supplier.Strategy.Specification<S, N>> | ||
: FreeStrategy<Supplier.Strategy.Specification<S, N>>; | ||
|
||
/** | ||
* Given the definition of specified supplier, create a function that | ||
* determines+constructs a supplier strategy for a given set of options. | ||
*/ | ||
export const forDefinition = <S extends Supplier.Specification>({ | ||
determineStrategy, | ||
strategyConstructors | ||
}: Supplier.Definition<S>) => <N extends Supplier.StrategyName<S>>( | ||
options: Supplier.Strategy.Constructor.Options<S, N> | ||
): Supplier<S, N> => { | ||
const strategyName = determineStrategy(options); | ||
const Strategy = strategyConstructors[strategyName]; | ||
|
||
// @ts-ignore since we can't figure out N from inside | ||
const supplier: Supplier<S, N> = new Strategy(options); | ||
return supplier; | ||
}; |
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