Fix circular dependencies in migrator
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			This commit is contained in:
		
							parent
							
								
									074a3187eb
								
							
						
					
					
						commit
						5940b6e2b3
					
				
							
								
								
									
										11
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								.drone.yml
									
									
									
									
									
								
							@ -103,10 +103,19 @@ steps:
 | 
				
			|||||||
      event:
 | 
					      event:
 | 
				
			||||||
        exclude: tag
 | 
					        exclude: tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name: build module
 | 
					  - name: Install dependencies
 | 
				
			||||||
    image: glmdev/node-pnpm:latest
 | 
					    image: glmdev/node-pnpm:latest
 | 
				
			||||||
    commands:
 | 
					    commands:
 | 
				
			||||||
      - pnpm i
 | 
					      - pnpm i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - name: Lint code
 | 
				
			||||||
 | 
					    image: glmdev/node-pnpm:latest
 | 
				
			||||||
 | 
					    commands:
 | 
				
			||||||
 | 
					      - pnpm lint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - name: build module
 | 
				
			||||||
 | 
					    image: glmdev/node-pnpm:latest
 | 
				
			||||||
 | 
					    commands:
 | 
				
			||||||
      - pnpm build
 | 
					      - pnpm build
 | 
				
			||||||
      - mkdir artifacts
 | 
					      - mkdir artifacts
 | 
				
			||||||
      - tar czf artifacts/extollo-lib.tar.gz lib
 | 
					      - tar czf artifacts/extollo-lib.tar.gz lib
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										55
									
								
								.idea/codeStyles/Project.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								.idea/codeStyles/Project.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					<component name="ProjectCodeStyleConfiguration">
 | 
				
			||||||
 | 
					  <code_scheme name="Project" version="173">
 | 
				
			||||||
 | 
					    <JSCodeStyleSettings version="0">
 | 
				
			||||||
 | 
					      <option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
 | 
				
			||||||
 | 
					      <option name="FORCE_SEMICOLON_STYLE" value="true" />
 | 
				
			||||||
 | 
					      <option name="USE_DOUBLE_QUOTES" value="false" />
 | 
				
			||||||
 | 
					      <option name="FORCE_QUOTE_STYlE" value="true" />
 | 
				
			||||||
 | 
					      <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
 | 
				
			||||||
 | 
					      <option name="OBJECT_LITERAL_WRAP" value="2" />
 | 
				
			||||||
 | 
					    </JSCodeStyleSettings>
 | 
				
			||||||
 | 
					    <TypeScriptCodeStyleSettings version="0">
 | 
				
			||||||
 | 
					      <option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
 | 
				
			||||||
 | 
					      <option name="FORCE_SEMICOLON_STYLE" value="true" />
 | 
				
			||||||
 | 
					      <option name="USE_DOUBLE_QUOTES" value="false" />
 | 
				
			||||||
 | 
					      <option name="FORCE_QUOTE_STYlE" value="true" />
 | 
				
			||||||
 | 
					      <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
 | 
				
			||||||
 | 
					      <option name="OBJECT_LITERAL_WRAP" value="2" />
 | 
				
			||||||
 | 
					    </TypeScriptCodeStyleSettings>
 | 
				
			||||||
 | 
					    <editorconfig>
 | 
				
			||||||
 | 
					      <option name="ENABLED" value="false" />
 | 
				
			||||||
 | 
					    </editorconfig>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="JavaScript">
 | 
				
			||||||
 | 
					      <option name="INDENT_CASE_FROM_SWITCH" value="false" />
 | 
				
			||||||
 | 
					      <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
 | 
				
			||||||
 | 
					      <option name="ALIGN_MULTILINE_FOR" value="false" />
 | 
				
			||||||
 | 
					      <option name="METHOD_CALL_CHAIN_WRAP" value="2" />
 | 
				
			||||||
 | 
					      <option name="IF_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					      <option name="DOWHILE_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					      <option name="WHILE_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					      <option name="FOR_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="PHP">
 | 
				
			||||||
 | 
					      <indentOptions>
 | 
				
			||||||
 | 
					        <option name="USE_TAB_CHARACTER" value="true" />
 | 
				
			||||||
 | 
					        <option name="SMART_TABS" value="true" />
 | 
				
			||||||
 | 
					      </indentOptions>
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="Shell Script">
 | 
				
			||||||
 | 
					      <indentOptions>
 | 
				
			||||||
 | 
					        <option name="INDENT_SIZE" value="4" />
 | 
				
			||||||
 | 
					        <option name="TAB_SIZE" value="4" />
 | 
				
			||||||
 | 
					      </indentOptions>
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="TypeScript">
 | 
				
			||||||
 | 
					      <option name="INDENT_CASE_FROM_SWITCH" value="false" />
 | 
				
			||||||
 | 
					      <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
 | 
				
			||||||
 | 
					      <option name="ALIGN_MULTILINE_FOR" value="false" />
 | 
				
			||||||
 | 
					      <option name="METHOD_CALL_CHAIN_WRAP" value="2" />
 | 
				
			||||||
 | 
					      <option name="IF_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					      <option name="DOWHILE_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					      <option name="WHILE_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					      <option name="FOR_BRACE_FORCE" value="3" />
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					  </code_scheme>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<component name="ProjectCodeStyleConfiguration">
 | 
				
			||||||
 | 
					  <state>
 | 
				
			||||||
 | 
					    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
 | 
				
			||||||
 | 
					  </state>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										19
									
								
								.idea/dataSources.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.idea/dataSources.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
 | 
				
			||||||
 | 
					    <data-source source="LOCAL" name="mongo@localhost" uuid="b05ce3f5-fadc-47d6-8621-e232ed1ad2f3">
 | 
				
			||||||
 | 
					      <driver-ref>mongo</driver-ref>
 | 
				
			||||||
 | 
					      <synchronize>true</synchronize>
 | 
				
			||||||
 | 
					      <jdbc-driver>com.dbschema.MongoJdbcDriver</jdbc-driver>
 | 
				
			||||||
 | 
					      <jdbc-url>mongodb://localhost:27017/extollo_1</jdbc-url>
 | 
				
			||||||
 | 
					      <working-dir>$ProjectFileDir$</working-dir>
 | 
				
			||||||
 | 
					    </data-source>
 | 
				
			||||||
 | 
					    <data-source source="LOCAL" name="extollo_1@db03.platform.local" uuid="c8dc268d-b69d-497a-9e6d-b5c6e5275835">
 | 
				
			||||||
 | 
					      <driver-ref>postgresql</driver-ref>
 | 
				
			||||||
 | 
					      <synchronize>true</synchronize>
 | 
				
			||||||
 | 
					      <jdbc-driver>org.postgresql.Driver</jdbc-driver>
 | 
				
			||||||
 | 
					      <jdbc-url>jdbc:postgresql://db03.platform.local:5432/extollo_1</jdbc-url>
 | 
				
			||||||
 | 
					      <working-dir>$ProjectFileDir$</working-dir>
 | 
				
			||||||
 | 
					    </data-source>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
@ -4,5 +4,6 @@
 | 
				
			|||||||
    <content url="file://$MODULE_DIR$" />
 | 
					    <content url="file://$MODULE_DIR$" />
 | 
				
			||||||
    <orderEntry type="inheritedJdk" />
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
    <orderEntry type="sourceFolder" forTests="false" />
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
 | 
					    <orderEntry type="module" module-name="extollo" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
</module>
 | 
					</module>
 | 
				
			||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
<project version="4">
 | 
					<project version="4">
 | 
				
			||||||
  <component name="ProjectModuleManager">
 | 
					  <component name="ProjectModuleManager">
 | 
				
			||||||
    <modules>
 | 
					    <modules>
 | 
				
			||||||
 | 
					      <module fileurl="file://$PROJECT_DIR$/../app/.idea/extollo.iml" filepath="$PROJECT_DIR$/../app/.idea/extollo.iml" />
 | 
				
			||||||
      <module fileurl="file://$PROJECT_DIR$/.idea/lib.iml" filepath="$PROJECT_DIR$/.idea/lib.iml" />
 | 
					      <module fileurl="file://$PROJECT_DIR$/.idea/lib.iml" filepath="$PROJECT_DIR$/.idea/lib.iml" />
 | 
				
			||||||
    </modules>
 | 
					    </modules>
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<project version="4">
 | 
					<project version="4">
 | 
				
			||||||
  <component name="VcsDirectoryMappings">
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
    <mapping directory="$PROJECT_DIR$" vcs="Git" />
 | 
					    <mapping directory="" vcs="Git" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										5114
									
								
								pnpm-lock.yaml
									
									
									
									
									
								
							
							
						
						
									
										5114
									
								
								pnpm-lock.yaml
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										29
									
								
								src/auth/basic-ui/BasicLoginController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/auth/basic-ui/BasicLoginController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import {Controller} from '../../http/Controller'
 | 
				
			||||||
 | 
					import {Injectable} from '../../di'
 | 
				
			||||||
 | 
					import {Route} from '../../http/routing/Route'
 | 
				
			||||||
 | 
					import {Request} from '../../http/lifecycle/Request'
 | 
				
			||||||
 | 
					import {view} from '../../http/response/ViewResponseFactory'
 | 
				
			||||||
 | 
					import {ResponseFactory} from '../../http/response/ResponseFactory'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class BasicLoginController extends Controller {
 | 
				
			||||||
 | 
					    public static routes(): void {
 | 
				
			||||||
 | 
					        Route.group('auth', () => {
 | 
				
			||||||
 | 
					            Route.get('login', (request: Request) => {
 | 
				
			||||||
 | 
					                const controller = <BasicLoginController> request.make(BasicLoginController)
 | 
				
			||||||
 | 
					                return controller.getLogin()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					                .alias('@auth.login')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Route.post('login', (request: Request) => {
 | 
				
			||||||
 | 
					                const controller = <BasicLoginController> request.make(BasicLoginController)
 | 
				
			||||||
 | 
					                return controller.getLogin()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					                .alias('@auth.login.attempt')
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public getLogin(): ResponseFactory {
 | 
				
			||||||
 | 
					        return view('@extollo:auth:login')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -21,3 +21,4 @@ export * from './Authentication'
 | 
				
			|||||||
export * from './config'
 | 
					export * from './config'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export * from './basic-ui/BasicLoginFormRequest'
 | 
					export * from './basic-ui/BasicLoginFormRequest'
 | 
				
			||||||
 | 
					export * from './basic-ui/BasicLoginController'
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										23
									
								
								src/cli/decorators.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/cli/decorators.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					import {ContainerBlueprint, Instantiable, isInstantiableOf} from '../di'
 | 
				
			||||||
 | 
					import {CommandLine} from './service'
 | 
				
			||||||
 | 
					import {Directive} from './Directive'
 | 
				
			||||||
 | 
					import {logIfDebugging} from '../util'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Register a class as a command-line Directive.
 | 
				
			||||||
 | 
					 * The class must extend Directive.
 | 
				
			||||||
 | 
					 * @constructor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const CLIDirective = (): ClassDecorator => {
 | 
				
			||||||
 | 
					    return (target) => {
 | 
				
			||||||
 | 
					        if ( isInstantiableOf(target, Directive) ) {
 | 
				
			||||||
 | 
					            logIfDebugging('extollo.cli.decorators', 'Registering CLIDirective blueprint:', target)
 | 
				
			||||||
 | 
					            ContainerBlueprint.getContainerBlueprint()
 | 
				
			||||||
 | 
					                .onResolve<CommandLine>(CommandLine, cli => {
 | 
				
			||||||
 | 
					                    cli.registerDirective(target as Instantiable<Directive>)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            logIfDebugging('extollo.cli.decorators', 'Skipping CLIDirective blueprint:', target)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import {DependencyKey, InstanceRef, Instantiable, isInstantiable, StaticClass} from './types'
 | 
					import {DependencyKey, InstanceRef, Instantiable, isInstantiable, StaticClass, TypedDependencyKey} from './types'
 | 
				
			||||||
import {AbstractFactory} from './factory/AbstractFactory'
 | 
					import {AbstractFactory} from './factory/AbstractFactory'
 | 
				
			||||||
import {collect, Collection, globalRegistry, logIfDebugging} from '../util'
 | 
					import {collect, Collection, globalRegistry, logIfDebugging} from '../util'
 | 
				
			||||||
import {Factory} from './factory/Factory'
 | 
					import {Factory} from './factory/Factory'
 | 
				
			||||||
@ -7,7 +7,7 @@ import {ClosureFactory} from './factory/ClosureFactory'
 | 
				
			|||||||
import NamedFactory from './factory/NamedFactory'
 | 
					import NamedFactory from './factory/NamedFactory'
 | 
				
			||||||
import SingletonFactory from './factory/SingletonFactory'
 | 
					import SingletonFactory from './factory/SingletonFactory'
 | 
				
			||||||
import {InvalidDependencyKeyError} from './error/InvalidDependencyKeyError'
 | 
					import {InvalidDependencyKeyError} from './error/InvalidDependencyKeyError'
 | 
				
			||||||
import {ContainerBlueprint} from './ContainerBlueprint'
 | 
					import {ContainerBlueprint, ContainerResolutionCallback} from './ContainerBlueprint'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type MaybeFactory<T> = AbstractFactory<T> | undefined
 | 
					export type MaybeFactory<T> = AbstractFactory<T> | undefined
 | 
				
			||||||
export type MaybeDependency = any | undefined
 | 
					export type MaybeDependency = any | undefined
 | 
				
			||||||
@ -17,18 +17,36 @@ export type ResolvedDependency = { paramIndex: number, key: DependencyKey, resol
 | 
				
			|||||||
 * A container of resolve-able dependencies that are created via inversion-of-control.
 | 
					 * A container of resolve-able dependencies that are created via inversion-of-control.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class Container {
 | 
					export class Container {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Given a Container instance, apply the ContainerBlueprint to it.
 | 
				
			||||||
 | 
					     * @param container
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static realizeContainer<T extends Container>(container: T): T {
 | 
				
			||||||
 | 
					        ContainerBlueprint.getContainerBlueprint()
 | 
				
			||||||
 | 
					            .resolve()
 | 
				
			||||||
 | 
					            .map(factory => container.registerFactory(factory))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ContainerBlueprint.getContainerBlueprint()
 | 
				
			||||||
 | 
					            .resolveConstructable()
 | 
				
			||||||
 | 
					            .map((factory: StaticClass<AbstractFactory<any>, any>) => container.registerFactory(container.make(factory)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ContainerBlueprint.getContainerBlueprint()
 | 
				
			||||||
 | 
					            .resolveResolutionCallbacks()
 | 
				
			||||||
 | 
					            .map((listener: {key: TypedDependencyKey<any>, callback: ContainerResolutionCallback<any>}) => {
 | 
				
			||||||
 | 
					                container.onResolve(listener.key)
 | 
				
			||||||
 | 
					                    .then(value => listener.callback(value))
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return container
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the global instance of this container.
 | 
					     * Get the global instance of this container.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static getContainer(): Container {
 | 
					    public static getContainer(): Container {
 | 
				
			||||||
        const existing = <Container | undefined> globalRegistry.getGlobal('extollo/injector')
 | 
					        const existing = <Container | undefined> globalRegistry.getGlobal('extollo/injector')
 | 
				
			||||||
        if ( !existing ) {
 | 
					        if ( !existing ) {
 | 
				
			||||||
            const container = new Container()
 | 
					            const container = Container.realizeContainer(new Container())
 | 
				
			||||||
 | 
					 | 
				
			||||||
            ContainerBlueprint.getContainerBlueprint()
 | 
					 | 
				
			||||||
                .resolve()
 | 
					 | 
				
			||||||
                .map(factory => container.registerFactory(factory))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            globalRegistry.setGlobal('extollo/injector', container)
 | 
					            globalRegistry.setGlobal('extollo/injector', container)
 | 
				
			||||||
            return container
 | 
					            return container
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -48,6 +66,12 @@ export class Container {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected instances: Collection<InstanceRef> = new Collection<InstanceRef>()
 | 
					    protected instances: Collection<InstanceRef> = new Collection<InstanceRef>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Collection of callbacks waiting for a dependency key to be resolved.
 | 
				
			||||||
 | 
					     * @protected
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected waitingResolveCallbacks: Collection<{ key: DependencyKey, callback: (t: unknown) => unknown }> = new Collection<{key: DependencyKey; callback:(t: unknown) => unknown}>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        this.registerSingletonInstance<Container>(Container, this)
 | 
					        this.registerSingletonInstance<Container>(Container, this)
 | 
				
			||||||
        this.registerSingleton('injector', this)
 | 
					        this.registerSingleton('injector', this)
 | 
				
			||||||
@ -172,6 +196,26 @@ export class Container {
 | 
				
			|||||||
        return this.instances.where('key', '=', key).isNotEmpty()
 | 
					        return this.instances.where('key', '=', key).isNotEmpty()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get a Promise that resolves the first time the given dependency key is resolved
 | 
				
			||||||
 | 
					     * by the application. If it has already been resolved, the Promise will resolve immediately.
 | 
				
			||||||
 | 
					     * @param key
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    onResolve<T>(key: TypedDependencyKey<T>): Promise<T> {
 | 
				
			||||||
 | 
					        if ( this.hasInstance(key) ) {
 | 
				
			||||||
 | 
					            return new Promise<T>(res => res(this.make<T>(key)))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Otherwise, we haven't instantiated an instance with this key yet,
 | 
				
			||||||
 | 
					        // so put it onto the waitlist.
 | 
				
			||||||
 | 
					        return new Promise<T>(res => {
 | 
				
			||||||
 | 
					            this.waitingResolveCallbacks.push({
 | 
				
			||||||
 | 
					                key,
 | 
				
			||||||
 | 
					                callback: (res as (t: unknown) => unknown),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns true if the container has a factory for the given key.
 | 
					     * Returns true if the container has a factory for the given key.
 | 
				
			||||||
     * @param {DependencyKey} key
 | 
					     * @param {DependencyKey} key
 | 
				
			||||||
@ -234,6 +278,15 @@ export class Container {
 | 
				
			|||||||
            value: newInstance,
 | 
					            value: newInstance,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.waitingResolveCallbacks = this.waitingResolveCallbacks.filter(waiter => {
 | 
				
			||||||
 | 
					            if ( waiter.key === key ) {
 | 
				
			||||||
 | 
					                waiter.callback(newInstance)
 | 
				
			||||||
 | 
					                return false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return true
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return newInstance
 | 
					        return newInstance
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,19 @@
 | 
				
			|||||||
import {DependencyKey, Instantiable} from './types'
 | 
					import {DependencyKey, Instantiable, StaticClass, TypedDependencyKey} from './types'
 | 
				
			||||||
import NamedFactory from './factory/NamedFactory'
 | 
					import NamedFactory from './factory/NamedFactory'
 | 
				
			||||||
import {AbstractFactory} from './factory/AbstractFactory'
 | 
					import {AbstractFactory} from './factory/AbstractFactory'
 | 
				
			||||||
import {Factory} from './factory/Factory'
 | 
					import {Factory} from './factory/Factory'
 | 
				
			||||||
import {ClosureFactory} from './factory/ClosureFactory'
 | 
					import {ClosureFactory} from './factory/ClosureFactory'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Simple type alias for a callback to a container's onResolve method. */
 | 
				
			||||||
 | 
					export type ContainerResolutionCallback<T> = (() => unknown) | ((t: T) => unknown)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Blueprint for newly-created containers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This is used to allow global helpers like `@Singleton()`
 | 
				
			||||||
 | 
					 * or `@CLIDirective()` while still supporting multiple
 | 
				
			||||||
 | 
					 * global Container instances at once.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export class ContainerBlueprint {
 | 
					export class ContainerBlueprint {
 | 
				
			||||||
    private static instance?: ContainerBlueprint
 | 
					    private static instance?: ContainerBlueprint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,6 +27,19 @@ export class ContainerBlueprint {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    protected factories: (() => AbstractFactory<any>)[] = []
 | 
					    protected factories: (() => AbstractFactory<any>)[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected constructableFactories: StaticClass<AbstractFactory<any>, any>[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected resolutionCallbacks: ({key: TypedDependencyKey<any>, callback: ContainerResolutionCallback<any>})[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Register some factory class with the container. Should take no construction params.
 | 
				
			||||||
 | 
					     * @param factory
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    registerFactory(factory: StaticClass<AbstractFactory<any>, any>): this {
 | 
				
			||||||
 | 
					        this.constructableFactories.push(factory)
 | 
				
			||||||
 | 
					        return this
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Register a basic instantiable class as a standard Factory with this container,
 | 
					     * Register a basic instantiable class as a standard Factory with this container,
 | 
				
			||||||
     * identified by a string name rather than static class.
 | 
					     * identified by a string name rather than static class.
 | 
				
			||||||
@ -47,7 +70,38 @@ export class ContainerBlueprint {
 | 
				
			|||||||
        return this
 | 
					        return this
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get an array of factory instances in the blueprint.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    resolve(): AbstractFactory<any>[] {
 | 
					    resolve(): AbstractFactory<any>[] {
 | 
				
			||||||
        return this.factories.map(x => x())
 | 
					        return this.factories.map(x => x())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Register an onResolve callback to be added to all newly-created containers.
 | 
				
			||||||
 | 
					     * @param key
 | 
				
			||||||
 | 
					     * @param callback
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    onResolve<T>(key: TypedDependencyKey<T>, callback: ContainerResolutionCallback<T>): this {
 | 
				
			||||||
 | 
					        this.resolutionCallbacks.push({
 | 
				
			||||||
 | 
					            key,
 | 
				
			||||||
 | 
					            callback,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        return this
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get an array of static Factory classes that need to be instantiated by
 | 
				
			||||||
 | 
					     * the container itself.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    resolveConstructable(): StaticClass<AbstractFactory<any>, any> {
 | 
				
			||||||
 | 
					        return [...this.constructableFactories]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get an array of DependencyKey-callback pairs to register with new containers.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    resolveResolutionCallbacks(): ({key: TypedDependencyKey<any>, callback: ContainerResolutionCallback<any>})[] {
 | 
				
			||||||
 | 
					        return [...this.resolutionCallbacks]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import 'reflect-metadata'
 | 
					import 'reflect-metadata'
 | 
				
			||||||
import {collect, Collection} from '../../util'
 | 
					import {collect, Collection, logIfDebugging} from '../../util'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    DependencyKey,
 | 
					    DependencyKey,
 | 
				
			||||||
    DependencyRequirement,
 | 
					    DependencyRequirement,
 | 
				
			||||||
@ -71,9 +71,10 @@ export const Injectable = (): ClassDecorator => {
 | 
				
			|||||||
 * If a `key` is specified, that DependencyKey will be injected.
 | 
					 * If a `key` is specified, that DependencyKey will be injected.
 | 
				
			||||||
 * Otherwise, the DependencyKey is inferred from the type annotation.
 | 
					 * Otherwise, the DependencyKey is inferred from the type annotation.
 | 
				
			||||||
 * @param key
 | 
					 * @param key
 | 
				
			||||||
 | 
					 * @param debug
 | 
				
			||||||
 * @constructor
 | 
					 * @constructor
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const Inject = (key?: DependencyKey): PropertyDecorator => {
 | 
					export const Inject = (key?: DependencyKey, { debug = false } = {}): PropertyDecorator => {
 | 
				
			||||||
    return (target, property) => {
 | 
					    return (target, property) => {
 | 
				
			||||||
        let propertyMetadata = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, target?.constructor || target) as Collection<PropertyDependency>
 | 
					        let propertyMetadata = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, target?.constructor || target) as Collection<PropertyDependency>
 | 
				
			||||||
        if ( !propertyMetadata ) {
 | 
					        if ( !propertyMetadata ) {
 | 
				
			||||||
@ -91,11 +92,18 @@ export const Inject = (key?: DependencyKey): PropertyDecorator => {
 | 
				
			|||||||
            if ( existing ) {
 | 
					            if ( existing ) {
 | 
				
			||||||
                existing.key = key
 | 
					                existing.key = key
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                propertyMetadata.push({ property,
 | 
					                propertyMetadata.push({
 | 
				
			||||||
                    key })
 | 
					                    property,
 | 
				
			||||||
 | 
					                    key,
 | 
				
			||||||
 | 
					                    debug,
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( debug ) {
 | 
				
			||||||
 | 
					            logIfDebugging('extollo.di.decoration', '[DEBUG] @Inject() - key:', key, 'property:', property, 'target:', target, 'target constructor:', target?.constructor, 'type:', type)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Reflect.defineMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, propertyMetadata, target?.constructor || target)
 | 
					        Reflect.defineMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, propertyMetadata, target?.constructor || target)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -152,3 +160,15 @@ export const Singleton = (name?: string): ClassDecorator => {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Register a factory class directly with any created containers.
 | 
				
			||||||
 | 
					 * @constructor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const FactoryProducer = (): ClassDecorator => {
 | 
				
			||||||
 | 
					    return (target) => {
 | 
				
			||||||
 | 
					        if ( isInstantiable(target) ) {
 | 
				
			||||||
 | 
					            ContainerBlueprint.getContainerBlueprint().registerFactory(target)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,16 @@ export function isInstantiable<T>(what: unknown): what is Instantiable<T> {
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns true if the given value is instantiable and, once instantiated,
 | 
				
			||||||
 | 
					 * will create an instance of the given static class.
 | 
				
			||||||
 | 
					 * @param what
 | 
				
			||||||
 | 
					 * @param type
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function isInstantiableOf<T>(what: unknown, type: StaticClass<T, any>): what is Instantiable<T> {
 | 
				
			||||||
 | 
					    return isInstantiable(what) && what.prototype instanceof type
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Type that identifies a value as a static class, even if it is not instantiable.
 | 
					 * Type that identifies a value as a static class, even if it is not instantiable.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -41,6 +51,11 @@ export function isStaticClass<T, T2>(something: unknown): something is StaticCla
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export type DependencyKey = Instantiable<any> | StaticClass<any, any> | string
 | 
					export type DependencyKey = Instantiable<any> | StaticClass<any, any> | string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A DependencyKey, but typed
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export type TypedDependencyKey<T> = Instantiable<T> | StaticClass<T, any> | string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Interface used to store dependency requirements by their place in the injectable
 | 
					 * Interface used to store dependency requirements by their place in the injectable
 | 
				
			||||||
 * target's parameters.
 | 
					 * target's parameters.
 | 
				
			||||||
@ -58,6 +73,7 @@ export interface DependencyRequirement {
 | 
				
			|||||||
export interface PropertyDependency {
 | 
					export interface PropertyDependency {
 | 
				
			||||||
    key: DependencyKey,
 | 
					    key: DependencyKey,
 | 
				
			||||||
    property: string | symbol,
 | 
					    property: string | symbol,
 | 
				
			||||||
 | 
					    debug?: boolean,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import {Container, ContainerBlueprint} from '../di'
 | 
					import {Container} from '../di'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    ErrorWithContext,
 | 
					    ErrorWithContext,
 | 
				
			||||||
    globalRegistry,
 | 
					    globalRegistry,
 | 
				
			||||||
@ -9,7 +9,6 @@ import {
 | 
				
			|||||||
    universalPath,
 | 
					    universalPath,
 | 
				
			||||||
    UniversalPath,
 | 
					    UniversalPath,
 | 
				
			||||||
} from '../util'
 | 
					} from '../util'
 | 
				
			||||||
 | 
					 | 
				
			||||||
import {Logging} from '../service/Logging'
 | 
					import {Logging} from '../service/Logging'
 | 
				
			||||||
import {RunLevelErrorHandler} from './RunLevelErrorHandler'
 | 
					import {RunLevelErrorHandler} from './RunLevelErrorHandler'
 | 
				
			||||||
import {Unit, UnitStatus} from './Unit'
 | 
					import {Unit, UnitStatus} from './Unit'
 | 
				
			||||||
@ -58,12 +57,7 @@ export class Application extends Container {
 | 
				
			|||||||
    public static getContainer(): Container {
 | 
					    public static getContainer(): Container {
 | 
				
			||||||
        const existing = <Container | undefined> globalRegistry.getGlobal('extollo/injector')
 | 
					        const existing = <Container | undefined> globalRegistry.getGlobal('extollo/injector')
 | 
				
			||||||
        if ( !existing ) {
 | 
					        if ( !existing ) {
 | 
				
			||||||
            const container = new Application()
 | 
					            const container = Application.realizeContainer(new Application())
 | 
				
			||||||
 | 
					 | 
				
			||||||
            ContainerBlueprint.getContainerBlueprint()
 | 
					 | 
				
			||||||
                .resolve()
 | 
					 | 
				
			||||||
                .map(factory => container.registerFactory(factory))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            globalRegistry.setGlobal('extollo/injector', container)
 | 
					            globalRegistry.setGlobal('extollo/injector', container)
 | 
				
			||||||
            return container
 | 
					            return container
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -79,18 +73,12 @@ export class Application extends Container {
 | 
				
			|||||||
        if ( existing instanceof Application ) {
 | 
					        if ( existing instanceof Application ) {
 | 
				
			||||||
            return existing
 | 
					            return existing
 | 
				
			||||||
        } else if ( existing ) {
 | 
					        } else if ( existing ) {
 | 
				
			||||||
            const app = new Application()
 | 
					            const app = Application.realizeContainer(new Application())
 | 
				
			||||||
            existing.cloneTo(app)
 | 
					            existing.cloneTo(app)
 | 
				
			||||||
 | 
					 | 
				
			||||||
            globalRegistry.setGlobal('extollo/injector', app)
 | 
					            globalRegistry.setGlobal('extollo/injector', app)
 | 
				
			||||||
            return app
 | 
					            return app
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            const app = new Application()
 | 
					            const app = Application.realizeContainer(new Application())
 | 
				
			||||||
 | 
					 | 
				
			||||||
            ContainerBlueprint.getContainerBlueprint()
 | 
					 | 
				
			||||||
                .resolve()
 | 
					 | 
				
			||||||
                .map(factory => app.registerFactory(factory))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            globalRegistry.setGlobal('extollo/injector', app)
 | 
					            globalRegistry.setGlobal('extollo/injector', app)
 | 
				
			||||||
            return app
 | 
					            return app
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -2,11 +2,13 @@ import {Directive, OptionDefinition} from '../../cli'
 | 
				
			|||||||
import {Injectable} from '../../di'
 | 
					import {Injectable} from '../../di'
 | 
				
			||||||
import {stringToPascal} from '../../util'
 | 
					import {stringToPascal} from '../../util'
 | 
				
			||||||
import {templateMigration} from '../template/migration'
 | 
					import {templateMigration} from '../template/migration'
 | 
				
			||||||
 | 
					import {CLIDirective} from '../../cli/decorators'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * CLI directive that creates migration classes from template.
 | 
					 * CLI directive that creates migration classes from template.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
 | 
					@CLIDirective()
 | 
				
			||||||
export class CreateMigrationDirective extends Directive {
 | 
					export class CreateMigrationDirective extends Directive {
 | 
				
			||||||
    getDescription(): string {
 | 
					    getDescription(): string {
 | 
				
			||||||
        return 'create a new migration'
 | 
					        return 'create a new migration'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,18 +1,20 @@
 | 
				
			|||||||
import {Directive, OptionDefinition} from '../../cli'
 | 
					import {Directive, OptionDefinition} from '../../cli'
 | 
				
			||||||
import {Container, Inject, Injectable} from '../../di'
 | 
					import {Container, Inject, Injectable} from '../../di'
 | 
				
			||||||
import {EventBus} from '../../event/EventBus'
 | 
					import {EventBus} from '../../event/EventBus'
 | 
				
			||||||
import {Migrator} from '../migrations/Migrator'
 | 
					 | 
				
			||||||
import {Migrations} from '../services/Migrations'
 | 
					import {Migrations} from '../services/Migrations'
 | 
				
			||||||
// import {ApplyingMigrationEvent} from '../migrations/events/ApplyingMigrationEvent'
 | 
					import {Migrator} from '../migrations/Migrator'
 | 
				
			||||||
// import {AppliedMigrationEvent} from '../migrations/events/AppliedMigrationEvent'
 | 
					import {ApplyingMigrationEvent} from '../migrations/events/ApplyingMigrationEvent'
 | 
				
			||||||
 | 
					import {AppliedMigrationEvent} from '../migrations/events/AppliedMigrationEvent'
 | 
				
			||||||
import {EventSubscription} from '../../event/types'
 | 
					import {EventSubscription} from '../../event/types'
 | 
				
			||||||
import {NothingToMigrateError} from '../migrations/NothingToMigrateError'
 | 
					import {NothingToMigrateError} from '../migrations/NothingToMigrateError'
 | 
				
			||||||
 | 
					import {CLIDirective} from '../../cli/decorators'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * CLI directive that applies migrations using the default Migrator.
 | 
					 * CLI directive that applies migrations using the default Migrator.
 | 
				
			||||||
 * @fixme Support dry run mode
 | 
					 * @fixme Support dry run mode
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
 | 
					@CLIDirective()
 | 
				
			||||||
export class MigrateDirective extends Directive {
 | 
					export class MigrateDirective extends Directive {
 | 
				
			||||||
    @Inject()
 | 
					    @Inject()
 | 
				
			||||||
    protected readonly bus!: EventBus
 | 
					    protected readonly bus!: EventBus
 | 
				
			||||||
@ -100,13 +102,13 @@ export class MigrateDirective extends Directive {
 | 
				
			|||||||
     * @protected
 | 
					     * @protected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async registerListeners(): Promise<void> {
 | 
					    protected async registerListeners(): Promise<void> {
 | 
				
			||||||
        // this.subscriptions.push(await this.bus.subscribe(ApplyingMigrationEvent, event => {
 | 
					        this.subscriptions.push(await this.bus.subscribe(ApplyingMigrationEvent, event => {
 | 
				
			||||||
        //     this.info(`Applying migration ${event.migration.identifier}...`)
 | 
					            this.info(`Applying migration ${event.migration.identifier}...`)
 | 
				
			||||||
        // }))
 | 
					        }))
 | 
				
			||||||
        //
 | 
					
 | 
				
			||||||
        // this.subscriptions.push(await this.bus.subscribe(AppliedMigrationEvent, event => {
 | 
					        this.subscriptions.push(await this.bus.subscribe(AppliedMigrationEvent, event => {
 | 
				
			||||||
        //     this.success(`Applied migration: ${event.migration.identifier}`)
 | 
					            this.success(`Applied migration: ${event.migration.identifier}`)
 | 
				
			||||||
        // }))
 | 
					        }))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Remove event bus listeners before finish. */
 | 
					    /** Remove event bus listeners before finish. */
 | 
				
			||||||
 | 
				
			|||||||
@ -3,16 +3,18 @@ import {Container, Inject, Injectable} from '../../di'
 | 
				
			|||||||
import {EventBus} from '../../event/EventBus'
 | 
					import {EventBus} from '../../event/EventBus'
 | 
				
			||||||
import {Migrator} from '../migrations/Migrator'
 | 
					import {Migrator} from '../migrations/Migrator'
 | 
				
			||||||
import {Migrations} from '../services/Migrations'
 | 
					import {Migrations} from '../services/Migrations'
 | 
				
			||||||
// import {RollingBackMigrationEvent} from '../migrations/events/RollingBackMigrationEvent'
 | 
					import {RollingBackMigrationEvent} from '../migrations/events/RollingBackMigrationEvent'
 | 
				
			||||||
// import {RolledBackMigrationEvent} from '../migrations/events/RolledBackMigrationEvent'
 | 
					import {RolledBackMigrationEvent} from '../migrations/events/RolledBackMigrationEvent'
 | 
				
			||||||
import {EventSubscription} from '../../event/types'
 | 
					import {EventSubscription} from '../../event/types'
 | 
				
			||||||
import {NothingToMigrateError} from '../migrations/NothingToMigrateError'
 | 
					import {NothingToMigrateError} from '../migrations/NothingToMigrateError'
 | 
				
			||||||
 | 
					import {CLIDirective} from '../../cli/decorators'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * CLI directive that undoes applied migrations using the default Migrator.
 | 
					 * CLI directive that undoes applied migrations using the default Migrator.
 | 
				
			||||||
 * @fixme Support dry run mode
 | 
					 * @fixme Support dry run mode
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
 | 
					@CLIDirective()
 | 
				
			||||||
export class RollbackDirective extends Directive {
 | 
					export class RollbackDirective extends Directive {
 | 
				
			||||||
    @Inject()
 | 
					    @Inject()
 | 
				
			||||||
    protected readonly bus!: EventBus
 | 
					    protected readonly bus!: EventBus
 | 
				
			||||||
@ -85,13 +87,13 @@ export class RollbackDirective extends Directive {
 | 
				
			|||||||
     * @protected
 | 
					     * @protected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async registerListeners(): Promise<void> {
 | 
					    protected async registerListeners(): Promise<void> {
 | 
				
			||||||
        // this.subscriptions.push(await this.bus.subscribe(RollingBackMigrationEvent, event => {
 | 
					        this.subscriptions.push(await this.bus.subscribe(RollingBackMigrationEvent, event => {
 | 
				
			||||||
        //     this.info(`Rolling-back migration ${event.migration.identifier}...`)
 | 
					            this.info(`Rolling-back migration ${event.migration.identifier}...`)
 | 
				
			||||||
        // }))
 | 
					        }))
 | 
				
			||||||
        //
 | 
					
 | 
				
			||||||
        // this.subscriptions.push(await this.bus.subscribe(RolledBackMigrationEvent, event => {
 | 
					        this.subscriptions.push(await this.bus.subscribe(RolledBackMigrationEvent, event => {
 | 
				
			||||||
        //     this.success(`Rolled-back migration: ${event.migration.identifier}`)
 | 
					            this.success(`Rolled-back migration: ${event.migration.identifier}`)
 | 
				
			||||||
        // }))
 | 
					        }))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Remove event bus listeners before finish. */
 | 
					    /** Remove event bus listeners before finish. */
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,8 @@ export * from './schema/TableBuilder'
 | 
				
			|||||||
export * from './schema/Schema'
 | 
					export * from './schema/Schema'
 | 
				
			||||||
export * from './schema/PostgresSchema'
 | 
					export * from './schema/PostgresSchema'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export * from './services/Migrations'
 | 
				
			||||||
 | 
					export * from './migrations/Migrator'
 | 
				
			||||||
export * from './migrations/NothingToMigrateError'
 | 
					export * from './migrations/NothingToMigrateError'
 | 
				
			||||||
export * from './migrations/events/MigrationEvent'
 | 
					export * from './migrations/events/MigrationEvent'
 | 
				
			||||||
export * from './migrations/events/ApplyingMigrationEvent'
 | 
					export * from './migrations/events/ApplyingMigrationEvent'
 | 
				
			||||||
@ -37,13 +39,11 @@ export * from './migrations/events/AppliedMigrationEvent'
 | 
				
			|||||||
export * from './migrations/events/RollingBackMigrationEvent'
 | 
					export * from './migrations/events/RollingBackMigrationEvent'
 | 
				
			||||||
export * from './migrations/events/RolledBackMigrationEvent'
 | 
					export * from './migrations/events/RolledBackMigrationEvent'
 | 
				
			||||||
export * from './migrations/Migration'
 | 
					export * from './migrations/Migration'
 | 
				
			||||||
export * from './migrations/Migrator'
 | 
					 | 
				
			||||||
export * from './migrations/MigratorFactory'
 | 
					export * from './migrations/MigratorFactory'
 | 
				
			||||||
export * from './migrations/DatabaseMigrator'
 | 
					export * from './migrations/DatabaseMigrator'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export * from './services/Database'
 | 
					export * from './services/Database'
 | 
				
			||||||
export * from './services/Models'
 | 
					export * from './services/Models'
 | 
				
			||||||
export * from './services/Migrations'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export * from './directive/CreateMigrationDirective'
 | 
					export * from './directive/CreateMigrationDirective'
 | 
				
			||||||
export * from './directive/MigrateDirective'
 | 
					export * from './directive/MigrateDirective'
 | 
				
			||||||
 | 
				
			|||||||
@ -3,10 +3,10 @@ import {Awaitable, collect, ErrorWithContext} from '../../util'
 | 
				
			|||||||
import {Migration} from './Migration'
 | 
					import {Migration} from './Migration'
 | 
				
			||||||
import {Migrations} from '../services/Migrations'
 | 
					import {Migrations} from '../services/Migrations'
 | 
				
			||||||
import {EventBus} from '../../event/EventBus'
 | 
					import {EventBus} from '../../event/EventBus'
 | 
				
			||||||
// import {ApplyingMigrationEvent} from './events/ApplyingMigrationEvent'
 | 
					import {ApplyingMigrationEvent} from './events/ApplyingMigrationEvent'
 | 
				
			||||||
// import {AppliedMigrationEvent} from './events/AppliedMigrationEvent'
 | 
					import {AppliedMigrationEvent} from './events/AppliedMigrationEvent'
 | 
				
			||||||
// import {RollingBackMigrationEvent} from './events/RollingBackMigrationEvent'
 | 
					import {RollingBackMigrationEvent} from './events/RollingBackMigrationEvent'
 | 
				
			||||||
// import {RolledBackMigrationEvent} from './events/RolledBackMigrationEvent'
 | 
					import {RolledBackMigrationEvent} from './events/RolledBackMigrationEvent'
 | 
				
			||||||
import {NothingToMigrateError} from './NothingToMigrateError'
 | 
					import {NothingToMigrateError} from './NothingToMigrateError'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -14,7 +14,7 @@ import {NothingToMigrateError} from './NothingToMigrateError'
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
export abstract class Migrator {
 | 
					export abstract class Migrator {
 | 
				
			||||||
    @Inject()
 | 
					    @Inject(Migrations, { debug: true })
 | 
				
			||||||
    protected readonly migrations!: Migrations
 | 
					    protected readonly migrations!: Migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject()
 | 
					    @Inject()
 | 
				
			||||||
@ -259,8 +259,8 @@ export abstract class Migrator {
 | 
				
			|||||||
     * @protected
 | 
					     * @protected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async applying(migration: Migration): Promise<void> {
 | 
					    protected async applying(migration: Migration): Promise<void> {
 | 
				
			||||||
        // const event = <ApplyingMigrationEvent> this.injector.make(ApplyingMigrationEvent, migration)
 | 
					        const event = <ApplyingMigrationEvent> this.injector.make(ApplyingMigrationEvent, migration)
 | 
				
			||||||
        // await this.bus.dispatch(event)
 | 
					        await this.bus.dispatch(event)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -269,8 +269,8 @@ export abstract class Migrator {
 | 
				
			|||||||
     * @protected
 | 
					     * @protected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async applied(migration: Migration): Promise<void> {
 | 
					    protected async applied(migration: Migration): Promise<void> {
 | 
				
			||||||
        // const event = <AppliedMigrationEvent> this.injector.make(AppliedMigrationEvent, migration)
 | 
					        const event = <AppliedMigrationEvent> this.injector.make(AppliedMigrationEvent, migration)
 | 
				
			||||||
        // await this.bus.dispatch(event)
 | 
					        await this.bus.dispatch(event)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -279,8 +279,8 @@ export abstract class Migrator {
 | 
				
			|||||||
     * @protected
 | 
					     * @protected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async rollingBack(migration: Migration): Promise<void> {
 | 
					    protected async rollingBack(migration: Migration): Promise<void> {
 | 
				
			||||||
        // const event = <RollingBackMigrationEvent> this.injector.make(RollingBackMigrationEvent, migration)
 | 
					        const event = <RollingBackMigrationEvent> this.injector.make(RollingBackMigrationEvent, migration)
 | 
				
			||||||
        // await this.bus.dispatch(event)
 | 
					        await this.bus.dispatch(event)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -289,7 +289,7 @@ export abstract class Migrator {
 | 
				
			|||||||
     * @protected
 | 
					     * @protected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async rolledBack(migration: Migration): Promise<void> {
 | 
					    protected async rolledBack(migration: Migration): Promise<void> {
 | 
				
			||||||
        // const event = <RolledBackMigrationEvent> this.injector.make(RolledBackMigrationEvent, migration)
 | 
					        const event = <RolledBackMigrationEvent> this.injector.make(RolledBackMigrationEvent, migration)
 | 
				
			||||||
        // await this.bus.dispatch(event)
 | 
					        await this.bus.dispatch(event)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import {
 | 
				
			|||||||
    PropertyDependency,
 | 
					    PropertyDependency,
 | 
				
			||||||
    isInstantiable,
 | 
					    isInstantiable,
 | 
				
			||||||
    DEPENDENCY_KEYS_METADATA_KEY,
 | 
					    DEPENDENCY_KEYS_METADATA_KEY,
 | 
				
			||||||
    DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, Instantiable, Injectable, Inject,
 | 
					    DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, Instantiable, Injectable, Inject, FactoryProducer,
 | 
				
			||||||
} from '../../di'
 | 
					} from '../../di'
 | 
				
			||||||
import {Collection, ErrorWithContext} from '../../util'
 | 
					import {Collection, ErrorWithContext} from '../../util'
 | 
				
			||||||
import {Logging} from '../../service/Logging'
 | 
					import {Logging} from '../../service/Logging'
 | 
				
			||||||
@ -17,6 +17,7 @@ import {DatabaseMigrator} from './DatabaseMigrator'
 | 
				
			|||||||
 * and produces an instance of the configured session driver implementation.
 | 
					 * and produces an instance of the configured session driver implementation.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
 | 
					@FactoryProducer()
 | 
				
			||||||
export class MigratorFactory extends AbstractFactory<Migrator> {
 | 
					export class MigratorFactory extends AbstractFactory<Migrator> {
 | 
				
			||||||
    @Inject()
 | 
					    @Inject()
 | 
				
			||||||
    protected readonly logging!: Logging
 | 
					    protected readonly logging!: Logging
 | 
				
			||||||
 | 
				
			|||||||
@ -2,22 +2,15 @@ import {Inject, Singleton} from '../../di'
 | 
				
			|||||||
import {CanonicalInstantiable} from '../../service/CanonicalInstantiable'
 | 
					import {CanonicalInstantiable} from '../../service/CanonicalInstantiable'
 | 
				
			||||||
import {Migration} from '../migrations/Migration'
 | 
					import {Migration} from '../migrations/Migration'
 | 
				
			||||||
import {CanonicalDefinition, CanonicalResolver} from '../../service/Canonical'
 | 
					import {CanonicalDefinition, CanonicalResolver} from '../../service/Canonical'
 | 
				
			||||||
import {Migrator} from '../migrations/Migrator'
 | 
					 | 
				
			||||||
import {UniversalPath} from '../../util'
 | 
					import {UniversalPath} from '../../util'
 | 
				
			||||||
import {lib} from '../../lib'
 | 
					import {lib} from '../../lib'
 | 
				
			||||||
import {CommandLine} from '../../cli'
 | 
					import {CommandLine} from '../../cli'
 | 
				
			||||||
import {MigrateDirective} from '../directive/MigrateDirective'
 | 
					 | 
				
			||||||
import {RollbackDirective} from '../directive/RollbackDirective'
 | 
					 | 
				
			||||||
import {CreateMigrationDirective} from '../directive/CreateMigrationDirective'
 | 
					 | 
				
			||||||
import {MigratorFactory} from '../migrations/MigratorFactory'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Service unit that loads and instantiates migration classes.
 | 
					 * Service unit that loads and instantiates migration classes.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Singleton()
 | 
					@Singleton()
 | 
				
			||||||
export class Migrations extends CanonicalInstantiable<Migration> {
 | 
					export class Migrations extends CanonicalInstantiable<Migration> {
 | 
				
			||||||
    protected migrator!: Migrator
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Inject()
 | 
					    @Inject()
 | 
				
			||||||
    protected readonly cli!: CommandLine
 | 
					    protected readonly cli!: CommandLine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -34,22 +27,10 @@ export class Migrations extends CanonicalInstantiable<Migration> {
 | 
				
			|||||||
            this.logging.debug(`Base migration path does not exist, or has no files: ${this.path}`)
 | 
					            this.logging.debug(`Base migration path does not exist, or has no files: ${this.path}`)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Register the migrator factory
 | 
					 | 
				
			||||||
        this.container().registerFactory(
 | 
					 | 
				
			||||||
            this.container().make<MigratorFactory>(MigratorFactory),
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.migrator = this.container().make(Migrator)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Register the migrations for @extollo/lib
 | 
					        // Register the migrations for @extollo/lib
 | 
				
			||||||
        const basePath = lib().concat('migrations')
 | 
					        const basePath = lib().concat('migrations')
 | 
				
			||||||
        const resolver = await this.buildMigrationNamespaceResolver('@extollo', basePath)
 | 
					        const resolver = await this.buildMigrationNamespaceResolver('@extollo', basePath)
 | 
				
			||||||
        this.registerNamespace('@extollo', resolver)
 | 
					        this.registerNamespace('@extollo', resolver)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Register the migrate CLI directives
 | 
					 | 
				
			||||||
        this.cli.registerDirective(MigrateDirective)
 | 
					 | 
				
			||||||
        this.cli.registerDirective(RollbackDirective)
 | 
					 | 
				
			||||||
        this.cli.registerDirective(CreateMigrationDirective)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async initCanonicalItem(definition: CanonicalDefinition): Promise<Migration> {
 | 
					    async initCanonicalItem(definition: CanonicalDefinition): Promise<Migration> {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
export function isDebugging(key: string): boolean {
 | 
					export function isDebugging(key: string): boolean {
 | 
				
			||||||
    const env = 'EXTOLLO_DEBUG_' + key.split(/(?:\s|\.)+/).join('_')
 | 
					    const env = 'EXTOLLO_DEBUG_' + key.split(/(?:\s|\.)+/).join('_')
 | 
				
			||||||
        .toUpperCase()
 | 
					        .toUpperCase()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return process.env[env] === 'yes'
 | 
					    return process.env[env] === 'yes'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user