import * as Mobx from 'mobx' ; import * as Types from '@meetalva/types' ; import { UserStore } from './user-store' ; import { DesignTimeUserStore } from './design-time-user-store' ; import * as uuid from 'uuid' ; import * as VM from 'vm' ; export interface UserStoreEnhancerModule { onStoreCreate ( store ) : DesignTimeUserStore ; } export interface UserStoreEnhancerInit { id : string ; typeScript : string ; javaScript : string ; } const userStoreApi = ( names ) => `
declare module "alva" {
	export type PropertyName = ${ names . join ( ' | ' ) };
	export type DesignTimeDescriptor = ConcreteDesignTimeDescriptor | ComputedDesignTimeDescriptor;

	export interface ConcreteDesignTimeDescriptor {
		type?: DesignTimePropertyType.Concrete;
		value: string;
		get?: undefined;
	}
	export interface ComputedDesignTimeDescriptor {
		type?: DesignTimePropertyType.Computed;
		value?: undefined;
		get(): string;
	}
	export type QualifiedDesignTimeDescriptor =
		| QualifiedConcreteDesignTimeDescriptor
		| QualifiedComputedDesignTimeDescriptor;
	export interface QualifiedConcreteDesignTimeDescriptor {
		type: DesignTimePropertyType.Concrete;
		value: string;
		get: undefined;
	}
	export interface QualifiedComputedDesignTimeDescriptor {
		type: DesignTimePropertyType.Computed;
		value: undefined;
		get(): string;
	}
	export declare enum DesignTimePropertyType {
		Computed = 0,
		Concrete = 1,
	}
	export declare class DesignTimeUserStore {
		getProperties(): DesignTimeProperty[];
		getProperty(name: PropertyName): DesignTimeProperty;
		defineProperty(name: string, descriptor: DesignTimeDescriptor): DesignTimeProperty;
	}
	export interface DesignTimePropertyInit {
		name: string;
		type: DesignTimePropertyType;
		value: string | undefined;
		getter: Computation | undefined;
	}
	export declare type Computation = () => string;
	export declare class DesignTimeProperty {
		configureProperty(descriptor: DesignTimeDescriptor): void;
		getName(): PropertyName;
		getType(): DesignTimePropertyType;
		getValue(): string | undefined;
		getGetter(): Computation | undefined;
	}
}` ; export const defaultCode = `import * as Alva from 'alva';

export function onStoreCreate(store: Alva.DesignTimeUserStore): Alva.DesignTimeUserStore {
	// Add properties to your store here, e.g.:
	// store.defineProperty('hello', { value: 'Hello' });
	// store.defineProperty('world', { value: 'World' });
	// store.defineProperty('helloWorld', { get: () => store.getProperty('hello').getValue() + ' ' + store.getProperty('world').getValue() });
	return store;
}
` ; export const defaultJavaScript = 'exports.onStoreCreate = function onStoreCreate(store) { return store; }' ; export class UserStoreEnhancer { public readonly model = Types . ModelName . UserStoreEnhancer ; @ Mobx . observable private id : string ; @ Mobx . observable private typeScript : string ; @ Mobx . observable private javaScript : string ; @ Mobx . computed private get module ( ) : UserStoreEnhancerModule { const context = { exports : { } , module : { exports : { } } , console } ; VM . runInNewContext ( this . javaScript , context ) ; return context . exports as UserStoreEnhancerModule ; } private userStore ? : UserStore ; public constructor ( init ) { this . id = init . id ; this . typeScript = init . typeScript ; this . javaScript = init . javaScript ; if ( ! init ) { this . id = uuid . v4 ( ) ; this . typeScript = defaultCode ; this . javaScript = defaultJavaScript ; } } public static from ( serialized ) { return new UserStoreEnhancer ( { id : serialized . id , typeScript : serialized . typeScript || serialized . code || '' , javaScript : serialized . javaScript } ) ; } public getApi ( ) { if ( ! this . userStore ) { return '' ; } return userStoreApi ( this . userStore . getProperties ( ) . map ( p => JSON . stringify ( p . getName ( ) ) ) ) ; } public getId ( ) { return this . id ; } public getJavaScript ( ) { return this . javaScript ; } public getTypeScript ( ) { return this . typeScript ; } public getModule ( ) { return this . module ; } @ Mobx . action public setTypeScript ( code ) { this . typeScript = code ; } @ Mobx . action public setJavaScript ( javaScript ) { this . javaScript = javaScript ; } public setUserStore ( userStore ) { this . userStore = userStore ; } public toJSON ( ) { return { model : this . model , id : this . id , typeScript : this . typeScript , javaScript : this . javaScript } ; } public update ( b ) { this . typeScript = b . typeScript ; this . javaScript = b . javaScript ; } }