├── .husky ├── .gitignore ├── pre-commit └── commit-msg ├── libs ├── nx-vercel │ ├── src │ │ ├── index.ts │ │ └── executors │ │ │ └── deploy │ │ │ ├── schema.d.ts │ │ │ ├── schema.json │ │ │ ├── executor.spec.ts │ │ │ └── executor.ts │ ├── generators.json │ ├── .babelrc │ ├── package.json │ ├── README.md │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── executors.json │ ├── tsconfig.json │ ├── jest.config.ts │ ├── .eslintrc.json │ └── project.json ├── nx-remotecache-s3 │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── nx-remotecache-s3.spec.ts │ │ │ ├── nx-remotecache-s3.ts │ │ │ ├── test-utils.ts │ │ │ ├── util.ts │ │ │ ├── setup-s3-task-runner.ts │ │ │ ├── util.spec.ts │ │ │ ├── s3-client.ts │ │ │ ├── s3-client.spec.ts │ │ │ └── setup-s3-task-runner.spec.ts │ ├── .babelrc │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── jest.config.ts │ ├── .eslintrc.json │ ├── package.json │ ├── project.json │ ├── README.md │ └── CHANGELOG.md └── eslint-config │ ├── base │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── prettier.ts │ │ │ ├── etc.ts │ │ │ ├── unicorn.ts │ │ │ ├── import.ts │ │ │ ├── rxjs.ts │ │ │ ├── eslint.ts │ │ │ └── typescript-eslint.ts │ │ ├── javascript.ts │ │ └── typescript.ts │ ├── .babelrc │ ├── tsconfig.lib.json │ ├── tsconfig.json │ ├── jest.config.ts │ ├── tsconfig.spec.json │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── project.json │ └── CHANGELOG.md │ └── angular │ ├── src │ ├── angular-template.ts │ ├── index.spec.ts │ ├── angular.ts │ ├── index.ts │ └── lib │ │ ├── rxjs-angular.ts │ │ ├── angular-template.ts │ │ ├── angular-eslint.ts │ │ └── ngrx.ts │ ├── .babelrc │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── jest.config.ts │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── project.json │ └── CHANGELOG.md ├── .eslintignore ├── .prettierrc ├── .vscode ├── settings.json └── extensions.json ├── .prettierignore ├── jest.config.ts ├── .env ├── jest.preset.js ├── .editorconfig ├── tools ├── tsconfig.tools.json └── scripts │ └── ignore-vercel-build.sh ├── commitlint.config.js ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── release.yml │ ├── codeql-analysis.yml │ └── ci.yml ├── .gitignore ├── tsconfig.base.json ├── .eslintrc.json ├── LICENSE ├── nx.json ├── README.md ├── package.json └── CODE_OF_CONDUCT.md /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /libs/nx-vercel/src/index.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": ["json"] 3 | } 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './lib/nx-remotecache-s3'; 2 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/index.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: ['./javascript', './typescript'], 3 | }; 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit "${1}" 5 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/prettier.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: ['prettier'], 3 | rules: {}, 4 | }; 5 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/angular-template.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: ['./lib/angular-template'], 3 | }; 4 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import index from './index'; 2 | 3 | test('default', () => expect(index).toBeDefined()); 4 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/angular.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: ['./lib/angular-eslint', './lib/rxjs-angular', './lib/ngrx'], 3 | }; 4 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/etc.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['etc'], 3 | rules: { 'etc/no-commented-out-code': 'error' }, 4 | }; 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | 6 | /.nx/cache 7 | /.nx/workspace-data -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /libs/nx-vercel/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "name": "nx-vercel", 4 | "version": "0.0.1", 5 | "generators": {} 6 | } 7 | -------------------------------------------------------------------------------- /libs/nx-vercel/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/index.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: [ 3 | '@pellegrims/eslint-config-base', 4 | './angular', 5 | './angular-template', 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /libs/eslint-config/base/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner", 6 | "dbaeumer.vscode-eslint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/unicorn.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['unicorn'], 3 | rules: { 4 | 'unicorn/filename-case': 'error', 5 | 'unicorn/no-abusive-eslint-disable': 'error', 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /libs/nx-vercel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pellegrims/nx-vercel", 3 | "version": "0.0.1", 4 | "main": "src/index.js", 5 | "generators": "./generators.json", 6 | "executors": "./executors.json" 7 | } 8 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/javascript.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: [ 3 | './lib/eslint', 4 | './lib/etc', 5 | './lib/import', 6 | './lib/unicorn', 7 | './lib/prettier', 8 | ], 9 | }; 10 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # Nx 18 enables using plugins to infer targets by default 2 | # This is disabled for existing workspaces to maintain compatibility 3 | # For more info, see: https://nx.dev/concepts/inferred-tasks 4 | NX_ADD_PLUGINS=false -------------------------------------------------------------------------------- /libs/nx-vercel/src/executors/deploy/schema.d.ts: -------------------------------------------------------------------------------- 1 | export type VercelEnvironment = 'preview' | 'production'; 2 | 3 | export interface BuildExecutorSchema { 4 | projectId: string; 5 | orgId: string; 6 | environment?: VercelEnvironment; 7 | } 8 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { 4 | ...nxPreset, 5 | collectCoverage: true, 6 | collectCoverageFrom: ['/**/*.{js,jsx,ts,tsx}'], 7 | coverageReporters: ['json'], 8 | }; 9 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/typescript.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: [ 3 | './lib/eslint', 4 | './lib/etc', 5 | './lib/import', 6 | './lib/rxjs', 7 | './lib/typescript-eslint', 8 | './lib/prettier', 9 | ], 10 | }; 11 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/nx-remotecache-s3.spec.ts: -------------------------------------------------------------------------------- 1 | import runner from './nx-remotecache-s3'; 2 | 3 | describe('nx-remotecache-s3', () => 4 | test('should have a defined runner', async () => 5 | expect(runner).toBeInstanceOf(Function))); 6 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/lib/rxjs-angular.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['rxjs-angular'], 3 | rules: { 4 | 'rxjs-angular/prefer-async-pipe': 'warn', 5 | 'rxjs-angular/prefer-takeuntil': [ 6 | 'error', 7 | { alias: ['untilDestroyed', 'take'] }, 8 | ], 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /libs/nx-vercel/README.md: -------------------------------------------------------------------------------- 1 | # nx-vercel 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build nx-vercel` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test nx-vercel` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /libs/nx-vercel/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/nx-vercel/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"] 7 | }, 8 | "include": ["**/*.ts"], 9 | "exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/import.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['import'], 3 | overrides: [ 4 | { 5 | files: ['*.ts', '*.tsx'], 6 | extends: ['plugin:import/typescript'], 7 | }, 8 | ], 9 | rules: { 10 | 'import/no-deprecated': 'warn', 11 | 'import/no-duplicates': 'error', 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /libs/eslint-config/base/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "declaration": true, 7 | "types": [] 8 | }, 9 | "include": ["**/*.ts"], 10 | "exclude": ["jest.config.ts", "**/*.spec.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "../../dist/out-tsc", 6 | "declaration": true, 7 | "types": ["node"] 8 | }, 9 | "exclude": ["**/*.spec.ts", "jest.config.ts"], 10 | "include": ["**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /libs/nx-vercel/executors.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "executors": { 4 | "deploy": { 5 | "implementation": "./src/executors/deploy/executor", 6 | "schema": "./src/executors/deploy/schema.json", 7 | "description": "Deploy to Vercel using the CLI" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/nx-vercel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'scope-enum': [ 5 | 2, 6 | 'always', 7 | [ 8 | 'eslint-config-base', 9 | 'eslint-config-angular', 10 | 'nx-remotecache-s3', 11 | 'nx-vercel', 12 | ], 13 | ], 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.spec.tsx", 11 | "**/*.spec.js", 12 | "**/*.spec.jsx", 13 | "**/*.d.ts", 14 | "jest.config.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/lib/angular-template.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: [ 3 | '@angular-eslint/template', 4 | 'eslint-plugin-angular-template-consistent-this', 5 | ], 6 | extends: ['plugin:@angular-eslint/template/recommended'], 7 | rules: { 8 | 'angular-template-consistent-this/eslint-plugin-angular-template-consistent-this': 9 | ['error', { properties: 'implicit' }], 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "../../../dist/out-tsc", 6 | "types": ["node"] 7 | }, 8 | "exclude": ["**/*.spec.ts", "jest.config.ts"], 9 | "include": [ 10 | "**/*.ts", 11 | "../../../node_modules/.pnpm/@types+node@14.14.33/node_modules/@types/node/globals.d.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"], 7 | "esModuleInterop": true 8 | }, 9 | "include": [ 10 | "**/*.spec.ts", 11 | "**/*.spec.tsx", 12 | "**/*.spec.js", 13 | "**/*.spec.jsx", 14 | "**/*.d.ts", 15 | "jest.config.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /libs/nx-vercel/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'nx-vercel', 4 | preset: '../../jest.preset.js', 5 | globals: {}, 6 | transform: { 7 | '^.+\\.[tj]s$': [ 8 | 'ts-jest', 9 | { 10 | tsconfig: '/tsconfig.spec.json', 11 | }, 12 | ], 13 | }, 14 | moduleFileExtensions: ['ts', 'js', 'html'], 15 | coverageDirectory: '../../coverage/libs/nx-vercel', 16 | }; 17 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/nx-remotecache-s3.ts: -------------------------------------------------------------------------------- 1 | import defaultTasksRunner from 'nx/src/tasks-runner/default-tasks-runner'; 2 | import { createCustomRunner } from 'nx-remotecache-custom'; 3 | import { setupS3TaskRunner } from './setup-s3-task-runner'; 4 | 5 | import type { S3Options } from './setup-s3-task-runner'; 6 | 7 | const runner: typeof defaultTasksRunner = 8 | createCustomRunner(setupS3TaskRunner); 9 | 10 | export default runner; 11 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/lib/angular-eslint.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['@angular-eslint'], 3 | extends: [ 4 | 'plugin:@angular-eslint/recommended', 5 | 'plugin:@angular-eslint/template/process-inline-templates', 6 | ], 7 | rules: { 8 | '@angular-eslint/use-lifecycle-interface': 'error', 9 | '@angular-eslint/use-component-view-encapsulation': 'error', 10 | '@angular-eslint/prefer-on-push-component-change-detection': 'warn', 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /libs/eslint-config/base/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ], 13 | "compilerOptions": { 14 | "forceConsistentCasingInFileNames": true, 15 | "strict": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /libs/eslint-config/base/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'eslint-config-base', 4 | preset: '../../../jest.preset.js', 5 | globals: {}, 6 | transform: { 7 | '^.+\\.[tj]sx?$': [ 8 | 'ts-jest', 9 | { 10 | tsconfig: '/tsconfig.spec.json', 11 | }, 12 | ], 13 | }, 14 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 15 | coverageDirectory: '../../../coverage/libs/eslint-config/base', 16 | }; 17 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/rxjs.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['rxjs'], 3 | extends: ['plugin:rxjs/recommended'], 4 | rules: { 5 | 'rxjs/no-implicit-any-catch': 'error', 6 | 'rxjs/no-unbound-methods': 'error', 7 | 'rxjs/no-unsafe-switchmap': 'error', 8 | 'rxjs/finnish': [ 9 | 'error', 10 | { 11 | functions: false, 12 | methods: false, 13 | parameters: false, 14 | strict: true, 15 | }, 16 | ], 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /libs/eslint-config/base/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "**/*.test.ts", 11 | "**/*.spec.ts", 12 | "**/*.test.tsx", 13 | "**/*.spec.tsx", 14 | "**/*.test.js", 15 | "**/*.spec.js", 16 | "**/*.test.jsx", 17 | "**/*.spec.jsx", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'nx-remotecache-s3', 4 | preset: '../../jest.preset.js', 5 | globals: {}, 6 | testEnvironment: 'node', 7 | transform: { 8 | '^.+\\.[tj]sx?$': [ 9 | 'ts-jest', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | }, 13 | ], 14 | }, 15 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 16 | coverageDirectory: '../../coverage/libs/nx-remotecache-s3', 17 | }; 18 | -------------------------------------------------------------------------------- /libs/nx-vercel/src/executors/deploy/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "title": "Deploy", 4 | "description": "Deploy to Vercel using the Vercel CLI", 5 | "type": "object", 6 | "properties": { 7 | "projectId": { 8 | "type": "string", 9 | "description": "Vercel project id" 10 | }, 11 | "orgId": { 12 | "type": "string", 13 | "description": "Vercel organization id" 14 | } 15 | }, 16 | "required": ["projectId", "orgId"] 17 | } 18 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'eslint-config-angular', 4 | preset: '../../../jest.preset.js', 5 | globals: {}, 6 | testEnvironment: 'node', 7 | transform: { 8 | '^.+\\.[tj]sx?$': [ 9 | 'ts-jest', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | }, 13 | ], 14 | }, 15 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 16 | coverageDirectory: '../../../coverage/libs/eslint-config/angular', 17 | }; 18 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "parserOptions": { 12 | "project": ["./tsconfig.*?.json"] 13 | }, 14 | "rules": { 15 | "@typescript-eslint/naming-convention": "off" 16 | } 17 | }, 18 | { 19 | "files": ["*.js", "*.jsx"], 20 | "rules": {} 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /libs/nx-vercel/src/executors/deploy/executor.spec.ts: -------------------------------------------------------------------------------- 1 | import executor from './executor'; 2 | 3 | jest.mock('child_process'); 4 | 5 | const OLD_ENV = process.env; 6 | 7 | describe('Build Executor', () => { 8 | // eslint-disable-next-line @typescript-eslint/naming-convention 9 | beforeEach(() => (process.env = { ...OLD_ENV, VERCEL_TOKEN: '123' })); 10 | afterEach(() => (process.env = { ...OLD_ENV })); 11 | it('can run', async () => { 12 | const output = await executor({ orgId: '123', projectId: '456' }); 13 | expect(output.success).toBe(true); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /libs/eslint-config/base/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "parserOptions": { 8 | "project": ["libs/eslint-config/base/tsconfig.*?.json"] 9 | }, 10 | "rules": {} 11 | }, 12 | { 13 | "files": ["*.ts", "*.tsx"], 14 | "rules": { 15 | "@typescript-eslint/naming-convention": "off" 16 | } 17 | }, 18 | { 19 | "files": ["*.js", "*.jsx"], 20 | "rules": {} 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "parserOptions": { "project": "./tsconfig.*?.json" }, 12 | "rules": {} 13 | }, 14 | { 15 | "files": ["*.js", "*.jsx"], 16 | "rules": {} 17 | }, 18 | { 19 | "files": ["*.json"], 20 | "parser": "jsonc-eslint-parser", 21 | "rules": { 22 | "@nx/dependency-checks": "error" 23 | } 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /libs/nx-vercel/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {}, 12 | "parserOptions": { "project": "./tsconfig.*?.json" } 13 | }, 14 | { 15 | "files": ["*.js", "*.jsx"], 16 | "rules": {} 17 | }, 18 | { 19 | "files": ["./package.json", "./generators.json", "./executors.json"], 20 | "parser": "jsonc-eslint-parser", 21 | "rules": { 22 | "@nx/nx-plugin-checks": "error" 23 | } 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/src/lib/ngrx.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['ngrx'], 3 | extends: ['plugin:ngrx/recommended'], 4 | rules: { 5 | 'ngrx/avoid-cyclic-effects': 'error', 6 | 'ngrx/avoid-mapping-selectors': 'error', 7 | 'ngrx/good-action-hygiene': 'error', 8 | 'ngrx/no-effect-decorator': 'error', 9 | 'ngrx/no-typed-global-store': 'error', 10 | 'ngrx/on-function-explicit-return-type': 'error', 11 | 'ngrx/prefer-effect-callback-in-block-statement': 'off', 12 | 'ngrx/prefer-inline-action-props': 'off', 13 | 'ngrx/select-style': 'error', 14 | 'ngrx/updater-explicit-return-type': 'error', 15 | 'ngrx/use-consistent-global-store-name': ['error', 'store$'], 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | *.iml 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | yarn-error.log 35 | testem.log 36 | /typings 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db 41 | /migrations.json 42 | 43 | .env.local 44 | 45 | # Next.js 46 | .next 47 | 48 | .vercel 49 | 50 | .nx/cache 51 | .nx/workspace-data 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2018", 12 | "module": "esnext", 13 | "lib": ["es2018", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@pellegrims/eslint-config-angular": [ 19 | "libs/eslint-config/angular/src/index.ts" 20 | ], 21 | "@pellegrims/eslint-config/base": [ 22 | "libs/eslint-config/base/src/index.ts" 23 | ], 24 | "@pellegrims/nx-remotecache-s3": ["libs/nx-remotecache-s3/src/index.ts"], 25 | "@pellegrims/nx-vercel": ["libs/nx-vercel/src/index.ts"] 26 | }, 27 | "strict": true, 28 | "noUnusedLocals": true, 29 | "noUnusedParameters": true 30 | }, 31 | "exclude": ["node_modules", "tmp"] 32 | } 33 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/test-utils.ts: -------------------------------------------------------------------------------- 1 | import { CustomRunnerOptions } from 'nx-remotecache-custom'; 2 | import { S3Options } from './setup-s3-task-runner'; 3 | 4 | export const emptyOptions: CustomRunnerOptions = { lifeCycle: {} }; 5 | 6 | export const defaultOptions: CustomRunnerOptions = { 7 | lifeCycle: {}, 8 | endpoint: 'optionsEndpoint', 9 | region: 'optionsRegion', 10 | forcePathStyle: true, 11 | profile: 'optionsProfile', 12 | bucket: 'optionsBucket', 13 | prefix: 'optionsPrefix', 14 | }; 15 | 16 | export const envValues: Record = { 17 | endpoint: 'envEndpoint', 18 | region: 'envRegion', 19 | forcePathStyle: 'true', 20 | profile: 'envProfile', 21 | bucket: 'envBucket', 22 | prefix: 'envPrefix', 23 | }; 24 | 25 | export const clearProxyInfo = () => { 26 | delete process.env.HTTPS_PROXY; 27 | delete process.env.https_proxy; 28 | delete process.env.HTTP_PROXY; 29 | delete process.env.http_proxy; 30 | delete process.env.NO_PROXY; 31 | delete process.env.no_proxy; 32 | }; 33 | -------------------------------------------------------------------------------- /tools/scripts/ignore-vercel-build.sh: -------------------------------------------------------------------------------- 1 | # Name of the app to check. Change this to your application name! 2 | APP=$1 3 | 4 | # Determine version of Nx installed 5 | NX_VERSION=$(node -e "console.log(require('./package.json').devDependencies['@nx/workspace'])") 6 | TS_VERSION=$(node -e "console.log(require('./package.json').devDependencies['typescript'])") 7 | 8 | # Install @nx/workspace in order to run the affected command 9 | pnpm install -D @nx/workspace@$NX_VERSION --prefer-offline 10 | pnpm install -D typescript@$TS_VERSION --prefer-offline 11 | 12 | # Run the affected command, comparing latest commit to the one before that 13 | # In the future, there should be an environment variable in Vercel to determine what the base for the affected comparison should be. 14 | npx nx affected:apps --plain --base HEAD~1 --head HEAD | grep $APP -q 15 | 16 | # Store result of the previous command (grep) 17 | IS_AFFECTED=$? 18 | 19 | if [ $IS_AFFECTED -eq 1 ]; then 20 | echo "🛑 - Build cancelled" 21 | exit 0 22 | elif [ $IS_AFFECTED -eq 0 ]; then 23 | echo "✅ - Build can proceed" 24 | exit 1 25 | fi 26 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/README.md: -------------------------------------------------------------------------------- 1 | # @pellegrims/eslint-config-angular 2 | 3 | [![npm package link](https://img.shields.io/npm/v/@pellegrims/eslint-config-angular)](https://www.npmjs.com/package/@pellegrims/eslint-config-angular) 4 | 5 | This package provides an opinionated shareable eslint config. 6 | 7 | ## Usage 8 | 9 | This package exports 2 ESLint configurations. 10 | 11 | To install all peer dependencies automatically: 12 | 13 | ```sh 14 | npx install-peerdeps --dev @pellegrims/eslint-config-angular 15 | ``` 16 | 17 | ### @pellegrims/eslint-config-angular/angular 18 | 19 | This entry points enables linting rules for angular. 20 | 21 | It requires the following packages: 22 | 23 | - `@angular-eslint/eslint-plugin` 24 | - '@pellegrims/eslint-config-base' 25 | - `eslint-plugin-ngrx` 26 | - `eslint-plugin-rxjs-angular` 27 | 28 | ### @pellegrims/eslint-config-angular/angular-template 29 | 30 | This entry points enables linting rules for angular templates. 31 | 32 | It requires the following packages: 33 | 34 | - `@angular-eslint/eslint-plugin-template` 35 | - `eslint-plugin-angular-template-consistent-this` 36 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": [ 27 | "plugin:@nx/typescript", 28 | "./dist/libs/eslint-config/base/src/typescript" 29 | ] 30 | }, 31 | { 32 | "files": ["*.js", "*.jsx"], 33 | "extends": [ 34 | "plugin:@nx/javascript", 35 | "./dist/libs/eslint-config/base/src/javascript" 36 | ] 37 | }, 38 | { 39 | "files": "*.json", 40 | "parser": "jsonc-eslint-parser", 41 | "rules": {} 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Robin Pellegrims 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libs/eslint-config/base/README.md: -------------------------------------------------------------------------------- 1 | # @pellegrims/eslint-config-base 2 | 3 | [![npm package link](https://img.shields.io/npm/v/@pellegrims/eslint-config-base)](https://www.npmjs.com/package/@pellegrims/eslint-config-base) 4 | 5 | This package provides an opinionated shareable eslint config for Typescript & Javascript. 6 | 7 | ## Usage 8 | 9 | This package exports 2 ESLint configurations. 10 | 11 | To install all peer dependencies automatically: 12 | 13 | ```sh 14 | npx install-peerdeps --dev @pellegrims/eslint-config-base 15 | ``` 16 | 17 | ### @pellegrims/eslint-config-base/javascript 18 | 19 | This entry points enables linting rules for javascript. 20 | 21 | It requires the following packages: 22 | 23 | - `eslint` 24 | - `eslint-plugin-etc` 25 | - `eslint-plugin-import` 26 | - `eslint-plugin-unicorn` 27 | 28 | ### @pellegrims/eslint-config-angular/typescript 29 | 30 | This entry points enables linting rules for typescript. 31 | 32 | It requires the following packages: 33 | 34 | - `@typescript-eslint/eslint-plugin` 35 | - `@typescript-eslint/parser` 36 | - `eslint` 37 | - `eslint-plugin-etc` 38 | - `eslint-plugin-import` 39 | - `eslint-plugin-rxjs` 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | with: 17 | fetch-depth: 0 18 | - name: git config 19 | run: | 20 | git config user.name "${GITHUB_ACTOR}" 21 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 22 | - name: Install dependencies 23 | uses: robinpellegrims/composite-actions/pnpm-install@main 24 | with: 25 | pnpm-version: 9.4.0 26 | - uses: actions/setup-node@v2 27 | with: 28 | node-version: 20 29 | registry-url: 'https://registry.npmjs.org' 30 | - run: pnpm nx affected ${{ github.event_name == 'workflow_dispatch' && '--all' || '--base=$BEFORE_SHA' }} --target=release --parallel=1 --baseBranch=master --push 31 | env: 32 | BEFORE_SHA: ${{ github.event.before }} 33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 34 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 35 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 36 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 37 | -------------------------------------------------------------------------------- /libs/nx-vercel/src/executors/deploy/executor.ts: -------------------------------------------------------------------------------- 1 | import { BuildExecutorSchema, VercelEnvironment } from './schema'; 2 | import { execSync } from 'child_process'; 3 | 4 | // Based on https://vercel.com/guides/how-can-i-use-github-actions-with-vercel 5 | 6 | export default async function runExecutor(options: BuildExecutorSchema) { 7 | if (!options.orgId) { 8 | throw new Error(`Missing "orgId" option`); 9 | } 10 | 11 | if (!options.projectId) { 12 | throw new Error(`Missing "projectId" option`); 13 | } 14 | 15 | const vercelToken = process.env['VERCEL_TOKEN']; 16 | 17 | if (!vercelToken) { 18 | throw new Error(`Missing "VERCEL_TOKEN" environment variable`); 19 | } 20 | 21 | const environment: VercelEnvironment = options.environment ?? 'preview'; 22 | const prodFlag = environment === 'production' ? '--prod' : ''; 23 | 24 | const env = `VERCEL_ORG_ID=${options.orgId} VERCEL_PROJECT_ID=${options.projectId}`; 25 | 26 | execSync( 27 | `${env} npx vercel pull --yes --environment=${environment} --token=${vercelToken}`, 28 | { stdio: 'inherit' } 29 | ); 30 | 31 | execSync(`${env} npx vercel build ${prodFlag} --token=${vercelToken}`, { 32 | stdio: 'inherit', 33 | }); 34 | 35 | execSync( 36 | `${env} npx vercel deploy --prebuilt ${prodFlag} --token=${vercelToken}`, 37 | { stdio: 'inherit' } 38 | ); 39 | 40 | return { success: true }; 41 | } 42 | -------------------------------------------------------------------------------- /libs/eslint-config/base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pellegrims/eslint-config-base", 3 | "version": "1.0.2", 4 | "description": "ESLint shareable configuration for Typescript & Javascript", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/robinpellegrims/pellegrims.git", 8 | "directory": "libs/eslint-config/base" 9 | }, 10 | "keywords": [ 11 | "eslint", 12 | "eslintconfig", 13 | "config", 14 | "pellegrims", 15 | "typescript", 16 | "javascript", 17 | "rxjs", 18 | "import", 19 | "etc", 20 | "unicorn", 21 | "prettier", 22 | "nx" 23 | ], 24 | "author": "Robin Pellegrims", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/robinpellegrims/pellegrims/labels/scope%3Aeslint-config" 28 | }, 29 | "homepage": "https://github.com/robinpellegrims/pellegrims/tree/master/libs/eslint-config/base", 30 | "peerDependencies": { 31 | "@typescript-eslint/eslint-plugin": "^6.11.0", 32 | "@typescript-eslint/parser": "^6.11.0", 33 | "eslint": "^8.46.0", 34 | "eslint-config-prettier": "^9.0.0", 35 | "eslint-plugin-etc": "^2.0.1", 36 | "eslint-plugin-import": "2.26.0", 37 | "eslint-plugin-rxjs": "^4.0.2", 38 | "eslint-plugin-unicorn": "^39.0.0" 39 | }, 40 | "exports": { 41 | "./": "./src/index.js", 42 | "./javascript": "./src/javascript.js", 43 | "./typescript": "./src/typescript.js" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pellegrims/eslint-config-angular", 3 | "version": "1.0.2", 4 | "description": "ESLint shareable configuration for Angular", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/robinpellegrims/pellegrims.git", 8 | "directory": "libs/eslint-config/angular" 9 | }, 10 | "keywords": [ 11 | "eslint", 12 | "eslintconfig", 13 | "config", 14 | "pellegrims", 15 | "typescript", 16 | "javascript", 17 | "angular", 18 | "ngrx", 19 | "rxjs", 20 | "import", 21 | "etc", 22 | "unicorn", 23 | "prettier", 24 | "nx" 25 | ], 26 | "author": "Robin Pellegrims", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/robinpellegrims/pellegrims/labels/scope%3Aeslint-config" 30 | }, 31 | "homepage": "https://github.com/robinpellegrims/pellegrims/tree/master/libs/eslint-config/angular", 32 | "dependencies": { 33 | "@pellegrims/eslint-config-base": "^0.0.2" 34 | }, 35 | "peerDependencies": { 36 | "@angular-eslint/eslint-plugin": "^13.0.1", 37 | "@angular-eslint/eslint-plugin-template": "^13.0.1", 38 | "eslint-plugin-angular-template-consistent-this": "^0.0.11", 39 | "eslint-plugin-ngrx": "^2.0.1", 40 | "eslint-plugin-rxjs-angular": "^2.0.0" 41 | }, 42 | "exports": { 43 | "./": "./src/index.js", 44 | "./angular": "./src/angular.js", 45 | "./angular-template": "./src/angular-template.js" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pellegrims/nx-remotecache-s3", 3 | "main": "src/index.js", 4 | "version": "8.1.0", 5 | "description": "Remote caching for @nrwl/nx using S3 storage", 6 | "scripts": { 7 | "test": "nx test nx-remotecache-s3" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/robinpellegrims/pellegrims.git", 12 | "directory": "libs/nx-remotecache-s3" 13 | }, 14 | "keywords": [ 15 | "nx", 16 | "remote", 17 | "cache", 18 | "remotecache", 19 | "s3", 20 | "storage", 21 | "typescript" 22 | ], 23 | "author": "Robin Pellegrims ", 24 | "contributors": [ 25 | "Steven Rathbauer " 26 | ], 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/robinpellegrims/pellegrims/issues?q=is%3Aissue+label%3Ascope%3Anx-remotecache-s3+" 30 | }, 31 | "homepage": "https://github.com/robinpellegrims/pellegrims/tree/master/libs/nx-remotecache-s3", 32 | "peerDependencies": { 33 | "nx": ">=20.0.0" 34 | }, 35 | "dependencies": { 36 | "@aws-sdk/client-s3": "^3.329.0", 37 | "@aws-sdk/client-sts": "^3.329.0", 38 | "@aws-sdk/credential-provider-node": "^3.329.0", 39 | "@aws-sdk/lib-storage": "^3.329.0", 40 | "@aws-sdk/types": "^3.329.0", 41 | "@smithy/node-http-handler": "^2.2.2", 42 | "hpagent": "^1.2.0", 43 | "matcher": "^4.0.0", 44 | "nx-remotecache-custom": "^20.0.0", 45 | "tslib": "^2.3.1" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /libs/nx-vercel/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nx-vercel", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/nx-vercel/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/js:tsc", 9 | "outputs": ["{options.outputPath}"], 10 | "options": { 11 | "outputPath": "dist/libs/nx-vercel", 12 | "main": "libs/nx-vercel/src/index.ts", 13 | "tsConfig": "libs/nx-vercel/tsconfig.lib.json", 14 | "assets": [ 15 | "libs/nx-vercel/*.md", 16 | { 17 | "input": "./libs/nx-vercel/src", 18 | "glob": "**/!(*.ts)", 19 | "output": "./src" 20 | }, 21 | { 22 | "input": "./libs/nx-vercel/src", 23 | "glob": "**/*.d.ts", 24 | "output": "./src" 25 | }, 26 | { 27 | "input": "./libs/nx-vercel", 28 | "glob": "generators.json", 29 | "output": "." 30 | }, 31 | { 32 | "input": "./libs/nx-vercel", 33 | "glob": "executors.json", 34 | "output": "." 35 | } 36 | ] 37 | } 38 | }, 39 | "lint": { 40 | "executor": "@nx/eslint:lint", 41 | "outputs": ["{options.outputFile}"] 42 | }, 43 | "test": { 44 | "executor": "@nx/jest:jest", 45 | "outputs": ["{workspaceRoot}/coverage/libs/nx-vercel"], 46 | "options": { 47 | "jestConfig": "libs/nx-vercel/jest.config.ts" 48 | } 49 | } 50 | }, 51 | "tags": [] 52 | } 53 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasksRunnerOptions": { 3 | "default": { 4 | "runner": "nx/tasks-runners/default" 5 | }, 6 | "remotecache-s3": { 7 | "runner": "./dist/libs/nx-remotecache-s3", 8 | "options": { 9 | "bucket": "monorepo-cache", 10 | "endpoint": "https://s3.eu-central-003.backblazeb2.com", 11 | "region": "us-west-000", 12 | "parallel": 1 13 | } 14 | } 15 | }, 16 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 17 | "targetDefaults": { 18 | "build": { 19 | "dependsOn": ["^build"], 20 | "inputs": ["production", "^production"], 21 | "cache": true 22 | }, 23 | "@nx/jest:jest": { 24 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], 25 | "cache": true, 26 | "options": { 27 | "passWithNoTests": true 28 | }, 29 | "configurations": { 30 | "ci": { 31 | "ci": true, 32 | "codeCoverage": true 33 | } 34 | } 35 | }, 36 | "@nx/eslint:lint": { 37 | "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], 38 | "cache": true 39 | } 40 | }, 41 | "namedInputs": { 42 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 43 | "sharedGlobals": [], 44 | "production": [ 45 | "default", 46 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", 47 | "!{projectRoot}/tsconfig.spec.json", 48 | "!{projectRoot}/jest.config.[jt]s", 49 | "!{projectRoot}/.eslintrc.json", 50 | "!{projectRoot}/src/test-setup.[jt]s" 51 | ] 52 | }, 53 | "defaultBase": "master", 54 | "useLegacyCache": true 55 | } 56 | -------------------------------------------------------------------------------- /libs/eslint-config/base/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-base", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/eslint-config/base/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/js:tsc", 9 | "outputs": ["{options.outputPath}"], 10 | "options": { 11 | "outputPath": "dist/libs/eslint-config/base", 12 | "main": "libs/eslint-config/base/src/index.ts", 13 | "tsConfig": "libs/eslint-config/base/tsconfig.lib.json", 14 | "assets": ["libs/eslint-config/base/*.md"] 15 | } 16 | }, 17 | "lint": { 18 | "executor": "@nx/eslint:lint", 19 | "outputs": ["{options.outputFile}"] 20 | }, 21 | "test": { 22 | "executor": "@nx/jest:jest", 23 | "outputs": ["{workspaceRoot}/coverage/libs/eslint-config/base"], 24 | "options": { 25 | "jestConfig": "libs/eslint-config/base/jest.config.ts" 26 | } 27 | }, 28 | "release": { 29 | "executor": "@jscutlery/semver:version", 30 | "options": { 31 | "postTargets": [ 32 | "eslint-config-base:github", 33 | "eslint-config-base:build", 34 | "eslint-config-base:publish" 35 | ] 36 | } 37 | }, 38 | "github": { 39 | "executor": "@jscutlery/semver:github", 40 | "options": { 41 | "tag": "${tag}", 42 | "notes": "${notes}" 43 | } 44 | }, 45 | "publish": { 46 | "executor": "ngx-deploy-npm:deploy", 47 | "options": { 48 | "access": "public", 49 | "distFolderPath": "dist/libs/eslint-config/base" 50 | }, 51 | "dependsOn": ["build"] 52 | } 53 | }, 54 | "tags": [] 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pellegrims 2 | 3 | [![CI](https://github.com/robinpellegrims/pellegrims/actions/workflows/ci.yml/badge.svg)](https://github.com/robinpellegrims/pellegrims/actions/workflows/ci.yml) 4 | 5 | Nx monorepo containing the following open source projects: 6 | 7 | | Project | Description | Version | 8 | | ----------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | 9 | | [@pellegrims/nx-remotecache-s3](./libs/nx-remotecache-s3) | A task runner for [nx](https://nx.dev) that uses an s3 Storage as a remote cache. | [![npm package link](https://img.shields.io/npm/v/@pellegrims/nx-remotecache-s3)](https://www.npmjs.com/package/@pellegrims/nx-remotecache-s3) | 10 | | [@pellegrims/eslint-config-base](./libs/eslint-config/base) | An opinionated shareable eslint config for Typescript & Javascript. | [![npm package link](https://img.shields.io/npm/v/@pellegrims/eslint-config-base)](https://www.npmjs.com/package/@pellegrims/eslint-config-base) | 11 | | [@pellegrims/eslint-config-angular](./libs/eslint-config/angular) | An opinionated shareable eslint config for Angular. | [![npm package link](https://img.shields.io/npm/v/@pellegrims/eslint-config-angular)](https://www.npmjs.com/package/@pellegrims/eslint-config-angular) | 12 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nx-remotecache-s3", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/nx-remotecache-s3/src", 5 | "projectType": "library", 6 | "targets": { 7 | "lint": { 8 | "executor": "@nx/eslint:lint", 9 | "outputs": ["{options.outputFile}"] 10 | }, 11 | "test": { 12 | "executor": "@nx/jest:jest", 13 | "outputs": ["{workspaceRoot}/coverage/libs/nx-remotecache-s3"], 14 | "options": { 15 | "jestConfig": "libs/nx-remotecache-s3/jest.config.ts" 16 | } 17 | }, 18 | "build": { 19 | "executor": "@nx/js:tsc", 20 | "outputs": ["{options.outputPath}"], 21 | "options": { 22 | "outputPath": "dist/libs/nx-remotecache-s3", 23 | "tsConfig": "libs/nx-remotecache-s3/tsconfig.lib.json", 24 | "packageJson": "libs/nx-remotecache-s3/package.json", 25 | "main": "libs/nx-remotecache-s3/src/index.ts", 26 | "assets": ["libs/nx-remotecache-s3/*.md"] 27 | } 28 | }, 29 | "release": { 30 | "executor": "@jscutlery/semver:version", 31 | "options": { 32 | "postTargets": [ 33 | "nx-remotecache-s3:github", 34 | "nx-remotecache-s3:build", 35 | "nx-remotecache-s3:publish" 36 | ] 37 | } 38 | }, 39 | "github": { 40 | "executor": "@jscutlery/semver:github", 41 | "options": { 42 | "tag": "${tag}", 43 | "notes": "${notes}" 44 | } 45 | }, 46 | "publish": { 47 | "executor": "ngx-deploy-npm:deploy", 48 | "options": { 49 | "access": "public", 50 | "distFolderPath": "dist/libs/nx-remotecache-s3" 51 | }, 52 | "dependsOn": ["build"] 53 | } 54 | }, 55 | "tags": [] 56 | } 57 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-angular", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/eslint-config/angular/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/js:tsc", 9 | "outputs": ["{options.outputPath}"], 10 | "options": { 11 | "outputPath": "dist/libs/eslint-config/angular", 12 | "tsConfig": "libs/eslint-config/angular/tsconfig.lib.json", 13 | "packageJson": "libs/eslint-config/angular/package.json", 14 | "main": "libs/eslint-config/angular/src/index.ts", 15 | "assets": ["libs/eslint-config/angular/*.md"] 16 | } 17 | }, 18 | "lint": { 19 | "executor": "@nx/eslint:lint", 20 | "outputs": ["{options.outputFile}"] 21 | }, 22 | "test": { 23 | "executor": "@nx/jest:jest", 24 | "outputs": ["{workspaceRoot}/coverage/libs/eslint-config/angular"], 25 | "options": { 26 | "jestConfig": "libs/eslint-config/angular/jest.config.ts" 27 | } 28 | }, 29 | "release": { 30 | "executor": "@jscutlery/semver:version", 31 | "options": { 32 | "postTargets": [ 33 | "eslint-config-angular:github", 34 | "eslint-config-angular:build", 35 | "eslint-config-angular:publish" 36 | ] 37 | } 38 | }, 39 | "github": { 40 | "executor": "@jscutlery/semver:github", 41 | "options": { 42 | "tag": "${tag}", 43 | "notes": "${notes}" 44 | } 45 | }, 46 | "publish": { 47 | "executor": "ngx-deploy-npm:deploy", 48 | "options": { 49 | "access": "public", 50 | "distFolderPath": "dist/libs/eslint-config/angular" 51 | }, 52 | "dependsOn": ["build"] 53 | } 54 | }, 55 | "tags": [] 56 | } 57 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/util.ts: -------------------------------------------------------------------------------- 1 | import { isMatch } from 'matcher'; 2 | 3 | const HTTP_PROXY = 'HTTP_PROXY'; 4 | const HTTPS_PROXY = 'HTTPS_PROXY'; 5 | const NO_PROXY = 'NO_PROXY'; 6 | 7 | export const getEnv = (key: string) => process.env[key]; 8 | 9 | export const buildCommonCommandInput = ( 10 | bucket: string | undefined, 11 | prefix: string, 12 | filename: string 13 | ) => ({ 14 | /* eslint-disable @typescript-eslint/naming-convention */ 15 | Bucket: bucket, 16 | Key: `${prefix}${filename}`, 17 | /* eslint-enable @typescript-eslint/naming-convention */ 18 | }); 19 | 20 | export const getHttpProxy = (): string | undefined => 21 | getEnv(HTTP_PROXY.toLowerCase()) || getEnv(HTTP_PROXY) || undefined; 22 | 23 | export const getHttpsProxy = (): string | undefined => 24 | getEnv(HTTPS_PROXY.toLowerCase()) || getEnv(HTTPS_PROXY) || undefined; 25 | 26 | export const getNoProxy = (): string | undefined => 27 | getEnv(NO_PROXY.toLowerCase()) || getEnv(NO_PROXY) || undefined; 28 | 29 | export const matchesNoProxy = ( 30 | subjectUrl: string, 31 | noProxy: string | undefined 32 | ) => { 33 | if (!noProxy) return false; 34 | 35 | const subjectUrlTokens = new URL(subjectUrl); 36 | const rules = noProxy.split(/[\s,]+/); 37 | 38 | for (const rule of rules) { 39 | const ruleMatch = rule 40 | .replace(/^(?\.)/, '*') 41 | .match(/^(?.+?)(?::(?\d+))?$/); 42 | 43 | if (!ruleMatch || !ruleMatch.groups) { 44 | throw new Error('Invalid NO_PROXY pattern.'); 45 | } 46 | 47 | if (!ruleMatch.groups.hostname) { 48 | throw new Error( 49 | 'NO_PROXY entry pattern must include hostname. Use * to match any hostname.' 50 | ); 51 | } 52 | 53 | const hostnameIsMatch = isMatch( 54 | subjectUrlTokens.hostname, 55 | ruleMatch.groups.hostname 56 | ); 57 | 58 | if ( 59 | hostnameIsMatch && 60 | (!ruleMatch.groups || 61 | !ruleMatch.groups.port || 62 | (subjectUrlTokens.port && 63 | subjectUrlTokens.port === ruleMatch.groups.port)) 64 | ) { 65 | return true; 66 | } 67 | } 68 | 69 | return false; 70 | }; 71 | -------------------------------------------------------------------------------- /libs/eslint-config/base/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). 4 | 5 | ## [1.0.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-1.0.1...eslint-config-base-1.0.2) (2024-11-10) 6 | 7 | ## [1.0.1](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-1.0.0...eslint-config-base-1.0.1) (2023-12-14) 8 | 9 | # [1.0.0](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.10...eslint-config-base-1.0.0) (2023-11-16) 10 | 11 | ### Build System 12 | 13 | - update nx v17.1.2 and run migrations and update related deps ([ce8348e](https://github.com/robinpellegrims/pellegrims/commit/ce8348ea890c8224338cec3a514b8ecd87cb13d3)) 14 | 15 | ### BREAKING CHANGES 16 | 17 | - requires nx >=17.0.0 18 | 19 | ## [0.0.10](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.9...eslint-config-base-0.0.10) (2023-08-13) 20 | 21 | ## [0.0.9](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.8...eslint-config-base-0.0.9) (2023-06-01) 22 | 23 | ## [0.0.8](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.7...eslint-config-base-0.0.8) (2023-05-15) 24 | 25 | ## [0.0.7](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.6...eslint-config-base-0.0.7) (2023-05-15) 26 | 27 | ## [0.0.6](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.5...eslint-config-base-0.0.6) (2023-03-07) 28 | 29 | ## [0.0.5](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.4...eslint-config-base-0.0.5) (2023-02-08) 30 | 31 | ## [0.0.4](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.3...eslint-config-base-0.0.4) (2022-11-27) 32 | 33 | ## [0.0.3](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.2...eslint-config-base-0.0.3) (2022-11-13) 34 | 35 | ## [0.0.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-base-0.0.1...eslint-config-base-0.0.2) (2022-10-08) 36 | 37 | ### Bug Fixes 38 | 39 | - **eslint-config-base:** fix package name ([3901957](https://github.com/robinpellegrims/pellegrims/commit/3901957855000c22eceba76e389a2722d74e29b6)) 40 | 41 | ## 0.0.1 (2022-10-08) 42 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/setup-s3-task-runner.ts: -------------------------------------------------------------------------------- 1 | import { Upload } from '@aws-sdk/lib-storage'; 2 | import { initEnv } from 'nx-remotecache-custom'; 3 | import { buildS3Client } from './s3-client'; 4 | import { buildCommonCommandInput, getEnv } from './util'; 5 | 6 | import type { CustomRunnerOptions } from 'nx-remotecache-custom'; 7 | import type { RemoteCacheImplementation } from 'nx-remotecache-custom/types/remote-cache-implementation'; 8 | 9 | const ENV_BUCKET = 'NXCACHE_S3_BUCKET'; 10 | const ENV_PREFIX = 'NXCACHE_S3_PREFIX'; 11 | 12 | export interface S3Options { 13 | bucket?: string; 14 | endpoint?: string; 15 | forcePathStyle?: boolean; 16 | prefix?: string; 17 | profile?: string; 18 | region?: string; 19 | } 20 | 21 | export const setupS3TaskRunner = async ( 22 | options: CustomRunnerOptions 23 | ): Promise => { 24 | initEnv(options); 25 | 26 | const s3Storage = buildS3Client(options); 27 | 28 | const bucket = getEnv(ENV_BUCKET) ?? options.bucket; 29 | const prefix = getEnv(ENV_PREFIX) ?? options.prefix ?? ''; 30 | 31 | return { 32 | name: 'S3', 33 | fileExists: async (filename: string) => { 34 | try { 35 | const result = await s3Storage.headObject( 36 | buildCommonCommandInput(bucket, prefix, filename) 37 | ); 38 | return !!result; 39 | } catch (error) { 40 | if ( 41 | (error as Error).name === '403' || 42 | (error as Error).name === 'NotFound' 43 | ) { 44 | return false; 45 | } else { 46 | throw error; 47 | } 48 | } 49 | }, 50 | retrieveFile: async (filename: string) => { 51 | const result = await s3Storage.getObject( 52 | buildCommonCommandInput(bucket, prefix, filename) 53 | ); 54 | return result.Body as NodeJS.ReadableStream; 55 | }, 56 | storeFile: (filename: string, stream) => { 57 | const upload = new Upload({ 58 | client: s3Storage, 59 | params: { 60 | ...buildCommonCommandInput(bucket, prefix, filename), 61 | // eslint-disable-next-line @typescript-eslint/naming-convention 62 | Body: stream, 63 | }, 64 | }); 65 | 66 | return upload.done(); 67 | }, 68 | }; 69 | }; 70 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/eslint.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: ['eslint:recommended'], 3 | rules: { 4 | 'arrow-body-style': ['error'], 5 | 'arrow-parens': ['off', 'always'], 6 | 'brace-style': ['off', 'off'], 7 | 'comma-dangle': 'off', 8 | complexity: 'error', 9 | curly: 'error', 10 | 'eol-last': 'off', 11 | eqeqeq: ['error', 'always'], 12 | 'guard-for-in': 'error', 13 | 'id-blacklist': 'off', 14 | 'id-length': ['error', { exceptions: ['_'] }], 15 | 'id-match': 'off', 16 | 'linebreak-style': 'off', 17 | 'max-classes-per-file': 'error', 18 | 'max-len': 'off', 19 | 'max-params': 'warn', 20 | 'new-parens': 'off', 21 | 'newline-per-chained-call': 'off', 22 | 'no-bitwise': 'error', 23 | 'no-caller': 'error', 24 | 'no-console': ['error', { allow: ['error', 'warn'] }], 25 | 'no-duplicate-imports': 'off', 26 | 'no-eval': 'error', 27 | 'no-extra-boolean-cast': 'error', 28 | 'no-extra-semi': 'off', 29 | 'no-irregular-whitespace': 'off', 30 | 'no-magic-numbers': ['warn', { ignore: [-1, 0, 1] }], 31 | 'no-multiple-empty-lines': 'off', 32 | 'no-nested-ternary': 'error', 33 | 'no-new-wrappers': 'error', 34 | 'no-param-reassign': 'error', 35 | 'no-prototype-builtins': 'error', 36 | 'no-restricted-imports': [ 37 | 'error', 38 | { 39 | paths: [ 40 | { 41 | name: '@ngneat/spectator', 42 | message: "Use '@ngneat/spectator/jest' instead. ", 43 | }, 44 | ], 45 | }, 46 | ], 47 | 'no-throw-literal': 'error', 48 | 'no-trailing-spaces': 'off', 49 | 'no-undef-init': 'error', 50 | 'no-underscore-dangle': 'off', 51 | 'no-unneeded-ternary': 'error', 52 | 'no-var': 'error', 53 | 'object-shorthand': 'error', 54 | 'one-var': ['error', 'never'], 55 | 'prefer-arrow-callback': 'error', 56 | 'prefer-const': 'error', 57 | 'prefer-object-spread': 'error', 58 | 'prefer-template': 'error', 59 | 'quote-props': ['error', 'as-needed'], 60 | radix: 'error', 61 | 'space-before-function-paren': 'off', 62 | 'space-in-parens': ['off', 'never'], 63 | 'spaced-comment': [ 64 | 'error', 65 | 'always', 66 | { block: { exceptions: ['*'] }, markers: ['/'] }, 67 | ], 68 | }, 69 | }; 70 | -------------------------------------------------------------------------------- /libs/eslint-config/base/src/lib/typescript-eslint.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | plugins: ['@typescript-eslint'], 3 | extends: [ 4 | 'plugin:@typescript-eslint/eslint-recommended', 5 | 'plugin:@typescript-eslint/recommended', 6 | ], 7 | rules: { 8 | '@typescript-eslint/array-type': ['error', { default: 'array' }], 9 | '@typescript-eslint/consistent-type-assertions': 'error', 10 | '@typescript-eslint/consistent-type-definitions': 'error', 11 | '@typescript-eslint/dot-notation': 'off', 12 | '@typescript-eslint/explicit-member-accessibility': [ 13 | 'off', 14 | { accessibility: 'explicit' }, 15 | ], 16 | '@typescript-eslint/indent': 'off', 17 | '@typescript-eslint/member-delimiter-style': [ 18 | 'off', 19 | { 20 | multiline: { delimiter: 'none', requireLast: true }, 21 | singleline: { delimiter: 'semi', requireLast: false }, 22 | }, 23 | ], 24 | '@typescript-eslint/member-ordering': 'error', 25 | '@typescript-eslint/naming-convention': 'error', 26 | '@typescript-eslint/no-explicit-any': ['error', { fixToUnknown: true }], 27 | '@typescript-eslint/no-inferrable-types': [ 28 | 'error', 29 | { ignoreParameters: true }, 30 | ], 31 | '@typescript-eslint/no-non-null-assertion': 'error', 32 | '@typescript-eslint/no-shadow': ['error', { hoist: 'all' }], 33 | '@typescript-eslint/no-this-alias': 'error', 34 | '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', 35 | '@typescript-eslint/no-unnecessary-type-arguments': 'error', 36 | '@typescript-eslint/no-unused-expressions': [ 37 | 'error', 38 | { allowTernary: true }, 39 | ], 40 | '@typescript-eslint/no-unused-vars': [ 41 | 'error', 42 | { ignoreRestSiblings: true }, 43 | ], 44 | '@typescript-eslint/no-var-requires': 'error', 45 | '@typescript-eslint/prefer-function-type': 'error', 46 | '@typescript-eslint/prefer-readonly': 'error', 47 | '@typescript-eslint/quotes': 'off', 48 | '@typescript-eslint/semi': ['off', null], 49 | '@typescript-eslint/type-annotation-spacing': 'off', 50 | '@typescript-eslint/unified-signatures': 'error', 51 | '@typescript-eslint/triple-slash-reference': ['error', { path: 'always' }], 52 | }, 53 | overrides: [ 54 | { 55 | files: ['*.tsx'], 56 | rules: { 57 | '@typescript-eslint/no-unused-vars': 'off', 58 | '@typescript-eslint/naming-convention': 'off', 59 | }, 60 | }, 61 | ], 62 | }; 63 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: 'CodeQL' 13 | 14 | on: 15 | push: 16 | branches: [master] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [master] 20 | schedule: 21 | - cron: '17 15 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: ['javascript'] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v2 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v2 71 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/util.spec.ts: -------------------------------------------------------------------------------- 1 | import { clearProxyInfo } from './test-utils'; 2 | import { 3 | buildCommonCommandInput, 4 | getEnv, 5 | getHttpProxy, 6 | getHttpsProxy, 7 | } from './util'; 8 | 9 | describe('util', () => { 10 | const originalEnv = process.env; 11 | 12 | afterEach(() => { 13 | process.env = { ...originalEnv }; 14 | jest.clearAllMocks(); 15 | }); 16 | 17 | describe('getEnv', () => { 18 | it('returns undefined when env does not exist', () => { 19 | expect(getEnv('TEST_ENV')).toBeUndefined(); 20 | }); 21 | it('returns "true" when env is defined as the string "true"', () => { 22 | process.env.TEST_ENV = 'true'; 23 | expect(getEnv('TEST_ENV')).toEqual('true'); 24 | }); 25 | it('returns "false" when env is defined as the string "false"', () => { 26 | process.env.TEST_ENV = 'false'; 27 | expect(getEnv('TEST_ENV')).toEqual('false'); 28 | }); 29 | }); 30 | describe('buildCommonCommandInput', () => { 31 | it('returns the object with Bucket undefined', () => { 32 | expect( 33 | buildCommonCommandInput(undefined, 'prefix', 'filename') 34 | ).toStrictEqual({ 35 | /* eslint-disable @typescript-eslint/naming-convention */ 36 | Bucket: undefined, 37 | Key: 'prefixfilename', 38 | /* eslint-enable @typescript-eslint/naming-convention */ 39 | }); 40 | }); 41 | it('returns the object', () => { 42 | expect( 43 | buildCommonCommandInput('bucket', 'prefix', 'filename') 44 | ).toStrictEqual({ 45 | /* eslint-disable @typescript-eslint/naming-convention */ 46 | Bucket: 'bucket', 47 | Key: 'prefixfilename', 48 | /* eslint-enable @typescript-eslint/naming-convention */ 49 | }); 50 | }); 51 | }); 52 | describe('get proxy information', () => { 53 | beforeEach(clearProxyInfo); 54 | 55 | it('should return undefined when http_proxy and HTTP_PROXY is not set', () => { 56 | expect(getHttpProxy()).toBe(undefined); 57 | }); 58 | it('should return imaproxy when http_proxy is set', () => { 59 | process.env.http_proxy = 'imaproxy'; 60 | expect(getHttpProxy()).toBe('imaproxy'); 61 | }); 62 | it('should return imaproxy when HTTP_PROXY is set', () => { 63 | process.env.HTTP_PROXY = 'imaproxy'; 64 | expect(getHttpProxy()).toBe('imaproxy'); 65 | }); 66 | it('should return undefined when https_proxy and HTTPS_PROXY is not set', () => { 67 | expect(getHttpsProxy()).toBe(undefined); 68 | }); 69 | it('should return imaproxy when https_proxy is set', () => { 70 | process.env.https_proxy = 'imaproxy'; 71 | expect(getHttpsProxy()).toBe('imaproxy'); 72 | }); 73 | it('should return imaproxy when HTTPS_PROXY is set', () => { 74 | process.env.HTTPS_PROXY = 'imaproxy'; 75 | expect(getHttpsProxy()).toBe('imaproxy'); 76 | }); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pellegrims", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "nx": "nx", 7 | "start": "nx serve", 8 | "build": "nx build", 9 | "lint": "nx lint", 10 | "test": "nx test", 11 | "e2e": "nx e2e", 12 | "prepare": "husky install", 13 | "postinstall": "nx run-many --target=build --projects=nx-remotecache-s3,eslint-config-base" 14 | }, 15 | "private": true, 16 | "dependencies": { 17 | "@aws-sdk/client-s3": "^3.473.0", 18 | "@aws-sdk/client-sts": "^3.473.0", 19 | "@aws-sdk/credential-provider-node": "^3.470.0", 20 | "@aws-sdk/lib-storage": "^3.473.0", 21 | "@aws-sdk/s3-request-presigner": "^3.473.0", 22 | "@aws-sdk/types": "^3.468.0", 23 | "@smithy/abort-controller": "^2.0.15", 24 | "@smithy/node-http-handler": "^2.2.2", 25 | "@swc/helpers": "0.5.11", 26 | "hpagent": "^1.2.0", 27 | "matcher": "^4.0.0", 28 | "nx-remotecache-custom": "^20.0.0", 29 | "semver": "^7.5.2", 30 | "tslib": "^2.0.0" 31 | }, 32 | "devDependencies": { 33 | "@commitlint/cli": "^17.0.2", 34 | "@commitlint/config-conventional": "^17.0.2", 35 | "@jscutlery/semver": "^5.2.0", 36 | "@nx/devkit": "20.8.2", 37 | "@nx/eslint": "20.8.2", 38 | "@nx/eslint-plugin": "20.8.2", 39 | "@nx/jest": "20.8.2", 40 | "@nx/js": "20.8.2", 41 | "@nx/node": "20.8.2", 42 | "@nx/plugin": "20.8.2", 43 | "@nx/workspace": "20.8.2", 44 | "@types/jest": "29.5.14", 45 | "@types/node": "18.19.21", 46 | "@typescript-eslint/eslint-plugin": "7.18.0", 47 | "@typescript-eslint/parser": "7.18.0", 48 | "eslint": "8.57.0", 49 | "eslint-config-next": "13.5.6", 50 | "eslint-config-prettier": "10.1.8", 51 | "eslint-plugin-cypress": "2.13.4", 52 | "eslint-plugin-etc": "^2.0.1", 53 | "eslint-plugin-import": "2.26.0", 54 | "eslint-plugin-jsx-a11y": "6.6.1", 55 | "eslint-plugin-react": "7.31.11", 56 | "eslint-plugin-react-hooks": "4.6.0", 57 | "eslint-plugin-rxjs": "^5.0.3", 58 | "eslint-plugin-unicorn": "^39.0.0", 59 | "husky": "^7.0.4", 60 | "jest": "29.7.0", 61 | "jest-environment-jsdom": "29.7.0", 62 | "jest-mock": "^28.1.1", 63 | "jsonc-eslint-parser": "^2.1.0", 64 | "lint-staged": "^12.0.3", 65 | "ngx-deploy-npm": "8.2.0", 66 | "nx": "20.8.2", 67 | "prettier": "2.7.1", 68 | "ts-jest": "29.2.5", 69 | "ts-node": "10.9.1", 70 | "ts-toolbelt": "^9.6.0", 71 | "typescript": "5.5.4", 72 | "vite": "5.4.21", 73 | "vitest": "^0.25.1", 74 | "webpack": "^5.94.0" 75 | }, 76 | "lint-staged": { 77 | "*.{js,json,css,scss,md,ts,html,tsx,jsx,yaml,yml}": [ 78 | "nx format --uncommitted" 79 | ] 80 | }, 81 | "pnpm": { 82 | "overrides": { 83 | "semver@>=7.0.0 <7.5.2": ">=7.5.2", 84 | "esbuild@<=0.24.2": ">=0.25.0", 85 | "tmp@<=0.2.3": ">=0.2.4", 86 | "vite@<=5.4.19": ">=5.4.20", 87 | "js-yaml@>=4.0.0 <4.1.1": ">=4.1.1" 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/s3-client.ts: -------------------------------------------------------------------------------- 1 | import { S3 } from '@aws-sdk/client-s3'; 2 | import { 3 | getEnv, 4 | getHttpProxy, 5 | getHttpsProxy, 6 | getNoProxy, 7 | matchesNoProxy, 8 | } from './util'; 9 | import { defaultProvider } from '@aws-sdk/credential-provider-node'; 10 | import { 11 | getDefaultRoleAssumer, 12 | getDefaultRoleAssumerWithWebIdentity, 13 | } from '@aws-sdk/client-sts'; 14 | import { NodeHttpHandler } from '@smithy/node-http-handler'; 15 | import { HttpsProxyAgent } from 'hpagent'; 16 | 17 | import type { S3ClientConfig } from '@aws-sdk/client-s3/dist-types/S3Client'; 18 | import type { DefaultProviderInit } from '@aws-sdk/credential-provider-node/dist-types/defaultProvider'; 19 | import type { AwsCredentialIdentity, Provider } from '@aws-sdk/types'; 20 | 21 | const ENV_ENDPOINT = 'NXCACHE_S3_ENDPOINT'; 22 | const ENV_PROFILE = 'NXCACHE_S3_PROFILE'; 23 | const ENV_FORCE_PATH_STYLE = 'NXCACHE_S3_FORCE_PATH_STYLE'; 24 | const ENV_REGION = 'NXCACHE_S3_REGION'; 25 | const ENV_ACCESS_KEY_ID = 'NXCACHE_S3_ACCESS_KEY_ID'; 26 | const ENV_SECRET_ACCESS_KEY = 'NXCACHE_S3_SECRET_ACCESS_KEY'; 27 | const DEFAULT_S3_ENDPOINT = 'https://s3.amazonaws.com'; 28 | 29 | function getHttpAgent(): HttpsProxyAgent { 30 | return new HttpsProxyAgent({ proxy: getHttpProxy() as string }); 31 | } 32 | 33 | function getHttpsAgent(): HttpsProxyAgent { 34 | return new HttpsProxyAgent({ proxy: getHttpsProxy() as string }); 35 | } 36 | 37 | export const getProxyConfig = (s3Endpoint: string = DEFAULT_S3_ENDPOINT) => ({ 38 | ...(!matchesNoProxy(s3Endpoint, getNoProxy()) && 39 | (getHttpProxy() || getHttpsProxy()) && { 40 | requestHandler: new NodeHttpHandler({ 41 | ...(getHttpProxy() && { httpAgent: getHttpAgent() }), 42 | ...(getHttpsProxy() && { httpsAgent: getHttpsAgent() }), 43 | }), 44 | }), 45 | }); 46 | 47 | export const buildS3Client = ( 48 | options: Pick & 49 | Pick 50 | ) => { 51 | const provider = getCredentialsProvider(options); 52 | 53 | return new S3({ 54 | endpoint: getEnv(ENV_ENDPOINT) ?? options.endpoint, 55 | region: getEnv(ENV_REGION) ?? options.region, 56 | credentials: provider, 57 | forcePathStyle: 58 | getEnv(ENV_FORCE_PATH_STYLE) === 'true' || options.forcePathStyle, 59 | ...getProxyConfig( 60 | getEnv(ENV_ENDPOINT) ?? 61 | (options.endpoint as string) ?? 62 | DEFAULT_S3_ENDPOINT 63 | ), 64 | }); 65 | }; 66 | 67 | const getCredentialsProvider = ( 68 | options: Pick & 69 | Pick 70 | ): AwsCredentialIdentity | Provider => { 71 | const awsAccessKeyIdOverride = getEnv(ENV_ACCESS_KEY_ID); 72 | const awsSecretAccessKeyOverride = getEnv(ENV_SECRET_ACCESS_KEY); 73 | 74 | if (awsAccessKeyIdOverride?.length && awsSecretAccessKeyOverride?.length) { 75 | return { 76 | accessKeyId: awsAccessKeyIdOverride, 77 | secretAccessKey: awsSecretAccessKeyOverride, 78 | }; 79 | } else { 80 | return defaultProvider({ 81 | profile: getEnv(ENV_PROFILE) ?? options.profile, 82 | roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(), 83 | roleAssumer: getDefaultRoleAssumer(), 84 | }); 85 | } 86 | }; 87 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | prepare: 12 | runs-on: ubuntu-latest 13 | if: ${{ !contains(github.event.head_commit.message, 'chore(release)') }} 14 | outputs: 15 | hasChanges: ${{ steps.affected.outputs.hasChanges }} 16 | matrix: ${{ steps.affected.outputs.matrix }} 17 | steps: 18 | - name: ⬇️ Checkout 19 | uses: actions/checkout@v3 20 | with: 21 | fetch-depth: 0 22 | - name: Install dependencies 23 | uses: robinpellegrims/composite-actions/pnpm-install@main 24 | with: 25 | pnpm-version: 9.4.0 26 | - uses: nrwl/nx-set-shas@v3 27 | # This line is needed for nx affected to work when CI is running on a PR 28 | - run: git branch --track master origin/master 29 | - name: Check format 30 | run: pnpm nx format:check 31 | - name: Calculate affected projects 32 | uses: actions/github-script@v7 33 | id: affected 34 | with: 35 | script: | 36 | // Calculate affected projects and define a matrix to use for the next job 37 | const maxRunners = 3; 38 | const targets = ['test', 'lint', 'e2e']; 39 | const serialTargets = ['e2e']; 40 | const matrix = { include: [] }; 41 | let hasChanges = false; 42 | 43 | for (const target of targets) { 44 | const command = `npx nx show projects --affected --json --with-target ${target}`; 45 | const { stdout: affected } = await exec.getExecOutput(command); 46 | const sortedProjects = JSON.parse(affected).sort(); 47 | 48 | if (sortedProjects.length > 0) { 49 | hasChanges = true; 50 | } 51 | 52 | const isSerialTarget = serialTargets.includes(target); 53 | const projectsCount = sortedProjects.length; 54 | const projectSliceSize = isSerialTarget 55 | ? 1 56 | : projectsCount <= 9 57 | ? 3 58 | : Math.max(Math.ceil(projectsCount / maxRunners), 3); 59 | const machineCount = isSerialTarget ? projectsCount : Math.max(Math.ceil(projectsCount / projectSliceSize), 1); 60 | const machineMatrix = Array.from(Array(machineCount).keys()).map((_, i) => `${i + 1}`); 61 | 62 | for (const machine of machineMatrix) { 63 | const machineIndex = Number(machine); 64 | const projects = 65 | machineIndex < machineCount 66 | ? sortedProjects.slice(projectSliceSize * (machineIndex - 1), projectSliceSize * machineIndex) 67 | : sortedProjects.slice(projectSliceSize * (machineIndex - 1)); 68 | 69 | if (projects.length > 0) { 70 | matrix.include.push({ 71 | distribution: machineIndex, 72 | parallel: isSerialTarget ? 1 : 3, 73 | projects: projects.join(','), 74 | target, 75 | }); 76 | } 77 | } 78 | } 79 | 80 | core.info(`hasChanges: ${hasChanges}`); 81 | core.info(`matrix: ${JSON.stringify(matrix)}`); 82 | 83 | core.setOutput(`hasChanges`, hasChanges); 84 | core.setOutput(`matrix`, matrix); 85 | 86 | execute: 87 | name: ${{ matrix.target }} (${{ matrix.distribution }}) 88 | if: ${{ needs.prepare.outputs.hasChanges == 'true' }} 89 | needs: prepare 90 | runs-on: ubuntu-latest 91 | continue-on-error: ${{ matrix.target == 'test' }} 92 | strategy: 93 | fail-fast: false 94 | matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} 95 | steps: 96 | - name: Checkout the code 97 | uses: actions/checkout@v2 98 | - name: Install dependencies 99 | uses: robinpellegrims/composite-actions/pnpm-install@main 100 | with: 101 | pnpm-version: 9.4.0 102 | - name: Execute 103 | uses: actions/github-script@v7 104 | id: execute 105 | with: 106 | script: | 107 | // Execute the target on the affected projects 108 | const target = process.env.MATRIX_TARGET; 109 | const projects = process.env.MATRIX_PROJECTS; 110 | const parallel = process.env.MATRIX_PARALLEL; 111 | const command = `npx nx run-many --target=${target} --projects=${projects} --parallel=${parallel}`; 112 | 113 | if (projects.length) { 114 | exec.exec(`${command} --runner=remotecache-s3 --verbose`); 115 | } 116 | env: 117 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 118 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 119 | MATRIX_TARGET: ${{ matrix.target }} 120 | MATRIX_PARALLEL: ${{ matrix.parallel }} 121 | MATRIX_PROJECTS: ${{ matrix.projects }} 122 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/s3-client.spec.ts: -------------------------------------------------------------------------------- 1 | import { setupS3TaskRunner } from './setup-s3-task-runner'; 2 | import { getProxyConfig } from './s3-client'; 3 | import { S3 } from '@aws-sdk/client-s3'; 4 | import { defaultProvider } from '@aws-sdk/credential-provider-node'; 5 | import { NodeHttpHandler } from '@smithy/node-http-handler'; 6 | import { 7 | clearProxyInfo, 8 | defaultOptions, 9 | emptyOptions, 10 | envValues, 11 | } from './test-utils'; 12 | 13 | jest.mock('@aws-sdk/client-s3'); 14 | jest.mock('@aws-sdk/credential-provider-node'); 15 | 16 | const s3Mock = jest.mocked(S3); 17 | 18 | const expectS3Instance = (params: { 19 | endpoint?: string; 20 | region?: string; 21 | forcePathStyle?: boolean; 22 | profile?: string; 23 | }) => { 24 | expect(defaultProvider).toHaveBeenCalledTimes(1); 25 | expect(defaultProvider).toHaveBeenCalledWith({ 26 | profile: params.profile, 27 | roleAssumerWithWebIdentity: expect.any(Function), 28 | roleAssumer: expect.any(Function), 29 | }); 30 | expect(s3Mock).toHaveBeenCalledTimes(1); 31 | expect(s3Mock).toHaveBeenCalledWith({ 32 | endpoint: params.endpoint, 33 | region: params.region, 34 | forcePathStyle: params.forcePathStyle, 35 | credentials: jest.mocked(defaultProvider).mock.results[0].value, 36 | }); 37 | }; 38 | 39 | describe('buildS3Client', () => { 40 | const originalEnv = process.env; 41 | 42 | beforeEach(clearProxyInfo); 43 | 44 | afterEach(() => { 45 | process.env = { ...originalEnv }; 46 | jest.clearAllMocks(); 47 | }); 48 | 49 | it('should be created only once', async () => { 50 | await setupS3TaskRunner(emptyOptions); 51 | expect(S3).toHaveBeenCalledTimes(1); 52 | }); 53 | 54 | it('with default parameters', async () => { 55 | await setupS3TaskRunner(emptyOptions); 56 | expectS3Instance({}); 57 | }); 58 | 59 | it('with parameters from options', async () => { 60 | await setupS3TaskRunner(defaultOptions); 61 | expectS3Instance({ ...defaultOptions }); 62 | }); 63 | 64 | it('with parameters from ENV variables (no proxy info)', async () => { 65 | process.env.NXCACHE_S3_ENDPOINT = envValues.endpoint; 66 | process.env.NXCACHE_S3_REGION = envValues.region; 67 | process.env.NXCACHE_S3_FORCE_PATH_STYLE = envValues.forcePathStyle; 68 | process.env.NXCACHE_S3_PROFILE = envValues.profile; 69 | await setupS3TaskRunner(defaultOptions); 70 | expectS3Instance({ ...envValues, forcePathStyle: true }); 71 | }); 72 | 73 | it('with parameters from ENV variables (with proxy info)', async () => { 74 | process.env.NXCACHE_S3_ENDPOINT = envValues.endpoint; 75 | process.env.NXCACHE_S3_REGION = envValues.region; 76 | process.env.NXCACHE_S3_FORCE_PATH_STYLE = envValues.forcePathStyle; 77 | process.env.NXCACHE_S3_PROFILE = envValues.profile; 78 | process.env.HTTP_PROXY = 'http://proxy.domain.com:8888'; 79 | process.env.HTTPS_PROXY = 'https://proxy.domain.com:8888'; 80 | 81 | await setupS3TaskRunner(defaultOptions); 82 | 83 | expect(defaultProvider).toHaveBeenCalledTimes(1); 84 | expect(defaultProvider).toHaveBeenCalledWith({ 85 | profile: envValues.profile, 86 | roleAssumer: expect.any(Function), 87 | roleAssumerWithWebIdentity: expect.any(Function), 88 | }); 89 | expect(s3Mock).toHaveBeenCalledTimes(1); 90 | expect(s3Mock).toHaveBeenCalledWith({ 91 | endpoint: envValues.endpoint, 92 | region: envValues.region, 93 | forcePathStyle: true, 94 | credentials: jest.mocked(defaultProvider).mock.results[0].value, 95 | requestHandler: expect.any(NodeHttpHandler), 96 | }); 97 | }); 98 | }); 99 | 100 | describe('getProxyConfig', () => { 101 | beforeEach(clearProxyInfo); 102 | 103 | it('should not set requestHandler when proxy info is unset', async () => { 104 | const proxyConfig = getProxyConfig(); 105 | 106 | expect(proxyConfig).toEqual({}); 107 | }); 108 | 109 | it('should not set requestHandler when the endpoint is in the no_proxy list', async () => { 110 | process.env.HTTPS_PROXY = 'https://proxy.domain.com:8888'; 111 | process.env.NO_PROXY = '.aws.com'; 112 | process.env.NXCACHE_S3_ENDPOINT = 'https://endpoint.aws.com'; 113 | 114 | const proxyConfig = getProxyConfig(); 115 | 116 | expect(proxyConfig).toEqual({}); 117 | }); 118 | 119 | it('should set requestHandler when httpProxy info is set', async () => { 120 | process.env.HTTP_PROXY = 'http://proxy.domain.com:8888'; 121 | process.env.NXCACHE_S3_ENDPOINT = 'https://endpoint.aws.com'; 122 | 123 | const proxyConfig = getProxyConfig(); 124 | 125 | expect(proxyConfig).toEqual({ 126 | requestHandler: expect.any(NodeHttpHandler), 127 | }); 128 | }); 129 | 130 | it('should set requestHandler when httpsProxy info is set', async () => { 131 | process.env.HTTPS_PROXY = 'https://proxy.domain.com:8888'; 132 | process.env.NXCACHE_S3_ENDPOINT = 'https://endpoint.aws.com'; 133 | 134 | const proxyConfig = getProxyConfig(); 135 | 136 | expect(proxyConfig).toEqual({ 137 | requestHandler: expect.any(NodeHttpHandler), 138 | }); 139 | }); 140 | }); 141 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /libs/eslint-config/angular/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). 4 | 5 | ## [1.0.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-1.0.1...eslint-config-angular-1.0.2) (2024-11-10) 6 | 7 | ## [1.0.1](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-1.0.0...eslint-config-angular-1.0.1) (2023-12-14) 8 | 9 | # [1.0.0](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.10...eslint-config-angular-1.0.0) (2023-11-16) 10 | 11 | ### Build System 12 | 13 | - update nx v17.1.2 and run migrations and update related deps ([ce8348e](https://github.com/robinpellegrims/pellegrims/commit/ce8348ea890c8224338cec3a514b8ecd87cb13d3)) 14 | 15 | ### BREAKING CHANGES 16 | 17 | - requires nx >=17.0.0 18 | 19 | ## [0.0.10](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.9...eslint-config-angular-0.0.10) (2023-08-13) 20 | 21 | ## [0.0.9](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.8...eslint-config-angular-0.0.9) (2023-06-01) 22 | 23 | ## [0.0.9](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.8...eslint-config-angular-0.0.9) (2023-06-01) 24 | 25 | ## [0.0.8](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.7...eslint-config-angular-0.0.8) (2023-05-15) 26 | 27 | ## [0.0.7](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.6...eslint-config-angular-0.0.7) (2023-05-15) 28 | 29 | ## [0.0.6](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.5...eslint-config-angular-0.0.6) (2023-03-07) 30 | 31 | ## [0.0.5](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.4...eslint-config-angular-0.0.5) (2023-02-08) 32 | 33 | ## [0.0.4](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.3...eslint-config-angular-0.0.4) (2022-11-27) 34 | 35 | ## [0.0.3](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.2...eslint-config-angular-0.0.3) (2022-11-13) 36 | 37 | ## [0.0.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-angular-0.0.1...eslint-config-angular-0.0.2) (2022-10-08) 38 | 39 | ### Bug Fixes 40 | 41 | - **eslint-config-angular:** move @pellegrims/eslint-config-base to dependencies ([5be9c68](https://github.com/robinpellegrims/pellegrims/commit/5be9c6805724d80de198583642a74f235a418c6d)) 42 | 43 | ## 0.0.1 (2022-10-08) 44 | 45 | ## [1.0.13](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.12...eslint-config-1.0.13) (2022-10-01) 46 | 47 | ## [1.0.12](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.11...eslint-config-1.0.12) (2022-09-14) 48 | 49 | ## [1.0.12](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.11...eslint-config-1.0.12) (2022-09-05) 50 | 51 | ## [1.0.12](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.11...eslint-config-1.0.12) (2022-09-04) 52 | 53 | ## [1.0.11](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.10...eslint-config-1.0.11) (2022-07-10) 54 | 55 | ## [1.0.10](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.9...eslint-config-1.0.10) (2022-06-19) 56 | 57 | ## [1.0.9](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.8...eslint-config-1.0.9) (2022-06-18) 58 | 59 | ## [1.0.8](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.7...eslint-config-1.0.8) (2022-06-13) 60 | 61 | ## [1.0.7](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.6...eslint-config-1.0.7) (2022-06-03) 62 | 63 | ## [1.0.6](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.5...eslint-config-1.0.6) (2022-04-25) 64 | 65 | ## [1.0.5](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.4...eslint-config-1.0.5) (2022-04-24) 66 | 67 | ## [1.0.4](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.3...eslint-config-1.0.4) (2022-04-24) 68 | 69 | ### Reverts 70 | 71 | - Revert "test(eslint-config): add basic test" ([2904247](https://github.com/robinpellegrims/pellegrims/commit/2904247e520138fe345f8882bcfaef751682aed4)) 72 | 73 | ## [1.0.4](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.3...eslint-config-1.0.4) (2022-04-24) 74 | 75 | ## [1.0.3](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.2...eslint-config-1.0.3) (2022-04-13) 76 | 77 | ## [1.0.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.1...eslint-config-1.0.2) (2022-02-18) 78 | 79 | ## [1.0.1](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-1.0.0...eslint-config-1.0.1) (2022-02-04) 80 | 81 | # [1.0.0](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-0.2.2...eslint-config-1.0.0) (2021-12-09) 82 | 83 | ### Features 84 | 85 | - **eslint-config:** v1 release ([163b266](https://github.com/robinpellegrims/pellegrims/commit/163b266d771344a3607270735f229b6b98773ec8)) 86 | 87 | ### BREAKING CHANGES 88 | 89 | - **eslint-config:** Peer dependencies updated: 90 | ESLint v8 91 | @angular-eslint v13 92 | TypeScript ESLint v5 93 | eslint-plugin-ngrx v2 94 | 95 | ## [0.2.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-0.2.1...eslint-config-0.2.2) (2021-12-09) 96 | 97 | ## [0.2.2](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-0.2.1...eslint-config-0.2.2) (2021-11-19) 98 | 99 | ## [0.2.1](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-0.2.0...eslint-config-0.2.1) (2021-11-18) 100 | 101 | ### Bug Fixes 102 | 103 | - **eslint-config:** fix angular-template-consistent-this declaration syntax ([5b457b7](https://github.com/robinpellegrims/pellegrims/commit/5b457b718d507d76ec6249ccd70bc84e0a2889e7)) 104 | 105 | # [0.2.0](https://github.com/robinpellegrims/pellegrims/compare/eslint-config-0.1.0...eslint-config-0.2.0) (2021-11-18) 106 | 107 | ### Bug Fixes 108 | 109 | - **eslint-config:** @angular-eslint/recommended not correctly extended ([ca54b58](https://github.com/robinpellegrims/pellegrims/commit/ca54b583d1934d8268a937843faad585f63eb9eb)) 110 | 111 | ### Features 112 | 113 | - **eslint-config:** add @angular-eslint/template/process-inline-templates ([d436bb5](https://github.com/robinpellegrims/pellegrims/commit/d436bb559c61456c515f7edf16d069886cd7ddfc)) 114 | 115 | # 0.1.0 (2021-11-18) 116 | 117 | ### Features 118 | 119 | - **eslint-config:** initial implementation ([754d82f](https://github.com/robinpellegrims/pellegrims/commit/754d82fd6e9bf140cd1ecd7fd6bbcf5f38fa5520)) 120 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/README.md: -------------------------------------------------------------------------------- 1 | [![npm package link](https://img.shields.io/npm/v/@pellegrims/nx-remotecache-s3)](https://www.npmjs.com/package/@pellegrims/nx-remotecache-s3) 2 | 3 | # @pellegrims/nx-remotecache-s3 4 | 5 | A task runner for [@nrwl/nx](https://nx.dev/react) that uses s3 storage as a remote cache. This enables all team members and CI servers to share a single cache. The concept and benefits of [computation caching](https://nx.dev/angular/guides/computation-caching) are explained in the NX documentation. 6 | 7 | This package was built with [nx-remotecache-custom](https://www.npmjs.com/package/nx-remotecache-custom) 🙌 8 | 9 | ## Setup 10 | 11 | ``` 12 | npm install --save-dev @pellegrims/nx-remotecache-s3 13 | ``` 14 | 15 | | Parameter | Description | Environment Variable / .env | `nx.json` | 16 | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ---------------- | 17 | | Endpoint | Optional. The fully qualified endpoint of the webservice. This is only required when using a custom (non-AWS) endpoint. | `NXCACHE_S3_ENDPOINT` | `endpoint` | 18 | | Bucket | Optional. Specify which bucket should be used for storing the cache. | `NXCACHE_S3_BUCKET` | `bucket` | 19 | | Prefix | Optional. Specify prefix path of target object key. | `NXCACHE_S3_PREFIX` | `prefix` | 20 | | Region | Optional. The AWS region to which this client will send requests. | `NXCACHE_S3_REGION` | `region` | 21 | | Profile | Optional. The AWS profile to use to authenticate. | `NXCACHE_S3_PROFILE` | `profile` | 22 | | Force Path Style | Optional. Whether to force path style URLs for S3 objects (e.g., `https://s3.amazonaws.com//` instead of `https://.s3.amazonaws.com/` | `NXCACHE_S3_FORCE_PATH_STYLE` | `forcePathStyle` | 23 | | Http Proxy | Optional. Useful when your environment must connect to a proxy to access the internet. | `http_proxy` \|\| `HTTP_PROXY` | | 24 | | Https Proxy | Optional. Useful when your environment must connect to a proxy to access the internet. | `https_proxy` \|\| `HTTPS_PROXY` | | 25 | | No Proxy | Optional. Useful when your environment must connect to a proxy to access the internet, but is not needed for connecting to aws. | `no_proxy` \|\| `NO_PROXY` | | 26 | 27 | ```json 28 | { 29 | "tasksRunnerOptions": { 30 | "default": { 31 | "runner": "@pellegrims/nx-remotecache-s3", 32 | "options": { 33 | "cacheableOperations": ["build", "test", "lint", "e2e"], 34 | "endpoint": "https://some-endpoint.com", 35 | "bucket": "name-of-bucket", 36 | "prefix": "prefix/", 37 | "region": "us-west-000", 38 | "profile": "name-of-aws-profile", 39 | "forcePathStyle": true 40 | } 41 | } 42 | } 43 | } 44 | ``` 45 | 46 | Authentication is handled by [@aws-sdk/credential-provider-node](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_node.html), so credentials will be attempted to be found from the following sources (listed in order of precedence): 47 | 48 | - Environment variables exposed via process.env (example: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) 49 | - SSO credentials from token cache 50 | - Web identity token credentials 51 | - Shared credentials and config ini files 52 | - The EC2/ECS Instance Metadata Service 53 | 54 | ## Run it 🚀 55 | 56 | Running tasks should now show the storage or retrieval from the remote cache: 57 | 58 | ``` 59 | ------------------------------------------------------------------------ 60 | Built Angular Package 61 | - from: /Users/name/example-workspace/libs/example-lib 62 | - to: /Users/name/example-workspace/dist/libs/example-lib 63 | ------------------------------------------------------------------------ 64 | ------------------------------------------------------------------------ 65 | Stored output to remote cache: s3 storage 66 | Hash: d3d2bea71ea0f3004304c5cc88cf91be50b02bb636ebbdfcc927626fd8edf1ae 67 | ------------------------------------------------------------------------ 68 | ``` 69 | 70 | ## Advanced Configuration 71 | 72 | See [nx-remotecache-custom](https://github.com/NiklasPor/nx-remotecache-custom#advanced-configuration) for more options like the ability to disable writes which may be useful if you only want to write to the cache from a CI but not localhost. 73 | 74 | ### Proxy Configuration 75 | 76 | To use a proxy to connect to the S3 bucket, set any of the `http_proxy` `https_proxy` `HTTP_PROXY` or `HTTPS_PROXY` environment variables, with the lowercase version taking precedence. If needed, the proxy can be bypassed by adding the S3 endpoint to the `no_proxy` or `NO_PROXY` environment variables. 77 | 78 | According to AWS, the `endpoint` and `region` parameters are meant to be mutually exclusive (though that isn't the case 100% of the time). Due to the complexity of creating a specific and valid s3 endpoint, and that there is no API provided by the aws-sdk libraries to generate one, this project handles checking the `no_proxy` for the s3 `endpoint` in the following manner. 79 | 80 | If the s3 `endpoint` has been configured, it will be checked against the `no_proxy` and if found, s3 requests will bypass the proxy. 81 | 82 | If the s3 `endpoint` has not been configured, it is assumed that the global s3 endpoint `s3.amazonaws.com` is being used, and the `no_proxy` will be checked for that url. Because of this, you could see the following behavior: 83 | 84 | - If the s3 client does use the global s3 `endpoint` to make requests and if that url has been added to the `no_proxy`, then those requests will correctly bypass the proxy. 85 | - If the s3 client does not use the global s3 `endpoint` (which could happen if a region other than us-east-1 is specified), and if that non global s3 `endpoint` has not been added to the `no_proxy`, then requests that should bypass the proxy will in fact NOT bypass the proxy. In this case, it is up to the user to determine which `endpoint` is being used and to add it to the `no_proxy`. 86 | 87 | TIP: `no_proxy` is a global env variable. To limit the blast radius of `no_proxy`, include the specific service subdomain in the `no_proxy` entry; e.g. `s3.amazonaws.com` vs `amazonaws.com`. 88 | 89 | ## More Custom Runners 90 | 91 | See [nx-remotecache-custom](https://github.com/NiklasPor/nx-remotecache-custom#all-custom-runners). 92 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/src/lib/setup-s3-task-runner.spec.ts: -------------------------------------------------------------------------------- 1 | import { S3 } from '@aws-sdk/client-s3'; 2 | import { Upload } from '@aws-sdk/lib-storage'; 3 | import { Readable } from 'stream'; 4 | import { setupS3TaskRunner } from './setup-s3-task-runner'; 5 | import { 6 | clearProxyInfo, 7 | defaultOptions, 8 | emptyOptions, 9 | envValues, 10 | } from './test-utils'; 11 | import type { CustomRunnerOptions } from 'nx-remotecache-custom'; 12 | import type { S3Options } from './setup-s3-task-runner'; 13 | 14 | const filename = 'someFilename'; 15 | const fileContent = 'content'; 16 | const fileContentStream = new Readable(); 17 | fileContentStream.push(fileContent); 18 | fileContentStream.push(null); 19 | 20 | jest.mock('@aws-sdk/client-s3'); 21 | jest.mock('@aws-sdk/lib-storage'); 22 | 23 | const s3Mock = jest.mocked(S3); 24 | const uploadMock = jest.mocked(Upload); 25 | jest.mocked(S3.prototype.getObject).mockImplementation(() => 26 | // eslint-disable-next-line @typescript-eslint/naming-convention 27 | Promise.resolve({ Body: fileContentStream }) 28 | ); 29 | 30 | jest.mock('@aws-sdk/credential-provider-node'); 31 | 32 | const mockHeadObjectError = (error: string) => 33 | jest 34 | .mocked(S3.prototype.headObject) 35 | .mockImplementation(() => Promise.reject({ name: error } as Error)); 36 | 37 | const mockHeadObjectSuccess = () => 38 | jest 39 | .mocked(S3.prototype.headObject) 40 | .mockImplementation(() => Promise.resolve({})); 41 | 42 | const headObjectCalledWithParams = async ({ 43 | runnerOptions, 44 | bucket, 45 | prefix, 46 | }: { 47 | runnerOptions: CustomRunnerOptions; 48 | bucket?: string; 49 | prefix?: string; 50 | }) => { 51 | const runner = await setupS3TaskRunner(runnerOptions); 52 | await runner.fileExists(filename); 53 | const safePrefix = prefix ?? ''; 54 | expect(s3Mock.prototype.headObject).toHaveBeenCalledWith({ 55 | // eslint-disable-next-line @typescript-eslint/naming-convention 56 | Bucket: bucket, 57 | // eslint-disable-next-line @typescript-eslint/naming-convention 58 | Key: safePrefix + filename, 59 | }); 60 | }; 61 | 62 | const getObjectCalledWithParams = async ({ 63 | runnerOptions, 64 | bucket, 65 | prefix, 66 | }: { 67 | runnerOptions: CustomRunnerOptions; 68 | bucket?: string; 69 | prefix?: string; 70 | }) => { 71 | const runner = await setupS3TaskRunner(runnerOptions); 72 | await runner.retrieveFile(filename); 73 | const safePrefix = prefix ?? ''; 74 | expect(s3Mock.prototype.getObject).toHaveBeenCalledWith({ 75 | // eslint-disable-next-line @typescript-eslint/naming-convention 76 | Bucket: bucket, 77 | // eslint-disable-next-line @typescript-eslint/naming-convention 78 | Key: safePrefix + filename, 79 | }); 80 | }; 81 | 82 | const uploadCalledWithParams = async ({ 83 | runnerOptions, 84 | bucket, 85 | prefix, 86 | }: { 87 | runnerOptions: CustomRunnerOptions; 88 | bucket?: string; 89 | prefix?: string; 90 | }) => { 91 | const runner = await setupS3TaskRunner(runnerOptions); 92 | await runner.storeFile(filename, fileContentStream); 93 | const safePrefix = prefix ?? ''; 94 | expect(uploadMock.mock.calls[0][0].params).toEqual({ 95 | /* eslint-disable @typescript-eslint/naming-convention */ 96 | Bucket: bucket, 97 | Key: safePrefix + filename, 98 | Body: fileContentStream, 99 | /* eslint-enable @typescript-eslint/naming-convention */ 100 | }); 101 | }; 102 | 103 | describe('setupS3TaskRunner', () => { 104 | const originalEnv = process.env; 105 | 106 | beforeEach(clearProxyInfo); 107 | 108 | afterEach(() => { 109 | process.env = { ...originalEnv }; 110 | jest.clearAllMocks(); 111 | }); 112 | 113 | it('should be defined', async () => { 114 | const runner = await setupS3TaskRunner(emptyOptions); 115 | expect(runner).toBeDefined(); 116 | }); 117 | 118 | it('should return an object implementing the RemoteCacheImplementation interface', async () => { 119 | const runner = await setupS3TaskRunner(emptyOptions); 120 | expect(runner.fileExists).toBeInstanceOf(Function); 121 | expect(runner.retrieveFile).toBeInstanceOf(Function); 122 | expect(runner.storeFile).toBeInstanceOf(Function); 123 | expect(runner.name).toMatch('S3'); 124 | }); 125 | 126 | describe('should implement RemoteCacheImplementation interface', () => { 127 | describe('fileExists', () => { 128 | describe('should call s3.headObject', () => { 129 | it('only once', async () => { 130 | const runner = await setupS3TaskRunner(emptyOptions); 131 | await runner.fileExists(filename); 132 | const method = s3Mock.prototype.headObject; 133 | expect(method).toBeCalledTimes(1); 134 | }); 135 | it('with default parameters', async () => 136 | await headObjectCalledWithParams({ 137 | runnerOptions: emptyOptions, 138 | ...emptyOptions, 139 | })); 140 | it('with parameters from options', async () => 141 | await headObjectCalledWithParams({ 142 | runnerOptions: defaultOptions, 143 | ...defaultOptions, 144 | })); 145 | it('with parameters from ENV variables', async () => { 146 | process.env.NXCACHE_S3_BUCKET = envValues.bucket; 147 | process.env.NXCACHE_S3_PREFIX = envValues.prefix; 148 | await headObjectCalledWithParams({ 149 | runnerOptions: defaultOptions, 150 | ...envValues, 151 | }); 152 | }); 153 | }); 154 | it('should throw an error if the api returns an unexpected error', async () => { 155 | const error = 'Unexpected error'; 156 | mockHeadObjectError(error); 157 | const runner = await setupS3TaskRunner(defaultOptions); 158 | await expect(runner.fileExists(filename)).rejects.toEqual({ 159 | name: 'Unexpected error', 160 | }); 161 | }); 162 | describe('should return', () => { 163 | it('false if the api returns 403', async () => { 164 | mockHeadObjectError('403'); 165 | const runner = await setupS3TaskRunner(defaultOptions); 166 | const exists = await runner.fileExists(filename); 167 | expect(exists).toBeFalsy(); 168 | }); 169 | it('false if the api returns NotFound', async () => { 170 | mockHeadObjectError('NotFound'); 171 | const runner = await setupS3TaskRunner(defaultOptions); 172 | const exists = await runner.fileExists(filename); 173 | expect(exists).toBeFalsy(); 174 | }); 175 | it('true if the file is found', async () => { 176 | mockHeadObjectSuccess(); 177 | const runner = await setupS3TaskRunner(defaultOptions); 178 | const exists = await runner.fileExists(filename); 179 | expect(exists).toBeTruthy(); 180 | }); 181 | }); 182 | }); 183 | describe('retrieveFile', () => { 184 | describe('should call s3.getObject', () => { 185 | it('only once', async () => { 186 | const runner = await setupS3TaskRunner(emptyOptions); 187 | await runner.retrieveFile(filename); 188 | expect(s3Mock.prototype.getObject).toHaveBeenCalledTimes(1); 189 | }); 190 | it('with default parameters', async () => 191 | await getObjectCalledWithParams({ 192 | runnerOptions: emptyOptions, 193 | ...emptyOptions, 194 | })); 195 | it('with parameters from options', async () => 196 | await getObjectCalledWithParams({ 197 | runnerOptions: defaultOptions, 198 | ...defaultOptions, 199 | })); 200 | it('with parameters from ENV variables', async () => { 201 | process.env.NXCACHE_S3_BUCKET = envValues.bucket; 202 | process.env.NXCACHE_S3_PREFIX = envValues.prefix; 203 | await getObjectCalledWithParams({ 204 | runnerOptions: defaultOptions, 205 | ...envValues, 206 | }); 207 | }); 208 | }); 209 | }); 210 | describe('storeFile', () => { 211 | describe('should call Upload', () => { 212 | it('only once', async () => { 213 | const runner = await setupS3TaskRunner(emptyOptions); 214 | await runner.storeFile(filename, fileContentStream); 215 | expect(uploadMock).toHaveBeenCalledTimes(1); 216 | }); 217 | it('with default parameters', async () => { 218 | await uploadCalledWithParams({ 219 | runnerOptions: emptyOptions, 220 | ...emptyOptions, 221 | }); 222 | }); 223 | it('with parameters from options', async () => { 224 | await uploadCalledWithParams({ 225 | runnerOptions: defaultOptions, 226 | ...defaultOptions, 227 | }); 228 | }); 229 | it('with parameters from ENV variables', async () => { 230 | process.env.NXCACHE_S3_BUCKET = envValues.bucket; 231 | process.env.NXCACHE_S3_PREFIX = envValues.prefix; 232 | await uploadCalledWithParams({ 233 | runnerOptions: defaultOptions, 234 | ...envValues, 235 | }); 236 | }); 237 | }); 238 | }); 239 | }); 240 | }); 241 | -------------------------------------------------------------------------------- /libs/nx-remotecache-s3/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). 4 | 5 | # [8.1.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-8.0.0...nx-remotecache-s3-8.1.0) (2024-11-10) 6 | 7 | ### Features 8 | 9 | - **nx-remotecache-s3:** support nx v20 ([4bccc51](https://github.com/robinpellegrims/pellegrims/commit/4bccc51f238df125779aadeddd91ea06d627732c)) 10 | 11 | # [8.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-7.1.0...nx-remotecache-s3-8.0.0) (2024-09-29) 12 | 13 | ### Bug Fixes 14 | 15 | - **nx-remotecache-s3:** remove readOnly param and env var ([ddb7051](https://github.com/robinpellegrims/pellegrims/commit/ddb70510b9ce6e8ec80b30d506fd490413f0c808)) 16 | 17 | ### BREAKING CHANGES 18 | 19 | - **nx-remotecache-s3:** Update to `write: false` or `NXCACHE_WRITE=false` from `nx-remotecache-custom`. 20 | 21 | # [7.1.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-7.0.0...nx-remotecache-s3-7.1.0) (2024-05-30) 22 | 23 | ### Features 24 | 25 | - add proxy support for nx-remotecache-s3 ([#267](https://github.com/robinpellegrims/pellegrims/issues/267)) ([f91742f](https://github.com/robinpellegrims/pellegrims/commit/f91742fde0a9b1b16e897aa6217cab460b9ab6ed)) 26 | 27 | # [7.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-6.0.0...nx-remotecache-s3-7.0.0) (2024-05-23) 28 | 29 | ### Features 30 | 31 | - update nx to v19.0.6 ([79bb766](https://github.com/robinpellegrims/pellegrims/commit/79bb766e6e9a80ebf88ded795f564a56880020c7)) 32 | 33 | ### BREAKING CHANGES 34 | 35 | - update nx to 19 36 | 37 | # [6.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-5.0.4...nx-remotecache-s3-6.0.0) (2024-03-02) 38 | 39 | ### Features 40 | 41 | - update nx to v18 ([8adc2e1](https://github.com/robinpellegrims/pellegrims/commit/8adc2e182a041df22fd67c90fb833b0fe968b23c)) 42 | 43 | ### BREAKING CHANGES 44 | 45 | - Update nx v18 46 | 47 | ## [5.0.4](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-5.0.3...nx-remotecache-s3-5.0.4) (2024-03-02) 48 | 49 | ## [5.0.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-5.0.2...nx-remotecache-s3-5.0.3) (2024-01-02) 50 | 51 | ### Bug Fixes 52 | 53 | - **nx-remotecache-s3:** add config value to provider call for role assumption ([1cae7fe](https://github.com/robinpellegrims/pellegrims/commit/1cae7fe4bd636b970ff0ebf7b4d4384d6cb154ea)) 54 | - **nx-remotecache-s3:** update test for provider call for role assumption ([66c785d](https://github.com/robinpellegrims/pellegrims/commit/66c785d9a737a44d29d2c429404c57960c1bd81d)) 55 | 56 | ## [5.0.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-5.0.1...nx-remotecache-s3-5.0.2) (2023-12-14) 57 | 58 | ## [5.0.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-5.0.0...nx-remotecache-s3-5.0.1) (2023-12-14) 59 | 60 | # [5.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-4.0.0...nx-remotecache-s3-5.0.0) (2023-11-16) 61 | 62 | ### Build System 63 | 64 | - update nx v17.1.2 and run migrations and update related deps ([ce8348e](https://github.com/robinpellegrims/pellegrims/commit/ce8348ea890c8224338cec3a514b8ecd87cb13d3)) 65 | 66 | ### BREAKING CHANGES 67 | 68 | - requires nx >=17.0.0 69 | 70 | # [4.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-3.0.1...nx-remotecache-s3-4.0.0) (2023-10-11) 71 | 72 | ### Build System 73 | 74 | - **nx-remotecache-s3:** adjust dependencies ([f7010a3](https://github.com/robinpellegrims/pellegrims/commit/f7010a36f9134828813b9d9a4491bd4f26104adb)) 75 | 76 | ### BREAKING CHANGES 77 | 78 | - **nx-remotecache-s3:** requires nx >=16.9.0 79 | 80 | ## [3.0.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-3.0.0...nx-remotecache-s3-3.0.1) (2023-08-13) 81 | 82 | # [3.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.1.3...nx-remotecache-s3-3.0.0) (2023-06-01) 83 | 84 | ### Features 85 | 86 | - update package to force version bump ([0dbdae0](https://github.com/robinpellegrims/pellegrims/commit/0dbdae01e6ad309881f91b94a0736ca5a43fc4ca)) 87 | 88 | ### BREAKING CHANGES 89 | 90 | - Minimum Nx version is now >=16.0.0 91 | 92 | ## [2.1.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.1.2...nx-remotecache-s3-2.1.3) (2023-06-01) 93 | 94 | ## [2.1.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.1.1...nx-remotecache-s3-2.1.2) (2023-05-15) 95 | 96 | ## [2.1.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.1.0...nx-remotecache-s3-2.1.1) (2023-05-15) 97 | 98 | # [2.1.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.0.3...nx-remotecache-s3-2.1.0) (2023-03-08) 99 | 100 | ### Features 101 | 102 | - add environment variable to explicitly set custom access key ID and secret access key for AWS ([#199](https://github.com/robinpellegrims/pellegrims/issues/199)) ([dd15562](https://github.com/robinpellegrims/pellegrims/commit/dd1556228756689f2d2106498e0e7aadaef39bf0)) 103 | 104 | ## [2.0.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.0.2...nx-remotecache-s3-2.0.3) (2023-03-07) 105 | 106 | ## [2.0.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.0.1...nx-remotecache-s3-2.0.2) (2023-03-07) 107 | 108 | ### Bug Fixes 109 | 110 | - **nx-remotecache-s3:** generated package.json is pinning all dependency versions ([4b6a25f](https://github.com/robinpellegrims/pellegrims/commit/4b6a25f5c1af0e1e2762369cc2364659198c1faf)), closes [#198](https://github.com/robinpellegrims/pellegrims/issues/198) 111 | 112 | ## [2.0.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-2.0.0...nx-remotecache-s3-2.0.1) (2023-02-08) 113 | 114 | # [2.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.5.2...nx-remotecache-s3-2.0.0) (2022-12-19) 115 | 116 | ### Features 117 | 118 | - **nx-remotecache-s3:** update envs to custom runner v3 format ([954b888](https://github.com/robinpellegrims/pellegrims/commit/954b8888cb4b4470b98933b9518786065c31a742)) 119 | 120 | ### BREAKING CHANGES 121 | 122 | - **nx-remotecache-s3:** ENV vars now start with `NXCACHE_` instead of `NX_CACHE_` 123 | 124 | ## [1.5.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.5.1...nx-remotecache-s3-1.5.2) (2022-12-19) 125 | 126 | ### Bug Fixes 127 | 128 | - **nx-remotecache-s3:** readonly not correctly calculated ([725dea1](https://github.com/robinpellegrims/pellegrims/commit/725dea18bafcf94d9a482892cae01ae652e768bf)) 129 | 130 | ## [1.5.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.5.0...nx-remotecache-s3-1.5.1) (2022-12-17) 131 | 132 | # [1.5.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.7...nx-remotecache-s3-1.5.0) (2022-12-17) 133 | 134 | ### Features 135 | 136 | - **nx-remotecache-s3:** update nx-remotecache-custom to v3 ([953494d](https://github.com/robinpellegrims/pellegrims/commit/953494d37fdd81ccd55705b41fd5e618323576f6)) 137 | 138 | ## [1.4.7](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.6...nx-remotecache-s3-1.4.7) (2022-12-13) 139 | 140 | ## [1.4.6](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.5...nx-remotecache-s3-1.4.6) (2022-12-12) 141 | 142 | ### Bug Fixes 143 | 144 | - **nx-remotecache-s3:** options.forcePathStyle and options.readOnly are never used ([9f90d13](https://github.com/robinpellegrims/pellegrims/commit/9f90d13fefeed5d330d81d4e803a02cd214e558e)), closes [#183](https://github.com/robinpellegrims/pellegrims/issues/183) 145 | 146 | ## [1.4.5](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.4...nx-remotecache-s3-1.4.5) (2022-12-04) 147 | 148 | ### Bug Fixes 149 | 150 | - **nx-remotecache-s3:** generated package.json is pinning all dependency versions ([f269201](https://github.com/robinpellegrims/pellegrims/commit/f26920146e4312b0b0e8295ea8020692d695c005)), closes [#181](https://github.com/robinpellegrims/pellegrims/issues/181) 151 | 152 | ## [1.4.4](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.3...nx-remotecache-s3-1.4.4) (2022-11-27) 153 | 154 | ## [1.4.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.2...nx-remotecache-s3-1.4.3) (2022-11-13) 155 | 156 | ## [1.4.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.1...nx-remotecache-s3-1.4.2) (2022-11-02) 157 | 158 | ### Bug Fixes 159 | 160 | - **nx-remotecache-s3:** fix 403 error handling for fileExists ([79b6532](https://github.com/robinpellegrims/pellegrims/commit/79b65324d36c8bd800e82bbb28dd8efb9d5255b4)) 161 | 162 | ## [1.4.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.4.0...nx-remotecache-s3-1.4.1) (2022-11-02) 163 | 164 | ### Bug Fixes 165 | 166 | - **nx-remotecache-s3:** update env boolean handling and error handling ([#174](https://github.com/robinpellegrims/pellegrims/issues/174)) ([6ff3a4a](https://github.com/robinpellegrims/pellegrims/commit/6ff3a4ad2e44d5dae35f66fcbb11e8a8a415c334)) 167 | 168 | # [1.4.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.3.0...nx-remotecache-s3-1.4.0) (2022-11-01) 169 | 170 | ### Features 171 | 172 | - **nx-remotecache-s3:** add readonly option ([9cb9b37](https://github.com/robinpellegrims/pellegrims/commit/9cb9b37d8bfe6043163ed43e1bd5df48794b358d)) 173 | 174 | # [1.3.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.2.3...nx-remotecache-s3-1.3.0) (2022-10-26) 175 | 176 | ### Features 177 | 178 | - **nx-remotecache-s3:** add force path style capability to S3Options ([3a778c4](https://github.com/robinpellegrims/pellegrims/commit/3a778c40fb786110de569080a031d0f88ade075d)) 179 | 180 | ## [1.2.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.2.2...nx-remotecache-s3-1.2.3) (2022-10-01) 181 | 182 | ## [1.2.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.2.1...nx-remotecache-s3-1.2.2) (2022-09-21) 183 | 184 | ### Bug Fixes 185 | 186 | - **nx-remotecache-s3:** missing peer dependency on @nrwl/workspace ([585cc40](https://github.com/robinpellegrims/pellegrims/commit/585cc405efa953a90f8141da8db445821b56c4fe)), closes [#156](https://github.com/robinpellegrims/pellegrims/issues/156) 187 | 188 | ## [1.2.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.2.0...nx-remotecache-s3-1.2.1) (2022-09-14) 189 | 190 | ## [1.2.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.2.0...nx-remotecache-s3-1.2.1) (2022-09-05) 191 | 192 | ## [1.2.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.2.0...nx-remotecache-s3-1.2.1) (2022-09-04) 193 | 194 | # [1.2.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.1.1...nx-remotecache-s3-1.2.0) (2022-08-29) 195 | 196 | ### Features 197 | 198 | - **nx-remotecache-s3:** add support for options.profile ([ba04295](https://github.com/robinpellegrims/pellegrims/commit/ba0429572c1e5b76987cc37808a483e2567ccede)) 199 | 200 | ## [1.1.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.1.0...nx-remotecache-s3-1.1.1) (2022-08-26) 201 | 202 | # [1.1.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.6...nx-remotecache-s3-1.1.0) (2022-08-26) 203 | 204 | ### Features 205 | 206 | - **nx-remotecache-s3:** add custom profile option ([bdbda58](https://github.com/robinpellegrims/pellegrims/commit/bdbda58b87d8b73e27cc20604e6800796e3f12d1)) 207 | 208 | ## [1.0.6](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.5...nx-remotecache-s3-1.0.6) (2022-07-10) 209 | 210 | ## [1.0.5](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.4...nx-remotecache-s3-1.0.5) (2022-06-19) 211 | 212 | ## [1.0.4](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.3...nx-remotecache-s3-1.0.4) (2022-06-18) 213 | 214 | ## [1.0.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.2...nx-remotecache-s3-1.0.3) (2022-06-13) 215 | 216 | ## [1.0.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.1...nx-remotecache-s3-1.0.2) (2022-06-03) 217 | 218 | ## [1.0.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-1.0.0...nx-remotecache-s3-1.0.1) (2022-04-25) 219 | 220 | # [1.0.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.3.1...nx-remotecache-s3-1.0.0) (2022-04-25) 221 | 222 | ### Features 223 | 224 | - **nx-remotecache-s3:** swap to standard AWS credentials ([#100](https://github.com/robinpellegrims/pellegrims/issues/100)) ([5e8038e](https://github.com/robinpellegrims/pellegrims/commit/5e8038efecfbb3485fdecf589146472bdacde937)), closes [#95](https://github.com/robinpellegrims/pellegrims/issues/95) 225 | 226 | ### BREAKING CHANGES 227 | 228 | - **nx-remotecache-s3:** authentication is now handled by @aws-sdk/credential-provider-node 229 | 230 | Following environment variables were removed: 231 | 232 | - NX_CACHE_S3_ACCESS_KEY_ID (replace by AWS_ACCESS_KEY_ID) 233 | - NX_CACHE_S3_SECRET_KEY (replace by AWS_SECRET_ACCESS_KEY) 234 | - NX_CACHE_S3_PROFILE 235 | 236 | ## [0.3.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.3.0...nx-remotecache-s3-0.3.1) (2022-04-24) 237 | 238 | # [0.3.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.2.3...nx-remotecache-s3-0.3.0) (2022-04-24) 239 | 240 | ### Features 241 | 242 | - **nx-remotecache-s3:** Add support for aws profile credential resolution. ([#93](https://github.com/robinpellegrims/pellegrims/issues/93)) ([c8e295b](https://github.com/robinpellegrims/pellegrims/commit/c8e295b0a1174470b93651b74b7b194012b107ea)) 243 | 244 | ## [0.2.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.2.2...nx-remotecache-s3-0.2.3) (2022-04-19) 245 | 246 | ## [0.2.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.2.1...nx-remotecache-s3-0.2.2) (2022-04-19) 247 | 248 | ### Bug Fixes 249 | 250 | - **nx-remotecache-s3:** add package dependencies ([c15e608](https://github.com/robinpellegrims/pellegrims/commit/c15e60834b5e6bde995e23138d487d3229957d85)), closes [#88](https://github.com/robinpellegrims/pellegrims/issues/88) 251 | 252 | ## [0.2.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.2.0...nx-remotecache-s3-0.2.1) (2022-04-13) 253 | 254 | # [0.2.0](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.8...nx-remotecache-s3-0.2.0) (2022-02-18) 255 | 256 | ### Bug Fixes 257 | 258 | - **nx-remotecache-s3:** fallback to aws-sdk-v3 credentials provider ([d6ba139](https://github.com/robinpellegrims/pellegrims/commit/d6ba139fc21f7f86a39e351cfb72b4c925c4f264)) 259 | 260 | ### Features 261 | 262 | - **nx-remotecache-s3:** add prefix path option ([bbf1727](https://github.com/robinpellegrims/pellegrims/commit/bbf172729779546d0e03eaae310c5164a231304d)) 263 | 264 | ## [0.1.8](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.7...nx-remotecache-s3-0.1.8) (2022-02-04) 265 | 266 | ## [0.1.7](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.6...nx-remotecache-s3-0.1.7) (2021-12-20) 267 | 268 | ### Bug Fixes 269 | 270 | - **nx-remotecache-s3:** bucket name from environment variable ([#53](https://github.com/robinpellegrims/pellegrims/issues/53)) ([21f6525](https://github.com/robinpellegrims/pellegrims/commit/21f6525d02e0a97995ffe9eaa553a88f6cdf09b5)) 271 | 272 | ## [0.1.6](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.5...nx-remotecache-s3-0.1.6) (2021-12-09) 273 | 274 | ## [0.1.5](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.4...nx-remotecache-s3-0.1.5) (2021-11-19) 275 | 276 | ## [0.1.4](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.3...nx-remotecache-s3-0.1.4) (2021-11-19) 277 | 278 | ## [0.1.3](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.2...nx-remotecache-s3-0.1.3) (2021-11-18) 279 | 280 | ## [0.1.2](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.1...nx-remotecache-s3-0.1.2) (2021-11-07) 281 | 282 | ## [0.1.1](https://github.com/robinpellegrims/pellegrims/compare/nx-remotecache-s3-0.1.0...nx-remotecache-s3-0.1.1) (2021-11-07) 283 | 284 | # 0.1.0 (2021-11-07) 285 | 286 | ### Features 287 | 288 | - **nx-remotecache-s3:** initial implementation ([b0c6244](https://github.com/robinpellegrims/pellegrims/commit/b0c6244da47cdad7aefca4329e01b366bd11abe5)) 289 | --------------------------------------------------------------------------------