Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -83,4 +83,9 @@ migrations.json
.nx/**

vite.config.*.timestamp*
vitest.config.*.timestamp*
vitest.config.*.timestamp*

# www reference files
projects/www/src/app/reference/**/*.json
.nx/cache
.nx/workspace-data
81 changes: 81 additions & 0 deletions migrate-content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const glob = require('fast-glob');
const { resolve, relative, join } = require('path');
const fs = require('fs').promises;

async function processMarkdownFiles(globPattern) {
try {
const files = await new Promise((resolve, reject) => {
const matches = glob.sync([globPattern]);
resolve(matches);
});
// console.log(files.length);

for (const filename of files) {
try {
const content = await fs.readFile(filename, 'utf8');
// Regex to match the opening tag and capture anything inside it
const updatedContent = content
.replace(/(<div class="alert is-helpful[^>]*>)([\s\S]*?)(<\/div>)/gs, (match, openingTagContent, innerContent) => {
return `<ngrx-docs-alert type="help">${innerContent}</ngrx-docs-alert>`
})
.replace(/(<div class="alert is-critical[^>]*>)([\s\S]*?)(<\/div>)/gs, (match, openingTagContent, innerContent) => {
return `<ngrx-docs-alert type="error">${innerContent}</ngrx-docs-alert>`
})
.replace(/(<div class="alert is-important[^>]*>)([\s\S]*?)(<\/div>)/gs, (match, openingTagContent, innerContent) => {
return `<ngrx-docs-alert type="inform">${innerContent}</ngrx-docs-alert>`
})
.replace(
/<code-example\s*([^>]*)>(.*?)<\/code-example>/gms,
(match, openingTagContent, innerContent) => {
if (innerContent.length === 0) {
// console.log('no content', openingTagContent, filename);
}

// console.log(`Found content in opening tag: ${openingTagContent} in: ${filename}`);
return '<ngrx-code-example ' + openingTagContent + '>\n\n```ts' + innerContent + '```\n\n</ngrx-code-example>';
}
).replaceAll('&gt;', '>').replaceAll('&lt;', '<')
.replaceAll(`
\`\`\`ts
\`\`\`

`, '')

if (updatedContent.includes('class="alert') && filename.includes('runtime')) {
console.log('updated alert', filename);
}

// .replace(/<div class="alert is-important">(\n*.*\n*.*)<\/div>/gs, (match, openingTagContent, innerContent) => {
// return `<ngrx-docs-alert type="inform">${openingTagContent}</ngrx-docs-alert>`
// });
// if (filename.includes('testing.md')) {
// console.log(updatedContent);
// }
// console.log('new file', join(`/Users/robertsbt/projects/ngrx/platform/projects/www/src/app/pages`, relative(`${process.cwd()}/projects/ngrx.io/content`, filename)));
// if (updatedContent !== content) {
await fs.writeFile(join(`${process.cwd()}/projects/www/src/app/pages`, relative(`${process.cwd()}/projects/ngrx.io/content`, filename)), updatedContent, 'utf8');
// console.log(`Processed and updated: ${join(`/Users/robertsbt/projects/ngrx/platform/projects/www/src/app/pages`, relative(`${process.cwd()}/projects/ngrx.io/content`, filename))}`);
// } else {
// console.log(`No changes in: ${filename}`);
// }
} catch (error) {
console.error(`Error processing file ${filename}:`, error);
}
}

console.log('Finished processing markdown files.');
} catch (error) {
console.error('Error during file globbing:', error);
}
}

// Example usage: Process all .md files in the current directory
const markdownGlob = process.cwd() + '/projects/ngrx.io/content/guide/**/*.md';
console.log(`Looking for markdown files matching: ${markdownGlob}`);
processMarkdownFiles(markdownGlob);

// You can also specify a different glob pattern, for example:
// processMarkdownFiles('docs/**/*.md'); // Process all .md files in the 'docs' directory and its subdirectories

//<div class="alert is-helpful">(\n*.*\n*.*)</div>
//<ngrx-docs-alert type="help">$1</ngrx-alert>
14 changes: 13 additions & 1 deletion modules/signals/project.json
Original file line number Diff line number Diff line change
@@ -25,12 +25,24 @@
{
"command": "pnpm exec tsc -p modules/signals/tsconfig.schematics.json"
},
{
"command": "pnpm exec rimraf node_modules/@ngrx/signals"
},
{
"command": "pnpm exec mkdirp node_modules/@ngrx/signals"
},
{
"command": "ncp dist/modules/signals node_modules/@ngrx/signals"
},
{
"command": "cpy LICENSE dist/modules/signals"
}
]
},
"outputs": ["{workspaceRoot}/dist/modules/signals"]
"outputs": [
"{workspaceRoot}/dist/modules/signals",
"{workspaceRoot}/node_modules/@ngrx/signals"
]
},
"lint": {
"executor": "@nx/eslint:lint",
77 changes: 77 additions & 0 deletions modules/store/src/action_creator.ts
Original file line number Diff line number Diff line change
@@ -12,9 +12,86 @@ import { REGISTERED_ACTION_TYPES } from './globals';
// Action creators taken from ts-action library and modified a bit to better
// fit current NgRx usage. Thank you Nicholas Jamieson (@cartant).

/**
* @description
* Creates a configured `Creator` function that, when called, returns an object in the shape of the
* `Action` interface with no additional metadata.
*
* @param type Describes the action that will be dispatched
*
* @usageNotes
*
* Declaring an action creator:
*
* ```ts
* export const increment = createAction('[Counter] Increment');
* ```
*
* Dispatching an action:
*
* ```ts
* store.dispatch(increment());
* ```
*
* Referencing the action in a reducer:
*
* ```ts
* on(CounterActions.increment, (state) => ({ ...state, count: state.count + 1 }))
* ```
*
* Referencing the action in an effect:
* ```ts
* effectName$ = createEffect(
* () => this.actions$.pipe(
* ofType(CounterActions.increment),
* // ...
* )
* );
* ```
*/
export function createAction<T extends string>(
type: T
): ActionCreator<T, () => Action<T>>;
/**
* @description
* Creates a configured `Creator` function that, when called, returns an object in the shape of the
* `Action` interface with metadata provided by the `props` or `emptyProps` functions.
*
* @param type Describes the action that will be dispatched
*
* @usageNotes
*
* Declaring an action creator:
*
* ```ts
* export const loginSuccess = createAction(
* '[Auth/API] Login Success',
* props<{ user: User }>()
* );
* ```
*
* Dispatching an action:
*
* ```ts
* store.dispatch(loginSuccess({ user: newUser }));
* ```
*
* Referencing the action in a reducer:
*
* ```ts
* on(AuthApiActions.loginSuccess, (state, { user }) => ({ ...state, user }))
* ```
*
* Referencing the action in an effect:
* ```ts
* effectName$ = createEffect(
* () => this.actions$.pipe(
* ofType(AuthApiActions.loginSuccess),
* // ...
* )
* );
* ```
*/
export function createAction<T extends string, P extends object>(
type: T,
config: ActionCreatorProps<P> & NotAllowedCheck<P>
71 changes: 71 additions & 0 deletions modules/store/src/store.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,37 @@ import { StateObservable } from './state';
import { assertDefined } from './helpers';

@Injectable()
/**
* @description
* Store is an injectable service that provides reactive state management and a public API for dispatching actions.
*
* @usageNotes
*
* In a component:
*
* ```ts
* import { Component, inject } from '@angular/core';
* import { Store } from '@ngrx/store';
*
* @Component({
* selector: 'app-my-component',
* template: `
* <div>{{ count() }}</div>
* <button (click)="increment()">Increment</button>
* `
* })
* export class MyComponent {
* private store = inject(Store);
*
* count = this.store.selectSignal(state => state.count);
*
* increment() {
* this.store.dispatch({ type: 'INCREMENT' });
* }
* }
* ```
*
*/
export class Store<T = object>
extends Observable<T>
implements Observer<Action>
@@ -54,29 +85,47 @@ export class Store<T = object>
mapFn: (state: T, props: Props) => K,
props: Props
): Observable<K>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<a extends keyof T>(key: a): Observable<T[a]>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<a extends keyof T, b extends keyof T[a]>(
key1: a,
key2: b
): Observable<T[a][b]>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<a extends keyof T, b extends keyof T[a], c extends keyof T[a][b]>(
key1: a,
key2: b,
key3: c
): Observable<T[a][b][c]>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<
a extends keyof T,
b extends keyof T[a],
c extends keyof T[a][b],
d extends keyof T[a][b][c]
>(key1: a, key2: b, key3: c, key4: d): Observable<T[a][b][c][d]>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<
a extends keyof T,
b extends keyof T[a],
c extends keyof T[a][b],
d extends keyof T[a][b][c],
e extends keyof T[a][b][c][d]
>(key1: a, key2: b, key3: c, key4: d, key5: e): Observable<T[a][b][c][d][e]>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<
a extends keyof T,
b extends keyof T[a],
@@ -92,6 +141,9 @@ export class Store<T = object>
key5: e,
key6: f
): Observable<T[a][b][c][d][e][f]>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<
a extends keyof T,
b extends keyof T[a],
@@ -109,6 +161,9 @@ export class Store<T = object>
key6: f,
...paths: string[]
): Observable<K>;
/**
* @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}
*/
select<Props = any, K = any>(
pathOrMapFn: ((state: T, props?: Props) => K) | string,
...paths: string[]
@@ -121,6 +176,22 @@ export class Store<T = object>
*
* @param selector selector function
* @param options select signal options
* @returns Signal of the state selected by the provided selector
* @usageNotes
*
* ```ts
* const count = this.store.selectSignal(state => state.count);
* ```
*
* Or with a selector created by @ngrx/store!createSelector:function
*
* ```ts
* const selectCount = createSelector(
* (state: State) => state.count,
* );
*
* const count = this.store.selectSignal(selectCount);
* ```
*/
selectSignal<K>(
selector: (state: T) => K,
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.