mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-10-06 10:02:00 +00:00
Compare commits
No commits in common. "bd9fbb4da52ef90a91b1ada93916850e4e500ce7" and "a9b720ee0839954bfbb9e5b0ab8820f2a1f52763" have entirely different histories.
bd9fbb4da5
...
a9b720ee08
11 changed files with 56 additions and 876 deletions
8
.github/workflows/deploy-mobile.yaml
vendored
8
.github/workflows/deploy-mobile.yaml
vendored
|
|
@ -1,9 +1,11 @@
|
|||
name: Deploy Mobile (iOS)
|
||||
|
||||
# Disabled during development. To activate for V1 release, change to:
|
||||
# on:
|
||||
# push:
|
||||
# branches: [main]
|
||||
# paths: ["mobile/**"]
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths: ["mobile/**"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
|
|
|
|||
21
README.md
21
README.md
|
|
@ -18,7 +18,7 @@ Monorepo with five primary services:
|
|||
proposal-system/
|
||||
├── api/ .NET 8 Web API (Lambda-hosted, EF Core + PostgreSQL)
|
||||
├── web/ React 19 + MUI v7 + Vite frontend
|
||||
├── mobile/ React Native 0.85 iOS app
|
||||
├── mobile/ React Native 0.79 iOS app
|
||||
├── lambdas/ Python 3.12 processing functions (arm64)
|
||||
├── infra/ CDK TypeScript (3 stacks)
|
||||
├── shared/ TypeScript API contracts (shared between web + mobile)
|
||||
|
|
@ -33,7 +33,7 @@ proposal-system/
|
|||
|---|---|
|
||||
| API | .NET 8, ASP.NET Core, EF Core + Npgsql, FluentValidation, Cognito JWT, Amazon.Lambda.AspNetCoreServer |
|
||||
| Web | React 19, TypeScript, MUI v7, Vite, Redux Toolkit, TanStack Query, axios |
|
||||
| Mobile | React Native CLI 0.85, React 19, React Native Paper, React Navigation, react-native-app-auth (PKCE), amazon-cognito-identity-js (SRP), Keychain, offline draft queue |
|
||||
| Mobile | React Native CLI 0.79, React 19, React Native Paper, React Navigation, react-native-app-auth (PKCE), Keychain, offline draft queue |
|
||||
| Lambdas | Python 3.12, arm64, pdfplumber, reportlab, httpx, boto3 |
|
||||
| Infrastructure | CDK TypeScript (aws-cdk-lib 2.253.1) |
|
||||
| AI/RAG | Bedrock Knowledge Base (Titan Embeddings v2), OpenSearch Serverless, Claude via Bedrock Runtime |
|
||||
|
|
@ -127,13 +127,11 @@ Calls `cd-cdk.yaml` reusable workflow:
|
|||
|
||||
Deploy uses OIDC role `githubdeploy-proposal-system`. Concurrency group prevents parallel deploys.
|
||||
|
||||
### Mobile Deploy
|
||||
### Mobile Deploy (currently disabled)
|
||||
|
||||
Workflow: `deploy-mobile.yaml` -- builds and uploads to TestFlight via `cd-mobile-ios.yaml` reusable workflow on `macos-26`.
|
||||
Workflow: `deploy-mobile.yaml` -- triggered by `workflow_dispatch` only (manual).
|
||||
|
||||
Triggers:
|
||||
- **Automatic**: push to `main` with changes in `mobile/**`
|
||||
- **Manual**: `workflow_dispatch` for on-demand builds
|
||||
To activate for release, change the trigger to push on main with path filter `mobile/**`.
|
||||
|
||||
## Mobile iOS
|
||||
|
||||
|
|
@ -149,6 +147,15 @@ Build and upload to TestFlight is handled by the `cd-mobile-ios.yaml` reusable w
|
|||
| `ASC_ISSUER_ID` | App Store Connect issuer |
|
||||
| `ASC_KEY_CONTENT` | App Store Connect API key (base64) |
|
||||
|
||||
To activate automatic deploys, update `deploy-mobile.yaml` trigger from `workflow_dispatch` to:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths: ["mobile/**"]
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. Dispatcher submits proposal request (web or mobile)
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ export class FoundationStack extends cdk.Stack {
|
|||
});
|
||||
|
||||
// Web App Client (PKCE)
|
||||
const webClient = userPool.addClient('WebClient', {
|
||||
userPool.addClient('WebClient', {
|
||||
userPoolClientName: 'proposal-system-web',
|
||||
generateSecret: false,
|
||||
authFlows: {
|
||||
|
|
@ -235,7 +235,7 @@ export class FoundationStack extends cdk.Stack {
|
|||
});
|
||||
|
||||
// Mobile App Client (PKCE)
|
||||
const mobileClient = userPool.addClient('MobileClient', {
|
||||
userPool.addClient('MobileClient', {
|
||||
userPoolClientName: 'proposal-system-mobile',
|
||||
generateSecret: false,
|
||||
authFlows: {
|
||||
|
|
@ -248,8 +248,8 @@ export class FoundationStack extends cdk.Stack {
|
|||
cognito.OAuthScope.EMAIL,
|
||||
cognito.OAuthScope.PROFILE,
|
||||
],
|
||||
callbackUrls: ['com.seahavenind.proposals://auth/callback'],
|
||||
logoutUrls: ['com.seahavenind.proposals://auth/logout'],
|
||||
callbackUrls: ['proposalsystem://callback'],
|
||||
logoutUrls: ['proposalsystem://logout'],
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -278,7 +278,5 @@ export class FoundationStack extends cdk.Stack {
|
|||
new cdk.CfnOutput(this, 'LibraryBucketName', { value: this.libraryBucket.bucketName });
|
||||
new cdk.CfnOutput(this, 'JobsQueueUrl', { value: this.jobsQueue.queueUrl });
|
||||
new cdk.CfnOutput(this, 'DbSecretArn', { value: this.dbSecret.secretArn });
|
||||
new cdk.CfnOutput(this, 'WebClientId', { value: webClient.userPoolClientId });
|
||||
new cdk.CfnOutput(this, 'MobileClientId', { value: mobileClient.userPoolClientId });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
# Proposal System — Mobile (iOS)
|
||||
|
||||
React Native 0.85 iOS app for Sea Haven Industries field dispatchers. Submit proposals, capture vendor documents, and manage drafts with offline support.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 24+
|
||||
- Ruby 3.x (for Fastlane)
|
||||
- Xcode 26+ with iOS 26 SDK
|
||||
- CocoaPods (installed via Bundler)
|
||||
|
||||
## Local Development
|
||||
|
||||
```bash
|
||||
# Install JS dependencies
|
||||
npm install
|
||||
|
||||
# Install Ruby dependencies (Fastlane, CocoaPods)
|
||||
bundle install
|
||||
|
||||
# Install native pods
|
||||
cd ios && bundle exec pod install && cd ..
|
||||
|
||||
# Start Metro bundler
|
||||
npm start
|
||||
|
||||
# Run on iOS simulator
|
||||
npm run ios
|
||||
```
|
||||
|
||||
### Environment
|
||||
|
||||
The app reads configuration from `src/config.ts`. In development mode (`__DEV__`), the API URL points to `http://localhost:5000/api`. Run the .NET API locally or use the development proxy.
|
||||
|
||||
### Authentication
|
||||
|
||||
Two login methods are supported:
|
||||
|
||||
- **Email/Password** — direct Cognito SRP auth via `amazon-cognito-identity-js`
|
||||
- **Google OAuth** — Cognito Hosted UI PKCE flow via `react-native-app-auth`
|
||||
|
||||
The iOS URL scheme `com.seahavenind.proposals` is registered in `Info.plist` for OAuth callbacks.
|
||||
|
||||
## Code Signing
|
||||
|
||||
Certificates and provisioning profiles are managed by **Fastlane Match** using S3 storage:
|
||||
|
||||
- **Bucket**: `seahaven-ios-certificates` (us-east-1)
|
||||
- **Bundle ID**: `com.seahavenind.proposals`
|
||||
- **Team ID**: `9KAQYC653W`
|
||||
|
||||
Match is configured in `fastlane/Matchfile`. The `MATCH_PASSWORD` secret decrypts signing assets.
|
||||
|
||||
## CI/CD
|
||||
|
||||
The `deploy-mobile.yaml` workflow triggers on push to `main` (with `mobile/**` path filter) or manual `workflow_dispatch`. It calls the `cd-mobile-ios.yaml` reusable workflow which:
|
||||
|
||||
1. Sets up `macos-26` runner with Xcode 26
|
||||
2. Installs dependencies and pods
|
||||
3. Retrieves signing assets via Match (S3)
|
||||
4. Builds the IPA with Fastlane
|
||||
5. Uploads to TestFlight
|
||||
|
||||
### Required GitHub Secrets
|
||||
|
||||
| Secret | Purpose |
|
||||
|---|---|
|
||||
| `AWS_DEPLOY_ROLE_ARN` | OIDC role for Match S3 access |
|
||||
| `MATCH_PASSWORD` | Signing asset decryption passphrase |
|
||||
| `ASC_KEY_ID` | App Store Connect API key ID |
|
||||
| `ASC_ISSUER_ID` | App Store Connect API issuer |
|
||||
| `ASC_KEY_CONTENT` | App Store Connect `.p8` key (base64) |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
mobile/
|
||||
├── src/
|
||||
│ ├── screens/ Auth, dispatcher, and admin screens
|
||||
│ ├── lib/api/ API clients (auth, proposals, line items, admin)
|
||||
│ ├── store/ Redux Toolkit (auth slice)
|
||||
│ ├── navigation/ React Navigation (RootNavigator)
|
||||
│ ├── components/ Reusable UI components
|
||||
│ ├── hooks/ useAuth, useOfflineDraft, usePaginatedList
|
||||
│ ├── theme/ Material Design 3 theming
|
||||
│ ├── constants/ App-wide constants
|
||||
│ └── config.ts Cognito + API configuration
|
||||
├── ios/ Xcode project, assets, Info.plist
|
||||
├── fastlane/ Fastfile, Matchfile, Appfile
|
||||
├── Gemfile Ruby dependencies
|
||||
└── package.json React Native 0.85.3
|
||||
```
|
||||
452
mobile/package-lock.json
generated
452
mobile/package-lock.json
generated
|
|
@ -16,7 +16,6 @@
|
|||
"@react-navigation/native-stack": "^7.2.0",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tanstack/react-query": "^5.100.10",
|
||||
"amazon-cognito-identity-js": "^6.3.0",
|
||||
"axios": "^1.16.0",
|
||||
"react": "^19.0.0",
|
||||
"react-native": "^0.85.3",
|
||||
|
|
@ -39,7 +38,6 @@
|
|||
"@react-native/metro-config": "^0.85.3",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-native-vector-icons": "^6.4.18",
|
||||
"patch-package": "^8.0.1",
|
||||
"typescript": "~5.7.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -50,62 +48,6 @@
|
|||
"typescript": "~5.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-crypto/sha256-js": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz",
|
||||
"integrity": "sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/util": "^1.2.2",
|
||||
"@aws-sdk/types": "^3.1.0",
|
||||
"tslib": "^1.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-crypto/util": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-1.2.2.tgz",
|
||||
"integrity": "sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "^3.1.0",
|
||||
"@aws-sdk/util-utf8-browser": "^3.0.0",
|
||||
"tslib": "^1.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/types": {
|
||||
"version": "3.973.8",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.8.tgz",
|
||||
"integrity": "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@smithy/types": "^4.14.1",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/types/node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/@aws-sdk/util-utf8-browser": {
|
||||
"version": "3.259.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
|
||||
"integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
||||
|
|
@ -2197,24 +2139,6 @@
|
|||
"integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@smithy/types": {
|
||||
"version": "4.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.2.tgz",
|
||||
"integrity": "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@smithy/types/node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
|
||||
|
|
@ -2345,13 +2269,6 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@yarnpkg/lockfile": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
|
||||
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/abort-controller": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
|
|
@ -2402,30 +2319,6 @@
|
|||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/amazon-cognito-identity-js": {
|
||||
"version": "6.3.16",
|
||||
"resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.16.tgz",
|
||||
"integrity": "sha512-HPGSBGD6Q36t99puWh0LnptxO/4icnk2kqIQ9cTJ2tFQo5NMUnWQIgtrTAk8nm+caqUbjDzXzG56GBjI2tS6jQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "1.2.2",
|
||||
"buffer": "4.9.2",
|
||||
"fast-base64-decode": "^1.0.0",
|
||||
"isomorphic-unfetch": "^3.0.0",
|
||||
"js-cookie": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/amazon-cognito-identity-js/node_modules/buffer": {
|
||||
"version": "4.9.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
||||
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.0.2",
|
||||
"ieee754": "^1.1.4",
|
||||
"isarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/anser": {
|
||||
"version": "1.4.10",
|
||||
"resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
|
||||
|
|
@ -2777,25 +2670,6 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
|
||||
"integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"get-intrinsic": "^1.3.0",
|
||||
"set-function-length": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
|
|
@ -3242,24 +3116,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
|
|
@ -3509,12 +3365,6 @@
|
|||
"integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/fast-base64-decode": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz",
|
||||
"integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
|
|
@ -3694,16 +3544,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-yarn-workspace-root": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
|
||||
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"micromatch": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/flow-enums-runtime": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
|
||||
|
|
@ -3887,19 +3727,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
|
|
@ -4048,6 +3875,7 @@
|
|||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -4240,28 +4068,12 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/isomorphic-unfetch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz",
|
||||
"integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.1",
|
||||
"unfetch": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-get-type": {
|
||||
"version": "29.6.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
|
||||
|
|
@ -4364,12 +4176,6 @@
|
|||
"@sideway/pinpoint": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-cookie": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
|
||||
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
|
@ -4401,33 +4207,6 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stable-stringify": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
|
||||
"integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.4",
|
||||
"isarray": "^2.0.5",
|
||||
"jsonify": "^0.0.1",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/json-stable-stringify/node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
|
|
@ -4450,26 +4229,6 @@
|
|||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
|
||||
"integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
|
||||
"dev": true,
|
||||
"license": "Public Domain",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/klaw-sync": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
|
||||
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.11"
|
||||
}
|
||||
},
|
||||
"node_modules/kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
|
|
@ -5183,16 +4942,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
|
|
@ -5249,26 +4998,6 @@
|
|||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
|
|
@ -5348,16 +5077,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
|
|
@ -5507,103 +5226,6 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz",
|
||||
"integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@yarnpkg/lockfile": "^1.1.0",
|
||||
"chalk": "^4.1.2",
|
||||
"ci-info": "^3.7.0",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"find-yarn-workspace-root": "^2.0.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"json-stable-stringify": "^1.0.2",
|
||||
"klaw-sync": "^6.0.0",
|
||||
"minimist": "^1.2.6",
|
||||
"open": "^7.4.2",
|
||||
"semver": "^7.5.3",
|
||||
"slash": "^2.0.0",
|
||||
"tmp": "^0.2.4",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"bin": {
|
||||
"patch-package": "index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14",
|
||||
"npm": ">5"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/ci-info": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
|
||||
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/sibiraj-s"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/jsonfile": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
|
||||
"integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/semver": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
|
||||
"integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/patch-package/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
|
|
@ -6520,24 +6142,6 @@
|
|||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
|
|
@ -6691,16 +6295,6 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
|
||||
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
|
||||
|
|
@ -6978,16 +6572,6 @@
|
|||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/tmpl": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
|
|
@ -7015,18 +6599,6 @@
|
|||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
|
||||
|
|
@ -7116,12 +6688,6 @@
|
|||
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unfetch": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz",
|
||||
"integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
|
||||
|
|
@ -7290,28 +6856,12 @@
|
|||
"defaults": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/whatwg-fetch": {
|
||||
"version": "3.6.20",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
|
||||
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
"start": "react-native start",
|
||||
"ios": "react-native run-ios",
|
||||
"android": "react-native run-android",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"postinstall": "patch-package"
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@proposal-system/api-contracts": "file:../shared/api-contracts",
|
||||
|
|
@ -18,7 +17,6 @@
|
|||
"@react-navigation/native-stack": "^7.2.0",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tanstack/react-query": "^5.100.10",
|
||||
"amazon-cognito-identity-js": "^6.3.0",
|
||||
"axios": "^1.16.0",
|
||||
"react": "^19.0.0",
|
||||
"react-native": "^0.85.3",
|
||||
|
|
@ -41,7 +39,6 @@
|
|||
"@react-native/metro-config": "^0.85.3",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-native-vector-icons": "^6.4.18",
|
||||
"patch-package": "^8.0.1",
|
||||
"typescript": "~5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
diff --git a/node_modules/@react-native-community/netinfo/ios/RNCConnectionState.m b/node_modules/@react-native-community/netinfo/ios/RNCConnectionState.m
|
||||
index 5a807a4..94e53f8 100644
|
||||
--- a/node_modules/@react-native-community/netinfo/ios/RNCConnectionState.m
|
||||
+++ b/node_modules/@react-native-community/netinfo/ios/RNCConnectionState.m
|
||||
@@ -47,24 +47,28 @@
|
||||
_expensive = true;
|
||||
|
||||
CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
|
||||
- if (netinfo) {
|
||||
- if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
|
||||
+ if (netinfo && [netinfo respondsToSelector:@selector(currentRadioAccessTechnology)]) {
|
||||
+#pragma clang diagnostic push
|
||||
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
+ NSString *radio = netinfo.currentRadioAccessTechnology;
|
||||
+#pragma clang diagnostic pop
|
||||
+ if ([radio isEqualToString:CTRadioAccessTechnologyGPRS] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyEdge] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
|
||||
_cellularGeneration = RNCCellularGeneration2g;
|
||||
- } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) {
|
||||
+ } else if ([radio isEqualToString:CTRadioAccessTechnologyWCDMA] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyHSDPA] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyHSUPA] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyeHRPD]) {
|
||||
_cellularGeneration = RNCCellularGeneration3g;
|
||||
- } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
|
||||
+ } else if ([radio isEqualToString:CTRadioAccessTechnologyLTE]) {
|
||||
_cellularGeneration = RNCCellularGeneration4g;
|
||||
} else if (@available(iOS 14.1, *)) {
|
||||
- if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNRNSA] ||
|
||||
- [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNR]) {
|
||||
+ if ([radio isEqualToString:CTRadioAccessTechnologyNRNSA] ||
|
||||
+ [radio isEqualToString:CTRadioAccessTechnologyNR]) {
|
||||
_cellularGeneration = RNCCellularGeneration5g;
|
||||
}
|
||||
}
|
||||
diff --git a/node_modules/@react-native-community/netinfo/ios/RNCNetInfo.mm b/node_modules/@react-native-community/netinfo/ios/RNCNetInfo.mm
|
||||
index baa2de0..6b75224 100644
|
||||
--- a/node_modules/@react-native-community/netinfo/ios/RNCNetInfo.mm
|
||||
+++ b/node_modules/@react-native-community/netinfo/ios/RNCNetInfo.mm
|
||||
@@ -190,7 +190,13 @@ RCT_EXPORT_METHOD(configure:(NSDictionary *)config)
|
||||
return nil;
|
||||
#else
|
||||
CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
|
||||
+ if (![netinfo respondsToSelector:@selector(subscriberCellularProvider)]) {
|
||||
+ return nil;
|
||||
+ }
|
||||
+#pragma clang diagnostic push
|
||||
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
CTCarrier *carrier = [netinfo subscriberCellularProvider];
|
||||
+#pragma clang diagnostic pop
|
||||
return carrier.carrierName;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ const Config = {
|
|||
API_URL: __DEV__
|
||||
? 'http://localhost:5000/api'
|
||||
: 'https://api.proposals.seahaven.com/api',
|
||||
COGNITO_DOMAIN: 'proposal-system-seahaven.auth.us-east-1.amazoncognito.com',
|
||||
COGNITO_CLIENT_ID: '3egjbljml6o9qg3q155t784018',
|
||||
COGNITO_USER_POOL_ID: 'us-east-1_DfWcl2q5z',
|
||||
COGNITO_DOMAIN: 'proposal-system.auth.us-east-1.amazoncognito.com',
|
||||
COGNITO_CLIENT_ID: '',
|
||||
COGNITO_USER_POOL_ID: '',
|
||||
COGNITO_REDIRECT_URI: 'com.seahavenind.proposals://auth/callback',
|
||||
COGNITO_SCOPES: ['openid', 'email', 'profile'],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { authorize, refresh, revoke } from 'react-native-app-auth';
|
||||
import Config from '../../config';
|
||||
import apiClient from './client';
|
||||
import { authenticateWithCredentials } from './cognito-auth';
|
||||
import {
|
||||
tokenStorage,
|
||||
userStorage,
|
||||
|
|
@ -39,25 +38,6 @@ export const authApi = {
|
|||
return profile;
|
||||
},
|
||||
|
||||
loginWithCredentials: async (
|
||||
email: string,
|
||||
password: string,
|
||||
): Promise<StoredUser> => {
|
||||
const cognitoTokens = await authenticateWithCredentials(email, password);
|
||||
|
||||
const tokens: StoredTokens = {
|
||||
accessToken: cognitoTokens.accessToken,
|
||||
idToken: cognitoTokens.idToken,
|
||||
refreshToken: cognitoTokens.refreshToken,
|
||||
expiresAt: cognitoTokens.expiresAt,
|
||||
};
|
||||
await tokenStorage.save(tokens);
|
||||
|
||||
const profile = await authApi.getMe();
|
||||
await userStorage.save(profile);
|
||||
return profile;
|
||||
},
|
||||
|
||||
refreshTokens: async (): Promise<void> => {
|
||||
const stored = await tokenStorage.get();
|
||||
if (!stored?.refreshToken) throw new Error('No refresh token');
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
import type { CognitoUserSession } from 'amazon-cognito-identity-js';
|
||||
import Config from '../../config';
|
||||
|
||||
export interface CognitoTokens {
|
||||
accessToken: string;
|
||||
idToken: string;
|
||||
refreshToken: string;
|
||||
expiresAt: string;
|
||||
}
|
||||
|
||||
function extractTokens(session: CognitoUserSession): CognitoTokens {
|
||||
const accessToken = session.getAccessToken();
|
||||
return {
|
||||
accessToken: accessToken.getJwtToken(),
|
||||
idToken: session.getIdToken().getJwtToken(),
|
||||
refreshToken: session.getRefreshToken().getToken(),
|
||||
expiresAt: new Date(accessToken.getExpiration() * 1000).toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function authenticateWithCredentials(
|
||||
email: string,
|
||||
password: string,
|
||||
): Promise<CognitoTokens> {
|
||||
// Lazy-load to keep amazon-cognito-identity-js out of the startup module graph
|
||||
const {
|
||||
CognitoUserPool,
|
||||
CognitoUser,
|
||||
AuthenticationDetails,
|
||||
} = await import('amazon-cognito-identity-js');
|
||||
|
||||
const userPool = new CognitoUserPool({
|
||||
UserPoolId: Config.COGNITO_USER_POOL_ID,
|
||||
ClientId: Config.COGNITO_CLIENT_ID,
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const cognitoUser = new CognitoUser({
|
||||
Username: email,
|
||||
Pool: userPool,
|
||||
});
|
||||
|
||||
const authDetails = new AuthenticationDetails({
|
||||
Username: email,
|
||||
Password: password,
|
||||
});
|
||||
|
||||
cognitoUser.authenticateUser(authDetails, {
|
||||
onSuccess: (session) => {
|
||||
resolve(extractTokens(session));
|
||||
},
|
||||
onFailure: (err) => {
|
||||
if (err.code === 'NotAuthorizedException') {
|
||||
reject(new Error('Incorrect email or password.'));
|
||||
} else if (err.code === 'UserNotFoundException') {
|
||||
reject(new Error('No account found with that email.'));
|
||||
} else if (err.code === 'UserNotConfirmedException') {
|
||||
reject(new Error('Account not confirmed. Contact your administrator.'));
|
||||
} else {
|
||||
reject(new Error(err.message || 'Authentication failed.'));
|
||||
}
|
||||
},
|
||||
newPasswordRequired: () => {
|
||||
reject(new Error('Password change required. Contact your administrator.'));
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,67 +1,23 @@
|
|||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
StyleSheet,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
ScrollView,
|
||||
} from 'react-native';
|
||||
import {
|
||||
Button,
|
||||
Text,
|
||||
Surface,
|
||||
TextInput,
|
||||
Divider,
|
||||
HelperText,
|
||||
} from 'react-native-paper';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { Button, Text, Surface } from 'react-native-paper';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { authApi } from '../../lib/api/auth';
|
||||
import { setUser, setError, clearError } from '../../store/slices/authSlice';
|
||||
import { setUser, setError } from '../../store/slices/authSlice';
|
||||
|
||||
export function LoginScreen() {
|
||||
const dispatch = useDispatch();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [localError, setLocalError] = useState('');
|
||||
|
||||
const handleGoogleLogin = async () => {
|
||||
const handleLogin = async () => {
|
||||
setLoading(true);
|
||||
setLocalError('');
|
||||
dispatch(clearError());
|
||||
try {
|
||||
const user = await authApi.login();
|
||||
dispatch(setUser(user));
|
||||
} catch (err) {
|
||||
const message =
|
||||
err instanceof Error ? err.message : 'Login failed. Please try again.';
|
||||
setLocalError(message);
|
||||
dispatch(setError(message));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCredentialLogin = async () => {
|
||||
if (!email.trim() || !password) {
|
||||
setLocalError('Email and password are required.');
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
setLocalError('');
|
||||
dispatch(clearError());
|
||||
try {
|
||||
const user = await authApi.loginWithCredentials(
|
||||
email.trim().toLowerCase(),
|
||||
password,
|
||||
);
|
||||
dispatch(setUser(user));
|
||||
} catch (err) {
|
||||
const message =
|
||||
err instanceof Error ? err.message : 'Login failed. Please try again.';
|
||||
setLocalError(message);
|
||||
dispatch(setError(message));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
|
@ -70,92 +26,28 @@ export function LoginScreen() {
|
|||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<KeyboardAvoidingView
|
||||
style={styles.flex}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.content}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
<Surface style={styles.logoContainer} elevation={0}>
|
||||
<Text variant="headlineLarge" style={styles.brand}>
|
||||
Sea Haven
|
||||
</Text>
|
||||
<Text variant="titleMedium" style={styles.brandSub}>
|
||||
Industries
|
||||
</Text>
|
||||
</Surface>
|
||||
|
||||
<Text variant="headlineSmall" style={styles.title}>
|
||||
Proposal System
|
||||
<View style={styles.content}>
|
||||
<Surface style={styles.logoContainer} elevation={0}>
|
||||
<Text variant="headlineLarge" style={styles.brand}>
|
||||
Sea Haven
|
||||
</Text>
|
||||
<Text variant="bodyLarge" style={styles.subtitle}>
|
||||
Submit and manage proposals from anywhere
|
||||
<Text variant="titleMedium" style={styles.brandSub}>
|
||||
Industries
|
||||
</Text>
|
||||
</Surface>
|
||||
|
||||
<View style={styles.form}>
|
||||
<TextInput
|
||||
label="Email"
|
||||
value={email}
|
||||
onChangeText={setEmail}
|
||||
autoCapitalize="none"
|
||||
autoComplete="email"
|
||||
keyboardType="email-address"
|
||||
textContentType="emailAddress"
|
||||
mode="outlined"
|
||||
disabled={loading}
|
||||
style={styles.input}
|
||||
/>
|
||||
<TextInput
|
||||
label="Password"
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry={!showPassword}
|
||||
autoCapitalize="none"
|
||||
autoComplete="password"
|
||||
textContentType="password"
|
||||
mode="outlined"
|
||||
disabled={loading}
|
||||
style={styles.input}
|
||||
right={
|
||||
<TextInput.Icon
|
||||
icon={showPassword ? 'eye-off' : 'eye'}
|
||||
onPress={() => setShowPassword(!showPassword)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
{localError ? (
|
||||
<HelperText type="error" visible>
|
||||
{localError}
|
||||
</HelperText>
|
||||
) : null}
|
||||
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={handleCredentialLogin}
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
contentStyle={styles.buttonContent}
|
||||
style={styles.button}
|
||||
>
|
||||
Sign In
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<View style={styles.dividerRow}>
|
||||
<Divider style={styles.dividerLine} />
|
||||
<Text variant="bodySmall" style={styles.dividerText}>
|
||||
OR
|
||||
</Text>
|
||||
<Divider style={styles.dividerLine} />
|
||||
</View>
|
||||
<Text variant="headlineSmall" style={styles.title}>
|
||||
Proposal System
|
||||
</Text>
|
||||
<Text variant="bodyLarge" style={styles.subtitle}>
|
||||
Submit and manage proposals from anywhere
|
||||
</Text>
|
||||
|
||||
<View style={styles.actions}>
|
||||
<Button
|
||||
mode="outlined"
|
||||
mode="contained"
|
||||
icon="google"
|
||||
onPress={handleGoogleLogin}
|
||||
onPress={handleLogin}
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
contentStyle={styles.buttonContent}
|
||||
|
|
@ -163,12 +55,12 @@ export function LoginScreen() {
|
|||
>
|
||||
Sign in with Google
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<Text variant="bodySmall" style={styles.footer}>
|
||||
Use your Sea Haven email to sign in
|
||||
</Text>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
<Text variant="bodySmall" style={styles.footer}>
|
||||
Use your Sea Haven Workspace account
|
||||
</Text>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
@ -178,15 +70,11 @@ const styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
backgroundColor: '#FAFAFA',
|
||||
},
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 32,
|
||||
paddingVertical: 24,
|
||||
},
|
||||
logoContainer: {
|
||||
alignItems: 'center',
|
||||
|
|
@ -209,33 +97,16 @@ const styles = StyleSheet.create({
|
|||
subtitle: {
|
||||
color: '#757575',
|
||||
textAlign: 'center',
|
||||
marginBottom: 32,
|
||||
marginBottom: 48,
|
||||
},
|
||||
form: {
|
||||
actions: {
|
||||
width: '100%',
|
||||
},
|
||||
input: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
buttonContent: {
|
||||
paddingVertical: 8,
|
||||
},
|
||||
button: {
|
||||
borderRadius: 8,
|
||||
width: '100%',
|
||||
},
|
||||
dividerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
marginVertical: 20,
|
||||
},
|
||||
dividerLine: {
|
||||
flex: 1,
|
||||
},
|
||||
dividerText: {
|
||||
color: '#9E9E9E',
|
||||
marginHorizontal: 16,
|
||||
},
|
||||
footer: {
|
||||
color: '#9E9E9E',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue