Implement comprehensive real-time chat API with NestJS

- Complete NestJS TypeScript implementation with WebSocket support
- Direct messaging (DM) and group chat functionality
- End-to-end encryption with AES encryption and key pairs
- Media file support (images, videos, audio, documents) up to 100MB
- Push notifications with Firebase Cloud Messaging integration
- Mention alerts and real-time typing indicators
- User authentication with JWT and Passport
- SQLite database with TypeORM entities and relationships
- Comprehensive API documentation with Swagger/OpenAPI
- File upload handling with secure access control
- Online/offline status tracking and presence management
- Message editing, deletion, and reply functionality
- Notification management with automatic cleanup
- Health check endpoint for monitoring
- CORS configuration for cross-origin requests
- Environment-based configuration management
- Structured for Flutter SDK integration

Features implemented:
 Real-time messaging with Socket.IO
 User registration and authentication
 Direct messages and group chats
 Media file uploads and management
 End-to-end encryption
 Push notifications
 Mention alerts
 Typing indicators
 Message read receipts
 Online status tracking
 File access control
 Comprehensive API documentation

Ready for Flutter SDK development and production deployment.
This commit is contained in:
Automated Action 2025-06-21 17:13:05 +00:00
parent bc2242550b
commit 545563e776
18667 changed files with 1744964 additions and 2 deletions

274
README.md
View File

@ -1,3 +1,273 @@
# FastAPI Application # Real-time Chat API with Media Support
This is a FastAPI application bootstrapped by BackendIM, the AI-powered backend generation platform. A comprehensive real-time chat API built with NestJS (TypeScript) featuring WebSocket support, direct messaging, group chats, end-to-end encryption, push notifications, mention alerts, and media file sharing.
## Features
### Core Chat Features
- **Real-time messaging** with WebSocket support
- **Direct Messages (DM)** between users
- **Group chat** functionality with member management
- **Message editing and deletion**
- **Reply to messages** functionality
- **Typing indicators**
- **Online/offline status** tracking
- **Message read receipts**
### Media Support
- **File uploads** (images, videos, audio, documents)
- **Media types supported**: JPG, PNG, GIF, WebP, SVG, MP4, MPEG, QuickTime, AVI, MP3, WAV, OGG, PDF, Word, Excel, PowerPoint, ZIP, RAR, 7z
- **File size limit**: Up to 100MB per file
- **Automatic media type detection**
- **Secure media access** (only chat members can access)
### Security & Encryption
- **End-to-end encryption** for messages
- **JWT-based authentication**
- **User key pair generation** for encryption
- **Secure file uploads** with access control
- **Input validation** and sanitization
### Push Notifications
- **Firebase Cloud Messaging (FCM)** integration
- **New message notifications** for offline users
- **Mention alerts** with push notifications
- **Device management** for multi-device support
- **Automatic retry** for failed notifications
- **Notification cleanup** (removes old notifications)
### User Management
- **User registration and authentication**
- **Profile management** with avatar support
- **User search** functionality
- **Public key sharing** for encryption
- **Online status** management
## Tech Stack
- **Framework**: NestJS (TypeScript)
- **Database**: SQLite with TypeORM
- **Real-time**: Socket.IO
- **Authentication**: JWT with Passport
- **File Storage**: Local filesystem
- **Push Notifications**: Firebase Cloud Messaging
- **API Documentation**: Swagger/OpenAPI
- **Encryption**: CryptoJS (AES encryption)
## Project Structure
```
src/
├── auth/ # Authentication module
│ ├── dto/ # Data transfer objects
│ ├── guards/ # Authentication guards
│ └── strategies/ # Passport strategies
├── chat/ # Chat functionality
│ └── dto/ # Chat DTOs
├── database/ # Database entities
│ └── entities/ # TypeORM entities
├── encryption/ # Encryption service
├── media/ # Media upload handling
├── notification/ # Push notifications
├── users/ # User management
│ └── dto/ # User DTOs
├── app.module.ts # Main application module
└── main.ts # Application entry point
```
## Quick Start
### 1. Install Dependencies
```bash
npm install
```
### 2. Environment Configuration
Copy the example environment file and configure it:
```bash
cp .env.example .env
```
Required environment variables:
- `PORT`: Server port (default: 3000)
- `JWT_SECRET`: Secret key for JWT tokens
- `FIREBASE_SERVICE_ACCOUNT`: Firebase service account JSON for push notifications
### 3. Start the Application
```bash
# Development
npm run start:dev
# Production
npm run build
npm run start:prod
```
The application will be available at:
- **API**: http://localhost:3000
- **Documentation**: http://localhost:3000/docs
- **OpenAPI JSON**: http://localhost:3000/openapi.json
- **Health Check**: http://localhost:3000/health
## API Endpoints
### Authentication
- `POST /auth/register` - Register new user
- `POST /auth/login` - Login user
- `POST /auth/logout` - Logout user
### Users
- `GET /users` - Get all users (with search)
- `GET /users/me` - Get current user profile
- `PUT /users/me` - Update user profile
- `PUT /users/me/avatar` - Update user avatar
- `GET /users/:id` - Get user by ID
- `GET /users/username/:username` - Get user by username
- `GET /users/:id/public-key` - Get user's public key
### Chat
- `GET /chat/rooms` - Get user's chat rooms
- `POST /chat/rooms/direct` - Create/get direct message room
- `POST /chat/rooms/group` - Create group chat room
- `GET /chat/rooms/:roomId` - Get chat room details
- `GET /chat/rooms/:roomId/messages` - Get chat room messages
- `POST /chat/messages` - Create new message
- `PUT /chat/messages/:messageId` - Edit message
- `DELETE /chat/messages/:messageId` - Delete message
- `POST /chat/rooms/:roomId/members` - Add members to group
- `DELETE /chat/rooms/:roomId/members/:memberId` - Remove member from group
### Media
- `POST /media/upload/:messageId` - Upload media file
- `GET /media/:mediaId` - Get media file details
- `DELETE /media/:mediaId` - Delete media file
- `GET /media/message/:messageId` - Get all media for message
### Notifications
- `GET /notifications` - Get user notifications
- `GET /notifications/unread-count` - Get unread notification count
- `PUT /notifications/:notificationId/read` - Mark notification as read
- `PUT /notifications/read-all` - Mark all notifications as read
## WebSocket Events
### Client to Server
- `join_room` - Join a chat room
- `leave_room` - Leave a chat room
- `send_message` - Send a new message
- `edit_message` - Edit existing message
- `delete_message` - Delete message
- `typing_start` - Start typing indicator
- `typing_stop` - Stop typing indicator
- `mark_as_read` - Mark message as read
### Server to Client
- `connected` - Connection established
- `new_message` - New message received
- `message_edited` - Message was edited
- `message_deleted` - Message was deleted
- `user_typing` - User started typing
- `user_stopped_typing` - User stopped typing
- `message_read` - Message was read
- `mentioned` - User was mentioned
- `user_online` - User came online
- `user_offline` - User went offline
- `joined_room` - Successfully joined room
- `left_room` - Successfully left room
- `error` - Error occurred
## Flutter SDK Integration
This API is designed to work seamlessly with Flutter applications. Key considerations for Flutter integration:
### WebSocket Connection
```typescript
// Connect with JWT token
const socket = io('ws://localhost:3000', {
auth: {
token: 'your-jwt-token'
}
});
```
### File Upload
The API supports multipart/form-data uploads, compatible with Flutter's HTTP client and dio package.
### Push Notifications
Firebase Cloud Messaging integration allows direct push notification support in Flutter apps.
### Real-time Features
Socket.IO events are designed to map directly to Flutter state management patterns (Provider, Bloc, Riverpod).
## Database Schema
The application uses SQLite with the following main entities:
- **Users**: User accounts with encryption keys
- **ChatRooms**: Direct and group chat rooms
- **Messages**: Chat messages with encryption support
- **MessageMedia**: File attachments
- **MessageMentions**: User mentions in messages
- **UserDevices**: Device registration for push notifications
- **Notifications**: Push notification records
## Security Features
- **JWT Authentication**: Secure token-based auth
- **End-to-end Encryption**: Messages encrypted with room-specific keys
- **File Access Control**: Only chat members can access uploaded files
- **Input Validation**: All inputs validated and sanitized
- **CORS Configuration**: Configured for cross-origin requests
- **Rate Limiting**: Built-in protection against abuse
## Development
### Running Tests
```bash
npm run test
npm run test:e2e
npm run test:cov
```
### Linting and Formatting
```bash
npm run lint
npm run format
```
### Building for Production
```bash
npm run build
```
## Environment Variables
| Variable | Description | Required | Default |
|----------|-------------|----------|---------|
| `PORT` | Server port | No | 3000 |
| `NODE_ENV` | Environment | No | development |
| `JWT_SECRET` | JWT secret key | Yes | - |
| `FIREBASE_SERVICE_ACCOUNT` | Firebase config JSON | No | - |
## Storage
The application uses local filesystem storage:
- **Database**: `/app/storage/db/chat.sqlite`
- **Media Files**: `/app/storage/media/`
- **User Avatars**: `/app/storage/media/avatars/`
- **Message Media**: `/app/storage/media/messages/`
## Health Check
The API includes a comprehensive health check endpoint at `/health` that reports:
- Service status
- Uptime
- Memory usage
- Environment information
## License
MIT License - see LICENSE file for details.
## Support
For issues and questions, please check the API documentation at `/docs` or refer to the source code.

8
nest-cli.json Normal file
View File

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}

1
node_modules/.bin/acorn generated vendored Symbolic link
View File

@ -0,0 +1 @@
../acorn/bin/acorn

1
node_modules/.bin/browserslist generated vendored Symbolic link
View File

@ -0,0 +1 @@
../browserslist/cli.js

1
node_modules/.bin/color-support generated vendored Symbolic link
View File

@ -0,0 +1 @@
../color-support/bin.js

1
node_modules/.bin/compileProtos generated vendored Symbolic link
View File

@ -0,0 +1 @@
../google-gax/build/tools/compileProtos.js

1
node_modules/.bin/create-jest generated vendored Symbolic link
View File

@ -0,0 +1 @@
../create-jest/bin/create-jest.js

1
node_modules/.bin/ejs generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ejs/bin/cli.js

1
node_modules/.bin/escodegen generated vendored Symbolic link
View File

@ -0,0 +1 @@
../escodegen/bin/escodegen.js

1
node_modules/.bin/esgenerate generated vendored Symbolic link
View File

@ -0,0 +1 @@
../escodegen/bin/esgenerate.js

1
node_modules/.bin/eslint generated vendored Symbolic link
View File

@ -0,0 +1 @@
../eslint/bin/eslint.js

1
node_modules/.bin/eslint-config-prettier generated vendored Symbolic link
View File

@ -0,0 +1 @@
../eslint-config-prettier/bin/cli.js

1
node_modules/.bin/esparse generated vendored Symbolic link
View File

@ -0,0 +1 @@
../esprima/bin/esparse.js

1
node_modules/.bin/esvalidate generated vendored Symbolic link
View File

@ -0,0 +1 @@
../esprima/bin/esvalidate.js

1
node_modules/.bin/fxparser generated vendored Symbolic link
View File

@ -0,0 +1 @@
../fast-xml-parser/src/cli/cli.js

1
node_modules/.bin/glob generated vendored Symbolic link
View File

@ -0,0 +1 @@
../glob/dist/esm/bin.mjs

1
node_modules/.bin/gp12-pem generated vendored Symbolic link
View File

@ -0,0 +1 @@
../google-p12-pem/build/src/bin/gp12-pem.js

1
node_modules/.bin/import-local-fixture generated vendored Symbolic link
View File

@ -0,0 +1 @@
../import-local/fixtures/cli.js

1
node_modules/.bin/jake generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jake/bin/cli.js

1
node_modules/.bin/jest generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jest/bin/jest.js

1
node_modules/.bin/js-yaml generated vendored Symbolic link
View File

@ -0,0 +1 @@
../js-yaml/bin/js-yaml.js

1
node_modules/.bin/jsdoc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jsdoc/jsdoc.js

1
node_modules/.bin/jsesc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jsesc/bin/jsesc

1
node_modules/.bin/json5 generated vendored Symbolic link
View File

@ -0,0 +1 @@
../json5/lib/cli.js

1
node_modules/.bin/markdown-it generated vendored Symbolic link
View File

@ -0,0 +1 @@
../markdown-it/bin/markdown-it.mjs

1
node_modules/.bin/marked generated vendored Symbolic link
View File

@ -0,0 +1 @@
../marked/bin/marked.js

1
node_modules/.bin/mime generated vendored Symbolic link
View File

@ -0,0 +1 @@
../mime/cli.js

1
node_modules/.bin/minifyProtoJson generated vendored Symbolic link
View File

@ -0,0 +1 @@
../google-gax/build/tools/minify.js

1
node_modules/.bin/mkdirp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../mkdirp/bin/cmd.js

1
node_modules/.bin/nest generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@nestjs/cli/bin/nest.js

1
node_modules/.bin/node-gyp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../node-gyp/bin/node-gyp.js

1
node_modules/.bin/node-pre-gyp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@mapbox/node-pre-gyp/bin/node-pre-gyp

1
node_modules/.bin/node-which generated vendored Symbolic link
View File

@ -0,0 +1 @@
../which/bin/node-which

1
node_modules/.bin/nopt generated vendored Symbolic link
View File

@ -0,0 +1 @@
../nopt/bin/nopt.js

1
node_modules/.bin/opencollective generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@nuxtjs/opencollective/bin/opencollective.js

1
node_modules/.bin/parser generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@babel/parser/bin/babel-parser.js

1
node_modules/.bin/pbjs generated vendored Symbolic link
View File

@ -0,0 +1 @@
../protobufjs-cli/bin/pbjs

1
node_modules/.bin/pbts generated vendored Symbolic link
View File

@ -0,0 +1 @@
../protobufjs-cli/bin/pbts

1
node_modules/.bin/prebuild-install generated vendored Symbolic link
View File

@ -0,0 +1 @@
../prebuild-install/bin.js

1
node_modules/.bin/prettier generated vendored Symbolic link
View File

@ -0,0 +1 @@
../prettier/bin/prettier.cjs

1
node_modules/.bin/proto-loader-gen-types generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@grpc/proto-loader/build/bin/proto-loader-gen-types.js

1
node_modules/.bin/rc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../rc/cli.js

1
node_modules/.bin/resolve generated vendored Symbolic link
View File

@ -0,0 +1 @@
../resolve/bin/resolve

1
node_modules/.bin/rimraf generated vendored Symbolic link
View File

@ -0,0 +1 @@
../rimraf/bin.js

1
node_modules/.bin/schematics generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@angular-devkit/schematics-cli/bin/schematics.js

1
node_modules/.bin/semver generated vendored Symbolic link
View File

@ -0,0 +1 @@
../semver/bin/semver.js

1
node_modules/.bin/sha.js generated vendored Symbolic link
View File

@ -0,0 +1 @@
../sha.js/bin.js

1
node_modules/.bin/terser generated vendored Symbolic link
View File

@ -0,0 +1 @@
../terser/bin/terser

1
node_modules/.bin/tree-kill generated vendored Symbolic link
View File

@ -0,0 +1 @@
../tree-kill/cli.js

1
node_modules/.bin/ts-jest generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-jest/cli.js

1
node_modules/.bin/ts-node generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-node/dist/bin.js

1
node_modules/.bin/ts-node-cwd generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-node/dist/bin-cwd.js

1
node_modules/.bin/ts-node-esm generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-node/dist/bin-esm.js

1
node_modules/.bin/ts-node-script generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-node/dist/bin-script.js

1
node_modules/.bin/ts-node-transpile-only generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-node/dist/bin-transpile.js

1
node_modules/.bin/ts-script generated vendored Symbolic link
View File

@ -0,0 +1 @@
../ts-node/dist/bin-script-deprecated.js

1
node_modules/.bin/tsc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../typescript/bin/tsc

1
node_modules/.bin/tsserver generated vendored Symbolic link
View File

@ -0,0 +1 @@
../typescript/bin/tsserver

1
node_modules/.bin/typeorm generated vendored Symbolic link
View File

@ -0,0 +1 @@
../typeorm/cli.js

1
node_modules/.bin/typeorm-ts-node-commonjs generated vendored Symbolic link
View File

@ -0,0 +1 @@
../typeorm/cli-ts-node-commonjs.js

1
node_modules/.bin/typeorm-ts-node-esm generated vendored Symbolic link
View File

@ -0,0 +1 @@
../typeorm/cli-ts-node-esm.js

1
node_modules/.bin/uglifyjs generated vendored Symbolic link
View File

@ -0,0 +1 @@
../uglify-js/bin/uglifyjs

1
node_modules/.bin/update-browserslist-db generated vendored Symbolic link
View File

@ -0,0 +1 @@
../update-browserslist-db/cli.js

1
node_modules/.bin/uuid generated vendored Symbolic link
View File

@ -0,0 +1 @@
../uuid/dist/bin/uuid

1
node_modules/.bin/webpack generated vendored Symbolic link
View File

@ -0,0 +1 @@
../webpack/bin/webpack.js

13310
node_modules/.package-lock.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

202
node_modules/@ampproject/remapping/LICENSE generated vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

218
node_modules/@ampproject/remapping/README.md generated vendored Normal file
View File

@ -0,0 +1,218 @@
# @ampproject/remapping
> Remap sequential sourcemaps through transformations to point at the original source code
Remapping allows you to take the sourcemaps generated through transforming your code and "remap"
them to the original source locations. Think "my minified code, transformed with babel and bundled
with webpack", all pointing to the correct location in your original source code.
With remapping, none of your source code transformations need to be aware of the input's sourcemap,
they only need to generate an output sourcemap. This greatly simplifies building custom
transformations (think a find-and-replace).
## Installation
```sh
npm install @ampproject/remapping
```
## Usage
```typescript
function remapping(
map: SourceMap | SourceMap[],
loader: (file: string, ctx: LoaderContext) => (SourceMap | null | undefined),
options?: { excludeContent: boolean, decodedMappings: boolean }
): SourceMap;
// LoaderContext gives the loader the importing sourcemap, tree depth, the ability to override the
// "source" location (where child sources are resolved relative to, or the location of original
// source), and the ability to override the "content" of an original source for inclusion in the
// output sourcemap.
type LoaderContext = {
readonly importer: string;
readonly depth: number;
source: string;
content: string | null | undefined;
}
```
`remapping` takes the final output sourcemap, and a `loader` function. For every source file pointer
in the sourcemap, the `loader` will be called with the resolved path. If the path itself represents
a transformed file (it has a sourcmap associated with it), then the `loader` should return that
sourcemap. If not, the path will be treated as an original, untransformed source code.
```js
// Babel transformed "helloworld.js" into "transformed.js"
const transformedMap = JSON.stringify({
file: 'transformed.js',
// 1st column of 2nd line of output file translates into the 1st source
// file, line 3, column 2
mappings: ';CAEE',
sources: ['helloworld.js'],
version: 3,
});
// Uglify minified "transformed.js" into "transformed.min.js"
const minifiedTransformedMap = JSON.stringify({
file: 'transformed.min.js',
// 0th column of 1st line of output file translates into the 1st source
// file, line 2, column 1.
mappings: 'AACC',
names: [],
sources: ['transformed.js'],
version: 3,
});
const remapped = remapping(
minifiedTransformedMap,
(file, ctx) => {
// The "transformed.js" file is an transformed file.
if (file === 'transformed.js') {
// The root importer is empty.
console.assert(ctx.importer === '');
// The depth in the sourcemap tree we're currently loading.
// The root `minifiedTransformedMap` is depth 0, and its source children are depth 1, etc.
console.assert(ctx.depth === 1);
return transformedMap;
}
// Loader will be called to load transformedMap's source file pointers as well.
console.assert(file === 'helloworld.js');
// `transformed.js`'s sourcemap points into `helloworld.js`.
console.assert(ctx.importer === 'transformed.js');
// This is a source child of `transformed`, which is a source child of `minifiedTransformedMap`.
console.assert(ctx.depth === 2);
return null;
}
);
console.log(remapped);
// {
// file: 'transpiled.min.js',
// mappings: 'AAEE',
// sources: ['helloworld.js'],
// version: 3,
// };
```
In this example, `loader` will be called twice:
1. `"transformed.js"`, the first source file pointer in the `minifiedTransformedMap`. We return the
associated sourcemap for it (its a transformed file, after all) so that sourcemap locations can
be traced through it into the source files it represents.
2. `"helloworld.js"`, our original, unmodified source code. This file does not have a sourcemap, so
we return `null`.
The `remapped` sourcemap now points from `transformed.min.js` into locations in `helloworld.js`. If
you were to read the `mappings`, it says "0th column of the first line output line points to the 1st
column of the 2nd line of the file `helloworld.js`".
### Multiple transformations of a file
As a convenience, if you have multiple single-source transformations of a file, you may pass an
array of sourcemap files in the order of most-recent transformation sourcemap first. Note that this
changes the `importer` and `depth` of each call to our loader. So our above example could have been
written as:
```js
const remapped = remapping(
[minifiedTransformedMap, transformedMap],
() => null
);
console.log(remapped);
// {
// file: 'transpiled.min.js',
// mappings: 'AAEE',
// sources: ['helloworld.js'],
// version: 3,
// };
```
### Advanced control of the loading graph
#### `source`
The `source` property can overridden to any value to change the location of the current load. Eg,
for an original source file, it allows us to change the location to the original source regardless
of what the sourcemap source entry says. And for transformed files, it allows us to change the
relative resolving location for child sources of the loaded sourcemap.
```js
const remapped = remapping(
minifiedTransformedMap,
(file, ctx) => {
if (file === 'transformed.js') {
// We pretend the transformed.js file actually exists in the 'src/' directory. When the nested
// source files are loaded, they will now be relative to `src/`.
ctx.source = 'src/transformed.js';
return transformedMap;
}
console.assert(file === 'src/helloworld.js');
// We could futher change the source of this original file, eg, to be inside a nested directory
// itself. This will be reflected in the remapped sourcemap.
ctx.source = 'src/nested/transformed.js';
return null;
}
);
console.log(remapped);
// {
// …,
// sources: ['src/nested/helloworld.js'],
// };
```
#### `content`
The `content` property can be overridden when we encounter an original source file. Eg, this allows
you to manually provide the source content of the original file regardless of whether the
`sourcesContent` field is present in the parent sourcemap. It can also be set to `null` to remove
the source content.
```js
const remapped = remapping(
minifiedTransformedMap,
(file, ctx) => {
if (file === 'transformed.js') {
// transformedMap does not include a `sourcesContent` field, so usually the remapped sourcemap
// would not include any `sourcesContent` values.
return transformedMap;
}
console.assert(file === 'helloworld.js');
// We can read the file to provide the source content.
ctx.content = fs.readFileSync(file, 'utf8');
return null;
}
);
console.log(remapped);
// {
// …,
// sourcesContent: [
// 'console.log("Hello world!")',
// ],
// };
```
### Options
#### excludeContent
By default, `excludeContent` is `false`. Passing `{ excludeContent: true }` will exclude the
`sourcesContent` field from the returned sourcemap. This is mainly useful when you want to reduce
the size out the sourcemap.
#### decodedMappings
By default, `decodedMappings` is `false`. Passing `{ decodedMappings: true }` will leave the
`mappings` field in a [decoded state](https://github.com/rich-harris/sourcemap-codec) instead of
encoding into a VLQ string.

75
node_modules/@ampproject/remapping/package.json generated vendored Normal file
View File

@ -0,0 +1,75 @@
{
"name": "@ampproject/remapping",
"version": "2.3.0",
"description": "Remap sequential sourcemaps through transformations to point at the original source code",
"keywords": [
"source",
"map",
"remap"
],
"main": "dist/remapping.umd.js",
"module": "dist/remapping.mjs",
"types": "dist/types/remapping.d.ts",
"exports": {
".": [
{
"types": "./dist/types/remapping.d.ts",
"browser": "./dist/remapping.umd.js",
"require": "./dist/remapping.umd.js",
"import": "./dist/remapping.mjs"
},
"./dist/remapping.umd.js"
],
"./package.json": "./package.json"
},
"files": [
"dist"
],
"author": "Justin Ridgewell <jridgewell@google.com>",
"repository": {
"type": "git",
"url": "git+https://github.com/ampproject/remapping.git"
},
"license": "Apache-2.0",
"engines": {
"node": ">=6.0.0"
},
"scripts": {
"build": "run-s -n build:*",
"build:rollup": "rollup -c rollup.config.js",
"build:ts": "tsc --project tsconfig.build.json",
"lint": "run-s -n lint:*",
"lint:prettier": "npm run test:lint:prettier -- --write",
"lint:ts": "npm run test:lint:ts -- --fix",
"prebuild": "rm -rf dist",
"prepublishOnly": "npm run preversion",
"preversion": "run-s test build",
"test": "run-s -n test:lint test:only",
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
"test:lint": "run-s -n test:lint:*",
"test:lint:prettier": "prettier --check '{src,test}/**/*.ts'",
"test:lint:ts": "eslint '{src,test}/**/*.ts'",
"test:only": "jest --coverage",
"test:watch": "jest --coverage --watch"
},
"devDependencies": {
"@rollup/plugin-typescript": "8.3.2",
"@types/jest": "27.4.1",
"@typescript-eslint/eslint-plugin": "5.20.0",
"@typescript-eslint/parser": "5.20.0",
"eslint": "8.14.0",
"eslint-config-prettier": "8.5.0",
"jest": "27.5.1",
"jest-config": "27.5.1",
"npm-run-all": "4.1.5",
"prettier": "2.6.2",
"rollup": "2.70.2",
"ts-jest": "27.1.4",
"tslib": "2.4.0",
"typescript": "4.6.3"
},
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
}
}

21
node_modules/@angular-devkit/core/LICENSE generated vendored Executable file
View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2017 Google, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

167
node_modules/@angular-devkit/core/README.md generated vendored Executable file
View File

@ -0,0 +1,167 @@
# Core
> Shared utilities for Angular DevKit.
# Exception
# Json
## Schema
### SchemaValidatorResult
```
export interface SchemaValidatorResult {
success: boolean;
errors?: string[];
}
```
### SchemaValidator
```
export interface SchemaValidator {
(data: any): Observable<SchemaValidatorResult>;
}
```
### SchemaFormatter
```
export interface SchemaFormatter {
readonly async: boolean;
validate(data: any): boolean | Observable<boolean>;
}
```
### SchemaRegistry
```
export interface SchemaRegistry {
compile(schema: Object): Observable<SchemaValidator>;
addFormat(name: string, formatter: SchemaFormatter): void;
}
```
### CoreSchemaRegistry
`SchemaRegistry` implementation using https://github.com/epoberezkin/ajv.
Constructor accepts object containing `SchemaFormatter` that will be added automatically.
```
export class CoreSchemaRegistry implements SchemaRegistry {
constructor(formats: { [name: string]: SchemaFormatter} = {}) {}
}
```
# Logger
# Utils
# Virtual FS
# Workspaces
The `workspaces` namespace provides an API for interacting with the workspace file formats.
It provides an abstraction of the underlying storage format of the workspace and provides
support for both reading and writing. Currently, the only supported format is the JSON-based
format used by the Angular CLI. For this format, the API provides internal change tracking of values which
enables fine-grained updates to the underlying storage of the workspace. This allows for the
retention of existing formatting and comments.
A workspace is defined via the following object model. Definition collection objects are specialized
Javascript `Map` objects with an additional `add` method to simplify addition and provide more localized
error checking of the newly added values.
```ts
export interface WorkspaceDefinition {
readonly extensions: Record<string, JsonValue | undefined>;
readonly projects: ProjectDefinitionCollection;
}
export interface ProjectDefinition {
readonly extensions: Record<string, JsonValue | undefined>;
readonly targets: TargetDefinitionCollection;
root: string;
prefix?: string;
sourceRoot?: string;
}
export interface TargetDefinition {
options?: Record<string, JsonValue | undefined>;
configurations?: Record<string, Record<string, JsonValue | undefined> | undefined>;
builder: string;
}
```
The API is asynchronous and has two main functions to facilitate reading, creation, and modifying
a workspace: `readWorkspace` and `writeWorkspace`.
```ts
export enum WorkspaceFormat {
JSON,
}
```
```ts
export function readWorkspace(
path: string,
host: WorkspaceHost,
format?: WorkspaceFormat,
): Promise<{ workspace: WorkspaceDefinition }>;
```
```ts
export function writeWorkspace(
workspace: WorkspaceDefinition,
host: WorkspaceHost,
path?: string,
format?: WorkspaceFormat,
): Promise<void>;
```
A `WorkspaceHost` abstracts the underlying data access methods from the functions. It provides
methods to read, write, and analyze paths. A utility function is provided to create
an instance of a `WorkspaceHost` from the Angular DevKit's virtual filesystem host abstraction.
```ts
export interface WorkspaceHost {
readFile(path: string): Promise<string>;
writeFile(path: string, data: string): Promise<void>;
isDirectory(path: string): Promise<boolean>;
isFile(path: string): Promise<boolean>;
}
export function createWorkspaceHost(host: virtualFs.Host): WorkspaceHost;
```
## Usage Example
To demonstrate the usage of the API, the following code will show how to add a option property
to a build target for an application.
```ts
import { NodeJsSyncHost } from '@angular-devkit/core/node';
import { workspaces } from '@angular-devkit/core';
async function demonstrate() {
const host = workspaces.createWorkspaceHost(new NodeJsSyncHost());
const { workspace } = await workspaces.readWorkspace('path/to/workspace/directory/', host);
const project = workspace.projects.get('my-app');
if (!project) {
throw new Error('my-app does not exist');
}
const buildTarget = project.targets.get('build');
if (!buildTarget) {
throw new Error('build target does not exist');
}
buildTarget.options.optimization = true;
await workspaces.writeWorkspace(workspace, host);
}
demonstrate();
```

15
node_modules/@angular-devkit/core/node/cli-logger.d.ts generated vendored Executable file
View File

@ -0,0 +1,15 @@
/**
* @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.io/license
*/
import { logging } from '../src';
export interface ProcessOutput {
write(buffer: string | Buffer): boolean;
}
/**
* A Logger that sends information to STDOUT and STDERR.
*/
export declare function createConsoleLogger(verbose?: boolean, stdout?: ProcessOutput, stderr?: ProcessOutput, colors?: Partial<Record<logging.LogLevel, (s: string) => string>>): logging.Logger;

58
node_modules/@angular-devkit/core/node/cli-logger.js generated vendored Executable file
View File

@ -0,0 +1,58 @@
"use strict";
/**
* @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.io/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createConsoleLogger = void 0;
const rxjs_1 = require("rxjs");
const src_1 = require("../src");
/**
* A Logger that sends information to STDOUT and STDERR.
*/
function createConsoleLogger(verbose = false, stdout = process.stdout, stderr = process.stderr, colors) {
const logger = new src_1.logging.IndentLogger('cling');
logger.pipe((0, rxjs_1.filter)((entry) => entry.level !== 'debug' || verbose)).subscribe((entry) => {
const color = colors && colors[entry.level];
let output = stdout;
switch (entry.level) {
case 'warn':
case 'fatal':
case 'error':
output = stderr;
break;
}
// If we do console.log(message) or process.stdout.write(message + '\n'), the process might
// stop before the whole message is written and the stream is flushed. This happens when
// streams are asynchronous.
//
// NodeJS IO streams are different depending on platform and usage. In POSIX environment,
// for example, they're asynchronous when writing to a pipe, but synchronous when writing
// to a TTY. In windows, it's the other way around. You can verify which is which with
// stream.isTTY and platform, but this is not good enough.
// In the async case, one should wait for the callback before sending more data or
// continuing the process. In our case it would be rather hard to do (but not impossible).
//
// Instead we take the easy way out and simply chunk the message and call the write
// function while the buffer drain itself asynchronously. With a smaller chunk size than
// the buffer, we are mostly certain that it works. In this case, the chunk has been picked
// as half a page size (4096/2 = 2048), minus some bytes for the color formatting.
// On POSIX it seems the buffer is 2 pages (8192), but just to be sure (could be different
// by platform).
//
// For more details, see https://nodejs.org/api/process.html#process_a_note_on_process_i_o
const chunkSize = 2000; // Small chunk.
let message = entry.message;
while (message) {
const chunk = message.slice(0, chunkSize);
message = message.slice(chunkSize);
output.write(color ? color(chunk) : chunk);
}
output.write('\n');
});
return logger;
}
exports.createConsoleLogger = createConsoleLogger;

46
node_modules/@angular-devkit/core/node/host.d.ts generated vendored Executable file
View File

@ -0,0 +1,46 @@
/**
* @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.io/license
*/
/// <reference types="node" />
/// <reference types="@types/node/fs" />
/// <reference types="@types/node/ts4.8/fs" />
import { Stats } from 'node:fs';
import { Observable } from 'rxjs';
import { Path, PathFragment, virtualFs } from '../src';
/**
* An implementation of the Virtual FS using Node as the background. There are two versions; one
* synchronous and one asynchronous.
*/
export declare class NodeJsAsyncHost implements virtualFs.Host<Stats> {
get capabilities(): virtualFs.HostCapabilities;
write(path: Path, content: virtualFs.FileBuffer): Observable<void>;
read(path: Path): Observable<virtualFs.FileBuffer>;
delete(path: Path): Observable<void>;
rename(from: Path, to: Path): Observable<void>;
list(path: Path): Observable<PathFragment[]>;
exists(path: Path): Observable<boolean>;
isDirectory(path: Path): Observable<boolean>;
isFile(path: Path): Observable<boolean>;
stat(path: Path): Observable<virtualFs.Stats<Stats>>;
watch(path: Path, _options?: virtualFs.HostWatchOptions): Observable<virtualFs.HostWatchEvent> | null;
}
/**
* An implementation of the Virtual FS using Node as the backend, synchronously.
*/
export declare class NodeJsSyncHost implements virtualFs.Host<Stats> {
get capabilities(): virtualFs.HostCapabilities;
write(path: Path, content: virtualFs.FileBuffer): Observable<void>;
read(path: Path): Observable<virtualFs.FileBuffer>;
delete(path: Path): Observable<void>;
rename(from: Path, to: Path): Observable<void>;
list(path: Path): Observable<PathFragment[]>;
exists(path: Path): Observable<boolean>;
isDirectory(path: Path): Observable<boolean>;
isFile(path: Path): Observable<boolean>;
stat(path: Path): Observable<virtualFs.Stats<Stats>>;
watch(path: Path, _options?: virtualFs.HostWatchOptions): Observable<virtualFs.HostWatchEvent> | null;
}

212
node_modules/@angular-devkit/core/node/host.js generated vendored Executable file
View File

@ -0,0 +1,212 @@
"use strict";
/**
* @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.io/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeJsSyncHost = exports.NodeJsAsyncHost = void 0;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const rxjs_1 = require("rxjs");
const src_1 = require("../src");
async function exists(path) {
try {
await node_fs_1.promises.access(path, node_fs_1.constants.F_OK);
return true;
}
catch {
return false;
}
}
// This will only be initialized if the watch() method is called.
// Otherwise chokidar appears only in type positions, and shouldn't be referenced
// in the JavaScript output.
let FSWatcher;
function loadFSWatcher() {
if (!FSWatcher) {
try {
FSWatcher = require('chokidar').FSWatcher;
}
catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
throw new Error('As of angular-devkit version 8.0, the "chokidar" package ' +
'must be installed in order to use watch() features.');
}
throw e;
}
}
}
/**
* An implementation of the Virtual FS using Node as the background. There are two versions; one
* synchronous and one asynchronous.
*/
class NodeJsAsyncHost {
get capabilities() {
return { synchronous: false };
}
write(path, content) {
return (0, rxjs_1.from)(node_fs_1.promises.mkdir((0, src_1.getSystemPath)((0, src_1.dirname)(path)), { recursive: true })).pipe((0, rxjs_1.mergeMap)(() => node_fs_1.promises.writeFile((0, src_1.getSystemPath)(path), new Uint8Array(content))));
}
read(path) {
return (0, rxjs_1.from)(node_fs_1.promises.readFile((0, src_1.getSystemPath)(path))).pipe((0, rxjs_1.map)((buffer) => new Uint8Array(buffer).buffer));
}
delete(path) {
return (0, rxjs_1.from)(node_fs_1.promises.rm((0, src_1.getSystemPath)(path), { force: true, recursive: true, maxRetries: 3 }));
}
rename(from, to) {
return (0, rxjs_1.from)(node_fs_1.promises.rename((0, src_1.getSystemPath)(from), (0, src_1.getSystemPath)(to)));
}
list(path) {
return (0, rxjs_1.from)(node_fs_1.promises.readdir((0, src_1.getSystemPath)(path))).pipe((0, rxjs_1.map)((names) => names.map((name) => (0, src_1.fragment)(name))));
}
exists(path) {
return (0, rxjs_1.from)(exists((0, src_1.getSystemPath)(path)));
}
isDirectory(path) {
return this.stat(path).pipe((0, rxjs_1.map)((stat) => stat.isDirectory()));
}
isFile(path) {
return this.stat(path).pipe((0, rxjs_1.map)((stat) => stat.isFile()));
}
// Some hosts may not support stat.
stat(path) {
return (0, rxjs_1.from)(node_fs_1.promises.stat((0, src_1.getSystemPath)(path)));
}
// Some hosts may not support watching.
watch(path, _options) {
return new rxjs_1.Observable((obs) => {
loadFSWatcher();
const watcher = new FSWatcher({ persistent: true });
watcher.add((0, src_1.getSystemPath)(path));
watcher
.on('change', (path) => {
obs.next({
path: (0, src_1.normalize)(path),
time: new Date(),
type: src_1.virtualFs.HostWatchEventType.Changed,
});
})
.on('add', (path) => {
obs.next({
path: (0, src_1.normalize)(path),
time: new Date(),
type: src_1.virtualFs.HostWatchEventType.Created,
});
})
.on('unlink', (path) => {
obs.next({
path: (0, src_1.normalize)(path),
time: new Date(),
type: src_1.virtualFs.HostWatchEventType.Deleted,
});
});
return () => {
void watcher.close();
};
}).pipe((0, rxjs_1.publish)(), (0, rxjs_1.refCount)());
}
}
exports.NodeJsAsyncHost = NodeJsAsyncHost;
/**
* An implementation of the Virtual FS using Node as the backend, synchronously.
*/
class NodeJsSyncHost {
get capabilities() {
return { synchronous: true };
}
write(path, content) {
return new rxjs_1.Observable((obs) => {
(0, node_fs_1.mkdirSync)((0, src_1.getSystemPath)((0, src_1.dirname)(path)), { recursive: true });
(0, node_fs_1.writeFileSync)((0, src_1.getSystemPath)(path), new Uint8Array(content));
obs.next();
obs.complete();
});
}
read(path) {
return new rxjs_1.Observable((obs) => {
const buffer = (0, node_fs_1.readFileSync)((0, src_1.getSystemPath)(path));
obs.next(new Uint8Array(buffer).buffer);
obs.complete();
});
}
delete(path) {
return new rxjs_1.Observable((obs) => {
(0, node_fs_1.rmSync)((0, src_1.getSystemPath)(path), { force: true, recursive: true, maxRetries: 3 });
obs.complete();
});
}
rename(from, to) {
return new rxjs_1.Observable((obs) => {
const toSystemPath = (0, src_1.getSystemPath)(to);
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(toSystemPath), { recursive: true });
(0, node_fs_1.renameSync)((0, src_1.getSystemPath)(from), toSystemPath);
obs.next();
obs.complete();
});
}
list(path) {
return new rxjs_1.Observable((obs) => {
const names = (0, node_fs_1.readdirSync)((0, src_1.getSystemPath)(path));
obs.next(names.map((name) => (0, src_1.fragment)(name)));
obs.complete();
});
}
exists(path) {
return new rxjs_1.Observable((obs) => {
obs.next((0, node_fs_1.existsSync)((0, src_1.getSystemPath)(path)));
obs.complete();
});
}
isDirectory(path) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.stat(path).pipe((0, rxjs_1.map)((stat) => stat.isDirectory()));
}
isFile(path) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.stat(path).pipe((0, rxjs_1.map)((stat) => stat.isFile()));
}
// Some hosts may not support stat.
stat(path) {
return new rxjs_1.Observable((obs) => {
obs.next((0, node_fs_1.statSync)((0, src_1.getSystemPath)(path)));
obs.complete();
});
}
// Some hosts may not support watching.
watch(path, _options) {
return new rxjs_1.Observable((obs) => {
loadFSWatcher();
const watcher = new FSWatcher({ persistent: false });
watcher.add((0, src_1.getSystemPath)(path));
watcher
.on('change', (path) => {
obs.next({
path: (0, src_1.normalize)(path),
time: new Date(),
type: src_1.virtualFs.HostWatchEventType.Changed,
});
})
.on('add', (path) => {
obs.next({
path: (0, src_1.normalize)(path),
time: new Date(),
type: src_1.virtualFs.HostWatchEventType.Created,
});
})
.on('unlink', (path) => {
obs.next({
path: (0, src_1.normalize)(path),
time: new Date(),
type: src_1.virtualFs.HostWatchEventType.Deleted,
});
});
return () => {
void watcher.close();
};
}).pipe((0, rxjs_1.publish)(), (0, rxjs_1.refCount)());
}
}
exports.NodeJsSyncHost = NodeJsSyncHost;

9
node_modules/@angular-devkit/core/node/index.d.ts generated vendored Executable file
View File

@ -0,0 +1,9 @@
/**
* @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.io/license
*/
export * from './cli-logger';
export * from './host';

25
node_modules/@angular-devkit/core/node/index.js generated vendored Executable file
View File

@ -0,0 +1,25 @@
"use strict";
/**
* @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.io/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./cli-logger"), exports);
__exportStar(require("./host"), exports);

23
node_modules/@angular-devkit/core/node/testing/index.d.ts generated vendored Executable file
View File

@ -0,0 +1,23 @@
/**
* @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.io/license
*/
/// <reference types="node" />
/// <reference types="@types/node/fs" />
/// <reference types="@types/node/ts4.8/fs" />
import * as fs from 'fs';
import { Path, virtualFs } from '../../src';
/**
* A Sync Scoped Host that creates a temporary directory and scope to it.
*/
export declare class TempScopedNodeJsSyncHost extends virtualFs.ScopedHost<fs.Stats> {
protected _sync?: virtualFs.SyncDelegateHost<fs.Stats>;
protected _root: Path;
constructor();
get files(): Path[];
get root(): Path;
get sync(): virtualFs.SyncDelegateHost<fs.Stats>;
}

78
node_modules/@angular-devkit/core/node/testing/index.js generated vendored Executable file
View File

@ -0,0 +1,78 @@
"use strict";
/**
* @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.io/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TempScopedNodeJsSyncHost = void 0;
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const src_1 = require("../../src");
const host_1 = require("../host");
/**
* A Sync Scoped Host that creates a temporary directory and scope to it.
*/
class TempScopedNodeJsSyncHost extends src_1.virtualFs.ScopedHost {
_sync;
_root;
constructor() {
const root = (0, src_1.normalize)(path.join(os.tmpdir(), `devkit-host-${+Date.now()}-${process.pid}`));
fs.mkdirSync((0, src_1.getSystemPath)(root));
super(new host_1.NodeJsSyncHost(), root);
this._root = root;
}
get files() {
const sync = this.sync;
function _visit(p) {
return sync
.list(p)
.map((fragment) => (0, src_1.join)(p, fragment))
.reduce((files, path) => {
if (sync.isDirectory(path)) {
return files.concat(_visit(path));
}
else {
return files.concat(path);
}
}, []);
}
return _visit((0, src_1.normalize)('/'));
}
get root() {
return this._root;
}
get sync() {
if (!this._sync) {
this._sync = new src_1.virtualFs.SyncDelegateHost(this);
}
return this._sync;
}
}
exports.TempScopedNodeJsSyncHost = TempScopedNodeJsSyncHost;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting Ben Lesh (ben@benlesh.com), Tracy Lee (tracy@thisdot.co) or OJ Kwon (kwon.ohjoong@gmail.com). All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,107 @@
# <img src="docs_app/src/assets/images/logos/Rx_Logo_S.png" alt="RxJS Logo" width="86" height="86"> RxJS: Reactive Extensions For JavaScript
![CI](https://github.com/reactivex/rxjs/workflows/CI/badge.svg)
[![npm version](https://badge.fury.io/js/rxjs.svg)](http://badge.fury.io/js/rxjs)
[![Join the chat at https://gitter.im/Reactive-Extensions/RxJS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Reactive-Extensions/RxJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# The Roadmap from RxJS 7 to 8
Curious what's next for RxJS? Follow along with [Issue 6367](https://github.com/ReactiveX/rxjs/issues/6367).
# RxJS 7
### FOR 6.X PLEASE GO TO [THE 6.x BRANCH](https://github.com/ReactiveX/rxjs/tree/6.x)
Reactive Extensions Library for JavaScript. This is a rewrite of [Reactive-Extensions/RxJS](https://github.com/Reactive-Extensions/RxJS) and is the latest production-ready version of RxJS. This rewrite is meant to have better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface.
[Apache 2.0 License](LICENSE.txt)
- [Code of Conduct](CODE_OF_CONDUCT.md)
- [Contribution Guidelines](CONTRIBUTING.md)
- [Maintainer Guidelines](docs_app/content/maintainer-guidelines.md)
- [API Documentation](https://rxjs.dev/)
## Versions In This Repository
- [master](https://github.com/ReactiveX/rxjs/commits/master) - This is all of the current work, which is against v7 of RxJS right now
- [6.x](https://github.com/ReactiveX/rxjs/tree/6.x) - This is the branch for version 6.X
Most PRs should be made to **master**.
## Important
By contributing or commenting on issues in this repository, whether you've read them or not, you're agreeing to the [Contributor Code of Conduct](CODE_OF_CONDUCT.md). Much like traffic laws, ignorance doesn't grant you immunity.
## Installation and Usage
### ES6 via npm
```shell
npm install rxjs
```
It's recommended to pull in the Observable creation methods you need directly from `'rxjs'` as shown below with `range`.
If you're using RxJS version 7.2 or above, you can pull in any operator you need from the same spot, `'rxjs'`.
```ts
import { range, filter, map } from 'rxjs';
range(1, 200)
.pipe(
filter(x => x % 2 === 1),
map(x => x + x)
)
.subscribe(x => console.log(x));
```
If you're using RxJS version below 7.2, you can pull in any operator you need from one spot, under `'rxjs/operators'`.
```ts
import { range } from 'rxjs';
import { filter, map } from 'rxjs/operators';
range(1, 200)
.pipe(
filter(x => x % 2 === 1),
map(x => x + x)
)
.subscribe(x => console.log(x));
```
### CDN
For CDN, you can use [unpkg](https://unpkg.com/):
[https://unpkg.com/rxjs@^7/dist/bundles/rxjs.umd.min.js](https://unpkg.com/rxjs@%5E7/dist/bundles/rxjs.umd.min.js)
The global namespace for rxjs is `rxjs`:
```js
const { range } = rxjs;
const { filter, map } = rxjs.operators;
range(1, 200)
.pipe(
filter(x => x % 2 === 1),
map(x => x + x)
)
.subscribe(x => console.log(x));
```
## Goals
- Smaller overall bundles sizes
- Provide better performance than preceding versions of RxJS
- To model/follow the [Observable Spec Proposal](https://github.com/zenparsing/es-observable) to the observable
- Provide more modular file structure in a variety of formats
- Provide more debuggable call stacks than preceding versions of RxJS
## Building/Testing
- `npm run compile` build everything
- `npm test` run tests
- `npm run dtslint` run dtslint tests
## Adding documentation
We appreciate all contributions to the documentation of any type. All of the information needed to get the docs app up and running locally as well as how to contribute can be found in the [documentation directory](./docs_app).

View File

@ -0,0 +1,8 @@
{
"name": "rxjs/ajax",
"types": "../dist/types/ajax/index.d.ts",
"main": "../dist/cjs/ajax/index.js",
"module": "../dist/esm5/ajax/index.js",
"es2015": "../dist/esm/ajax/index.js",
"sideEffects": false
}

View File

@ -0,0 +1,8 @@
{
"name": "rxjs/fetch",
"types": "../dist/types/fetch/index.d.ts",
"main": "../dist/cjs/fetch/index.js",
"module": "../dist/esm5/fetch/index.js",
"es2015": "../dist/esm/fetch/index.js",
"sideEffects": false
}

View File

@ -0,0 +1,8 @@
{
"name": "rxjs/operators",
"types": "../dist/types/operators/index.d.ts",
"main": "../dist/cjs/operators/index.js",
"module": "../dist/esm5/operators/index.js",
"es2015": "../dist/esm/operators/index.js",
"sideEffects": false
}

View File

@ -0,0 +1,245 @@
{
"name": "rxjs",
"version": "7.8.1",
"description": "Reactive Extensions for modern JavaScript",
"main": "./dist/cjs/index.js",
"module": "./dist/esm5/index.js",
"es2015": "./dist/esm/index.js",
"types": "index.d.ts",
"typesVersions": {
">=4.2": {
"*": [
"dist/types/*"
]
}
},
"sideEffects": false,
"exports": {
".": {
"types": "./dist/types/index.d.ts",
"node": "./dist/cjs/index.js",
"require": "./dist/cjs/index.js",
"es2015": "./dist/esm/index.js",
"default": "./dist/esm5/index.js"
},
"./ajax": {
"types": "./dist/types/ajax/index.d.ts",
"node": "./dist/cjs/ajax/index.js",
"require": "./dist/cjs/ajax/index.js",
"es2015": "./dist/esm/ajax/index.js",
"default": "./dist/esm5/ajax/index.js"
},
"./fetch": {
"types": "./dist/types/fetch/index.d.ts",
"node": "./dist/cjs/fetch/index.js",
"require": "./dist/cjs/fetch/index.js",
"es2015": "./dist/esm/fetch/index.js",
"default": "./dist/esm5/fetch/index.js"
},
"./operators": {
"types": "./dist/types/operators/index.d.ts",
"node": "./dist/cjs/operators/index.js",
"require": "./dist/cjs/operators/index.js",
"es2015": "./dist/esm/operators/index.js",
"default": "./dist/esm5/operators/index.js"
},
"./testing": {
"types": "./dist/types/testing/index.d.ts",
"node": "./dist/cjs/testing/index.js",
"require": "./dist/cjs/testing/index.js",
"es2015": "./dist/esm/testing/index.js",
"default": "./dist/esm5/testing/index.js"
},
"./webSocket": {
"types": "./dist/types/webSocket/index.d.ts",
"node": "./dist/cjs/webSocket/index.js",
"require": "./dist/cjs/webSocket/index.js",
"es2015": "./dist/esm/webSocket/index.js",
"default": "./dist/esm5/webSocket/index.js"
},
"./internal/*": {
"types": "./dist/types/internal/*.d.ts",
"node": "./dist/cjs/internal/*.js",
"require": "./dist/cjs/internal/*.js",
"es2015": "./dist/esm/internal/*.js",
"default": "./dist/esm5/internal/*.js"
},
"./package.json": "./package.json"
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"lint-staged": {
"*.js": "eslint --cache --fix",
"(src|spec)/**/*.ts": [
"tslint --fix",
"prettier --write"
],
"*.{js,css,md}": "prettier --write"
},
"scripts": {
"changelog": "npx conventional-changelog-cli -p angular -i CHANGELOG.md -s",
"build:spec:browser": "echo \"Browser test is not working currently\" && exit -1 && webpack --config spec/support/webpack.mocha.config.js",
"lint_spec": "tslint -c spec/tslint.json -p spec/tsconfig.json \"spec/**/*.ts\"",
"lint_src": "tslint -c tslint.json -p src/tsconfig.base.json \"src/**/*.ts\"",
"lint": "npm-run-all --parallel lint_*",
"dtslint": "tsc -b ./src/tsconfig.types.json && tslint -c spec-dtslint/tslint.json -p spec-dtslint/tsconfig.json \"spec-dtslint/**/*.ts\"",
"prepublishOnly": "npm run build:package && npm run lint && npm run test && npm run test:circular && npm run dtslint && npm run test:side-effects",
"publish_docs": "./publish_docs.sh",
"test": "cross-env TS_NODE_PROJECT=tsconfig.mocha.json mocha --config spec/support/.mocharc.js \"spec/**/*-spec.ts\"",
"test:esm": "node spec/module-test-spec.mjs",
"test:browser": "echo \"Browser test is not working currently\" && exit -1 && npm-run-all build:spec:browser && opn spec/support/mocha-browser-runner.html",
"test:circular": "dependency-cruiser --validate .dependency-cruiser.json -x \"^node_modules\" dist/esm5",
"test:systemjs": "node integration/systemjs/systemjs-compatibility-spec.js",
"test:side-effects": "check-side-effects --test integration/side-effects/side-effects.json",
"test:side-effects:update": "npm run test:side-effects -- --update",
"test:import": "ts-node ./integration/import/runner.ts",
"compile": "tsc -b ./src/tsconfig.cjs.json ./src/tsconfig.cjs.spec.json ./src/tsconfig.esm.json ./src/tsconfig.esm5.json ./src/tsconfig.esm5.rollup.json ./src/tsconfig.types.json ./src/tsconfig.types.spec.json ./spec/tsconfig.json",
"build:clean": "shx rm -rf ./dist",
"build:global": "node ./tools/make-umd-bundle.js && node ./tools/make-closure-core.js",
"build:package": "npm-run-all build:clean compile build:global && node ./tools/prepare-package.js && node ./tools/generate-alias.js",
"watch": "nodemon -w \"src/\" -w \"spec/\" -e ts -x npm test",
"watch:dtslint": "nodemon -w \"src/\" -w \"spec-dtslint/\" -e ts -x npm run dtslint"
},
"repository": {
"type": "git",
"url": "https://github.com/reactivex/rxjs.git"
},
"keywords": [
"Rx",
"RxJS",
"ReactiveX",
"ReactiveExtensions",
"Streams",
"Observables",
"Observable",
"Stream",
"ES6",
"ES2015"
],
"author": "Ben Lesh <ben@benlesh.com>",
"contributors": [
{
"name": "Ben Lesh",
"email": "ben@benlesh.com"
},
{
"name": "Paul Taylor",
"email": "paul.e.taylor@me.com"
},
{
"name": "Jeff Cross",
"email": "crossj@google.com"
},
{
"name": "Matthew Podwysocki",
"email": "matthewp@microsoft.com"
},
{
"name": "OJ Kwon",
"email": "kwon.ohjoong@gmail.com"
},
{
"name": "Andre Staltz",
"email": "andre@staltz.com"
}
],
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/ReactiveX/RxJS/issues"
},
"homepage": "https://rxjs.dev",
"dependencies": {
"tslib": "^2.1.0"
},
"devDependencies": {
"@angular-devkit/build-optimizer": "0.4.6",
"@angular-devkit/schematics": "^11.0.7",
"@swc/core": "^1.2.128",
"@swc/helpers": "^0.3.2",
"@types/chai": "^4.2.11",
"@types/lodash": "4.14.102",
"@types/mocha": "^7.0.2",
"@types/node": "^14.14.6",
"@types/shelljs": "^0.8.8",
"@types/sinon": "4.1.3",
"@types/sinon-chai": "2.7.29",
"@types/source-map": "^0.5.2",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/parser": "^4.29.1",
"babel-polyfill": "6.26.0",
"chai": "^4.2.0",
"check-side-effects": "0.0.23",
"color": "3.0.0",
"colors": "1.1.2",
"cross-env": "5.1.3",
"cz-conventional-changelog": "1.2.0",
"dependency-cruiser": "^9.12.0",
"escape-string-regexp": "1.0.5",
"eslint": "^7.8.1",
"eslint-plugin-jasmine": "^2.10.1",
"form-data": "^3.0.0",
"fs-extra": "^8.1.0",
"glob": "7.1.2",
"google-closure-compiler-js": "20170218.0.0",
"husky": "^4.2.5",
"klaw-sync": "3.0.2",
"lint-staged": "^10.2.11",
"lodash": "^4.17.15",
"minimist": "^1.2.5",
"mocha": "^8.1.3",
"nodemon": "^1.9.2",
"npm-run-all": "4.1.2",
"opn-cli": "3.1.0",
"platform": "1.3.5",
"prettier": "^2.5.1",
"promise": "8.0.1",
"rollup": "0.66.6",
"rollup-plugin-alias": "1.4.0",
"rollup-plugin-inject": "2.0.0",
"rollup-plugin-node-resolve": "2.0.0",
"shelljs": "^0.8.4",
"shx": "^0.3.2",
"sinon": "4.3.0",
"sinon-chai": "2.14.0",
"source-map-support": "0.5.3",
"systemjs": "^0.21.0",
"ts-node": "^9.1.1",
"tslint": "^5.20.1",
"tslint-config-prettier": "^1.18.0",
"tslint-etc": "1.13.10",
"tslint-no-toplevel-property-access": "0.0.2",
"tslint-no-unused-expression-chai": "0.0.3",
"typescript": "~4.2.0",
"validate-commit-msg": "2.14.0",
"web-streams-polyfill": "^3.0.2",
"webpack": "^4.31.0"
},
"files": [
"dist/bundles",
"dist/cjs/**/!(*.tsbuildinfo)",
"dist/esm/**/!(*.tsbuildinfo)",
"dist/esm5/**/!(*.tsbuildinfo)",
"dist/types/**/!(*.tsbuildinfo)",
"ajax",
"fetch",
"operators",
"testing",
"webSocket",
"src",
"CHANGELOG.md",
"CODE_OF_CONDUCT.md",
"LICENSE.txt",
"package.json",
"README.md",
"tsconfig.json"
],
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "validate-commit-msg"
}
}
}

View File

@ -0,0 +1,5 @@
(function (root, factory) {
root.Rx = factory();
})(window || global || this, function () {
return require('../dist/package/Rx');
});

View File

@ -0,0 +1,4 @@
export { ajax } from '../internal/ajax/ajax';
export { AjaxError, AjaxTimeoutError } from '../internal/ajax/errors';
export { AjaxResponse } from '../internal/ajax/AjaxResponse';
export { AjaxRequest, AjaxConfig, AjaxDirection } from '../internal/ajax/types';

View File

@ -0,0 +1 @@
export { fromFetch } from '../internal/observable/dom/fetch';

View File

@ -0,0 +1,209 @@
//////////////////////////////////////////////////////////
// Here we need to reference our other deep imports
// so VS code will figure out where they are
// see conversation here:
// https://github.com/microsoft/TypeScript/issues/43034
//////////////////////////////////////////////////////////
// tslint:disable: no-reference
// It's tempting to add references to all of the deep-import locations, but
// adding references to those that require DOM types breaks Node projects.
/// <reference path="./operators/index.ts" />
/// <reference path="./testing/index.ts" />
// tslint:enable: no-reference
/* Observable */
export { Observable } from './internal/Observable';
export { ConnectableObservable } from './internal/observable/ConnectableObservable';
export { GroupedObservable } from './internal/operators/groupBy';
export { Operator } from './internal/Operator';
export { observable } from './internal/symbol/observable';
export { animationFrames } from './internal/observable/dom/animationFrames';
/* Subjects */
export { Subject } from './internal/Subject';
export { BehaviorSubject } from './internal/BehaviorSubject';
export { ReplaySubject } from './internal/ReplaySubject';
export { AsyncSubject } from './internal/AsyncSubject';
/* Schedulers */
export { asap, asapScheduler } from './internal/scheduler/asap';
export { async, asyncScheduler } from './internal/scheduler/async';
export { queue, queueScheduler } from './internal/scheduler/queue';
export { animationFrame, animationFrameScheduler } from './internal/scheduler/animationFrame';
export { VirtualTimeScheduler, VirtualAction } from './internal/scheduler/VirtualTimeScheduler';
export { Scheduler } from './internal/Scheduler';
/* Subscription */
export { Subscription } from './internal/Subscription';
export { Subscriber } from './internal/Subscriber';
/* Notification */
export { Notification, NotificationKind } from './internal/Notification';
/* Utils */
export { pipe } from './internal/util/pipe';
export { noop } from './internal/util/noop';
export { identity } from './internal/util/identity';
export { isObservable } from './internal/util/isObservable';
/* Promise Conversion */
export { lastValueFrom } from './internal/lastValueFrom';
export { firstValueFrom } from './internal/firstValueFrom';
/* Error types */
export { ArgumentOutOfRangeError } from './internal/util/ArgumentOutOfRangeError';
export { EmptyError } from './internal/util/EmptyError';
export { NotFoundError } from './internal/util/NotFoundError';
export { ObjectUnsubscribedError } from './internal/util/ObjectUnsubscribedError';
export { SequenceError } from './internal/util/SequenceError';
export { TimeoutError } from './internal/operators/timeout';
export { UnsubscriptionError } from './internal/util/UnsubscriptionError';
/* Static observable creation exports */
export { bindCallback } from './internal/observable/bindCallback';
export { bindNodeCallback } from './internal/observable/bindNodeCallback';
export { combineLatest } from './internal/observable/combineLatest';
export { concat } from './internal/observable/concat';
export { connectable } from './internal/observable/connectable';
export { defer } from './internal/observable/defer';
export { empty } from './internal/observable/empty';
export { forkJoin } from './internal/observable/forkJoin';
export { from } from './internal/observable/from';
export { fromEvent } from './internal/observable/fromEvent';
export { fromEventPattern } from './internal/observable/fromEventPattern';
export { generate } from './internal/observable/generate';
export { iif } from './internal/observable/iif';
export { interval } from './internal/observable/interval';
export { merge } from './internal/observable/merge';
export { never } from './internal/observable/never';
export { of } from './internal/observable/of';
export { onErrorResumeNext } from './internal/observable/onErrorResumeNext';
export { pairs } from './internal/observable/pairs';
export { partition } from './internal/observable/partition';
export { race } from './internal/observable/race';
export { range } from './internal/observable/range';
export { throwError } from './internal/observable/throwError';
export { timer } from './internal/observable/timer';
export { using } from './internal/observable/using';
export { zip } from './internal/observable/zip';
export { scheduled } from './internal/scheduled/scheduled';
/* Constants */
export { EMPTY } from './internal/observable/empty';
export { NEVER } from './internal/observable/never';
/* Types */
export * from './internal/types';
/* Config */
export { config, GlobalConfig } from './internal/config';
/* Operators */
export { audit } from './internal/operators/audit';
export { auditTime } from './internal/operators/auditTime';
export { buffer } from './internal/operators/buffer';
export { bufferCount } from './internal/operators/bufferCount';
export { bufferTime } from './internal/operators/bufferTime';
export { bufferToggle } from './internal/operators/bufferToggle';
export { bufferWhen } from './internal/operators/bufferWhen';
export { catchError } from './internal/operators/catchError';
export { combineAll } from './internal/operators/combineAll';
export { combineLatestAll } from './internal/operators/combineLatestAll';
export { combineLatestWith } from './internal/operators/combineLatestWith';
export { concatAll } from './internal/operators/concatAll';
export { concatMap } from './internal/operators/concatMap';
export { concatMapTo } from './internal/operators/concatMapTo';
export { concatWith } from './internal/operators/concatWith';
export { connect, ConnectConfig } from './internal/operators/connect';
export { count } from './internal/operators/count';
export { debounce } from './internal/operators/debounce';
export { debounceTime } from './internal/operators/debounceTime';
export { defaultIfEmpty } from './internal/operators/defaultIfEmpty';
export { delay } from './internal/operators/delay';
export { delayWhen } from './internal/operators/delayWhen';
export { dematerialize } from './internal/operators/dematerialize';
export { distinct } from './internal/operators/distinct';
export { distinctUntilChanged } from './internal/operators/distinctUntilChanged';
export { distinctUntilKeyChanged } from './internal/operators/distinctUntilKeyChanged';
export { elementAt } from './internal/operators/elementAt';
export { endWith } from './internal/operators/endWith';
export { every } from './internal/operators/every';
export { exhaust } from './internal/operators/exhaust';
export { exhaustAll } from './internal/operators/exhaustAll';
export { exhaustMap } from './internal/operators/exhaustMap';
export { expand } from './internal/operators/expand';
export { filter } from './internal/operators/filter';
export { finalize } from './internal/operators/finalize';
export { find } from './internal/operators/find';
export { findIndex } from './internal/operators/findIndex';
export { first } from './internal/operators/first';
export { groupBy, BasicGroupByOptions, GroupByOptionsWithElement } from './internal/operators/groupBy';
export { ignoreElements } from './internal/operators/ignoreElements';
export { isEmpty } from './internal/operators/isEmpty';
export { last } from './internal/operators/last';
export { map } from './internal/operators/map';
export { mapTo } from './internal/operators/mapTo';
export { materialize } from './internal/operators/materialize';
export { max } from './internal/operators/max';
export { mergeAll } from './internal/operators/mergeAll';
export { flatMap } from './internal/operators/flatMap';
export { mergeMap } from './internal/operators/mergeMap';
export { mergeMapTo } from './internal/operators/mergeMapTo';
export { mergeScan } from './internal/operators/mergeScan';
export { mergeWith } from './internal/operators/mergeWith';
export { min } from './internal/operators/min';
export { multicast } from './internal/operators/multicast';
export { observeOn } from './internal/operators/observeOn';
export { onErrorResumeNextWith } from './internal/operators/onErrorResumeNextWith';
export { pairwise } from './internal/operators/pairwise';
export { pluck } from './internal/operators/pluck';
export { publish } from './internal/operators/publish';
export { publishBehavior } from './internal/operators/publishBehavior';
export { publishLast } from './internal/operators/publishLast';
export { publishReplay } from './internal/operators/publishReplay';
export { raceWith } from './internal/operators/raceWith';
export { reduce } from './internal/operators/reduce';
export { repeat, RepeatConfig } from './internal/operators/repeat';
export { repeatWhen } from './internal/operators/repeatWhen';
export { retry, RetryConfig } from './internal/operators/retry';
export { retryWhen } from './internal/operators/retryWhen';
export { refCount } from './internal/operators/refCount';
export { sample } from './internal/operators/sample';
export { sampleTime } from './internal/operators/sampleTime';
export { scan } from './internal/operators/scan';
export { sequenceEqual } from './internal/operators/sequenceEqual';
export { share, ShareConfig } from './internal/operators/share';
export { shareReplay, ShareReplayConfig } from './internal/operators/shareReplay';
export { single } from './internal/operators/single';
export { skip } from './internal/operators/skip';
export { skipLast } from './internal/operators/skipLast';
export { skipUntil } from './internal/operators/skipUntil';
export { skipWhile } from './internal/operators/skipWhile';
export { startWith } from './internal/operators/startWith';
export { subscribeOn } from './internal/operators/subscribeOn';
export { switchAll } from './internal/operators/switchAll';
export { switchMap } from './internal/operators/switchMap';
export { switchMapTo } from './internal/operators/switchMapTo';
export { switchScan } from './internal/operators/switchScan';
export { take } from './internal/operators/take';
export { takeLast } from './internal/operators/takeLast';
export { takeUntil } from './internal/operators/takeUntil';
export { takeWhile } from './internal/operators/takeWhile';
export { tap, TapObserver } from './internal/operators/tap';
export { throttle, ThrottleConfig } from './internal/operators/throttle';
export { throttleTime } from './internal/operators/throttleTime';
export { throwIfEmpty } from './internal/operators/throwIfEmpty';
export { timeInterval } from './internal/operators/timeInterval';
export { timeout, TimeoutConfig, TimeoutInfo } from './internal/operators/timeout';
export { timeoutWith } from './internal/operators/timeoutWith';
export { timestamp } from './internal/operators/timestamp';
export { toArray } from './internal/operators/toArray';
export { window } from './internal/operators/window';
export { windowCount } from './internal/operators/windowCount';
export { windowTime } from './internal/operators/windowTime';
export { windowToggle } from './internal/operators/windowToggle';
export { windowWhen } from './internal/operators/windowWhen';
export { withLatestFrom } from './internal/operators/withLatestFrom';
export { zipAll } from './internal/operators/zipAll';
export { zipWith } from './internal/operators/zipWith';

View File

@ -0,0 +1,14 @@
/*
* Note that we cannot apply the `internal` tag here because the declaration
* needs to survive the `stripInternal` option. Otherwise, `AnyCatcher` will
* be `any` in the `.d.ts` files.
*/
declare const anyCatcherSymbol: unique symbol;
/**
* This is just a type that we're using to identify `any` being passed to
* function overloads. This is used because of situations like {@link forkJoin},
* where it could return an `Observable<T[]>` or an `Observable<{ [key: K]: T }>`,
* so `forkJoin(any)` would mean we need to return `Observable<unknown>`.
*/
export type AnyCatcher = typeof anyCatcherSymbol;

View File

@ -0,0 +1,41 @@
import { Subject } from './Subject';
import { Subscriber } from './Subscriber';
/**
* A variant of Subject that only emits a value when it completes. It will emit
* its latest value to all its observers on completion.
*
* @class AsyncSubject<T>
*/
export class AsyncSubject<T> extends Subject<T> {
private _value: T | null = null;
private _hasValue = false;
private _isComplete = false;
/** @internal */
protected _checkFinalizedStatuses(subscriber: Subscriber<T>) {
const { hasError, _hasValue, _value, thrownError, isStopped, _isComplete } = this;
if (hasError) {
subscriber.error(thrownError);
} else if (isStopped || _isComplete) {
_hasValue && subscriber.next(_value!);
subscriber.complete();
}
}
next(value: T): void {
if (!this.isStopped) {
this._value = value;
this._hasValue = true;
}
}
complete(): void {
const { _hasValue, _value, _isComplete } = this;
if (!_isComplete) {
this._isComplete = true;
_hasValue && super.next(_value!);
super.complete();
}
}
}

View File

@ -0,0 +1,39 @@
import { Subject } from './Subject';
import { Subscriber } from './Subscriber';
import { Subscription } from './Subscription';
/**
* A variant of Subject that requires an initial value and emits its current
* value whenever it is subscribed to.
*
* @class BehaviorSubject<T>
*/
export class BehaviorSubject<T> extends Subject<T> {
constructor(private _value: T) {
super();
}
get value(): T {
return this.getValue();
}
/** @internal */
protected _subscribe(subscriber: Subscriber<T>): Subscription {
const subscription = super._subscribe(subscriber);
!subscription.closed && subscriber.next(this._value);
return subscription;
}
getValue(): T {
const { hasError, thrownError, _value } = this;
if (hasError) {
throw thrownError;
}
this._throwIfClosed();
return _value;
}
next(value: T): void {
super.next((this._value = value));
}
}

View File

@ -0,0 +1,243 @@
import { PartialObserver, ObservableNotification, CompleteNotification, NextNotification, ErrorNotification } from './types';
import { Observable } from './Observable';
import { EMPTY } from './observable/empty';
import { of } from './observable/of';
import { throwError } from './observable/throwError';
import { isFunction } from './util/isFunction';
// TODO: When this enum is removed, replace it with a type alias. See #4556.
/**
* @deprecated Use a string literal instead. `NotificationKind` will be replaced with a type alias in v8.
* It will not be replaced with a const enum as those are not compatible with isolated modules.
*/
export enum NotificationKind {
NEXT = 'N',
ERROR = 'E',
COMPLETE = 'C',
}
/**
* Represents a push-based event or value that an {@link Observable} can emit.
* This class is particularly useful for operators that manage notifications,
* like {@link materialize}, {@link dematerialize}, {@link observeOn}, and
* others. Besides wrapping the actual delivered value, it also annotates it
* with metadata of, for instance, what type of push message it is (`next`,
* `error`, or `complete`).
*
* @see {@link materialize}
* @see {@link dematerialize}
* @see {@link observeOn}
* @deprecated It is NOT recommended to create instances of `Notification` directly.
* Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
* For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
* Will be removed in v8.
*/
export class Notification<T> {
/**
* A value signifying that the notification will "next" if observed. In truth,
* This is really synonymous with just checking `kind === "N"`.
* @deprecated Will be removed in v8. Instead, just check to see if the value of `kind` is `"N"`.
*/
readonly hasValue: boolean;
/**
* Creates a "Next" notification object.
* @param kind Always `'N'`
* @param value The value to notify with if observed.
* @deprecated Internal implementation detail. Use {@link Notification#createNext createNext} instead.
*/
constructor(kind: 'N', value?: T);
/**
* Creates an "Error" notification object.
* @param kind Always `'E'`
* @param value Always `undefined`
* @param error The error to notify with if observed.
* @deprecated Internal implementation detail. Use {@link Notification#createError createError} instead.
*/
constructor(kind: 'E', value: undefined, error: any);
/**
* Creates a "completion" notification object.
* @param kind Always `'C'`
* @deprecated Internal implementation detail. Use {@link Notification#createComplete createComplete} instead.
*/
constructor(kind: 'C');
constructor(public readonly kind: 'N' | 'E' | 'C', public readonly value?: T, public readonly error?: any) {
this.hasValue = kind === 'N';
}
/**
* Executes the appropriate handler on a passed `observer` given the `kind` of notification.
* If the handler is missing it will do nothing. Even if the notification is an error, if
* there is no error handler on the observer, an error will not be thrown, it will noop.
* @param observer The observer to notify.
*/
observe(observer: PartialObserver<T>): void {
return observeNotification(this as ObservableNotification<T>, observer);
}
/**
* Executes a notification on the appropriate handler from a list provided.
* If a handler is missing for the kind of notification, nothing is called
* and no error is thrown, it will be a noop.
* @param next A next handler
* @param error An error handler
* @param complete A complete handler
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
do(next: (value: T) => void, error: (err: any) => void, complete: () => void): void;
/**
* Executes a notification on the appropriate handler from a list provided.
* If a handler is missing for the kind of notification, nothing is called
* and no error is thrown, it will be a noop.
* @param next A next handler
* @param error An error handler
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
do(next: (value: T) => void, error: (err: any) => void): void;
/**
* Executes the next handler if the Notification is of `kind` `"N"`. Otherwise
* this will not error, and it will be a noop.
* @param next The next handler
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
do(next: (value: T) => void): void;
do(nextHandler: (value: T) => void, errorHandler?: (err: any) => void, completeHandler?: () => void): void {
const { kind, value, error } = this;
return kind === 'N' ? nextHandler?.(value!) : kind === 'E' ? errorHandler?.(error) : completeHandler?.();
}
/**
* Executes a notification on the appropriate handler from a list provided.
* If a handler is missing for the kind of notification, nothing is called
* and no error is thrown, it will be a noop.
* @param next A next handler
* @param error An error handler
* @param complete A complete handler
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
accept(next: (value: T) => void, error: (err: any) => void, complete: () => void): void;
/**
* Executes a notification on the appropriate handler from a list provided.
* If a handler is missing for the kind of notification, nothing is called
* and no error is thrown, it will be a noop.
* @param next A next handler
* @param error An error handler
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
accept(next: (value: T) => void, error: (err: any) => void): void;
/**
* Executes the next handler if the Notification is of `kind` `"N"`. Otherwise
* this will not error, and it will be a noop.
* @param next The next handler
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
accept(next: (value: T) => void): void;
/**
* Executes the appropriate handler on a passed `observer` given the `kind` of notification.
* If the handler is missing it will do nothing. Even if the notification is an error, if
* there is no error handler on the observer, an error will not be thrown, it will noop.
* @param observer The observer to notify.
* @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
*/
accept(observer: PartialObserver<T>): void;
accept(nextOrObserver: PartialObserver<T> | ((value: T) => void), error?: (err: any) => void, complete?: () => void) {
return isFunction((nextOrObserver as any)?.next)
? this.observe(nextOrObserver as PartialObserver<T>)
: this.do(nextOrObserver as (value: T) => void, error as any, complete as any);
}
/**
* Returns a simple Observable that just delivers the notification represented
* by this Notification instance.
*
* @deprecated Will be removed in v8. To convert a `Notification` to an {@link Observable},
* use {@link of} and {@link dematerialize}: `of(notification).pipe(dematerialize())`.
*/
toObservable(): Observable<T> {
const { kind, value, error } = this;
// Select the observable to return by `kind`
const result =
kind === 'N'
? // Next kind. Return an observable of that value.
of(value!)
: //
kind === 'E'
? // Error kind. Return an observable that emits the error.
throwError(() => error)
: //
kind === 'C'
? // Completion kind. Kind is "C", return an observable that just completes.
EMPTY
: // Unknown kind, return falsy, so we error below.
0;
if (!result) {
// TODO: consider removing this check. The only way to cause this would be to
// use the Notification constructor directly in a way that is not type-safe.
// and direct use of the Notification constructor is deprecated.
throw new TypeError(`Unexpected notification kind ${kind}`);
}
return result;
}
private static completeNotification = new Notification('C') as Notification<never> & CompleteNotification;
/**
* A shortcut to create a Notification instance of the type `next` from a
* given value.
* @param {T} value The `next` value.
* @return {Notification<T>} The "next" Notification representing the
* argument.
* @nocollapse
* @deprecated It is NOT recommended to create instances of `Notification` directly.
* Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
* For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
* Will be removed in v8.
*/
static createNext<T>(value: T) {
return new Notification('N', value) as Notification<T> & NextNotification<T>;
}
/**
* A shortcut to create a Notification instance of the type `error` from a
* given error.
* @param {any} [err] The `error` error.
* @return {Notification<T>} The "error" Notification representing the
* argument.
* @nocollapse
* @deprecated It is NOT recommended to create instances of `Notification` directly.
* Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
* For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
* Will be removed in v8.
*/
static createError(err?: any) {
return new Notification('E', undefined, err) as Notification<never> & ErrorNotification;
}
/**
* A shortcut to create a Notification instance of the type `complete`.
* @return {Notification<any>} The valueless "complete" Notification.
* @nocollapse
* @deprecated It is NOT recommended to create instances of `Notification` directly.
* Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
* For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
* Will be removed in v8.
*/
static createComplete(): Notification<never> & CompleteNotification {
return Notification.completeNotification;
}
}
/**
* Executes the appropriate handler on a passed `observer` given the `kind` of notification.
* If the handler is missing it will do nothing. Even if the notification is an error, if
* there is no error handler on the observer, an error will not be thrown, it will noop.
* @param notification The notification object to observe.
* @param observer The observer to notify.
*/
export function observeNotification<T>(notification: ObservableNotification<T>, observer: PartialObserver<T>) {
const { kind, value, error } = notification as any;
if (typeof kind !== 'string') {
throw new TypeError('Invalid notification, missing "kind"');
}
kind === 'N' ? observer.next?.(value!) : kind === 'E' ? observer.error?.(error) : observer.complete?.();
}

View File

@ -0,0 +1,40 @@
import { CompleteNotification, NextNotification, ErrorNotification } from './types';
/**
* A completion object optimized for memory use and created to be the
* same "shape" as other notifications in v8.
* @internal
*/
export const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();
/**
* Internal use only. Creates an optimized error notification that is the same "shape"
* as other notifications.
* @internal
*/
export function errorNotification(error: any): ErrorNotification {
return createNotification('E', undefined, error) as any;
}
/**
* Internal use only. Creates an optimized next notification that is the same "shape"
* as other notifications.
* @internal
*/
export function nextNotification<T>(value: T) {
return createNotification('N', value, undefined) as NextNotification<T>;
}
/**
* Ensures that all notifications created internally have the same "shape" in v8.
*
* TODO: This is only exported to support a crazy legacy test in `groupBy`.
* @internal
*/
export function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {
return {
kind,
value,
error,
};
}

View File

@ -0,0 +1,498 @@
import { Operator } from './Operator';
import { SafeSubscriber, Subscriber } from './Subscriber';
import { isSubscription, Subscription } from './Subscription';
import { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';
import { observable as Symbol_observable } from './symbol/observable';
import { pipeFromArray } from './util/pipe';
import { config } from './config';
import { isFunction } from './util/isFunction';
import { errorContext } from './util/errorContext';
/**
* A representation of any set of values over any amount of time. This is the most basic building block
* of RxJS.
*
* @class Observable<T>
*/
export class Observable<T> implements Subscribable<T> {
/**
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
*/
source: Observable<any> | undefined;
/**
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
*/
operator: Operator<any, T> | undefined;
/**
* @constructor
* @param {Function} subscribe the function that is called when the Observable is
* initially subscribed to. This function is given a Subscriber, to which new values
* can be `next`ed, or an `error` method can be called to raise an error, or
* `complete` can be called to notify of a successful completion.
*/
constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic) {
if (subscribe) {
this._subscribe = subscribe;
}
}
// HACK: Since TypeScript inherits static properties too, we have to
// fight against TypeScript here so Subject can have a different static create signature
/**
* Creates a new Observable by calling the Observable constructor
* @owner Observable
* @method create
* @param {Function} subscribe? the subscriber function to be passed to the Observable constructor
* @return {Observable} a new observable
* @nocollapse
* @deprecated Use `new Observable()` instead. Will be removed in v8.
*/
static create: (...args: any[]) => any = <T>(subscribe?: (subscriber: Subscriber<T>) => TeardownLogic) => {
return new Observable<T>(subscribe);
};
/**
* Creates a new Observable, with this Observable instance as the source, and the passed
* operator defined as the new observable's operator.
* @method lift
* @param operator the operator defining the operation to take on the observable
* @return a new observable with the Operator applied
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
* If you have implemented an operator using `lift`, it is recommended that you create an
* operator by simply returning `new Observable()` directly. See "Creating new operators from
* scratch" section here: https://rxjs.dev/guide/operators
*/
lift<R>(operator?: Operator<T, R>): Observable<R> {
const observable = new Observable<R>();
observable.source = this;
observable.operator = operator;
return observable;
}
subscribe(observerOrNext?: Partial<Observer<T>> | ((value: T) => void)): Subscription;
/** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */
subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;
/**
* Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.
*
* <span class="informal">Use it when you have all these Observables, but still nothing is happening.</span>
*
* `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It
* might be for example a function that you passed to Observable's constructor, but most of the time it is
* a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means
* that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often
* the thought.
*
* Apart from starting the execution of an Observable, this method allows you to listen for values
* that an Observable emits, as well as for when it completes or errors. You can achieve this in two
* of the following ways.
*
* The first way is creating an object that implements {@link Observer} interface. It should have methods
* defined by that interface, but note that it should be just a regular JavaScript object, which you can create
* yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do
* not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also
* that your object does not have to implement all methods. If you find yourself creating a method that doesn't
* do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,
* it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,
* use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or
* `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide
* an `error` method to avoid missing thrown errors.
*
* The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.
* This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent
* of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,
* if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,
* since `subscribe` recognizes these functions by where they were placed in function call. When it comes
* to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.
*
* You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events
* and you also handled emissions internally by using operators (e.g. using `tap`).
*
* Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.
* This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean
* up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback
* provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.
*
* Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.
* It is an Observable itself that decides when these functions will be called. For example {@link of}
* by default emits all its values synchronously. Always check documentation for how given Observable
* will behave when subscribed and if its default behavior can be modified with a `scheduler`.
*
* #### Examples
*
* Subscribe with an {@link guide/observer Observer}
*
* ```ts
* import { of } from 'rxjs';
*
* const sumObserver = {
* sum: 0,
* next(value) {
* console.log('Adding: ' + value);
* this.sum = this.sum + value;
* },
* error() {
* // We actually could just remove this method,
* // since we do not really care about errors right now.
* },
* complete() {
* console.log('Sum equals: ' + this.sum);
* }
* };
*
* of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.
* .subscribe(sumObserver);
*
* // Logs:
* // 'Adding: 1'
* // 'Adding: 2'
* // 'Adding: 3'
* // 'Sum equals: 6'
* ```
*
* Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})
*
* ```ts
* import { of } from 'rxjs'
*
* let sum = 0;
*
* of(1, 2, 3).subscribe(
* value => {
* console.log('Adding: ' + value);
* sum = sum + value;
* },
* undefined,
* () => console.log('Sum equals: ' + sum)
* );
*
* // Logs:
* // 'Adding: 1'
* // 'Adding: 2'
* // 'Adding: 3'
* // 'Sum equals: 6'
* ```
*
* Cancel a subscription
*
* ```ts
* import { interval } from 'rxjs';
*
* const subscription = interval(1000).subscribe({
* next(num) {
* console.log(num)
* },
* complete() {
* // Will not be called, even when cancelling subscription.
* console.log('completed!');
* }
* });
*
* setTimeout(() => {
* subscription.unsubscribe();
* console.log('unsubscribed!');
* }, 2500);
*
* // Logs:
* // 0 after 1s
* // 1 after 2s
* // 'unsubscribed!' after 2.5s
* ```
*
* @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,
* or the first of three possible handlers, which is the handler for each value emitted from the subscribed
* Observable.
* @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,
* the error will be thrown asynchronously as unhandled.
* @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.
* @return {Subscription} a subscription reference to the registered handlers
* @method subscribe
*/
subscribe(
observerOrNext?: Partial<Observer<T>> | ((value: T) => void) | null,
error?: ((error: any) => void) | null,
complete?: (() => void) | null
): Subscription {
const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);
errorContext(() => {
const { operator, source } = this;
subscriber.add(
operator
? // We're dealing with a subscription in the
// operator chain to one of our lifted operators.
operator.call(subscriber, source)
: source
? // If `source` has a value, but `operator` does not, something that
// had intimate knowledge of our API, like our `Subject`, must have
// set it. We're going to just call `_subscribe` directly.
this._subscribe(subscriber)
: // In all other cases, we're likely wrapping a user-provided initializer
// function, so we need to catch errors and handle them appropriately.
this._trySubscribe(subscriber)
);
});
return subscriber;
}
/** @internal */
protected _trySubscribe(sink: Subscriber<T>): TeardownLogic {
try {
return this._subscribe(sink);
} catch (err) {
// We don't need to return anything in this case,
// because it's just going to try to `add()` to a subscription
// above.
sink.error(err);
}
}
/**
* Used as a NON-CANCELLABLE means of subscribing to an observable, for use with
* APIs that expect promises, like `async/await`. You cannot unsubscribe from this.
*
* **WARNING**: Only use this with observables you *know* will complete. If the source
* observable does not complete, you will end up with a promise that is hung up, and
* potentially all of the state of an async function hanging out in memory. To avoid
* this situation, look into adding something like {@link timeout}, {@link take},
* {@link takeWhile}, or {@link takeUntil} amongst others.
*
* #### Example
*
* ```ts
* import { interval, take } from 'rxjs';
*
* const source$ = interval(1000).pipe(take(4));
*
* async function getTotal() {
* let total = 0;
*
* await source$.forEach(value => {
* total += value;
* console.log('observable -> ' + value);
* });
*
* return total;
* }
*
* getTotal().then(
* total => console.log('Total: ' + total)
* );
*
* // Expected:
* // 'observable -> 0'
* // 'observable -> 1'
* // 'observable -> 2'
* // 'observable -> 3'
* // 'Total: 6'
* ```
*
* @param next a handler for each value emitted by the observable
* @return a promise that either resolves on observable completion or
* rejects with the handled error
*/
forEach(next: (value: T) => void): Promise<void>;
/**
* @param next a handler for each value emitted by the observable
* @param promiseCtor a constructor function used to instantiate the Promise
* @return a promise that either resolves on observable completion or
* rejects with the handled error
* @deprecated Passing a Promise constructor will no longer be available
* in upcoming versions of RxJS. This is because it adds weight to the library, for very
* little benefit. If you need this functionality, it is recommended that you either
* polyfill Promise, or you create an adapter to convert the returned native promise
* to whatever promise implementation you wanted. Will be removed in v8.
*/
forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise<void>;
forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise<void> {
promiseCtor = getPromiseCtor(promiseCtor);
return new promiseCtor<void>((resolve, reject) => {
const subscriber = new SafeSubscriber<T>({
next: (value) => {
try {
next(value);
} catch (err) {
reject(err);
subscriber.unsubscribe();
}
},
error: reject,
complete: resolve,
});
this.subscribe(subscriber);
}) as Promise<void>;
}
/** @internal */
protected _subscribe(subscriber: Subscriber<any>): TeardownLogic {
return this.source?.subscribe(subscriber);
}
/**
* An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable
* @method Symbol.observable
* @return {Observable} this instance of the observable
*/
[Symbol_observable]() {
return this;
}
/* tslint:disable:max-line-length */
pipe(): Observable<T>;
pipe<A>(op1: OperatorFunction<T, A>): Observable<A>;
pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;
pipe<A, B, C>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>): Observable<C>;
pipe<A, B, C, D>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>
): Observable<D>;
pipe<A, B, C, D, E>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>
): Observable<E>;
pipe<A, B, C, D, E, F>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>
): Observable<F>;
pipe<A, B, C, D, E, F, G>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>
): Observable<G>;
pipe<A, B, C, D, E, F, G, H>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>,
op8: OperatorFunction<G, H>
): Observable<H>;
pipe<A, B, C, D, E, F, G, H, I>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>,
op8: OperatorFunction<G, H>,
op9: OperatorFunction<H, I>
): Observable<I>;
pipe<A, B, C, D, E, F, G, H, I>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>,
op8: OperatorFunction<G, H>,
op9: OperatorFunction<H, I>,
...operations: OperatorFunction<any, any>[]
): Observable<unknown>;
/* tslint:enable:max-line-length */
/**
* Used to stitch together functional operators into a chain.
* @method pipe
* @return {Observable} the Observable result of all of the operators having
* been called in the order they were passed in.
*
* ## Example
*
* ```ts
* import { interval, filter, map, scan } from 'rxjs';
*
* interval(1000)
* .pipe(
* filter(x => x % 2 === 0),
* map(x => x + x),
* scan((acc, x) => acc + x)
* )
* .subscribe(x => console.log(x));
* ```
*/
pipe(...operations: OperatorFunction<any, any>[]): Observable<any> {
return pipeFromArray(operations)(this);
}
/* tslint:disable:max-line-length */
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */
toPromise(): Promise<T | undefined>;
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */
toPromise(PromiseCtor: typeof Promise): Promise<T | undefined>;
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */
toPromise(PromiseCtor: PromiseConstructorLike): Promise<T | undefined>;
/* tslint:enable:max-line-length */
/**
* Subscribe to this Observable and get a Promise resolving on
* `complete` with the last emission (if any).
*
* **WARNING**: Only use this with observables you *know* will complete. If the source
* observable does not complete, you will end up with a promise that is hung up, and
* potentially all of the state of an async function hanging out in memory. To avoid
* this situation, look into adding something like {@link timeout}, {@link take},
* {@link takeWhile}, or {@link takeUntil} amongst others.
*
* @method toPromise
* @param [promiseCtor] a constructor function used to instantiate
* the Promise
* @return A Promise that resolves with the last value emit, or
* rejects on an error. If there were no emissions, Promise
* resolves with undefined.
* @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise
*/
toPromise(promiseCtor?: PromiseConstructorLike): Promise<T | undefined> {
promiseCtor = getPromiseCtor(promiseCtor);
return new promiseCtor((resolve, reject) => {
let value: T | undefined;
this.subscribe(
(x: T) => (value = x),
(err: any) => reject(err),
() => resolve(value)
);
}) as Promise<T | undefined>;
}
}
/**
* Decides between a passed promise constructor from consuming code,
* A default configured promise constructor, and the native promise
* constructor and returns it. If nothing can be found, it will throw
* an error.
* @param promiseCtor The optional promise constructor to passed by consuming code
*/
function getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {
return promiseCtor ?? config.Promise ?? Promise;
}
function isObserver<T>(value: any): value is Observer<T> {
return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);
}
function isSubscriber<T>(value: any): value is Subscriber<T> {
return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));
}

View File

@ -0,0 +1,9 @@
import { Subscriber } from './Subscriber';
import { TeardownLogic } from './types';
/***
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
*/
export interface Operator<T, R> {
call(subscriber: Subscriber<R>, source: any): TeardownLogic;
}

View File

@ -0,0 +1,110 @@
import { Subject } from './Subject';
import { TimestampProvider } from './types';
import { Subscriber } from './Subscriber';
import { Subscription } from './Subscription';
import { dateTimestampProvider } from './scheduler/dateTimestampProvider';
/**
* A variant of {@link Subject} that "replays" old values to new subscribers by emitting them when they first subscribe.
*
* `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,
* `ReplaySubject` "observes" values by having them passed to its `next` method. When it observes a value, it will store that
* value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.
*
* When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in
* a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will
* error if it has observed an error.
*
* There are two main configuration items to be concerned with:
*
* 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.
* 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.
*
* Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values
* are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.
*
* ### Differences with BehaviorSubject
*
* `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:
*
* 1. `BehaviorSubject` comes "primed" with a single value upon construction.
* 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.
*
* @see {@link Subject}
* @see {@link BehaviorSubject}
* @see {@link shareReplay}
*/
export class ReplaySubject<T> extends Subject<T> {
private _buffer: (T | number)[] = [];
private _infiniteTimeWindow = true;
/**
* @param bufferSize The size of the buffer to replay on subscription
* @param windowTime The amount of time the buffered items will stay buffered
* @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to
* calculate the amount of time something has been buffered.
*/
constructor(
private _bufferSize = Infinity,
private _windowTime = Infinity,
private _timestampProvider: TimestampProvider = dateTimestampProvider
) {
super();
this._infiniteTimeWindow = _windowTime === Infinity;
this._bufferSize = Math.max(1, _bufferSize);
this._windowTime = Math.max(1, _windowTime);
}
next(value: T): void {
const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;
if (!isStopped) {
_buffer.push(value);
!_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);
}
this._trimBuffer();
super.next(value);
}
/** @internal */
protected _subscribe(subscriber: Subscriber<T>): Subscription {
this._throwIfClosed();
this._trimBuffer();
const subscription = this._innerSubscribe(subscriber);
const { _infiniteTimeWindow, _buffer } = this;
// We use a copy here, so reentrant code does not mutate our array while we're
// emitting it to a new subscriber.
const copy = _buffer.slice();
for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {
subscriber.next(copy[i] as T);
}
this._checkFinalizedStatuses(subscriber);
return subscription;
}
private _trimBuffer() {
const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;
// If we don't have an infinite buffer size, and we're over the length,
// use splice to truncate the old buffer values off. Note that we have to
// double the size for instances where we're not using an infinite time window
// because we're storing the values and the timestamps in the same array.
const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;
_bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);
// Now, if we're not in an infinite time window, remove all values where the time is
// older than what is allowed.
if (!_infiniteTimeWindow) {
const now = _timestampProvider.now();
let last = 0;
// Search the array for the first timestamp that isn't expired and
// truncate the buffer up to that point.
for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {
last = i;
}
last && _buffer.splice(0, last + 1);
}
}
}

View File

@ -0,0 +1,62 @@
import { Action } from './scheduler/Action';
import { Subscription } from './Subscription';
import { SchedulerLike, SchedulerAction } from './types';
import { dateTimestampProvider } from './scheduler/dateTimestampProvider';
/**
* An execution context and a data structure to order tasks and schedule their
* execution. Provides a notion of (potentially virtual) time, through the
* `now()` getter method.
*
* Each unit of work in a Scheduler is called an `Action`.
*
* ```ts
* class Scheduler {
* now(): number;
* schedule(work, delay?, state?): Subscription;
* }
* ```
*
* @class Scheduler
* @deprecated Scheduler is an internal implementation detail of RxJS, and
* should not be used directly. Rather, create your own class and implement
* {@link SchedulerLike}. Will be made internal in v8.
*/
export class Scheduler implements SchedulerLike {
public static now: () => number = dateTimestampProvider.now;
constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {
this.now = now;
}
/**
* A getter method that returns a number representing the current time
* (at the time this function was called) according to the scheduler's own
* internal clock.
* @return {number} A number that represents the current time. May or may not
* have a relation to wall-clock time. May or may not refer to a time unit
* (e.g. milliseconds).
*/
public now: () => number;
/**
* Schedules a function, `work`, for execution. May happen at some point in
* the future, according to the `delay` parameter, if specified. May be passed
* some context object, `state`, which will be passed to the `work` function.
*
* The given arguments will be processed an stored as an Action object in a
* queue of actions.
*
* @param {function(state: ?T): ?Subscription} work A function representing a
* task, or some unit of work to be executed by the Scheduler.
* @param {number} [delay] Time to wait before executing the work, where the
* time unit is implicit and defined by the Scheduler itself.
* @param {T} [state] Some contextual data that the `work` function uses when
* called by the Scheduler.
* @return {Subscription} A subscription in order to be able to unsubscribe
* the scheduled work.
*/
public schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay: number = 0, state?: T): Subscription {
return new this.schedulerActionCtor<T>(this, work).schedule(state, delay);
}
}

Some files were not shown because too many files have changed in this diff Show More