Skip to content

Commit

Permalink
feat(store): add standalone features
Browse files Browse the repository at this point in the history
  • Loading branch information
arturovt committed Apr 23, 2023
1 parent ccbb949 commit a1aa6db
Show file tree
Hide file tree
Showing 36 changed files with 765 additions and 298 deletions.
26 changes: 0 additions & 26 deletions integration/app/app-routing.module.ts

This file was deleted.

17 changes: 14 additions & 3 deletions integration/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { FormArray, FormBuilder, FormControl } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
import {
FormArray,
FormBuilder,
FormControl,
FormsModule,
ReactiveFormsModule
} from '@angular/forms';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { Store } from '@ngxs/store';
import { Observable } from 'rxjs';

Expand All @@ -11,7 +19,10 @@ import { Extras, Pizza, Todo } from '@integration/store/todos/todos.model';

@Component({
selector: 'app-root',
templateUrl: './app.component.html'
templateUrl: './app.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, RouterModule, FormsModule, ReactiveFormsModule]
})
export class AppComponent implements OnInit {
allExtras: Extras[] = [
Expand Down
23 changes: 0 additions & 23 deletions integration/app/app.module.ts

This file was deleted.

4 changes: 2 additions & 2 deletions integration/main.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ if (environment.production) {
enableProdMode();
}

export { AppServerModule } from './app/app.server.module';
export { renderModuleFactory } from '@angular/platform-server';
export { AppComponent } from './app/app.component';
export { APP_ID_VALUE, SHARED_PLATFORM_PROVIDERS } from './shared-platform-providers';
10 changes: 7 additions & 3 deletions integration/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { AppComponent } from './app/app.component';
import { SHARED_PLATFORM_PROVIDERS } from './shared-platform-providers';

if (environment.production) {
enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);
bootstrapApplication(AppComponent, {
providers: [provideAnimations(), ...SHARED_PLATFORM_PROVIDERS]
});
45 changes: 32 additions & 13 deletions integration/server.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
import 'zone.js/node';

import { readFile } from 'fs/promises';
import { join } from 'path';
import * as express from 'express';
import { Provider } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { renderApplication } from '@angular/platform-server';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import * as express from 'express';
import { existsSync } from 'fs';
import { join } from 'path';

import { AppServerModule } from './main.server';
import { AppComponent, APP_ID_VALUE, SHARED_PLATFORM_PROVIDERS } from './main.server';

interface RenderOptions {
req: express.Request;
providers: Provider[];
}

// The Express app is exported so that it can be used by serverless Functions.
export function app() {
const server = express();
const distFolder = join(process.cwd(), 'dist-integration');
const indexHtml = existsSync(join(distFolder, 'index.original.html'))
? 'index.original.html'
: 'index';
let indexHtmlContent: string | null = null;

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine(
'html',
ngExpressEngine({
bootstrap: AppServerModule
}) as any
async (
path: string,
options: object,
callback: (error: Error | null, content: string) => void
) => {
const { req, providers } = options as RenderOptions;

indexHtmlContent ||= await readFile(path, { encoding: 'utf-8' });

const html = await renderApplication(AppComponent, {
providers,
appId: APP_ID_VALUE,
document: indexHtmlContent,
url: `${req.baseUrl}${req.url}`
});

callback(null, html);
}
);

server.set('view engine', 'html');
Expand All @@ -40,9 +58,10 @@ export function app() {

// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, {
res.render('index', {
req,
providers: [
...SHARED_PLATFORM_PROVIDERS,
{ provide: APP_BASE_HREF, useValue: req.baseUrl },
{ provide: REQUEST, useValue: req },
{ provide: RESPONSE, useValue: res }
Expand Down
50 changes: 50 additions & 0 deletions integration/shared-platform-providers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { APP_ID } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideStore, withNgxsOptions } from '@ngxs/store';
import { withNgxsFormPlugin } from '@ngxs/form-plugin';
import { withNgxsLoggerPlugin } from '@ngxs/logger-plugin';
import { withNgxsReduxDevtoolsPlugin } from '@ngxs/devtools-plugin';
import { withNgxsRouterPlugin } from '@ngxs/router-plugin';
import { withNgxsStoragePlugin } from '@ngxs/storage-plugin';

import { TodosState } from '@integration/store/todos/todos.state';
import { TodoState } from '@integration/store/todos/todo/todo.state';
import { TODOS_STORAGE_KEY } from '@integration/store/todos/todos.model';

import { environment } from './environments/environment';

export const APP_ID_VALUE = 'integration-app';

export const SHARED_PLATFORM_PROVIDERS = [
{ provide: APP_ID, useValue: APP_ID_VALUE },

provideRouter([
{ path: '', pathMatch: 'full', redirectTo: '/list' },
{
path: 'list',
loadChildren: () => import('@integration/list/list.module').then(m => m.ListModule)
},
{
path: 'detail',
loadChildren: () => import('@integration/detail/detail.module').then(m => m.DetailModule)
},
{
path: 'counter',
loadChildren: () =>
import('@integration/counter/counter.module').then(m => m.CounterModule)
}
]),

provideStore(
[TodosState, TodoState],
withNgxsOptions({
developmentMode: !environment.production,
selectorOptions: {}
}),
withNgxsFormPlugin(),
withNgxsLoggerPlugin({ logger: console, collapsed: false, disabled: true }),
withNgxsReduxDevtoolsPlugin({ disabled: environment.production }),
withNgxsRouterPlugin(),
withNgxsStoragePlugin({ key: [TODOS_STORAGE_KEY] })
)
];
1 change: 1 addition & 0 deletions integration/tsconfig.editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "./tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"module": "esnext",
"types": ["jest", "node"]
}
}
3 changes: 2 additions & 1 deletion integration/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": false
},
"angularCompilerOptions": {
"strictInjectionParameters": true,
Expand Down
17 changes: 16 additions & 1 deletion packages/devtools-plugin/src/devtools.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NgModule, ModuleWithProviders, InjectionToken } from '@angular/core';
import { NGXS_PLUGINS } from '@ngxs/store';
import { NGXS_PLUGINS, NgxsStoreFeature, withNgxsPlugin } from '@ngxs/store';

import { NgxsDevtoolsOptions, NGXS_DEVTOOLS_OPTIONS } from './symbols';
import { NgxsReduxDevtoolsPlugin } from './devtools.plugin';
Expand Down Expand Up @@ -39,3 +39,18 @@ export class NgxsReduxDevtoolsPluginModule {
};
}
}

export function withNgxsReduxDevtoolsPlugin(options?: NgxsDevtoolsOptions): NgxsStoreFeature {
return [
withNgxsPlugin(NgxsReduxDevtoolsPlugin),
{
provide: USER_OPTIONS,
useValue: options
},
{
provide: NGXS_DEVTOOLS_OPTIONS,
useFactory: devtoolsOptionsFactory,
deps: [USER_OPTIONS]
}
];
}
2 changes: 1 addition & 1 deletion packages/devtools-plugin/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { NgxsReduxDevtoolsPluginModule } from './devtools.module';
export { NgxsReduxDevtoolsPluginModule, withNgxsReduxDevtoolsPlugin } from './devtools.module';
export { NgxsReduxDevtoolsPlugin } from './devtools.plugin';
export * from './symbols';
9 changes: 7 additions & 2 deletions packages/form-plugin/src/form.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { NGXS_PLUGINS } from '@ngxs/store';
import { NgxsFormPlugin } from './form.plugin';
import { ReactiveFormsModule } from '@angular/forms';
import { NGXS_PLUGINS, NgxsStoreFeature, withNgxsPlugin } from '@ngxs/store';

import { NgxsFormPlugin } from './form.plugin';
import { FormDirective } from './directive';

@NgModule({
Expand All @@ -23,3 +24,7 @@ export class NgxsFormPluginModule {
};
}
}

export function withNgxsFormPlugin(): NgxsStoreFeature {
return [withNgxsPlugin(NgxsFormPlugin)];
}
2 changes: 1 addition & 1 deletion packages/form-plugin/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { NgxsFormPluginModule } from './form.module';
export { NgxsFormPluginModule, withNgxsFormPlugin } from './form.module';
export { NgxsFormPlugin } from './form.plugin';
export { FormDirective as ɵFormDirective } from './directive';
export * from './actions';
14 changes: 13 additions & 1 deletion packages/logger-plugin/src/logger.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core';
import { NGXS_PLUGINS } from '@ngxs/store';
import { NGXS_PLUGINS, withNgxsPlugin, NgxsStoreFeature } from '@ngxs/store';
import { NgxsLoggerPlugin } from './logger.plugin';
import { NgxsLoggerPluginOptions, NGXS_LOGGER_PLUGIN_OPTIONS } from './symbols';

Expand Down Expand Up @@ -45,3 +45,15 @@ export class NgxsLoggerPluginModule {
};
}
}

export function withNgxsLoggerPlugin(options?: NgxsLoggerPluginOptions): NgxsStoreFeature {
return [
withNgxsPlugin(NgxsLoggerPlugin),
{ provide: USER_OPTIONS, useValue: options },
{
provide: NGXS_LOGGER_PLUGIN_OPTIONS,
useFactory: loggerOptionsFactory,
deps: [USER_OPTIONS]
}
];
}
2 changes: 1 addition & 1 deletion packages/logger-plugin/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { NgxsLoggerPluginModule } from './logger.module';
export { NgxsLoggerPluginModule, withNgxsLoggerPlugin } from './logger.module';
export { NgxsLoggerPlugin } from './logger.plugin';
export * from './symbols';
16 changes: 6 additions & 10 deletions packages/logger-plugin/tests/helpers/setup-with-logger.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { ErrorHandler } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { NgxsModule, Store } from '@ngxs/store';
import { Store, provideStore } from '@ngxs/store';
import { StateClass } from '@ngxs/store/internals';
import { NgxsLoggerPluginOptions, withNgxsLoggerPlugin } from '@ngxs/logger-plugin';

import { LoggerSpy } from './logger-spy';
import { NoopErrorHandler } from '../../../store/tests/helpers/utils';
import { NgxsLoggerPluginModule, NgxsLoggerPluginOptions } from '../../';

export function setupWithLogger(states: StateClass[], opts?: NgxsLoggerPluginOptions) {
const logger = new LoggerSpy();

TestBed.configureTestingModule({
imports: [
NgxsModule.forRoot(states),
NgxsLoggerPluginModule.forRoot({
...opts,
logger
})
],
providers: [{ provide: ErrorHandler, useClass: NoopErrorHandler }]
providers: [
provideStore(states, withNgxsLoggerPlugin({ ...opts, logger })),
{ provide: ErrorHandler, useClass: NoopErrorHandler }
]
});

const store: Store = TestBed.inject(Store);
Expand Down
2 changes: 1 addition & 1 deletion packages/router-plugin/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { NgxsRouterPluginModule } from './router.module';
export { NgxsRouterPluginModule, withNgxsRouterPlugin } from './router.module';
export { RouterState, RouterStateModel } from './router.state';
export {
RouterStateSerializer,
Expand Down
15 changes: 14 additions & 1 deletion packages/router-plugin/src/router.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { NgxsModule } from '@ngxs/store';
import { NgxsModule, NgxsStoreFeature, provideFeatureStore } from '@ngxs/store';

import { RouterState } from './router.state';
import { DefaultRouterStateSerializer, RouterStateSerializer } from './serializer';
Expand Down Expand Up @@ -31,3 +31,16 @@ export class NgxsRouterPluginModule {
};
}
}

export function withNgxsRouterPlugin(options?: NgxsRouterPluginOptions): NgxsStoreFeature {
return [
provideFeatureStore([RouterState]),
{ provide: USER_OPTIONS, useValue: options },
{
provide: NGXS_ROUTER_PLUGIN_OPTIONS,
useFactory: createRouterPluginOptions,
deps: [USER_OPTIONS]
},
{ provide: RouterStateSerializer, useClass: DefaultRouterStateSerializer }
];
}
2 changes: 1 addition & 1 deletion packages/storage-plugin/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { NgxsStoragePluginModule } from './storage.module';
export { NgxsStoragePluginModule, withNgxsStoragePlugin } from './storage.module';
export { NgxsStoragePlugin } from './storage.plugin';
export * from './symbols';
export * from './engines';
Loading

0 comments on commit a1aa6db

Please sign in to comment.