-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add migration schematic for breaking changes
- Loading branch information
Showing
14 changed files
with
743 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Why is this needed | ||
|
||
May schematic utilities are deep imports, hence not part of [Angular's public API surface](https://github.com/angular/angular/blob/main/contributing-docs/public-api-surface.md) | ||
|
||
> A deep import is an import deeper than one of the package's entry point. For instance `@angular/core` is a regular import. But `@angular/core/src/utils` is a deep import. | ||
For instance: | ||
|
||
- `@schematics/angular/utility` | ||
- `@angular-devkit/core/src/utils` | ||
|
||
So the files needed from there are copy / pasted in here to avoid coupling to non-public APIs which can be dangerous (for instance breaking changes) | ||
|
||
Indeed, [some `@angular/core` schematic utils mysteriously disappeared in v15.1](https://stackoverflow.com/a/79123753/3263250) | ||
|
||
Existing `npm` libraries with exported utils aren't very popular or maintained at the moment of writing this. For instance: | ||
|
||
- [`schematics-utilities`](https://www.npmjs.com/package/schematics-utilities). Most popular one. Exports copy/pasted utils from Angular's schematics package and Angular Material package. [Latest release is from 2021 (3+ years ago)](https://github.com/nitayneeman/schematics-utilities/releases/tag/v2.0.3). [Depends on Angular v8 and Typescript v3](https://github.com/nitayneeman/schematics-utilities/blob/v2.0.3/package.json#L38-L41) | ||
- [`@hug/ngx-schematics-utilities`](https://www.npmjs.com/package/@hug/ngx-schematics-utilities). Modern schematics with a builder-like pattern. It's updated: [latest release was last month](https://github.com/DSI-HUG/ngx-schematics-utilities/releases/tag/10.1.4). [Depends with peer dependencies (yay!) on Angular > v17](https://github.com/DSI-HUG/ngx-schematics-utilities/blob/10.1.4/projects/lib/package.json#L53-L58). Not very popular though. So prefer copy/pasting for now. |
69 changes: 69 additions & 0 deletions
69
projects/ngx-meta/schematics/external-utils/angular-devkit/core/src/utils/strings.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,69 @@ | ||
// Partial extraction from | ||
// https://github.com/angular/angular-cli/blob/18.2.10/packages/angular_devkit/core/src/utils/strings.ts | ||
const STRING_CAMELIZE_REGEXP = /(-|_|\.|\s)+(.)?/g | ||
|
||
/** | ||
Returns the lowerCamelCase form of a string. | ||
```javascript | ||
camelize('innerHTML'); // 'innerHTML' | ||
camelize('action_name'); // 'actionName' | ||
camelize('css-class-name'); // 'cssClassName' | ||
camelize('my favorite items'); // 'myFavoriteItems' | ||
camelize('My Favorite Items'); // 'myFavoriteItems' | ||
``` | ||
@method camelize | ||
@param {String} str The string to camelize. | ||
@return {String} the camelized string. | ||
*/ | ||
export function camelize(str: string): string { | ||
return str | ||
.replace( | ||
STRING_CAMELIZE_REGEXP, | ||
(_match: string, _separator: string, chr: string) => { | ||
return chr ? chr.toUpperCase() : '' | ||
}, | ||
) | ||
.replace(/^([A-Z])/, (match: string) => match.toLowerCase()) | ||
} | ||
|
||
/** | ||
Returns the UpperCamelCase form of a string. | ||
@example | ||
```javascript | ||
'innerHTML'.classify(); // 'InnerHTML' | ||
'action_name'.classify(); // 'ActionName' | ||
'css-class-name'.classify(); // 'CssClassName' | ||
'my favorite items'.classify(); // 'MyFavoriteItems' | ||
'app.component'.classify(); // 'AppComponent' | ||
``` | ||
@method classify | ||
@param {String} str the string to classify | ||
@return {String} the classified string | ||
*/ | ||
export function classify(str: string): string { | ||
return str | ||
.split('.') | ||
.map((part) => capitalize(camelize(part))) | ||
.join('') | ||
} | ||
|
||
/** | ||
Returns the Capitalized form of a string | ||
```javascript | ||
'innerHTML'.capitalize() // 'InnerHTML' | ||
'action_name'.capitalize() // 'Action_name' | ||
'css-class-name'.capitalize() // 'Css-class-name' | ||
'my favorite items'.capitalize() // 'My favorite items' | ||
``` | ||
@method capitalize | ||
@param {String} str The string to capitalize. | ||
@return {String} The capitalized string. | ||
*/ | ||
export function capitalize(str: string): string { | ||
return str.charAt(0).toUpperCase() + str.slice(1) | ||
} |
114 changes: 114 additions & 0 deletions
114
projects/ngx-meta/schematics/external-utils/schematics/angular/utility/change.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,114 @@ | ||
// Partial extraction from | ||
// https://github.com/angular/angular-cli/blob/18.2.10/packages/schematics/angular/utility/change.ts | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.dev/license | ||
*/ | ||
|
||
import { UpdateRecorder } from '@angular-devkit/schematics' | ||
|
||
export interface Change { | ||
// The file this change should be applied to. Some changes might not apply to | ||
// a file (maybe the config). | ||
readonly path: string | null | ||
|
||
// The order this change should be applied. Normally the position inside the file. | ||
// Changes are applied from the bottom of a file to the top. | ||
readonly order: number | ||
|
||
// The description of this change. This will be outputted in a dry or verbose run. | ||
readonly description: string | ||
} | ||
|
||
/** | ||
* An operation that does nothing. | ||
*/ | ||
export class NoopChange implements Change { | ||
description = 'No operation.' | ||
order = Infinity | ||
path = null | ||
} | ||
|
||
/** | ||
* Will add text to the source code. | ||
*/ | ||
export class InsertChange implements Change { | ||
order: number | ||
description: string | ||
|
||
constructor( | ||
public path: string, | ||
public pos: number, | ||
public toAdd: string, | ||
) { | ||
if (pos < 0) { | ||
throw new Error('Negative positions are invalid') | ||
} | ||
this.description = `Inserted ${toAdd} into position ${pos} of ${path}` | ||
this.order = pos | ||
} | ||
} | ||
|
||
/** | ||
* Will remove text from the source code. | ||
*/ | ||
export class RemoveChange implements Change { | ||
order: number | ||
description: string | ||
|
||
constructor( | ||
public path: string, | ||
pos: number, | ||
public toRemove: string, | ||
) { | ||
if (pos < 0) { | ||
throw new Error('Negative positions are invalid') | ||
} | ||
this.description = `Removed ${toRemove} into position ${pos} of ${path}` | ||
this.order = pos | ||
} | ||
} | ||
|
||
/** | ||
* Will replace text from the source code. | ||
*/ | ||
export class ReplaceChange implements Change { | ||
order: number | ||
description: string | ||
|
||
constructor( | ||
public path: string, | ||
pos: number, | ||
public oldText: string, | ||
public newText: string, | ||
) { | ||
if (pos < 0) { | ||
throw new Error('Negative positions are invalid') | ||
} | ||
this.description = `Replaced ${oldText} into position ${pos} of ${path} with ${newText}` | ||
this.order = pos | ||
} | ||
} | ||
|
||
export function applyToUpdateRecorder( | ||
recorder: UpdateRecorder, | ||
changes: Change[], | ||
): void { | ||
for (const change of changes) { | ||
if (change instanceof InsertChange) { | ||
recorder.insertLeft(change.pos, change.toAdd) | ||
} else if (change instanceof RemoveChange) { | ||
recorder.remove(change.order, change.toRemove.length) | ||
} else if (change instanceof ReplaceChange) { | ||
recorder.remove(change.order, change.oldText.length) | ||
recorder.insertLeft(change.order, change.newText) | ||
} else if (!(change instanceof NoopChange)) { | ||
throw new Error( | ||
'Unknown Change type encountered when updating a recorder.', | ||
) | ||
} | ||
} | ||
} |
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,10 @@ | ||
{ | ||
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json", | ||
"schematics": { | ||
"tree-shakeable-manager-providers": { | ||
"version": "1.0.0-beta.31", | ||
"description": "Updates non tree-shakeable built-in metadata manager providers into tree-shakeable ones", | ||
"factory": "./migrations/tree-shakeable-manager-providers#migrate" | ||
} | ||
} | ||
} |
Oops, something went wrong.