Skip to content

Commit

Permalink
Merge pull request #7 from reduxjs/ng-add
Browse files Browse the repository at this point in the history
feat: Support `ng add`
  • Loading branch information
crutchcorn authored Sep 11, 2024
2 parents 01cf046 + 49aacb3 commit 4816f9b
Show file tree
Hide file tree
Showing 37 changed files with 3,594 additions and 14 deletions.
3 changes: 3 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
"test": {
"builder": "@angular-devkit/build-angular:jest",
"options": {
"exclude": [
"**/schematics/ng-add/*.spec.ts"
],
"tsConfig": "projects/angular-redux/tsconfig.spec.json",
"polyfills": [
"zone.js",
Expand Down
17 changes: 15 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"build": "ng build angular-redux && tsc -p projects/angular-redux/tsconfig.schematics.json && yarn build:copy",
"build:copy": "cd ./projects/angular-redux/schematics && copyfiles \"**/*.json\" ../../../dist/angular-redux/schematics",
"build:ng": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
"test": "yarn test:ng && yarn test:schematics",
"test:ng": "ng test",
"test:schematics": "cd projects/angular-redux/schematics && jest"
},
"workspaces": {
"packages": [
"projects/*"
]
},
"private": true,
"dependencies": {
Expand All @@ -32,12 +41,16 @@
"@testing-library/dom": "^10.0.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/user-event": "^14.5.2",
"@types/copyfiles": "^2",
"@types/jasmine": "~5.1.0",
"@types/jest": "^29.5.12",
"@types/node": "^22.5.4",
"copyfiles": "^2.4.1",
"jasmine-core": "~5.2.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"ng-packagr": "^18.2.0",
"ts-jest": "^29.2.5",
"typescript": "~5.5.2"
},
"packageManager": "[email protected]"
Expand Down
29 changes: 27 additions & 2 deletions projects/angular-redux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Official Angular bindings for [Redux](https://github.com/reduxjs/redux).
Performant and flexible.


![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/reduxjs/angular-redux/test.yml?style=flat-square) [![npm version](https://img.shields.io/npm/v/@reduxjs/angular-redux.svg?style=flat-square)](https://www.npmjs.com/package/@reduxjs/angular-redux)
[![npm downloads](https://img.shields.io/npm/dm/@reduxjs/angular-redux.svg?style=flat-square)](https://www.npmjs.com/package/@reduxjs/angular-redux)

Expand All @@ -14,6 +13,32 @@ Performant and flexible.

Angular Redux requires **Angular 17.3 or later**.

### Installing with `ng add`

You can install the Store to your project with the following `ng add` command <a href="https://angular.dev/cli/add" target="_blank">(details here)</a>:

```sh
ng add @reduxjs/angular-redux@latest
```

#### Optional `ng add` flags

| flag | description | value type | default value |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|---------------
| `--path` | Path to the module that you wish to add the import for the StoreModule to. | `string` |
| `--project` | Name of the project defined in your `angular.json` to help locating the module to add the `provideRedux` to. | `string` |
| `--module` | Name of file containing the module that you wish to add the import for the `provideRedux` to. Can also include the relative path to the file. For example, `src/app/app.module.ts`. | `string` | `app`
| `--storePath` | The file path to create the state in. | `string` | `store` |

This command will automate the following steps:

1. Update `package.json` > `dependencies` with Redux, Redux Toolkit, and Angular Redux
2. Run `npm install` to install those dependencies.
3. Update your `src/app/app.module.ts` > `imports` array with `provideRedux({store})`
4. If the project is using a `standalone bootstrap`, it adds `provideRedux({store})` into the application config.

## Installing with `npm` or `yarn`

To use React Redux with your Angular app, install it as a dependency:

```bash
Expand All @@ -35,7 +60,7 @@ modules](https://webpack.js.org/api/module-methods/#commonjs).

The following Angular component works as-expected:

```angular-ts
```typescript
import { Component } from '@angular/core'
import { injectSelector, injectDispatch } from "@reduxjs/angular-redux";
import { decrement, increment } from './store/counter-slice'
Expand Down
5 changes: 5 additions & 0 deletions projects/angular-redux/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
"peerDependencies": {
"@angular/common": ">=17.3.0",
"@angular/core": ">=17.3.0",
"@reduxjs/toolkit": "^2.2.7",
"redux": "^5.0.0"
},
"peerDependenciesMeta": {
"@reduxjs/toolkit": {
"optional": true
},
"redux": {
"optional": true
}
},
"schematics": "./schematics/collection.json",
"dependencies": {
"tslib": "^2.3.0"
},
Expand Down
4 changes: 4 additions & 0 deletions projects/angular-redux/schematics-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This code is originally from NgRx:

https://github.com/ngrx/platform/tree/main/modules/schematics-core
https://github.com/ngrx/platform/tree/main/modules/store/schematics-core
84 changes: 84 additions & 0 deletions projects/angular-redux/schematics-core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
dasherize,
decamelize,
camelize,
classify,
underscore,
group,
capitalize,
featurePath,
pluralize,
} from './utility/strings';

export {
findNodes,
getSourceNodes,
getDecoratorMetadata,
getContentOfKeyLiteral,
insertAfterLastOccurrence,
insertImport,
addBootstrapToModule,
addDeclarationToModule,
addExportToModule,
addImportToModule,
addProviderToComponent,
addProviderToModule,
replaceImport,
containsProperty,
} from './utility/ast-utils';

export {
NoopChange,
InsertChange,
RemoveChange,
ReplaceChange,
createReplaceChange,
createChangeRecorder,
commitChanges
} from './utility/change';
export type {
Host,
Change
} from './utility/change';

export {getWorkspace, getWorkspacePath} from './utility/config';
export type { AppConfig } from './utility/config';

export { findComponentFromOptions } from './utility/find-component';

export {
findModule,
findModuleFromOptions,
buildRelativePath
} from './utility/find-module';
export type { ModuleOptions } from './utility/find-module';

export { findPropertyInAstObject } from './utility/json-utilts';

export { getProjectPath, getProject, isLib } from './utility/project';

export const stringUtils = {
dasherize,
decamelize,
camelize,
classify,
underscore,
group,
capitalize,
featurePath,
pluralize,
};

export { parseName } from './utility/parse-name';

export { addPackageToPackageJson } from './utility/package';

export {
visitTSSourceFiles,
visitNgModuleImports,
visitNgModuleExports,
visitComponents,
visitDecorator,
visitNgModules,
visitTemplates,
} from './utility/visitors';
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { UnitTestTree } from '@angular-devkit/schematics/testing';

export function createAppModule(
tree: UnitTestTree,
path?: string
): UnitTestTree {
tree.create(
path || '/src/app/app.module.ts',
`
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
`
);

return tree;
}

export function createAppModuleWithEffects(
tree: UnitTestTree,
path: string,
effects?: string
): UnitTestTree {
tree.create(
path || '/src/app/app.module.ts',
`
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { EffectsModule } from '@ngrx/effects';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
${effects}
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
`
);

return tree;
}
26 changes: 26 additions & 0 deletions projects/angular-redux/schematics-core/testing/create-package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Tree } from '@angular-devkit/schematics';
import {
UnitTestTree,
SchematicTestRunner,
} from '@angular-devkit/schematics/testing';

export const packagePath = '/package.json';

export function createPackageJson(
prefix: string,
pkg: string,
tree: UnitTestTree,
version = '5.2.0',
packagePath = '/package.json'
) {
tree.create(
packagePath,
`{
"dependencies": {
"@ngrx/${pkg}": "${prefix}${version}"
}
}`
);

return tree;
}
34 changes: 34 additions & 0 deletions projects/angular-redux/schematics-core/testing/create-reducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { UnitTestTree } from '@angular-devkit/schematics/testing';

export function createReducers(
tree: UnitTestTree,
path?: string,
project = 'bar'
) {
tree.create(
path || `/projects/${project}/src/app/reducers/index.ts`,
`
import { isDevMode } from '@angular/core';
import {
ActionReducer,
ActionReducerMap,
createFeatureSelector,
createSelector,
MetaReducer
} from '@ngrx/${'store'}';
export interface State {
}
export const reducers: ActionReducerMap<State> = {
};
export const metaReducers: MetaReducer<State>[] = isDevMode() ? [] : [];
`
);

return tree;
}
69 changes: 69 additions & 0 deletions projects/angular-redux/schematics-core/testing/create-workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {
SchematicTestRunner,
UnitTestTree,
} from '@angular-devkit/schematics/testing';

export const defaultWorkspaceOptions = {
name: 'workspace',
newProjectRoot: 'projects',
version: '6.0.0',
};

export const defaultAppOptions = {
name: 'bar',
inlineStyle: false,
inlineTemplate: false,
viewEncapsulation: 'Emulated',
routing: false,
style: 'css',
skipTests: false,
standalone: false,
};

const defaultLibOptions = {
name: 'baz',
};

export function getTestProjectPath(
workspaceOptions: any = defaultWorkspaceOptions,
appOptions: any = defaultAppOptions
) {
return `/${workspaceOptions.newProjectRoot}/${appOptions.name}`;
}

export async function createWorkspace(
schematicRunner: SchematicTestRunner,
appTree: UnitTestTree,
workspaceOptions = defaultWorkspaceOptions,
appOptions = defaultAppOptions,
libOptions = defaultLibOptions
) {
appTree = await schematicRunner.runExternalSchematic(
'@schematics/angular',
'workspace',
workspaceOptions
);

appTree = await schematicRunner.runExternalSchematic(
'@schematics/angular',
'application',
appOptions,
appTree
);

appTree = await schematicRunner.runExternalSchematic(
'@schematics/angular',
'application',
{ ...appOptions, name: 'bar-standalone', standalone: true },
appTree
);

appTree = await schematicRunner.runExternalSchematic(
'@schematics/angular',
'library',
libOptions,
appTree
);

return appTree;
}
Loading

0 comments on commit 4816f9b

Please sign in to comment.