Skip to content

Commit

Permalink
refactor(ngrid): bump angular to version 8.2.2
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

- This bump included a bump in TS as well, to 3.5.3. TS 3.5.3 introduces a breaking change which was fixed in this commit.
- Moving from @angular/cli 8.0.3 introduces a breaking change. The package @ngtools/webpack@8.0.4 is now adding `ctorParameters` property to all classes with ctor params, even the non-injectable ones which now will have a hard reference leading to a circular dependency error. This commit includes a refactor of the code to fit this paradigm until someone in angular understands this and push a fix...
  • Loading branch information
shlomiassaf committed Aug 18, 2019
1 parent f92b37a commit 8f82092
Show file tree
Hide file tree
Showing 14 changed files with 627 additions and 472 deletions.
6 changes: 3 additions & 3 deletions libs/ngrid/src/lib/data-source/data-source-adapter.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export function fromRefreshDataWrapper<T>(change: PblDataSourceTriggerChange<Ref
export type CoValue<P extends keyof PblDataSourceTriggerCache> = P extends keyof PblDataSourceTriggers ? PblDataSourceTriggers[P] : PblDataSourceTriggerCache[P];

export function createChangeContainer<P extends keyof PblDataSourceTriggerCache>(type: P,
value: CoValue<P>,
cache: PblDataSourceTriggerCache): TriggerChangedEventFor<P> {
value: CoValue<P>,
cache: PblDataSourceTriggerCache): TriggerChangedEventFor<P> {
if (type === 'pagination') {
const pagination: PblDataSourceTriggers['pagination'] = (value || {}) as any;
const cached = cache['pagination'];
Expand All @@ -73,7 +73,7 @@ export function createChangeContainer<P extends keyof PblDataSourceTriggerCache>
if (value === cachedValue) {
return createNotChangedEvent(cachedValue) as any;
} else if (value !== EMPTY && cachedValue !== EMPTY) {
const fn: (prev: PblDataSourceTriggerCache[P], curr: PblDataSourceTriggerCache[P]) => boolean = DEEP_COMPARATORS[type];
const fn: (prev: PblDataSourceTriggerCache[P], curr: PblDataSourceTriggerCache[P]) => boolean = DEEP_COMPARATORS[type as any];
if (fn(cachedValue, value as any)) {
return createNotChangedEvent(cachedValue) as any;
}
Expand Down
30 changes: 24 additions & 6 deletions libs/ngrid/src/lib/ext/plugin-control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,36 @@ const TABLE_PLUGIN_CONTEXT = new WeakMap<PblNgridComponent<any>, PblNgridPluginC

/** @internal */
export class PblNgridPluginContext<T = any> {
readonly controller: PblNgridPluginController<T>;
readonly events: Observable<PblNgridEvents>;
private _events = new Subject<PblNgridEvents>();

constructor(public table: PblNgridComponent<any>, public injector: Injector, public extApi: PblNgridExtensionApi) {
// workaround, we need a parameter-less constructor since @ngtools/webpack@8.0.4
// Non @Injectable classes are now getting addded with hard reference to the ctor params which at the class creation point are undefined
// forwardRef() will not help since it's not inject by angular, we instantiate the class..
// probably due to https://github.com/angular/angular-cli/commit/639198499973e0f437f059b3c933c72c733d93d8
static create<T = any>(table: PblNgridComponent<any>, injector: Injector, extApi: PblNgridExtensionApi): PblNgridPluginContext<T> {
if (TABLE_PLUGIN_CONTEXT.has(table)) {
throw new Error(`Table is already registered for extensions.`);
}

TABLE_PLUGIN_CONTEXT.set(table, this);
const instance = new PblNgridPluginContext<T>();
TABLE_PLUGIN_CONTEXT.set(table, instance);

instance.table = table;
instance.injector = injector;
instance.extApi = extApi;
instance.controller = new PblNgridPluginController(instance);

return instance;
}

table: PblNgridComponent<any>;
injector: Injector;
extApi: PblNgridExtensionApi;
controller: PblNgridPluginController<T>;
readonly events: Observable<PblNgridEvents>;
private _events = new Subject<PblNgridEvents>();

private constructor() {
this.events = this._events.asObservable();
this.controller = new PblNgridPluginController(this);
}

emitEvent(event: PblNgridEvents): void {
Expand Down
20 changes: 19 additions & 1 deletion libs/ngrid/src/lib/table/column-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,30 @@ export interface AutoSizeToFitOptions {

export class ColumnApi<T> {

// workaround, we need a parameter-less constructor since @ngtools/webpack@8.0.4
// Non @Injectable classes are now getting addded with hard reference to the ctor params which at the class creation point are undefined
// forwardRef() will not help since it's not inject by angular, we instantiate the class..
// probably due to https://github.com/angular/angular-cli/commit/639198499973e0f437f059b3c933c72c733d93d8
static create<T>(table: PblNgridComponent<T>, store: PblColumnStore, extApi: PblNgridExtensionApi): ColumnApi<T> {
const instance = new ColumnApi<T>();

instance.table = table;
instance.store = store;
instance.extApi = extApi;

return instance;
}

get groupByColumns(): PblColumn[] { return this.store.groupBy; }
get visibleColumnIds(): string[] { return this.store.columnIds; }
get visibleColumns(): PblColumn[] { return this.store.columns; }
get columns(): PblColumn[] { return this.store.allColumns; }

constructor(private table: PblNgridComponent<T>, private store: PblColumnStore, private extApi: PblNgridExtensionApi) { }
private table: PblNgridComponent<T>;
private store: PblColumnStore;
private extApi: PblNgridExtensionApi;

private constructor() { }

/**
* Returns the `PblColumn` at the specified index from the list of rendered columns (i.e. not hidden).
Expand Down
45 changes: 40 additions & 5 deletions libs/ngrid/src/lib/table/context/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,23 @@ import { PblMetaColumn } from '../columns/meta-column';
import { PblRowContext } from './row';

export class MetaCellContext<T = any, TCol extends PblMetaColumn | PblColumn = PblMetaColumn> implements PblNgridMetaCellContext<T, TCol> {
col: TCol;
table: PblNgridComponent<any>;
get $implicit(): MetaCellContext<T, TCol> { return this; }
constructor(public col: TCol, public table: PblNgridComponent<any>) {}

protected constructor() {}

// workaround, we need a parameter-less constructor since @ngtools/webpack@8.0.4
// Non @Injectable classes are now getting addded with hard reference to the ctor params which at the class creation point are undefined
// forwardRef() will not help since it's not inject by angular, we instantiate the class..
// probably due to https://github.com/angular/angular-cli/commit/639198499973e0f437f059b3c933c72c733d93d8
static create<T = any, TCol extends PblMetaColumn | PblColumn = PblMetaColumn>(col: TCol, table: PblNgridComponent<T>): MetaCellContext<T, TCol> {
const instance = new MetaCellContext<T, TCol>();
instance.col = col;
instance.table = table;
return instance;
}

}

export class PblCellContext<T = any> implements PblNgridCellContext<T> {
Expand All @@ -28,17 +43,37 @@ export class PblCellContext<T = any> implements PblNgridCellContext<T> {
private _focused = false;
private _selected = false;

constructor(private _rowContext: PblRowContext<T>, public col: PblColumn, private extApi: PblNgridExtensionApi<T>) {
this.table = extApi.table;
this.index = this.table.columnApi.indexOf(col);
private _rowContext: PblRowContext<T>;
public col: PblColumn;
private extApi: PblNgridExtensionApi<T>;

protected constructor() { }

// workaround, we need a parameter-less constructor since @ngtools/webpack@8.0.4
// Non @Injectable classes are now getting addded with hard reference to the ctor params which at the class creation point are undefined
// forwardRef() will not help since it's not inject by angular, we instantiate the class..
// probably due to https://github.com/angular/angular-cli/commit/639198499973e0f437f059b3c933c72c733d93d8
static create<T = any>(rowContext: PblRowContext<T>, col: PblColumn, extApi: PblNgridExtensionApi<T>): PblCellContext<T> {
const instance = new PblCellContext<T>();

instance._rowContext = rowContext;
instance.col = col;
instance.extApi = extApi;

Object.defineProperties(instance, {
table: { value: extApi.table },
index: { value: extApi.table.columnApi.indexOf(col) },
});

return instance;
}

static defaultState<T = any>(): CellContextState<T> {
return { editing: false, focused: false, selected: false };
}

clone(): PblCellContext<T> {
const ctx = new PblCellContext<T>(this._rowContext, this.col, this.extApi);
const ctx = PblCellContext.create<T>(this._rowContext, this.col, this.extApi);
ctx.fromState(this.getState(), this._rowContext, true);
return ctx;
}
Expand Down
2 changes: 1 addition & 1 deletion libs/ngrid/src/lib/table/context/row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class PblRowContext<T> implements PblNgridRowContext<T> {
const len = columns.length;

for (let columnIndex = 0; columnIndex < len; columnIndex++) {
const cellContext = new PblCellContext<T>(this, columns[columnIndex], extApi);
const cellContext = PblCellContext.create<T>(this, columns[columnIndex], extApi);
cells.push(cellContext);
}
}
Expand Down
6 changes: 3 additions & 3 deletions libs/ngrid/src/lib/table/directives/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ export class PblNgridHeaderCellComponent<T extends COLUMN = COLUMN> extends CdkH
ngOnInit(): void {
const col: COLUMN = this.columnDef.column;
if (col instanceof PblColumn) {
this.cellCtx = new PblNgridDataHeaderExtensionContext(this as PblNgridHeaderCellComponent<PblColumn>, this.vcRef.injector);
this.cellCtx = PblNgridDataHeaderExtensionContext.createDateHeaderCtx(this as PblNgridHeaderCellComponent<PblColumn>, this.vcRef.injector);
} else {
this.cellCtx = new MetaCellContext(col, this.table);
this.cellCtx = MetaCellContext.create(col, this.table);
}
}

Expand Down Expand Up @@ -285,6 +285,6 @@ export class PblNgridFooterCellDirective extends CdkFooterCell implements DoChec
}

ngOnInit(): void {
this.cellCtx = new MetaCellContext(this.columnDef.column, this.table);
this.cellCtx = MetaCellContext.create(this.columnDef.column, this.table);
}
}
17 changes: 15 additions & 2 deletions libs/ngrid/src/lib/table/directives/registry.directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,21 @@ export abstract class PblNgridMultiComponentRegistry<T, TKind extends keyof PblN
}

export class PblNgridDataHeaderExtensionContext<T = any> extends MetaCellContext<T, PblColumn> {
constructor(headerCell: PblNgridHeaderCellComponent<PblColumn>, public readonly injector: Injector) {
super(headerCell.columnDef.column, headerCell.table);
readonly injector: Injector

protected constructor() { super(); }

// workaround, we need a parameter-less constructor since @ngtools/webpack@8.0.4
// Non @Injectable classes are now getting addded with hard reference to the ctor params which at the class creation point are undefined
// forwardRef() will not help since it's not inject by angular, we instantiate the class..
// probably due to https://github.com/angular/angular-cli/commit/639198499973e0f437f059b3c933c72c733d93d8
static createDateHeaderCtx<T = any>(headerCell: PblNgridHeaderCellComponent<PblColumn>, injector: Injector): PblNgridDataHeaderExtensionContext<T> {
const instance = new PblNgridDataHeaderExtensionContext<T>();

instance.col = headerCell.columnDef.column;
instance.table = headerCell.table;
Object.defineProperty(instance, 'injector', { value: injector });
return instance;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class PblNgridRegistryService implements OnDestroy {
* If not found WILL NOT search the parent.
*/
getMulti<T extends keyof PblNgridMultiRegistryMap>(kind: T): Array<PblNgridMultiRegistryMap[T]> | undefined {
return this._multi[kind]
return this._multi[kind] as Array<PblNgridMultiRegistryMap[T]>;
}

addMulti<T extends keyof PblNgridMultiRegistryMap>(kind: T, cellDef: PblNgridMultiRegistryMap[T]): void {
Expand Down
4 changes: 2 additions & 2 deletions libs/ngrid/src/lib/table/table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ export class PblNgridComponent<T = any> implements AfterContentInit, AfterViewIn
this.noFiller = tableConfig.noFiller;

this.initExtApi();
this.columnApi = new ColumnApi<T>(this, this._store, this._extApi);
this.columnApi = ColumnApi.create<T>(this, this._store, this._extApi);
this.initPlugins(injector, elRef, vcRef);
}

Expand Down Expand Up @@ -816,7 +816,7 @@ export class PblNgridComponent<T = any> implements AfterContentInit, AfterViewIn
],
parent: injector,
});
this._plugin = new PblNgridPluginContext(this, pluginInjector, this._extApi);
this._plugin = PblNgridPluginContext.create(this, pluginInjector, this._extApi);
bindToDataSource(this._plugin);
}

Expand Down
113 changes: 8 additions & 105 deletions libs/ngrid/src/lib/table/utils/type-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,11 @@
// COPIED FROM https://github.com/pelotom/type-zoo
// https://stackoverflow.com/questions/49579094/typescript-conditional-types-filter-out-readonly-properties-pick-only-requir

// TypeScript Version: 2.8
export type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? A : B;

/**
* Drop keys `K` from `T`.
*
* @see https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-377567046
*/
export type Omit<T, K extends keyof any> = T extends any ? Pick<T, Exclude<keyof T, K>> : never;
export type WritableKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];

/**
* Like `T & U`, but where there are overlapping properties using the
* type from U only.
*
* @see Old: https://github.com/pelotom/type-zoo/issues/2
* @see Old: https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458
* @see New: https://github.com/pelotom/type-zoo/pull/14#discussion_r183527882
*/
export type Overwrite<T, U> = Omit<T, keyof T & keyof U> & U;

/**
* Use to prevent a usage of type `T` from being inferred in other generics.
*
* Example:
* declare function assertEqual<T>(actual: T, expected: NoInfer<T>): boolean;
*
* Type `T` will now only be inferred based on the type of the `actual` param, and
* the `expected` param is required to be assignable to the type of `actual`.
* This allows you to give one particular usage of type `T` full control over how the
* compiler infers type `T`.
*
* @see https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-322267089
*/
export type NoInfer<T> = T & { [K in keyof T]: T[K] };

/**
* Forgets contextual knowledge of partiality of keys.
*/
export type Purify<T extends string> = { [P in T]: T }[T];

/**
* Selects the type of the 0th parameter in a function-type
*/
export type Param0<Func> = Func extends (a: infer T, ...args: any[]) => any ? T : never;
/**
* Selects the type of the 1st parameter in a function-type
*/
export type Param1<Func> = Func extends (a: any, b: infer T, ...args: any[]) => any ? T : never;
/**
* Selects the type of the 2nd parameter in a function-type
*/
export type Param2<Func> = Func extends (a: any, b: any, c: infer T, ...args: any[]) => any
? T
: never;
/**
* Selects the type of the 3rd parameter in a function-type
*/
export type Param3<Func> = Func extends (a: any, b: any, c: any, d: infer T, ...args: any[]) => any
? T
: never;
/**
* Selects the types of all the parameters in a function-type.
* Warnings:
* - This is probably less performant if you're only looking up a single param! {@see Param0-Param# }
* - This omits rest parameters (...args:any[])
*/
export type ParamTypes<F extends Function> = F extends () => any // tslint:disable-line
? {}
: F extends (p0: infer P0) => any
? [P0]
: F extends (p0: infer P0, p1: infer P1) => any
? [P0, P1]
: F extends (p0: infer P0, p1: infer P1, p2: infer P2) => any
? [P0, P1, P2]
: F extends (p0: infer P0, p1: infer P1, p2: infer P2, p3: infer P3) => any
? [P0, P1, P2, P3]
: // ... -- extend this at your own risk, this could be bad for compilation performance!
never;

/**
* Picks 2 levels deep into a nested object!
*
* @see https://gist.github.com/staltz/368866ea6b8a167fbdac58cddf79c1bf
*/
export type Pick2<T, K1 extends keyof T, K2 extends keyof T[K1]> = {
[P1 in K1]: { [P2 in K2]: (T[K1])[P2] }
};

/**
* Picks 3 levels deep into a nested object!
*
* @see https://gist.github.com/staltz/368866ea6b8a167fbdac58cddf79c1bf
*/
export type Pick3<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]> = {
[P1 in K1]: { [P2 in K2]: { [P3 in K3]: ((T[K1])[K2])[P3] } }
};

/**
* Picks 4 levels deep into a nested object!
*/
export type Pick4<
T,
K1 extends keyof T,
K2 extends keyof T[K1],
K3 extends keyof T[K1][K2],
K4 extends keyof T[K1][K2][K3]
> = { [P1 in K1]: { [P2 in K2]: { [P3 in K3]: { [P4 in K4]: (((T[K1])[K2])[K3])[P4] } } } };
export type ReadonlyKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PblColumnTypeDefinition } from '@pebula/ngrid';
import { PblColumnTypeDefinition, PblColumn, PblColumnDefinition, PblMetaRowDefinitions } from '@pebula/ngrid';
import { createStateChunkHandler } from '../../handling';

export function registerColumnDefChildHandlers() {
Expand Down Expand Up @@ -63,7 +63,10 @@ export function registerColumnDefChildHandlers() {
}
break;
}
ctx.source[key] = stateValue;

// We must assert the type starting from 3.5 onwards
// See "Fixes to unsound writes to indexed access types" in https://devblogs.microsoft.com/typescript/announcing-typescript-3-5
ctx.source[key as keyof (PblColumn | PblColumnDefinition)] = stateValue;
}

})
Expand All @@ -79,9 +82,14 @@ export function registerColumnDefChildHandlers() {
return active[key];
}
})
.deserialize( (key, stateValue, ctx) => ctx.source[key] = stateValue )
.deserialize( (key, stateValue, ctx) => {
// We must assert the type starting from 3.5 onwards
// See "Fixes to unsound writes to indexed access types" in https://devblogs.microsoft.com/typescript/announcing-typescript-3-5
ctx.source[key] = stateValue as any;
})
.register();


/* ====================================================================================================================================================== */

createStateChunkHandler('metaRow')
Expand Down
Loading

0 comments on commit 8f82092

Please sign in to comment.