mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2026-03-22 18:25:29 +00:00
Compare commits
No commits in common. "master" and "3.13.1" have entirely different histories.
103
.coderabbit.yaml
103
.coderabbit.yaml
@ -1,103 +0,0 @@
|
||||
# CodeRabbit Configuration
|
||||
# https://docs.coderabbit.ai/guides/configure-coderabbit
|
||||
|
||||
language: de
|
||||
|
||||
reviews:
|
||||
pre_merge_checks:
|
||||
docstrings:
|
||||
mode: "off"
|
||||
|
||||
# Automatisches Review für alle PRs
|
||||
auto_review:
|
||||
enabled: true
|
||||
drafts: false
|
||||
base_branches:
|
||||
- master
|
||||
- main
|
||||
|
||||
auto_approve:
|
||||
enabled: true
|
||||
|
||||
# Review-Einstellungen
|
||||
request_changes_workflow: true
|
||||
high_level_summary: true
|
||||
poem: false
|
||||
review_status: true
|
||||
collapse_walkthrough: false
|
||||
changed_files_summary: true
|
||||
|
||||
# Pfad-Filter (Dateien die ignoriert werden)
|
||||
path_filters:
|
||||
- "!**/*.lock"
|
||||
- "!**/package-lock.json"
|
||||
- "!**/yarn.lock"
|
||||
- "!**/*.snap"
|
||||
- "!**/coverage/**"
|
||||
- "!**/dist/**"
|
||||
- "!**/node_modules/**"
|
||||
- "!**/*.min.js"
|
||||
- "!**/*.min.css"
|
||||
- "!**/.git/**"
|
||||
- "!**/storybook-static/**"
|
||||
|
||||
# Instruktionen für spezifische Pfade
|
||||
path_instructions:
|
||||
- path: "webapp/**/*.vue"
|
||||
instructions: |
|
||||
Prüfe Vue.js Best Practices:
|
||||
- Composition API Verwendung
|
||||
- Props Validierung
|
||||
- Event-Handling
|
||||
- Reaktivität
|
||||
|
||||
- path: "webapp/**/*.spec.js"
|
||||
instructions: |
|
||||
Prüfe Test-Qualität:
|
||||
- Aussagekräftige Test-Namen
|
||||
- Edge Cases abgedeckt
|
||||
- Mocking korrekt verwendet
|
||||
|
||||
- path: "backend/**/*.js"
|
||||
instructions: |
|
||||
Prüfe Backend Best Practices:
|
||||
- Error Handling
|
||||
- Input Validierung
|
||||
- SQL Injection Prevention
|
||||
- Performance (N+1 Queries)
|
||||
|
||||
- path: "packages/ui/**/*.ts"
|
||||
instructions: |
|
||||
Prüfe UI Library Standards:
|
||||
- TypeScript Typisierung
|
||||
- Vue 2/3 Kompatibilität (vue-demi)
|
||||
- Accessibility (WCAG 2.1)
|
||||
- CVA Varianten-Pattern
|
||||
|
||||
- path: "packages/ui/**/*.vue"
|
||||
instructions: |
|
||||
Prüfe UI Komponenten:
|
||||
- Render-Funktion Pattern für vue-demi
|
||||
- Props mit korrekten Types
|
||||
- Slots dokumentiert
|
||||
- Keine Template-Syntax (nur h() für Vue 2/3 Kompatibilität)
|
||||
|
||||
# Chat-Befehle
|
||||
chat:
|
||||
auto_reply: true
|
||||
|
||||
# Ton und Stil
|
||||
tone_instructions: |
|
||||
Sei konstruktiv und freundlich.
|
||||
Erkläre das "Warum" hinter Vorschlägen.
|
||||
Priorisiere Sicherheit > Korrektheit > Performance > Lesbarkeit.
|
||||
Schlage konkrete Code-Änderungen vor wenn möglich.
|
||||
|
||||
# Knowledge Base (Repository-spezifisches Wissen)
|
||||
knowledge_base:
|
||||
learnings:
|
||||
scope: auto
|
||||
issues:
|
||||
scope: auto
|
||||
pull_requests:
|
||||
scope: auto
|
||||
68
.github/dependabot.yml
vendored
68
.github/dependabot.yml
vendored
@ -126,71 +126,3 @@ updates:
|
||||
day: "saturday"
|
||||
timezone: "Europe/Berlin"
|
||||
time: "03:00"
|
||||
|
||||
# ui library
|
||||
- package-ecosystem: npm
|
||||
open-pull-requests-limit: 99
|
||||
directory: "/packages/ui"
|
||||
rebase-strategy: "disabled"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "saturday"
|
||||
timezone: "Europe/Berlin"
|
||||
time: "03:00"
|
||||
groups:
|
||||
vue:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "vue*"
|
||||
- "@vue*"
|
||||
vite:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "vite*"
|
||||
- "@vitejs*"
|
||||
vitest:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "vitest*"
|
||||
- "@vitest*"
|
||||
|
||||
# ui examples
|
||||
- package-ecosystem: npm
|
||||
open-pull-requests-limit: 99
|
||||
directory: "/packages/ui/examples/vue3-tailwind"
|
||||
rebase-strategy: "disabled"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "saturday"
|
||||
timezone: "Europe/Berlin"
|
||||
time: "03:00"
|
||||
|
||||
- package-ecosystem: npm
|
||||
open-pull-requests-limit: 99
|
||||
directory: "/packages/ui/examples/vue3-css"
|
||||
rebase-strategy: "disabled"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "saturday"
|
||||
timezone: "Europe/Berlin"
|
||||
time: "03:00"
|
||||
|
||||
- package-ecosystem: npm
|
||||
open-pull-requests-limit: 99
|
||||
directory: "/packages/ui/examples/vue2-tailwind"
|
||||
rebase-strategy: "disabled"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "saturday"
|
||||
timezone: "Europe/Berlin"
|
||||
time: "03:00"
|
||||
|
||||
- package-ecosystem: npm
|
||||
open-pull-requests-limit: 99
|
||||
directory: "/packages/ui/examples/vue2-css"
|
||||
rebase-strategy: "disabled"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "saturday"
|
||||
timezone: "Europe/Berlin"
|
||||
time: "03:00"
|
||||
|
||||
5
.github/file-filters.yml
vendored
5
.github/file-filters.yml
vendored
@ -1,9 +1,5 @@
|
||||
# These file filter patterns are used by the action https://github.com/dorny/paths-filter
|
||||
|
||||
ui: &ui
|
||||
- '.github/workflows/ui-*.yml'
|
||||
- 'packages/ui/**/*'
|
||||
|
||||
backend: &backend
|
||||
- '.github/workflows/test-backend.yml'
|
||||
- 'backend/**/*'
|
||||
@ -18,7 +14,6 @@ webapp: &webapp
|
||||
- 'webapp/**/*'
|
||||
- 'styleguide/**/*'
|
||||
- 'package.json'
|
||||
- *ui
|
||||
|
||||
docs-check: &docs-check
|
||||
- '.github/workflows/check-documentation.yml'
|
||||
|
||||
10
.github/workflows/check-documentation.yml
vendored
10
.github/workflows/check-documentation.yml
vendored
@ -11,10 +11,10 @@ jobs:
|
||||
documentation: ${{ steps.changes.outputs.documentation }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Check for markdown file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
@ -28,7 +28,7 @@ jobs:
|
||||
if: needs.files-changed.outputs.markdown == 'true'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Remove uncheckable documentation files
|
||||
run: rm -rf ./CHANGELOG.md # workaround until https://github.com/gaurav-nelson/github-action-markdown-link-check/pull/183 has been done
|
||||
@ -51,10 +51,10 @@ jobs:
|
||||
if: needs.files-changed.outputs.documentation == 'true'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Setup Node 20
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
|
||||
42
.github/workflows/cleanup-cache-at-pr-closing.yml
vendored
Normal file
42
.github/workflows/cleanup-cache-at-pr-closing.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
###############################################################################
|
||||
# A Github repo has max 10 GB of cache.
|
||||
# https://github.blog/changelog/2021-11-23-github-actions-cache-size-is-now-increased-to-10gb-per-repository/
|
||||
#
|
||||
# To avoid "cache thrashing" by their cache eviction policy it is recommended
|
||||
# to apply a cache cleanup workflow at PR closing to dele cache leftovers of
|
||||
# the current branch:
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||
###############################################################################
|
||||
|
||||
name: ocelot.social cache cleanup on pr closing
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
clean-branch-cache:
|
||||
name: Cleanup branch cache
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
REPO=${{ github.repository }}
|
||||
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
10
.github/workflows/deploy-documentation.yml
vendored
10
.github/workflows/deploy-documentation.yml
vendored
@ -13,10 +13,10 @@ jobs:
|
||||
documentation: ${{ steps.changes.outputs.documentation }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
@ -27,10 +27,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Setup Node 20
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
run: npm install && npm run docs:build
|
||||
|
||||
- name: Deploy Vuepress to Github Pages
|
||||
uses: crazy-max/ghaction-github-pages@1d6ee9b181a81033a16bd707a1401afa978daab4 # v4.0.0
|
||||
uses: crazy-max/ghaction-github-pages@df5cc2bfa78282ded844b354faee141f06b41865 # v4.0.0
|
||||
with:
|
||||
target_branch: gh-pages
|
||||
build_dir: .vuepress/dist
|
||||
|
||||
12
.github/workflows/docker-push.yml
vendored
12
.github/workflows/docker-push.yml
vendored
@ -59,18 +59,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
@ -83,7 +81,7 @@ jobs:
|
||||
type=sha
|
||||
- name: Build and push Docker images
|
||||
id: push
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
|
||||
with:
|
||||
context: ${{ matrix.app.context }}
|
||||
target: ${{ matrix.app.target }}
|
||||
@ -91,5 +89,3 @@ jobs:
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha,scope=${{ matrix.app.name }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.app.name }}
|
||||
|
||||
14
.github/workflows/publish.yml
vendored
14
.github/workflows/publish.yml
vendored
@ -14,11 +14,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0 # Fetch full History for changelog
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Setup env
|
||||
@ -58,11 +58,11 @@ jobs:
|
||||
needs: [github_tag]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0 # Fetch full History for changelog
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Setup env
|
||||
@ -72,7 +72,7 @@ jobs:
|
||||
echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
|
||||
- run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
|
||||
#- name: Repository Dispatch
|
||||
# uses: peter-evans/repository-dispatch@11446b25a5fd252975d4bdf43d8989a5ac4f16c5 # v3.0.0
|
||||
# uses: peter-evans/repository-dispatch@cf70392543065ca62813db6712a06df1c4f4ae9f # v3.0.0
|
||||
# with:
|
||||
# token: ${{ github.token }}
|
||||
# event-type: trigger-ocelot-build-success
|
||||
@ -80,7 +80,7 @@ jobs:
|
||||
# client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
|
||||
- name: Repository Dispatch stage.ocelot.social
|
||||
uses: peter-evans/repository-dispatch@11446b25a5fd252975d4bdf43d8989a5ac4f16c5 # v3.0.0
|
||||
uses: peter-evans/repository-dispatch@cf70392543065ca62813db6712a06df1c4f4ae9f # v3.0.0
|
||||
with:
|
||||
token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository
|
||||
event-type: trigger-ocelot-build-success
|
||||
@ -88,7 +88,7 @@ jobs:
|
||||
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
|
||||
- name: Repository Dispatch stage.yunite.me
|
||||
uses: peter-evans/repository-dispatch@11446b25a5fd252975d4bdf43d8989a5ac4f16c5 # v3.0.0
|
||||
uses: peter-evans/repository-dispatch@cf70392543065ca62813db6712a06df1c4f4ae9f # v3.0.0
|
||||
with:
|
||||
token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository
|
||||
event-type: trigger-ocelot-build-success
|
||||
|
||||
71
.github/workflows/test-backend.yml
vendored
71
.github/workflows/test-backend.yml
vendored
@ -11,10 +11,10 @@ jobs:
|
||||
backend: ${{ steps.changes.outputs.backend }}
|
||||
docker: ${{ steps.changes.outputs.docker }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Check for backend file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
@ -28,24 +28,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Neo4J | Build 'community' image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: neo4j
|
||||
file: neo4j/Dockerfile
|
||||
target: community
|
||||
load: true
|
||||
tags: ghcr.io/ocelot-social-community/ocelot-social/neo4j:community
|
||||
cache-from: type=gha,scope=neo4j
|
||||
cache-to: type=gha,mode=max,scope=neo4j
|
||||
|
||||
- name: Save image for test job
|
||||
run: docker save "ghcr.io/ocelot-social-community/ocelot-social/neo4j:community" > /tmp/neo4j.tar
|
||||
run: |
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml build neo4j
|
||||
docker save "ghcr.io/ocelot-social-community/ocelot-social/neo4j:community" > /tmp/neo4j.tar
|
||||
|
||||
- name: Cache docker images
|
||||
id: cache-neo4j
|
||||
@ -61,24 +49,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: backend | Build 'test' image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: backend
|
||||
file: backend/Dockerfile
|
||||
target: test
|
||||
load: true
|
||||
tags: ghcr.io/ocelot-social-community/ocelot-social/backend:test
|
||||
cache-from: type=gha,scope=backend-test
|
||||
cache-to: type=gha,mode=max,scope=backend-test
|
||||
|
||||
- name: Save image for test job
|
||||
run: docker save "ghcr.io/ocelot-social-community/ocelot-social/backend:test" > /tmp/backend.tar
|
||||
run: |
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml build backend
|
||||
docker save "ghcr.io/ocelot-social-community/ocelot-social/backend:test" > /tmp/backend.tar
|
||||
|
||||
- name: Cache docker images
|
||||
id: cache-backend
|
||||
@ -94,17 +70,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version-file: 'backend/.nvmrc'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: 'backend/yarn.lock'
|
||||
|
||||
- name: backend | Lint
|
||||
run: cd backend && yarn --frozen-lockfile && yarn run lint
|
||||
run: cd backend && yarn && yarn run lint
|
||||
|
||||
unit_test_backend:
|
||||
name: Unit tests - Backend
|
||||
@ -115,7 +89,7 @@ jobs:
|
||||
checks: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Restore Neo4J cache
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4.0.2
|
||||
@ -153,3 +127,20 @@ jobs:
|
||||
- name: backend | Unit test incl. coverage check
|
||||
run: docker compose exec -T backend yarn test
|
||||
|
||||
cleanup:
|
||||
name: Cleanup
|
||||
if: ${{ needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' }}
|
||||
needs: [files-changed, unit_test_backend]
|
||||
runs-on: ubuntu-latest
|
||||
permissions: write-all
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Delete cache
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
KEY="${{ github.run_id }}-backend-neo4j-cache"
|
||||
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||
KEY="${{ github.run_id }}-backend-cache"
|
||||
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||
|
||||
166
.github/workflows/test-e2e.yml
vendored
166
.github/workflows/test-e2e.yml
vendored
@ -8,52 +8,28 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
|
||||
|
||||
- name: Copy backend env file
|
||||
run: |
|
||||
cp backend/.env.test_e2e backend/.env
|
||||
cp webapp/.env.template webapp/.env
|
||||
|
||||
- name: Neo4J | Build image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: neo4j
|
||||
file: neo4j/Dockerfile
|
||||
target: community
|
||||
load: true
|
||||
tags: ghcr.io/ocelot-social-community/ocelot-social/neo4j:community
|
||||
cache-from: type=gha,scope=neo4j
|
||||
cache-to: type=gha,mode=max,scope=neo4j
|
||||
|
||||
- name: Backend | Build image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: backend
|
||||
file: backend/Dockerfile
|
||||
target: test
|
||||
load: true
|
||||
tags: ghcr.io/ocelot-social-community/ocelot-social/backend:test
|
||||
cache-from: type=gha,scope=backend-test
|
||||
cache-to: type=gha,mode=max,scope=backend-test
|
||||
|
||||
- name: Pull third-party images
|
||||
- name: Build backend and dependencies
|
||||
run: |
|
||||
docker pull quay.io/minio/minio:latest
|
||||
docker pull quay.io/minio/mc:latest
|
||||
docker pull maildev/maildev:latest
|
||||
# Build and start all required images for backend
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach neo4j backend --build
|
||||
|
||||
- name: Save all images
|
||||
run: |
|
||||
# Save the build images
|
||||
docker save "ghcr.io/ocelot-social-community/ocelot-social/backend:test" > /tmp/backend.tar
|
||||
docker save "ghcr.io/ocelot-social-community/ocelot-social/neo4j:community" > /tmp/neo4j.tar
|
||||
docker save "quay.io/minio/minio:latest" > /tmp/minio.tar
|
||||
docker save "quay.io/minio/mc:latest" > /tmp/minio-mc.tar
|
||||
docker save "maildev/maildev:latest" > /tmp/mailserver.tar
|
||||
|
||||
# Stop the containers
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml down
|
||||
|
||||
- name: Cache docker images
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4.0.2
|
||||
with:
|
||||
@ -70,24 +46,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
- name: Copy backend env file
|
||||
run: |
|
||||
cp backend/.env.test_e2e backend/.env
|
||||
cp webapp/.env.template webapp/.env
|
||||
|
||||
- name: Webapp | Build 'test' image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: .
|
||||
file: webapp/Dockerfile
|
||||
target: test
|
||||
load: true
|
||||
tags: ghcr.io/ocelot-social-community/ocelot-social/webapp:test
|
||||
cache-from: type=gha,scope=webapp-test
|
||||
cache-to: type=gha,mode=max,scope=webapp-test
|
||||
|
||||
- name: Save image for test jobs
|
||||
run: docker save "ghcr.io/ocelot-social-community/ocelot-social/webapp:test" > /tmp/webapp.tar
|
||||
- name: Build docker image
|
||||
run: |
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach webapp --build --no-deps
|
||||
docker save "ghcr.io/ocelot-social-community/ocelot-social/webapp:test" > /tmp/webapp.tar
|
||||
|
||||
- name: Cache docker image
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4.0.2
|
||||
@ -103,10 +72,10 @@ jobs:
|
||||
run: rm -rf /opt/hostedtoolcache
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.4.0
|
||||
with:
|
||||
node-version-file: 'backend/.nvmrc'
|
||||
cache: 'yarn'
|
||||
@ -118,8 +87,7 @@ jobs:
|
||||
|
||||
- name: Install cypress requirements
|
||||
run: |
|
||||
sudo wget --no-verbose -O /opt/cucumber-json-formatter "https://github.com/cucumber/json-formatter/releases/download/v19.0.0/cucumber-json-formatter-linux-amd64"
|
||||
echo "66a2ef158866c3ecb3d8e49a7189814a485bddca43e133e4ca5735b8d3951bf7 /opt/cucumber-json-formatter" | sha256sum -c -
|
||||
sudo wget --no-verbose -O /opt/cucumber-json-formatter "https://github.com/cucumber/json-formatter/releases/download/v19.0.0/cucumber-json-formatter-linux-386"
|
||||
sudo chmod +x /opt/cucumber-json-formatter
|
||||
cd backend
|
||||
yarn install
|
||||
@ -137,39 +105,26 @@ jobs:
|
||||
/home/runner/work/Ocelot-Social/Ocelot-Social
|
||||
key: ${{ github.run_id }}-e2e-cypress
|
||||
|
||||
list_features:
|
||||
name: List Feature Files
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
features: ${{ steps.list.outputs.features }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: List feature files
|
||||
id: list
|
||||
run: |
|
||||
FEATURES=$(find cypress/e2e/ -maxdepth 1 -name "*.feature" -printf '%f\n' | sort | jq -R -s -c 'split("\n") | map(select(length > 0))')
|
||||
echo "features=$FEATURES" >> $GITHUB_OUTPUT
|
||||
|
||||
fullstack_tests:
|
||||
name: E2E | ${{ matrix.feature }}
|
||||
name: Fullstack | tests
|
||||
if: success()
|
||||
needs: [prepare_backend_environment, prepare_webapp_image, prepare_cypress, list_features]
|
||||
needs: [prepare_backend_environment, prepare_webapp_image, prepare_cypress]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
jobs: 8
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
feature: ${{ fromJson(needs.list_features.outputs.features) }}
|
||||
# run copies of the current job in parallel
|
||||
job: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
steps:
|
||||
- name: Delete huge unnecessary tools folder
|
||||
run: rm -rf /opt/hostedtoolcache
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.4.0
|
||||
with:
|
||||
node-version-file: 'backend/.nvmrc'
|
||||
cache: 'yarn'
|
||||
@ -201,22 +156,10 @@ jobs:
|
||||
path: /tmp/webapp.tar
|
||||
key: ${{ github.run_id }}-e2e-webapp-cache
|
||||
|
||||
- name: Copy env files
|
||||
run: |
|
||||
cp webapp/.env.template webapp/.env
|
||||
cp backend/.env.test_e2e backend/.env
|
||||
|
||||
- name: Ensure cucumber-json-formatter exists
|
||||
run: |
|
||||
if [ ! -f /opt/cucumber-json-formatter ]; then
|
||||
sudo wget --no-verbose -O /opt/cucumber-json-formatter "https://github.com/cucumber/json-formatter/releases/download/v19.0.0/cucumber-json-formatter-linux-amd64"
|
||||
echo "66a2ef158866c3ecb3d8e49a7189814a485bddca43e133e4ca5735b8d3951bf7 /opt/cucumber-json-formatter" | sha256sum -c -
|
||||
fi
|
||||
sudo chmod +x /opt/cucumber-json-formatter
|
||||
sudo ln -fs /opt/cucumber-json-formatter /usr/bin/cucumber-json-formatter
|
||||
|
||||
- name: Boot up test system | docker compose
|
||||
run: |
|
||||
chmod +x /opt/cucumber-json-formatter
|
||||
sudo ln -fs /opt/cucumber-json-formatter /usr/bin/cucumber-json-formatter
|
||||
docker load < /tmp/neo4j.tar
|
||||
docker load < /tmp/backend.tar
|
||||
docker load < /tmp/minio.tar
|
||||
@ -224,24 +167,11 @@ jobs:
|
||||
docker load < /tmp/mailserver.tar
|
||||
docker load < /tmp/webapp.tar
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach backend mailserver webapp
|
||||
|
||||
echo "Waiting for backend (max 120s)..."
|
||||
timeout 120 bash -c 'until curl -sf -X POST -H "Content-Type: application/json" -d "{\"query\":\"{__typename}\"}" http://localhost:4000 > /dev/null 2>&1; do sleep 5; done'
|
||||
echo "Backend is ready."
|
||||
|
||||
echo "Waiting for webapp (max 120s)..."
|
||||
timeout 120 bash -c 'until curl -sf http://localhost:3000 > /dev/null 2>&1; do sleep 5; done'
|
||||
echo "Webapp is ready."
|
||||
|
||||
- name: Initialize database
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn db:migrate init
|
||||
|
||||
- name: Migrate database
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn db:migrate up
|
||||
sleep 90s
|
||||
|
||||
- name: Full stack tests | run tests
|
||||
id: e2e-tests
|
||||
run: yarn run cypress:run --spec "cypress/e2e/${{ matrix.feature }}"
|
||||
run: yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} )
|
||||
|
||||
- name: Full stack tests | if tests failed, compile html report
|
||||
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||
@ -252,21 +182,29 @@ jobs:
|
||||
- name: Full stack tests | if tests failed, upload report
|
||||
id: e2e-report
|
||||
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: e2e-report-${{ matrix.feature }}
|
||||
name: ocelot-e2e-test-report-pr${{ needs.docker_preparation.outputs.pr-number }}
|
||||
path: /home/runner/work/Ocelot-Social/Ocelot-Social/cypress/reports/cucumber_html_report
|
||||
|
||||
e2e_status:
|
||||
name: E2E | Status
|
||||
if: always()
|
||||
needs: [fullstack_tests]
|
||||
cleanup_cache:
|
||||
name: Cleanup Cache
|
||||
needs: fullstack_tests
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Check E2E results
|
||||
run: |
|
||||
if [ "${{ needs.fullstack_tests.result }}" != "success" ]; then
|
||||
echo "E2E tests failed or were cancelled (result: ${{ needs.fullstack_tests.result }})"
|
||||
exit 1
|
||||
fi
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
|
||||
|
||||
- name: Full stack tests | cleanup cache
|
||||
run: |
|
||||
cacheKeys=$(gh cache list --json key --jq '.[] | select(.key | startswith("${{ github.run_id }}-e2e-")) | .key')
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeys
|
||||
do
|
||||
gh cache delete "$cacheKey"
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
62
.github/workflows/test-webapp.yml
vendored
62
.github/workflows/test-webapp.yml
vendored
@ -11,10 +11,10 @@ jobs:
|
||||
docker: ${{ steps.changes.outputs.docker }}
|
||||
webapp: ${{ steps.changes.outputs.webapp }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Check for frontend file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
@ -28,10 +28,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version-file: 'webapp/.nvmrc'
|
||||
|
||||
@ -43,28 +43,16 @@ jobs:
|
||||
build_test_webapp:
|
||||
name: Docker Build Test - Webapp
|
||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp == 'true'
|
||||
needs: files-changed
|
||||
needs: [files-changed, prepare]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Webapp | Build 'test' image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: .
|
||||
file: webapp/Dockerfile
|
||||
target: test
|
||||
load: true
|
||||
tags: ghcr.io/ocelot-social-community/ocelot-social/webapp:test
|
||||
cache-from: type=gha,scope=webapp-test
|
||||
cache-to: type=gha,mode=max,scope=webapp-test
|
||||
|
||||
- name: Save image for test job
|
||||
run: docker save "ghcr.io/ocelot-social-community/ocelot-social/webapp:test" > /tmp/webapp.tar
|
||||
run: |
|
||||
docker build --target test -f webapp/Dockerfile -t "ocelotsocialnetwork/webapp:test" .
|
||||
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
|
||||
|
||||
- name: Cache docker image
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4.0.2
|
||||
@ -79,17 +67,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||
with:
|
||||
node-version-file: 'webapp/.nvmrc'
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: 'webapp/yarn.lock'
|
||||
|
||||
- name: webapp | Lint
|
||||
run: cd webapp && yarn --frozen-lockfile && yarn run lint
|
||||
run: cd webapp && yarn && yarn run lint
|
||||
|
||||
unit_test_webapp:
|
||||
name: Unit Tests - Webapp
|
||||
@ -100,7 +86,7 @@ jobs:
|
||||
checks: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||
|
||||
- name: Restore webapp cache
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4.0.2
|
||||
@ -116,8 +102,26 @@ jobs:
|
||||
cp webapp/.env.template webapp/.env
|
||||
cp backend/.env.template backend/.env
|
||||
|
||||
- name: Start webapp container
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp
|
||||
- name: backend | docker compose
|
||||
# doesn't work without the --build flag - this either means we should not load the cached images or cache the correct image
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp --build
|
||||
|
||||
- name: webapp | Unit tests incl. coverage check
|
||||
run: docker compose exec -T webapp yarn test
|
||||
|
||||
cleanup:
|
||||
name: Cleanup
|
||||
if: ${{ needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp == 'true' }}
|
||||
needs: [files-changed, unit_test_webapp]
|
||||
runs-on: ubuntu-latest
|
||||
permissions: write-all
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Delete cache
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
KEY="${{ github.run_id }}-webapp-cache"
|
||||
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||
|
||||
|
||||
1
.github/workflows/test.lint_pr.yml
vendored
1
.github/workflows/test.lint_pr.yml
vendored
@ -29,7 +29,6 @@ jobs:
|
||||
# Configure which scopes are allowed (newline delimited).
|
||||
scopes: |
|
||||
backend
|
||||
package/ui
|
||||
webapp
|
||||
maintenance
|
||||
database
|
||||
|
||||
95
.github/workflows/ui-build.yml
vendored
95
.github/workflows/ui-build.yml
vendored
@ -1,95 +0,0 @@
|
||||
name: UI Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
build:
|
||||
name: Build
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build library
|
||||
run: npm run build
|
||||
|
||||
- name: Verify build output
|
||||
run: |
|
||||
echo "Checking build output..."
|
||||
|
||||
# Check that dist directory exists
|
||||
if [ ! -d "dist" ]; then
|
||||
echo "::error::dist directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check required files exist
|
||||
FILES=(
|
||||
"dist/index.mjs"
|
||||
"dist/index.cjs"
|
||||
"dist/index.d.ts"
|
||||
"dist/index.d.cts"
|
||||
"dist/tailwind.preset.mjs"
|
||||
"dist/tailwind.preset.cjs"
|
||||
"dist/tailwind.preset.d.ts"
|
||||
"dist/tailwind.preset.d.cts"
|
||||
"dist/style.css"
|
||||
)
|
||||
|
||||
for file in "${FILES[@]}"; do
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "::error::Missing required file: $file"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ $file"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "All build outputs verified!"
|
||||
|
||||
- name: Validate package
|
||||
run: npm run validate
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: dist
|
||||
path: packages/ui/dist/
|
||||
retention-days: 7
|
||||
121
.github/workflows/ui-compatibility.yml
vendored
121
.github/workflows/ui-compatibility.yml
vendored
@ -1,121 +0,0 @@
|
||||
name: UI Compatibility
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
build-library:
|
||||
name: Build Library
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build library
|
||||
run: npm run build
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ui-dist
|
||||
path: packages/ui/dist/
|
||||
retention-days: 1
|
||||
|
||||
test-compatibility:
|
||||
name: Test Compatibility
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: [files-changed, build-library]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
example:
|
||||
- vue3-tailwind
|
||||
- vue3-css
|
||||
- vue2-tailwind
|
||||
- vue2-css
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui/examples/${{ matrix.example }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: ui-dist
|
||||
path: packages/ui/dist/
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/examples/${{ matrix.example }}/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
|
||||
- name: Build example app
|
||||
run: npm run build
|
||||
|
||||
compatibility-result:
|
||||
name: Compatibility Result
|
||||
if: always()
|
||||
needs: [files-changed, test-compatibility]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Skip if no UI changes
|
||||
if: needs.files-changed.outputs.ui != 'true'
|
||||
run: echo "No UI changes detected, skipping."
|
||||
|
||||
- name: Check matrix results
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
run: |
|
||||
if [ "${{ needs.test-compatibility.result }}" != "success" ]; then
|
||||
echo "Compatibility tests failed"
|
||||
exit 1
|
||||
fi
|
||||
59
.github/workflows/ui-docker.yml
vendored
59
.github/workflows/ui-docker.yml
vendored
@ -1,59 +0,0 @@
|
||||
name: UI Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
build:
|
||||
name: Build Docker Image
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Build development image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: ./packages/ui
|
||||
file: ./packages/ui/Dockerfile
|
||||
target: development
|
||||
push: false
|
||||
tags: ocelot-social/ui:development
|
||||
cache-from: type=gha,scope=ui-development
|
||||
cache-to: type=gha,mode=max,scope=ui-development
|
||||
|
||||
- name: Build production image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: ./packages/ui
|
||||
file: ./packages/ui/Dockerfile
|
||||
target: production
|
||||
push: false
|
||||
tags: ocelot-social/ui:latest
|
||||
cache-from: type=gha,scope=ui-production
|
||||
cache-to: type=gha,mode=max,scope=ui-production
|
||||
54
.github/workflows/ui-lint.yml
vendored
54
.github/workflows/ui-lint.yml
vendored
@ -1,54 +0,0 @@
|
||||
name: UI Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
lint:
|
||||
name: ESLint
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run ESLint
|
||||
run: npm run lint
|
||||
|
||||
- name: Run TypeScript type check
|
||||
run: npm run typecheck
|
||||
65
.github/workflows/ui-release.yml
vendored
65
.github/workflows/ui-release.yml
vendored
@ -1,65 +0,0 @@
|
||||
name: UI Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'packages/ui/**'
|
||||
- 'release-please-config.json'
|
||||
- '.release-please-manifest.json'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
release-please:
|
||||
name: Release Please
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_created: ${{ steps.release.outputs['packages/ui--release_created'] }}
|
||||
tag_name: ${{ steps.release.outputs['packages/ui--tag_name'] }}
|
||||
version: ${{ steps.release.outputs['packages/ui--version'] }}
|
||||
|
||||
steps:
|
||||
- name: Release Please
|
||||
id: release
|
||||
uses: googleapis/release-please-action@v4
|
||||
with:
|
||||
config-file: release-please-config.json
|
||||
manifest-file: .release-please-manifest.json
|
||||
|
||||
publish:
|
||||
name: Publish to npm
|
||||
needs: release-please
|
||||
if: ${{ needs.release-please.outputs.release_created == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Validate package
|
||||
run: npm run validate
|
||||
|
||||
- name: Publish to npm
|
||||
run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
54
.github/workflows/ui-size.yml
vendored
54
.github/workflows/ui-size.yml
vendored
@ -1,54 +0,0 @@
|
||||
name: UI Size
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
size:
|
||||
name: Bundle Size Check
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Check bundle size
|
||||
run: npm run size
|
||||
74
.github/workflows/ui-storybook.yml
vendored
74
.github/workflows/ui-storybook.yml
vendored
@ -1,74 +0,0 @@
|
||||
name: UI Storybook
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
build:
|
||||
name: Build Storybook
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build Storybook
|
||||
run: npm run storybook:build
|
||||
|
||||
- name: Verify build output
|
||||
run: |
|
||||
echo "Checking Storybook build output..."
|
||||
|
||||
if [ ! -d "storybook-static" ]; then
|
||||
echo "::error::storybook-static directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "storybook-static/index.html" ]; then
|
||||
echo "::error::index.html not found in storybook-static"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Storybook build verified!"
|
||||
|
||||
- name: Upload Storybook artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: storybook-static
|
||||
path: packages/ui/storybook-static/
|
||||
retention-days: 7
|
||||
59
.github/workflows/ui-test.yml
vendored
59
.github/workflows/ui-test.yml
vendored
@ -1,59 +0,0 @@
|
||||
name: UI Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
test:
|
||||
name: Unit Tests
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: npm run test:coverage
|
||||
|
||||
- name: Upload coverage report
|
||||
uses: actions/upload-artifact@v7
|
||||
if: always()
|
||||
with:
|
||||
name: coverage-report
|
||||
path: packages/ui/coverage/
|
||||
retention-days: 7
|
||||
51
.github/workflows/ui-verify.yml
vendored
51
.github/workflows/ui-verify.yml
vendored
@ -1,51 +0,0 @@
|
||||
name: UI Verify
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
verify:
|
||||
name: Completeness Check
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Check component completeness
|
||||
run: npm run verify
|
||||
64
.github/workflows/ui-visual.yml
vendored
64
.github/workflows/ui-visual.yml
vendored
@ -1,64 +0,0 @@
|
||||
name: UI Visual
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/ui
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ui: ${{ steps.changes.outputs.ui }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for file changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
|
||||
visual:
|
||||
name: Visual Regression
|
||||
if: needs.files-changed.outputs.ui == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'packages/ui/.tool-versions'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: packages/ui/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install chromium --with-deps
|
||||
|
||||
- name: Run visual tests
|
||||
run: npm run test:visual
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v7
|
||||
if: failure()
|
||||
with:
|
||||
name: visual-test-results
|
||||
path: |
|
||||
packages/ui/test-results/
|
||||
packages/ui/playwright-report/
|
||||
retention-days: 7
|
||||
@ -1,3 +0,0 @@
|
||||
{
|
||||
"packages/ui": "0.0.1"
|
||||
}
|
||||
160
CHANGELOG.md
160
CHANGELOG.md
@ -4,168 +4,8 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [3.14.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.14.0...3.14.1)
|
||||
|
||||
- refactor(package/ui): eslint config it4c update [`#9233`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9233)
|
||||
- build(deps): bump @aws-sdk/client-s3 from 3.985.0 to 3.990.0 in /backend [`#9224`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9224)
|
||||
- build(deps-dev): bump eslint-plugin-vuejs-accessibility from 2.4.1 to 2.5.0 in /packages/ui [`#9226`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9226)
|
||||
- build(deps-dev): bump eslint-plugin-storybook from 10.2.7 to 10.2.8 in /packages/ui [`#9228`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9228)
|
||||
- build(deps-dev): bump glob from 13.0.1 to 13.0.3 in /packages/ui [`#9230`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9230)
|
||||
- build(deps-dev): bump @types/node from 25.2.2 to 25.2.3 in /packages/ui [`#9232`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9232)
|
||||
- fix(package/ui): os-button class to ensure branding compatibility [`#9211`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9211)
|
||||
- refactor(webapp): vue3 migration - button - icon + circle + loading [`#9208`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9208)
|
||||
- fix(workflow): fix workflow not to double build the webapp image when running unit test [`#9210`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9210)
|
||||
- build(deps-dev): bump the babel group with 3 updates [`#9109`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9109)
|
||||
- build(deps): bump email-templates from 12.0.3 to 13.0.1 in /backend [`#9091`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9091)
|
||||
- build(deps-dev): bump eslint-plugin-jest from 29.12.2 to 29.13.0 in /backend [`#9186`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9186)
|
||||
- fix(backend): fix categories filter [`#9209`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9209)
|
||||
- build(deps-dev): bump eslint-plugin-jsonc from 2.21.0 to 2.21.1 in /backend [`#9188`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9188)
|
||||
- build(deps-dev): bump dotenv from 17.2.3 to 17.2.4 [`#9166`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9166)
|
||||
- build(deps): bump actions/setup-node from 4 to 6 [`#9184`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9184)
|
||||
- build(deps): bump actions/checkout from 4 to 6 [`#9185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9185)
|
||||
- build(deps): bump actions/upload-artifact from 4 to 6 [`#9182`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9182)
|
||||
- feat(webapp): correct version + commits [`#9203`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9203)
|
||||
- fix(workflow): rename ui compatibility test [`#9207`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9207)
|
||||
- refactor(workflow): cache packages [`#9206`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9206)
|
||||
- refactor(workflow): all e2e are running in parallel [`#9205`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9205)
|
||||
- fix(workflow): ensure ui workflows always run, but be skipped if not needed [`#9204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9204)
|
||||
- build(deps-dev): bump @types/node from 25.2.1 to 25.2.2 in /backend [`#9187`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9187)
|
||||
- fix(webapp): properly switch language on static pages [`#9202`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9202)
|
||||
- fix(webapp): make static pages available when logged out [`#9201`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9201)
|
||||
- refactor(webapp): vue3 migration - phase 3 - integration [`#9180`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9180)
|
||||
- fix(backend): ensure a pinned post is accessible even tho the user was muted [`#9200`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9200)
|
||||
- fix(backend): fix structure of unit test reports [`#9199`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9199)
|
||||
- refactor(package/ui): extract rules to eslint config it4c & update package [`#9198`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9198)
|
||||
- refactor(workflow): remove auto-approve workflow [`#9197`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9197)
|
||||
- refactor(workflow): add a new scope for PRs: package/ui [`#9196`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9196)
|
||||
- build(deps-dev): bump @types/node from 25.2.1 to 25.2.2 in /packages/ui [`#9193`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9193)
|
||||
- build(deps-dev): bump vue from 3.5.27 to 3.5.28 in /packages/ui in the vue group [`#9191`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9191)
|
||||
- refactor(backend): reports query parameterization and resolver cleanup with test coverage [`#9156`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9156)
|
||||
- fix(workflow): allow code rabbit to approve PRs [`#9195`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9195)
|
||||
- feat(workflow): coderabbit [`#9194`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9194)
|
||||
|
||||
#### [3.14.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.13.1...3.14.0)
|
||||
|
||||
> 9 February 2026
|
||||
|
||||
- chore(release): v3.14.0 [`#9181`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9181)
|
||||
- refactor(webapp): vue3 migration - phase 2 - setup [`#9161`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9161)
|
||||
- build(deps): bump nginx from 1.29.4-alpine to 1.29.5-alpine in /webapp [`#9162`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9162)
|
||||
- build(deps): bump node from 25.5.0-alpine to 25.6.0-alpine in /backend [`#9163`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9163)
|
||||
- build(deps): bump node from 25.5.0-alpine to 25.6.0-alpine in /webapp [`#9164`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9164)
|
||||
- build(deps-dev): bump cypress from 15.9.0 to 15.10.0 in the cypress group [`#9165`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9165)
|
||||
- build(deps-dev): bump webpack from 5.104.1 to 5.105.0 [`#9167`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9167)
|
||||
- build(deps): bump nodemailer from 7.0.13 to 8.0.0 in /backend [`#9168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9168)
|
||||
- build(deps): bump minimatch from 10.1.1 to 10.1.2 in /backend [`#9169`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9169)
|
||||
- build(deps-dev): bump @types/node from 25.1.0 to 25.2.1 in /backend [`#9171`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9171)
|
||||
- build(deps): bump @aws-sdk/client-s3 and @aws-sdk/lib-storage in /backend [`#9173`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9173)
|
||||
- refactor(workflow): do not clean cache after run [`#9155`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9155)
|
||||
- build(deps-dev): bump eslint-plugin-jest from 29.12.1 to 29.12.2 in /backend [`#9177`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9177)
|
||||
- build(deps): bump peter-evans/repository-dispatch from cf70392543065ca62813db6712a06df1c4f4ae9f to f49a8ac5751834a0666df77deb0289abbe2b3a78 [`#9179`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9179)
|
||||
- refactor(webapp): vue 2.7.16 [`#9160`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9160)
|
||||
- refactor(backend): test roles [`#9157`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9157)
|
||||
- refactor(backend): middleware before/after [`#9128`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9128)
|
||||
- build(deps): bump node from 25.4.0-alpine to 25.5.0-alpine in /webapp [`#9147`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9147)
|
||||
- build(deps): bump node from 25.4.0-alpine to 25.5.0-alpine in /backend [`#9148`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9148)
|
||||
- build(deps): bump actions/cache from 5.0.2 to 5.0.3 [`#9149`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9149)
|
||||
- build(deps): bump docker/login-action from 3.6.0 to 3.7.0 [`#9150`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9150)
|
||||
- build(deps): bump @aws-sdk/client-s3 and @aws-sdk/lib-storage in /backend [`#9151`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9151)
|
||||
- build(deps-dev): bump @types/node from 25.0.10 to 25.1.0 in /backend [`#9152`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9152)
|
||||
- refactor(backend): properly model group-membership [`#9124`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9124)
|
||||
- fix(webapp): allow internal path for custom button [`#9129`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9129)
|
||||
- feat(backend): db script disable notifications [`#9131`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9131)
|
||||
- feat(backend): group pins [`#9034`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9034)
|
||||
- refactor(backend): lint graphql [`#8473`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8473)
|
||||
- fix(backend): fix bug in notifications settings for currentUser [`#9130`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9130)
|
||||
- fix(backend): fix email url encoding [`#9127`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9127)
|
||||
- refactor(other): consolidate Node.js versions and fix e2e workflow [`#9126`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9126)
|
||||
- build(deps): bump cheerio from 1.1.2 to 1.2.0 in /backend [`#9141`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9141)
|
||||
- build(deps-dev): bump @types/node from 25.0.9 to 25.0.10 in /backend [`#9142`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9142)
|
||||
- build(deps): bump @aws-sdk/client-s3 and @aws-sdk/lib-storage in /backend [`#9144`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9144)
|
||||
- build(deps): bump peter-evans/repository-dispatch from 09094272a794c6105029af051e3831908c649b6c to cf70392543065ca62813db6712a06df1c4f4ae9f [`#9145`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9145)
|
||||
- build(deps): bump the metascraper group in /backend with 12 updates [`#9136`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9136)
|
||||
- build(deps-dev): bump sass-embedded from 1.97.2 to 1.97.3 [`#9135`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9135)
|
||||
- build(deps): bump preview-email from 3.1.0 to 3.1.1 in /backend [`#9138`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9138)
|
||||
- fix(webapp): allow running frontend tests locally [`#9125`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9125)
|
||||
- build(deps): bump node from 25.3.0-alpine to 25.4.0-alpine in /webapp [`#9133`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9133)
|
||||
- build(deps-dev): bump @cucumber/cucumber from 12.5.0 to 12.6.0 in the cypress group [`#9134`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9134)
|
||||
- build(deps): bump lodash from 4.17.21 to 4.17.23 in /backend [`#9140`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9140)
|
||||
- build(deps-dev): bump prettier from 3.8.0 to 3.8.1 in /webapp [`#9139`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9139)
|
||||
- build(deps-dev): bump prettier from 3.8.0 to 3.8.1 in /backend [`#9143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9143)
|
||||
- build(deps): bump actions/checkout from 6.0.1 to 6.0.2 [`#9146`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9146)
|
||||
- build(deps): bump node from 25.3.0-alpine to 25.4.0-alpine in /backend [`#9132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9132)
|
||||
- feat(backend): admin creation command for production [`#9057`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9057)
|
||||
- fix(backend): fix permissions for GroupInviteCodes [`#9121`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9121)
|
||||
- fix(backend): fix group-myRole field query [`#9102`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9102)
|
||||
- refactor(e2e): optimize step definitions loading with filepart pairing [`#9122`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9122)
|
||||
- fix(webapp): fix cta-join-group, can crash when group is not defined [`#9103`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9103)
|
||||
- fix(backend): fix active categories when inproperly configured [`#9123`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9123)
|
||||
- fix(webapp): fix local webapp tests [`#9104`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9104)
|
||||
- build(deps-dev): bump the cypress group across 1 directory with 3 updates [`#9058`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9058)
|
||||
- build(deps): bump node from 25.2.1-alpine to 25.3.0-alpine in /webapp [`#9105`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9105)
|
||||
- build(deps): bump actions/setup-node from 6.1.0 to 6.2.0 [`#9107`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9107)
|
||||
- build(deps): bump node from 25.2.1-alpine to 25.3.0-alpine in /backend [`#9106`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9106)
|
||||
- build(deps): bump actions/cache from 5.0.1 to 5.0.2 [`#9108`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9108)
|
||||
- build(deps-dev): bump eslint-plugin-n from 17.23.1 to 17.23.2 in /backend [`#9110`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9110)
|
||||
- build(deps-dev): bump @types/lodash from 4.17.21 to 4.17.23 in /backend [`#9111`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9111)
|
||||
- build(deps): bump @aws-sdk/lib-storage from 3.958.0 to 3.967.0 in /backend [`#9113`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9113)
|
||||
- build(deps-dev): bump eslint-plugin-prettier from 5.5.4 to 5.5.5 in /backend [`#9114`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9114)
|
||||
- build(deps-dev): bump @eslint-community/eslint-plugin-eslint-comments from 4.5.0 to 4.6.0 in /backend [`#9120`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9120)
|
||||
- build(deps-dev): bump prettier from 3.7.4 to 3.8.0 in /webapp [`#9117`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9117)
|
||||
- build(deps): bump ioredis from 5.9.1 to 5.9.2 in /backend [`#9119`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9119)
|
||||
- build(deps): bump @aws-sdk/client-s3 from 3.967.0 to 3.971.0 in /backend [`#9118`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9118)
|
||||
- build(deps-dev): bump eslint-plugin-prettier from 5.5.4 to 5.5.5 in /webapp [`#9115`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9115)
|
||||
- build(deps-dev): bump prettier from 3.7.4 to 3.8.0 in /backend [`#9116`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9116)
|
||||
- build(deps-dev): bump @types/node from 25.0.7 to 25.0.9 in /backend [`#9112`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9112)
|
||||
- build(deps): bump the metascraper group in /backend with 12 updates [`#9063`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9063)
|
||||
- build(deps-dev): bump eslint-plugin-jest from 29.12.0 to 29.12.1 in /backend [`#9090`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9090)
|
||||
- build(deps): bump ioredis from 5.8.2 to 5.9.1 in /backend [`#9095`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9095)
|
||||
- build(deps): bump @aws-sdk/client-s3 from 3.958.0 to 3.966.0 in /backend [`#9100`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9100)
|
||||
- build(deps): bump @aws-sdk/lib-storage from 3.933.0 to 3.958.0 in /backend [`#9093`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9093)
|
||||
- build(deps-dev): bump @types/node from 25.0.3 to 25.0.5 in /backend [`#9096`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9096)
|
||||
- build(deps): bump peter-evans/repository-dispatch from 46fabd2783425293d3f24bc1080da28d046e2dd3 to 09094272a794c6105029af051e3831908c649b6c [`#9089`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9089)
|
||||
- build(deps): bump vue-advanced-chat from 2.0.11 to 2.1.2 in /webapp [`#9084`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9084)
|
||||
- build(deps): bump nginx from 1.29.3-alpine to 1.29.4-alpine in /webapp [`#9070`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9070)
|
||||
- build(deps): bump @aws-sdk/client-s3 from 3.933.0 to 3.958.0 in /backend [`#9086`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9086)
|
||||
- build(deps-dev): bump @types/node from 24.10.1 to 25.0.3 in /backend [`#9078`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9078)
|
||||
- build(deps-dev): bump eslint-plugin-jest from 29.1.0 to 29.11.0 in /backend [`#9087`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9087)
|
||||
- build(deps): bump express from 5.1.0 to 5.2.1 in /backend [`#9065`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9065)
|
||||
- build(deps-dev): bump @types/lodash from 4.17.20 to 4.17.21 in /backend [`#9051`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9051)
|
||||
- build(deps-dev): bump ts-jest from 29.4.5 to 29.4.6 in /backend [`#9069`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9069)
|
||||
- build(deps): bump validator from 13.15.23 to 13.15.26 in /webapp [`#9083`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9083)
|
||||
- build(deps): bump validator from 13.15.23 to 13.15.26 in /backend [`#9080`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9080)
|
||||
- build(deps): bump nodemailer from 7.0.10 to 7.0.12 in /backend [`#9088`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9088)
|
||||
- build(deps): bump actions/upload-artifact from 5.0.0 to 6.0.0 [`#9072`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9072)
|
||||
- build(deps): bump peter-evans/repository-dispatch from d2c43ab06ec1cddd2c2a0aae659681b8465ce87a to 46fabd2783425293d3f24bc1080da28d046e2dd3 [`#9060`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9060)
|
||||
- build(deps-dev): bump prettier from 3.6.2 to 3.7.4 in /webapp [`#9059`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9059)
|
||||
- build(deps): bump docker/metadata-action from 5.9.0 to 5.10.0 [`#9049`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9049)
|
||||
- build(deps): bump actions/setup-node from 6.0.0 to 6.1.0 [`#9061`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9061)
|
||||
- build(deps): bump gaurav-nelson/github-action-markdown-link-check from 1.0.16 to 1.0.17 [`#8329`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8329)
|
||||
- build(deps): bump actions/cache from 4.3.0 to 5.0.1 [`#9071`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9071)
|
||||
- build(deps): bump actions/checkout from 5.0.0 to 6.0.1 [`#9062`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9062)
|
||||
- build(deps-dev): bump prettier from 3.6.2 to 3.7.4 in /backend [`#9067`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9067)
|
||||
- build(deps): bump mime-types from 3.0.1 to 3.0.2 in /backend [`#9044`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9044)
|
||||
- build(deps): bump cross-env from 10.0.0 to 10.1.0 in /backend [`#8943`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8943)
|
||||
- build(deps): bump validator from 13.15.20 to 13.15.23 in /webapp [`#9029`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9029)
|
||||
- build(deps-dev): bump nodemon from 3.1.10 to 3.1.11 in /backend [`#9028`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9028)
|
||||
- build(deps): bump node from 25.1.0-alpine to 25.2.0-alpine in /backend [`#9024`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9024)
|
||||
- build(deps): bump node from 25.1.0-alpine to 25.2.0-alpine in /webapp [`#9023`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9023)
|
||||
- build(deps): bump docker/metadata-action from 5.8.0 to 5.9.0 [`#9014`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9014)
|
||||
- build(deps-dev): bump cypress from 15.5.0 to 15.6.0 in the cypress group [`#9016`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9016)
|
||||
- build(deps): bump bcryptjs from 3.0.2 to 3.0.3 in /backend [`#9019`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9019)
|
||||
- build(deps): bump @aws-sdk/lib-storage from 3.917.0 to 3.922.0 in /backend [`#9022`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9022)
|
||||
- build(deps): bump peter-evans/repository-dispatch from 2c856c63feddee6147cab2f38801935b6a59a765 to d2c43ab06ec1cddd2c2a0aae659681b8465ce87a [`#9025`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9025)
|
||||
- build(deps): bump amannn/action-semantic-pull-request from e49f57ce06c1747542fce2243c7a98682384bc0e to 069817c298f23fab00a8f29a2e556a5eac0f6390 [`#9026`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9026)
|
||||
- build(deps-dev): bump eslint-plugin-jest from 29.0.1 to 29.1.0 in /backend [`#9027`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9027)
|
||||
- build(deps): bump @aws-sdk/client-s3 from 3.922.0 to 3.932.0 in /backend [`#9030`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9030)
|
||||
- build(deps-dev): bump @types/node from 24.9.2 to 24.10.1 in /backend [`#9031`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9031)
|
||||
- build(deps): bump validator from 13.15.20 to 13.15.23 in /backend [`#9033`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9033)
|
||||
|
||||
#### [3.13.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.13.0...3.13.1)
|
||||
|
||||
> 1 November 2025
|
||||
|
||||
- chore(release): v3.13.1 [`#9003`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9003)
|
||||
- build(deps): bump nginx from 1.29.2-alpine to 1.29.3-alpine in /webapp [`#9005`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9005)
|
||||
- build(deps): bump minimatch from 10.0.3 to 10.1.1 in /backend [`#9009`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9009)
|
||||
- build(deps-dev): bump @types/node from 24.9.1 to 24.9.2 in /backend [`#9010`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9010)
|
||||
|
||||
3
backend/.eslintignore
Normal file
3
backend/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
build/
|
||||
coverage/
|
||||
263
backend/.eslintrc.cjs
Normal file
263
backend/.eslintrc.cjs
Normal file
@ -0,0 +1,263 @@
|
||||
// eslint-disable-next-line import/no-commonjs
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['prettier', '@typescript-eslint', 'import', 'n', 'promise', 'security', 'no-catch-all'],
|
||||
extends: [
|
||||
'standard',
|
||||
'eslint:recommended',
|
||||
'plugin:n/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript',
|
||||
'plugin:promise/recommended',
|
||||
'plugin:@eslint-community/eslint-comments/recommended',
|
||||
'prettier',
|
||||
],
|
||||
settings: {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx'],
|
||||
},
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
project: ['./tsconfig.json', './backend/tsconfig.json'],
|
||||
},
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-catch-all/no-catch-all': 'error',
|
||||
'no-console': 'error',
|
||||
camelcase: 'error',
|
||||
'no-debugger': 'error',
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
{
|
||||
htmlWhitespaceSensitivity: 'ignore',
|
||||
},
|
||||
],
|
||||
// import
|
||||
'import/export': 'error',
|
||||
// 'import/no-deprecated': 'error',
|
||||
'import/no-empty-named-blocks': 'error',
|
||||
'import/no-extraneous-dependencies': 'error',
|
||||
'import/no-mutable-exports': 'error',
|
||||
'import/no-unused-modules': 'error',
|
||||
'import/no-named-as-default': 'error',
|
||||
'import/no-named-as-default-member': 'error',
|
||||
'import/no-amd': 'error',
|
||||
'import/no-commonjs': 'error',
|
||||
'import/no-import-module-exports': 'error',
|
||||
'import/no-nodejs-modules': 'off',
|
||||
'import/unambiguous': 'off', // not compatible with .eslintrc.cjs
|
||||
'import/default': 'error',
|
||||
'import/named': 'off', // has false positives
|
||||
'import/namespace': 'error',
|
||||
'import/no-absolute-path': 'error',
|
||||
'import/no-cycle': 'error',
|
||||
'import/no-dynamic-require': 'error',
|
||||
'import/no-internal-modules': 'off',
|
||||
'import/no-relative-packages': 'error',
|
||||
'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }],
|
||||
'import/no-self-import': 'error',
|
||||
'import/no-unresolved': 'error',
|
||||
'import/no-useless-path-segments': 'error',
|
||||
'import/no-webpack-loader-syntax': 'error',
|
||||
'import/consistent-type-specifier-style': 'error',
|
||||
'import/exports-last': 'off',
|
||||
'import/extensions': 'error',
|
||||
'import/first': 'error',
|
||||
'import/group-exports': 'off',
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-anonymous-default-export': 'off', // not compatible with neode
|
||||
'import/no-default-export': 'off', // not compatible with neode
|
||||
'import/no-duplicates': 'error',
|
||||
'import/no-named-default': 'error',
|
||||
'import/no-namespace': 'error',
|
||||
'import/no-unassigned-import': 'error',
|
||||
'import/order': [
|
||||
'error',
|
||||
{
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
||||
'newlines-between': 'always',
|
||||
pathGroups: [
|
||||
{
|
||||
pattern: '@?*/**',
|
||||
group: 'external',
|
||||
position: 'after',
|
||||
},
|
||||
{
|
||||
pattern: '@/**',
|
||||
group: 'external',
|
||||
position: 'after',
|
||||
},
|
||||
],
|
||||
alphabetize: {
|
||||
order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */,
|
||||
caseInsensitive: true /* ignore case. Options: [true, false] */,
|
||||
},
|
||||
distinctGroup: true,
|
||||
},
|
||||
],
|
||||
'import/prefer-default-export': 'off',
|
||||
|
||||
// n
|
||||
// 'n/callback-return': 'error',
|
||||
'n/exports-style': 'error',
|
||||
'n/file-extension-in-import': ['error', 'never'],
|
||||
'n/global-require': 'error',
|
||||
'n/handle-callback-err': 'error',
|
||||
// 'n/hashbang': 'error', // part of n/recommended
|
||||
'n/no-callback-literal': 'error',
|
||||
// 'n/no-deprecated-api': 'error', // part of n/recommended
|
||||
// 'n/no-exports-assign': 'error', // part of n/recommended
|
||||
'n/no-extraneous-import': 'off', // duplicate of import/no-extraneous-dependencies // part of n/recommended
|
||||
// 'n/no-extraneous-require': 'error', // part of n/recommended
|
||||
'n/no-hide-core-modules': 'error',
|
||||
'n/no-missing-import': 'off', // not compatible with typescript // part of n/recommended
|
||||
// 'n/no-missing-require': 'error', // part of n/recommended
|
||||
'n/no-mixed-requires': 'error',
|
||||
'n/no-new-require': 'error',
|
||||
'n/no-path-concat': 'error',
|
||||
'n/no-process-env': 'error',
|
||||
// 'n/no-process-exit': 'error', // part of n/recommended
|
||||
'n/no-restricted-import': 'error',
|
||||
'n/no-restricted-require': 'error',
|
||||
'n/no-sync': 'error',
|
||||
// 'n/no-unpublished-bin': 'error', // part of n/recommended
|
||||
'n/no-unpublished-import': [
|
||||
'error',
|
||||
{ allowModules: ['apollo-server-testing', 'rosie', '@faker-js/faker', 'ts-jest'] },
|
||||
], // part of n/recommended
|
||||
'n/no-unpublished-require': ['error', { allowModules: ['ts-jest', 'require-json5'] }], // part of n/recommended
|
||||
// 'n/no-unsupported-features/es-builtins': 'error', // part of n/recommended
|
||||
// 'n/no-unsupported-features/es-syntax': 'error', // part of n/recommended
|
||||
// 'n/no-unsupported-features/node-builtins': 'error', // part of n/recommended
|
||||
'n/prefer-global/buffer': 'error',
|
||||
'n/prefer-global/console': 'error',
|
||||
'n/prefer-global/process': 'error',
|
||||
'n/prefer-global/text-decoder': 'error',
|
||||
'n/prefer-global/text-encoder': 'error',
|
||||
'n/prefer-global/url': 'error',
|
||||
'n/prefer-global/url-search-params': 'error',
|
||||
'n/prefer-node-protocol': 'error',
|
||||
'n/prefer-promises/dns': 'error',
|
||||
'n/prefer-promises/fs': 'error',
|
||||
// 'n/process-exit-as-throw': 'error', // part of n/recommended
|
||||
'n/shebang': 'error',
|
||||
|
||||
// promise
|
||||
// 'promise/always-return': 'error', // part of promise/recommended
|
||||
'promise/avoid-new': 'error',
|
||||
// 'promise/catch-or-return': 'error', // part of promise/recommended
|
||||
// 'promise/no-callback-in-promise': 'warn', // part of promise/recommended
|
||||
'promise/no-multiple-resolved': 'error',
|
||||
'promise/no-native': 'off', // ES5 only
|
||||
// 'promise/no-nesting': 'warn', // part of promise/recommended
|
||||
// 'promise/no-new-statics': 'error', // part of promise/recommended
|
||||
// 'promise/no-promise-in-callback': 'warn', // part of promise/recommended
|
||||
// 'promise/no-return-in-finally': 'warn', // part of promise/recommended
|
||||
// 'promise/no-return-wrap': 'error', // part of promise/recommended
|
||||
// 'promise/param-names': 'error', // part of promise/recommended
|
||||
'promise/prefer-await-to-callbacks': 'error',
|
||||
'promise/prefer-catch': 'error',
|
||||
'promise/spec-only': 'error',
|
||||
// 'promise/valid-params': 'error', // part of promise/recommended
|
||||
|
||||
// eslint comments
|
||||
'@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
|
||||
'@eslint-community/eslint-comments/no-restricted-disable': 'error',
|
||||
'@eslint-community/eslint-comments/no-use': 'off',
|
||||
'@eslint-community/eslint-comments/require-description': 'off',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.js', '*.cjs', '*.ts', '*.tsx'],
|
||||
extends: ['plugin:security/recommended-legacy'],
|
||||
},
|
||||
// only for ts files
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'plugin:@typescript-eslint/strict',
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
// allow explicitly defined dangling promises
|
||||
// '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
|
||||
'no-void': ['error', { allowAsStatement: true }],
|
||||
// ignore prefer-regexp-exec rule to allow string.match(regex)
|
||||
'@typescript-eslint/prefer-regexp-exec': 'off',
|
||||
// this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486
|
||||
'import/unambiguous': 'off',
|
||||
// this is not compatible with typeorm, due to joined tables can be null, but are not defined as nullable
|
||||
'@typescript-eslint/no-unnecessary-condition': 'off',
|
||||
// respect underscore as acceptable unused variable
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.json'],
|
||||
// this is to properly reference the referenced project database without requirement of compiling it
|
||||
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.spec.ts'],
|
||||
plugins: ['jest'],
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
rules: {
|
||||
'jest/no-disabled-tests': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/prefer-to-have-length': 'error',
|
||||
'jest/valid-expect': 'error',
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
'jest/unbound-method': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
extends: ['plugin:jsonc/recommended-with-jsonc'],
|
||||
files: ['*.json', '*.json5', '*.jsonc'],
|
||||
parser: 'jsonc-eslint-parser',
|
||||
},
|
||||
{
|
||||
files: ['*.graphql', '*.gql'],
|
||||
parser: '@graphql-eslint/eslint-plugin',
|
||||
plugins: ['@graphql-eslint'],
|
||||
extends: ['plugin:@graphql-eslint/schema-recommended'],
|
||||
rules: {
|
||||
'@graphql-eslint/description-style': ['error', { style: 'inline' }],
|
||||
'@graphql-eslint/require-description': 'off',
|
||||
'@graphql-eslint/naming-convention': 'off',
|
||||
'@graphql-eslint/strict-id-in-types': 'off',
|
||||
'@graphql-eslint/no-typename-prefix': 'off',
|
||||
// incompatible: `depends on a GraphQL validation rule "XXX" but it's not available in the "graphql" version you are using. Skipping…`
|
||||
'@graphql-eslint/known-directives': 'off',
|
||||
'@graphql-eslint/known-argument-names': 'off',
|
||||
'@graphql-eslint/known-type-names': 'off',
|
||||
'@graphql-eslint/lone-schema-definition': 'off',
|
||||
'@graphql-eslint/provided-required-arguments': 'off',
|
||||
'@graphql-eslint/unique-directive-names': 'off',
|
||||
'@graphql-eslint/unique-directive-names-per-location': 'off',
|
||||
'@graphql-eslint/unique-field-definition-names': 'off',
|
||||
'@graphql-eslint/unique-operation-types': 'off',
|
||||
'@graphql-eslint/unique-type-names': 'off',
|
||||
},
|
||||
parserOptions: {
|
||||
schema: './src/graphql/types/**/*.gql',
|
||||
assumeValid: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
9
backend/.prettierrc.cjs
Normal file
9
backend/.prettierrc.cjs
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
module.exports = {
|
||||
semi: false,
|
||||
printWidth: 100,
|
||||
singleQuote: true,
|
||||
trailingComma: "all",
|
||||
tabWidth: 2,
|
||||
bracketSpacing: true
|
||||
};
|
||||
@ -1,5 +1,4 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:25.8.1-alpine AS base
|
||||
FROM node:25.5.0-alpine AS base
|
||||
LABEL org.label-schema.name="ocelot.social:backend"
|
||||
LABEL org.label-schema.description="Backend of the Social Network Software ocelot.social"
|
||||
LABEL org.label-schema.usage="https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/README.md"
|
||||
@ -29,15 +28,13 @@ ONBUILD COPY ./branding/email/ src/middleware/helpers/email/
|
||||
ONBUILD COPY ./branding/middlewares/ src/middleware/branding/
|
||||
ONBUILD COPY ./branding/data/ src/db/data
|
||||
ONBUILD COPY ./branding/public/ public/
|
||||
ONBUILD RUN --mount=type=cache,target=/yarn-cache,sharing=locked \
|
||||
yarn install --production=false --frozen-lockfile --non-interactive --cache-folder /yarn-cache
|
||||
ONBUILD RUN yarn install --production=false --frozen-lockfile --non-interactive
|
||||
ONBUILD RUN yarn run build
|
||||
ONBUILD RUN mkdir /build
|
||||
ONBUILD RUN cp -r ./build /build
|
||||
ONBUILD RUN cp -r ./public /build
|
||||
ONBUILD RUN cp -r ./package.json yarn.lock /build
|
||||
ONBUILD RUN --mount=type=cache,target=/yarn-cache,sharing=locked \
|
||||
cd /build && yarn install --production=true --frozen-lockfile --non-interactive --cache-folder /yarn-cache
|
||||
ONBUILD RUN cd /build && yarn install --production=true --frozen-lockfile --non-interactive
|
||||
|
||||
FROM build AS test
|
||||
# required for the migrations
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import config from 'eslint-config-it4c'
|
||||
import graphql from 'eslint-config-it4c/modules/graphql'
|
||||
import jest from 'eslint-config-it4c/modules/jest'
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: ['node_modules/', 'build/', 'coverage/'],
|
||||
},
|
||||
...config,
|
||||
...jest,
|
||||
// GraphQL schema linting (extend file pattern to include .gql)
|
||||
...graphql.map((c) => ({
|
||||
...c,
|
||||
files: ['**/*.graphql', '**/*.gql'],
|
||||
})),
|
||||
{
|
||||
files: ['**/*.graphql', '**/*.gql'],
|
||||
// TODO: Parser must be set explicitly because the it4c module only provides
|
||||
// plugins and rules, not languageOptions. Without this, ESLint uses the JS
|
||||
// parser for .gql files. Remove when fixed in eslint-config-it4c.
|
||||
languageOptions: {
|
||||
parser: graphql[0].plugins['@graphql-eslint'].parser,
|
||||
parserOptions: {
|
||||
graphQLConfig: {
|
||||
schema: './src/graphql/types/**/*.gql',
|
||||
documents: './src/graphql/queries/**/*.gql',
|
||||
},
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Would require descriptions on every type/field/input — too noisy for now
|
||||
'@graphql-eslint/require-description': 'off',
|
||||
// camelCase operation names and _id/_ne underscores conflict with existing schema
|
||||
'@graphql-eslint/naming-convention': 'off',
|
||||
// Many types (Image, File, InviteCode, etc.) intentionally lack id: ID!
|
||||
'@graphql-eslint/strict-id-in-types': 'off',
|
||||
// Fields like groupType, queryLocations match parent type name by coincidence
|
||||
'@graphql-eslint/no-typename-prefix': 'off',
|
||||
// neo4j-graphql-js adds arguments (first, offset) at runtime not present in static schema
|
||||
'@graphql-eslint/known-argument-names': 'off',
|
||||
// TODO: operations-recommended rules must be disabled because the it4c
|
||||
// graphql module bundles both schema and operations configs together.
|
||||
// Remove when eslint-config-it4c exports them separately (e.g. graphql/schema).
|
||||
'@graphql-eslint/executable-definitions': 'off',
|
||||
// neo4j-graphql-js adds fields at runtime (_id, relations) not present in static schema
|
||||
'@graphql-eslint/fields-on-correct-type': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Backend-specific TypeScript overrides
|
||||
files: ['**/*.ts'],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: {
|
||||
allowDefaultProject: ['eslint.config.ts', 'jest.config.ts', 'prettier.config.ts'],
|
||||
},
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// TypeORM compatibility: joined tables can be null but are not defined as nullable
|
||||
'@typescript-eslint/no-unnecessary-condition': 'off',
|
||||
// Allow string.match(regex) instead of regex.exec(string)
|
||||
'@typescript-eslint/prefer-regexp-exec': 'off',
|
||||
// TODO: gradually add return types to exported functions, then remove this override
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
// Allow @/* path aliases in relative parent imports
|
||||
'import-x/no-relative-parent-imports': ['error', { ignore: ['@/*'] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
// Jest test file overrides
|
||||
files: ['**/*.spec.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Config files: allow require() of devDependencies
|
||||
files: ['*.config.{js,mjs,cjs,ts,mts,cts}'],
|
||||
rules: {
|
||||
'n/no-unpublished-require': 'off',
|
||||
},
|
||||
},
|
||||
]
|
||||
27
backend/jest.config.cjs
Normal file
27
backend/jest.config.cjs
Normal file
@ -0,0 +1,27 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const requireJSON5 = require('require-json5')
|
||||
const { pathsToModuleNameMapper } = require('ts-jest')
|
||||
|
||||
const { compilerOptions } = requireJSON5('./tsconfig.json')
|
||||
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: [
|
||||
'**/*.ts',
|
||||
'!**/node_modules/**',
|
||||
'!**/test/**',
|
||||
'!**/build/**',
|
||||
'!**/src/**/?(*.)+(spec|test).ts?(x)',
|
||||
'!**/src/db/**',
|
||||
],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 92,
|
||||
},
|
||||
},
|
||||
testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'],
|
||||
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
|
||||
import { pathsToModuleNameMapper } from 'ts-jest'
|
||||
import { parseConfigFileTextToJson } from 'typescript'
|
||||
|
||||
// eslint-disable-next-line n/no-sync -- config files are synchronous by nature
|
||||
const tsconfigText = readFileSync('./tsconfig.json', 'utf-8')
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- parseConfigFileTextToJson returns untyped config
|
||||
const { config } = parseConfigFileTextToJson('tsconfig.json', tsconfigText)
|
||||
const paths = (config as { compilerOptions: { paths: Record<string, string[]> } }).compilerOptions
|
||||
.paths
|
||||
|
||||
export default {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: [
|
||||
'**/*.ts',
|
||||
'!**/node_modules/**',
|
||||
'!**/test/**',
|
||||
'!**/build/**',
|
||||
'!**/src/**/?(*.)+(spec|test).ts?(x)',
|
||||
'!**/src/db/**',
|
||||
'!*.config.ts',
|
||||
'!**/*.d.ts',
|
||||
'!**/gql-register.ts',
|
||||
],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 92,
|
||||
},
|
||||
},
|
||||
testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'],
|
||||
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
|
||||
transform: {
|
||||
'\\.gql$': '<rootDir>/test/graphqlTransform.ts',
|
||||
'\\.tsx?$': 'ts-jest',
|
||||
},
|
||||
moduleNameMapper: pathsToModuleNameMapper(paths, { prefix: '<rootDir>/' }),
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ocelot-social-backend",
|
||||
"version": "3.14.1",
|
||||
"version": "3.13.1",
|
||||
"description": "GraphQL Backend for ocelot.social",
|
||||
"repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social",
|
||||
"author": "ocelot.social Community",
|
||||
@ -10,20 +10,20 @@
|
||||
"scripts": {
|
||||
"start": "node build/src/",
|
||||
"build": "tsc && tsc-alias && ./scripts/build.copy.files.sh",
|
||||
"dev": "nodemon --exec tsx src/index.ts -e js,ts,gql",
|
||||
"dev": "nodemon --exec ts-node --require tsconfig-paths/register src/index.ts -e js,ts,gql",
|
||||
"dev:debug": "nodemon --exec node --inspect=0.0.0.0:9229 build/src/index.js -e js,ts,gql",
|
||||
"lint": "eslint --max-warnings 0 .",
|
||||
"lint": "eslint --max-warnings=0 --report-unused-disable-directives --ext .js,.ts,.cjs,.json,.json5,.jsonc,.graphql,.gql .",
|
||||
"test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --runInBand --coverage --forceExit --detectOpenHandles",
|
||||
"db:reset": "tsx src/db/reset.ts",
|
||||
"db:reset:withmigrations": "tsx src/db/reset-with-migrations.ts",
|
||||
"db:seed": "tsx --require ./src/graphql/gql-register.ts src/db/seed.ts",
|
||||
"db:data:admin": "tsx src/db/admin.ts",
|
||||
"db:data:badges": "tsx src/db/badges.ts",
|
||||
"db:data:branding": "tsx src/db/data-branding.ts",
|
||||
"db:data:categories": "tsx src/db/categories.ts",
|
||||
"db:reset": "ts-node --require tsconfig-paths/register src/db/reset.ts",
|
||||
"db:reset:withmigrations": "ts-node --require tsconfig-paths/register src/db/reset-with-migrations.ts",
|
||||
"db:seed": "ts-node --require tsconfig-paths/register src/db/seed.ts",
|
||||
"db:data:admin": "ts-node --require tsconfig-paths/register src/db/admin.ts",
|
||||
"db:data:badges": "ts-node --require tsconfig-paths/register src/db/badges.ts",
|
||||
"db:data:branding": "ts-node --require tsconfig-paths/register src/db/data-branding.ts",
|
||||
"db:data:categories": "ts-node --require tsconfig-paths/register src/db/categories.ts",
|
||||
"db:migrate": "migrate --compiler 'ts:./src/db/compiler.ts' --migrations-dir ./src/db/migrations --store ./src/db/migrate/store.ts",
|
||||
"db:migrate:create": "migrate --compiler 'ts:./src/db/compiler.ts' --migrations-dir ./src/db/migrations --template-file ./src/db/migrate/template.ts --date-format 'yyyymmddHHmmss' create",
|
||||
"db:func:disable:notifications": "tsx src/db/disable-notifications.ts",
|
||||
"db:func:disable:notifications": "ts-node --require tsconfig-paths/register src/db/disable-notifications.ts",
|
||||
"prod:migrate": "migrate --migrations-dir ./build/src/db/migrations --store ./build/src/db/migrate/store.js",
|
||||
"prod:db:data:branding": "node build/src/db/data-branding.js",
|
||||
"prod:db:data:categories": "node build/src/db/categories.js",
|
||||
@ -31,90 +31,105 @@
|
||||
"prod:db:func:disable:notifications": "node build/src/db/disable-notifications.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/server": "^4.11.3",
|
||||
"@aws-sdk/client-s3": "^3.1005.0",
|
||||
"@aws-sdk/lib-storage": "^3.1000.0",
|
||||
"@graphql-tools/load-files": "^7.0.0",
|
||||
"@graphql-tools/merge": "^9.0.0",
|
||||
"@aws-sdk/client-s3": "^3.980.0",
|
||||
"@aws-sdk/lib-storage": "^3.980.0",
|
||||
"@sentry/node": "^5.30.0",
|
||||
"@types/mime-types": "^3.0.1",
|
||||
"apollo-server": "~2.14.2",
|
||||
"apollo-server-express": "^2.14.2",
|
||||
"bcryptjs": "~3.0.3",
|
||||
"body-parser": "^2.2.2",
|
||||
"body-parser": "^1.20.3",
|
||||
"cheerio": "~1.2.0",
|
||||
"cross-env": "~10.1.0",
|
||||
"dotenv": "~17.0.1",
|
||||
"email-templates": "^13.0.1",
|
||||
"email-templates": "^12.0.3",
|
||||
"express": "^4.22.1",
|
||||
"graphql": "^16.13.0",
|
||||
"graphql": "^14.6.0",
|
||||
"graphql-middleware": "~6.1.35",
|
||||
"graphql-middleware-sentry": "^3.2.1",
|
||||
"graphql-redis-subscriptions": "^2.7.0",
|
||||
"graphql-shield": "^7.6.5",
|
||||
"graphql-subscriptions": "^2.0.0",
|
||||
"graphql-shield": "~7.2.2",
|
||||
"graphql-subscriptions": "^1.1.0",
|
||||
"graphql-tag": "~2.10.3",
|
||||
"graphql-upload": "^13.0.0",
|
||||
"graphql-ws": "^5.16.2",
|
||||
"helmet": "~8.1.0",
|
||||
"ioredis": "^5.10.1",
|
||||
"ioredis": "^5.9.2",
|
||||
"jsonwebtoken": "~8.5.1",
|
||||
"languagedetect": "^2.0.0",
|
||||
"linkify-html": "^4.3.2",
|
||||
"linkifyjs": "^4.3.2",
|
||||
"lodash": "~4.17.23",
|
||||
"metascraper": "^5.50.0",
|
||||
"metascraper-author": "^5.50.0",
|
||||
"metascraper-date": "^5.50.0",
|
||||
"metascraper-description": "^5.50.0",
|
||||
"metascraper-image": "^5.50.0",
|
||||
"metascraper-lang": "^5.50.0",
|
||||
"merge-graphql-schemas": "^1.7.8",
|
||||
"metascraper": "^5.49.19",
|
||||
"metascraper-author": "^5.49.19",
|
||||
"metascraper-date": "^5.49.19",
|
||||
"metascraper-description": "^5.49.19",
|
||||
"metascraper-image": "^5.49.19",
|
||||
"metascraper-lang": "^5.49.19",
|
||||
"metascraper-lang-detector": "^4.10.2",
|
||||
"metascraper-logo": "^5.50.0",
|
||||
"metascraper-publisher": "^5.50.0",
|
||||
"metascraper-logo": "^5.49.19",
|
||||
"metascraper-publisher": "^5.49.19",
|
||||
"metascraper-soundcloud": "^5.34.4",
|
||||
"metascraper-title": "^5.50.0",
|
||||
"metascraper-url": "^5.50.0",
|
||||
"metascraper-video": "^5.50.0",
|
||||
"metascraper-youtube": "^5.50.0",
|
||||
"metascraper-title": "^5.49.19",
|
||||
"metascraper-url": "^5.49.19",
|
||||
"metascraper-video": "^5.49.19",
|
||||
"metascraper-youtube": "^5.49.20",
|
||||
"migrate": "^2.1.0",
|
||||
"mime-types": "^3.0.2",
|
||||
"minimatch": "^10.2.4",
|
||||
"minimatch": "^10.1.1",
|
||||
"mustache": "^4.2.0",
|
||||
"neo4j-driver": "^4.4.11",
|
||||
"neo4j-graphql-js": "2.11.5",
|
||||
"neode": "^0.4.9",
|
||||
"node-fetch": "^2.7.0",
|
||||
"nodemailer": "^8.0.3",
|
||||
"nodemailer": "^7.0.12",
|
||||
"nodemailer-html-to-text": "^3.2.0",
|
||||
"preview-email": "^3.1.1",
|
||||
"pug": "^3.0.4",
|
||||
"sanitize-html": "~2.17.1",
|
||||
"slugify": "^1.6.8",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"pug": "^3.0.3",
|
||||
"sanitize-html": "~2.17.0",
|
||||
"slugify": "^1.6.6",
|
||||
"trunc-html": "~1.1.2",
|
||||
"tslog": "^4.10.2",
|
||||
"uuid": "~9.0.1",
|
||||
"validator": "^13.15.26",
|
||||
"ws": "^8.18.2",
|
||||
"xregexp": "^5.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "^4.6.0",
|
||||
"@faker-js/faker": "9.9.0",
|
||||
"@graphql-eslint/eslint-plugin": "^3.20.1",
|
||||
"@types/email-templates": "^10.0.4",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/jsonwebtoken": "~8.5.1",
|
||||
"@types/lodash": "^4.17.24",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/lodash": "^4.17.23",
|
||||
"@types/node": "^25.1.0",
|
||||
"@types/request": "^2.48.13",
|
||||
"@types/slug": "^5.0.9",
|
||||
"@types/uuid": "~9.0.1",
|
||||
"@types/ws": "^8.18.1",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-config-it4c": "^0.12.0",
|
||||
"jest": "^30.3.0",
|
||||
"nodemon": "~3.1.14",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"apollo-server-testing": "~2.11.0",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-jest": "^29.12.1",
|
||||
"eslint-plugin-jsonc": "^2.21.0",
|
||||
"eslint-plugin-n": "^17.23.2",
|
||||
"eslint-plugin-no-catch-all": "^1.1.0",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
"eslint-plugin-promise": "^7.2.1",
|
||||
"eslint-plugin-security": "^3.0.1",
|
||||
"jest": "^30.2.0",
|
||||
"nodemon": "~3.1.11",
|
||||
"prettier": "^3.8.1",
|
||||
"require-json5": "^1.3.0",
|
||||
"rosie": "^2.1.1",
|
||||
"ts-jest": "^29.4.6",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsc-alias": "^1.8.16",
|
||||
"tsx": "^4.21.0",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"resolutions": {
|
||||
@ -124,9 +139,7 @@
|
||||
"**/string-width": "4.2.0",
|
||||
"**/wrap-ansi": "7.0.0",
|
||||
"**/jwa": "^2.0.1",
|
||||
"**/@types/express": "4.17.25",
|
||||
"neo4j-graphql-js/graphql": "^16.11.0",
|
||||
"graphql-upload/graphql": "^16.11.0"
|
||||
"**/@types/express": "4.17.25"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.12.1"
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export { default } from 'eslint-config-it4c/prettier'
|
||||
@ -1,17 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable import-x/no-namespace */
|
||||
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
|
||||
/* eslint-disable n/no-process-env */
|
||||
import { config } from 'dotenv'
|
||||
// eslint-disable-next-line import/no-namespace
|
||||
import * as SMTPTransport from 'nodemailer/lib/smtp-pool'
|
||||
|
||||
import emails from './emails'
|
||||
import metadata from './metadata'
|
||||
|
||||
import type * as SMTPTransport from 'nodemailer/lib/smtp-pool'
|
||||
|
||||
// Load env file
|
||||
config()
|
||||
|
||||
@ -54,7 +51,6 @@ const SMTP_DKIM_KEYSELECTOR = env.SMTP_DKIM_KEYSELECTOR
|
||||
const SMTP_DKIM_PRIVATEKEY = env.SMTP_DKIM_PRIVATEKEY?.replace(/\\n/g, '\n') // replace all "\n" in .env string by real line break
|
||||
const SMTP_MAX_CONNECTIONS = (env.SMTP_MAX_CONNECTIONS && parseInt(env.SMTP_MAX_CONNECTIONS)) || 5
|
||||
const SMTP_MAX_MESSAGES = (env.SMTP_MAX_MESSAGES && parseInt(env.SMTP_MAX_MESSAGES)) || 100
|
||||
const SMTP_REJECT_UNAUTHORIZED = env.SMTP_REJECT_UNAUTHORIZED !== 'false' // default = true
|
||||
|
||||
const nodemailerTransportOptions: SMTPTransport.Options = {
|
||||
host: SMTP_HOST,
|
||||
@ -64,9 +60,6 @@ const nodemailerTransportOptions: SMTPTransport.Options = {
|
||||
pool: true,
|
||||
maxConnections: SMTP_MAX_CONNECTIONS,
|
||||
maxMessages: SMTP_MAX_MESSAGES,
|
||||
tls: {
|
||||
rejectUnauthorized: SMTP_REJECT_UNAUTHORIZED,
|
||||
},
|
||||
}
|
||||
if (SMTP_USERNAME && SMTP_PASSWORD) {
|
||||
nodemailerTransportOptions.auth = {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
import { getDriver, getNeode } from '@db/neo4j'
|
||||
|
||||
import type { Driver } from 'neo4j-driver'
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
|
||||
import databaseContext from '@context/database'
|
||||
import pubsubContext from '@context/pubsub'
|
||||
import CONFIG from '@src/config'
|
||||
import type { DecodedUser } from '@src/jwt/decode'
|
||||
import { decode } from '@src/jwt/decode'
|
||||
import ocelotLogger from '@src/logger'
|
||||
import type OcelotLogger from '@src/logger'
|
||||
|
||||
import type { DecodedUser } from '@src/jwt/decode'
|
||||
import type { ApolloServerExpressConfig } from 'apollo-server-express'
|
||||
|
||||
const serverDatabase = databaseContext()
|
||||
const serverPubsub = pubsubContext()
|
||||
@ -14,14 +18,14 @@ export const getContext =
|
||||
database?: ReturnType<typeof databaseContext>
|
||||
pubsub?: ReturnType<typeof pubsubContext>
|
||||
authenticatedUser: DecodedUser | null | undefined
|
||||
logger?: typeof ocelotLogger
|
||||
logger?: typeof OcelotLogger
|
||||
config: typeof CONFIG
|
||||
}) =>
|
||||
async (req: { headers: { authorization?: string } }) => {
|
||||
const {
|
||||
database = serverDatabase,
|
||||
pubsub = serverPubsub,
|
||||
authenticatedUser,
|
||||
authenticatedUser = undefined,
|
||||
logger = ocelotLogger,
|
||||
config = CONFIG,
|
||||
} = opts ?? {}
|
||||
@ -40,11 +44,18 @@ export const getContext =
|
||||
req,
|
||||
cypherParams: {
|
||||
currentUserId: user ? user.id : null,
|
||||
languageDefault: config.LANGUAGE_DEFAULT.toUpperCase(),
|
||||
},
|
||||
config,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const context: ApolloServerExpressConfig['context'] = async (options) => {
|
||||
const { connection, req } = options
|
||||
if (connection) {
|
||||
return connection.context
|
||||
} else {
|
||||
return getContext()(req)
|
||||
}
|
||||
}
|
||||
export type Context = Awaited<ReturnType<ReturnType<typeof getContext>>>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { getNeode } from './neo4j'
|
||||
import { trophies, verification } from './seed/badges'
|
||||
|
||||
// eslint-disable-next-line import-x/newline-after-import
|
||||
// eslint-disable-next-line import/newline-after-import
|
||||
;(async function () {
|
||||
const neode = getNeode()
|
||||
try {
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
/* eslint-disable import-x/no-commonjs */
|
||||
// eslint-disable-next-line n/no-unpublished-require
|
||||
const tsx = require('tsx/cjs/api')
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable import/no-commonjs */
|
||||
// eslint-disable-next-line n/no-unpublished-require, @typescript-eslint/no-var-requires
|
||||
const tsNode = require('ts-node')
|
||||
// eslint-disable-next-line import/no-unassigned-import, n/no-unpublished-require
|
||||
require('tsconfig-paths/register')
|
||||
|
||||
module.exports = tsx.register
|
||||
module.exports = tsNode.register
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable @typescript-eslint/await-thenable */
|
||||
import { readdir } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ const run = async () => {
|
||||
if (args.length !== 1) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Usage: yarn run db:func:disable-notifications <email>')
|
||||
|
||||
// eslint-disable-next-line n/no-process-exit
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ const run = async () => {
|
||||
if (!emailRegex.test(email)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error: Invalid email address format')
|
||||
|
||||
// eslint-disable-next-line n/no-process-exit
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@ -46,13 +46,13 @@ const run = async () => {
|
||||
if (result !== '1') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`User with email address ${email} not found`)
|
||||
|
||||
// eslint-disable-next-line n/no-process-exit
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Notifications for User with email address ${email} disabled`)
|
||||
|
||||
// eslint-disable-next-line n/no-process-exit
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable n/no-unpublished-import */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
import { faker } from '@faker-js/faker'
|
||||
import { hashSync } from 'bcryptjs'
|
||||
import { Factory } from 'rosie'
|
||||
@ -15,11 +13,10 @@ import { v4 as uuid } from 'uuid'
|
||||
import { generateInviteCode } from '@graphql/resolvers/inviteCodes'
|
||||
import { isUniqueFor } from '@middleware/sluggifyMiddleware'
|
||||
import uniqueSlug from '@middleware/slugify/uniqueSlug'
|
||||
import { Context } from '@src/context'
|
||||
|
||||
import { getDriver, getNeode } from './neo4j'
|
||||
|
||||
import type { Context } from '@src/context'
|
||||
|
||||
const neode = getNeode()
|
||||
|
||||
const uniqueImageUrl = (imageUrl) => {
|
||||
@ -52,14 +49,14 @@ Factory.define('category')
|
||||
.attr('id', uuid)
|
||||
.attr('icon', 'globe')
|
||||
.attr('name', 'Global Peace & Nonviolence')
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('Category', buildObject)
|
||||
})
|
||||
|
||||
Factory.define('badge')
|
||||
.attr('type', 'crowdfunding')
|
||||
.attr('status', 'permanent')
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('Badge', buildObject)
|
||||
})
|
||||
|
||||
@ -70,7 +67,7 @@ Factory.define('image')
|
||||
.attr('alt', faker.lorem.sentence)
|
||||
.attr('type', 'image/jpeg')
|
||||
.attr('url', null)
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
if (!buildObject.url) {
|
||||
buildObject.url = faker.image.urlPicsumPhotos({
|
||||
width: buildObject.width,
|
||||
@ -87,7 +84,7 @@ Factory.define('file')
|
||||
.attr('name', faker.lorem.slug)
|
||||
.attr('type', 'image/jpeg')
|
||||
.attr('url', null)
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
if (!buildObject.url) {
|
||||
buildObject.url = faker.image.urlPicsumPhotos()
|
||||
}
|
||||
@ -174,8 +171,8 @@ Factory.define('post')
|
||||
return Promise.all([Factory.build('category')])
|
||||
}) */
|
||||
.option('tagIds', [])
|
||||
.option('tags', ['tagIds'], async (tagIds) => {
|
||||
return Promise.all(tagIds.map(async (id) => neode.find('Tag', id)))
|
||||
.option('tags', ['tagIds'], (tagIds) => {
|
||||
return Promise.all(tagIds.map((id) => neode.find('Tag', id)))
|
||||
})
|
||||
.option('authorId', null)
|
||||
.option('author', ['authorId'], (authorId) => {
|
||||
@ -230,55 +227,6 @@ Factory.define('post')
|
||||
return post
|
||||
})
|
||||
|
||||
Factory.define('group')
|
||||
.option('ownerId', null)
|
||||
.option('owner', ['ownerId'], (ownerId) => {
|
||||
if (ownerId) return neode.find('User', ownerId)
|
||||
return Factory.build('user')
|
||||
})
|
||||
.attrs({
|
||||
id: uuid,
|
||||
name: faker.company.name,
|
||||
about: faker.lorem.sentence,
|
||||
description: faker.lorem.paragraphs,
|
||||
groupType: 'public',
|
||||
actionRadius: 'regional',
|
||||
deleted: false,
|
||||
disabled: false,
|
||||
})
|
||||
.attr('slug', ['slug', 'name'], (slug, name) => {
|
||||
return slug || slugify(name, { lower: true })
|
||||
})
|
||||
.attr(
|
||||
'descriptionExcerpt',
|
||||
['descriptionExcerpt', 'description'],
|
||||
(descriptionExcerpt, description) => {
|
||||
return descriptionExcerpt || description
|
||||
},
|
||||
)
|
||||
.after(async (buildObject, options) => {
|
||||
const [group, owner] = await Promise.all([neode.create('Group', buildObject), options.owner])
|
||||
const session = driver.session()
|
||||
try {
|
||||
await session.writeTransaction((txc) =>
|
||||
txc.run(
|
||||
`
|
||||
MATCH (owner:User {id: $ownerId}), (group:Group {id: $groupId})
|
||||
MERGE (owner)-[:CREATED]->(group)
|
||||
MERGE (owner)-[membership:MEMBER_OF]->(group)
|
||||
SET membership.createdAt = toString(datetime()),
|
||||
membership.updatedAt = toString(datetime()),
|
||||
membership.role = 'owner'
|
||||
`,
|
||||
{ ownerId: owner.get('id'), groupId: buildObject.id },
|
||||
),
|
||||
)
|
||||
} finally {
|
||||
await session.close()
|
||||
}
|
||||
return group
|
||||
})
|
||||
|
||||
Factory.define('comment')
|
||||
.option('postId', null)
|
||||
.option('post', ['postId'], (postId) => {
|
||||
@ -316,7 +264,7 @@ Factory.define('donations')
|
||||
.attr('showDonations', true)
|
||||
.attr('goal', 15000)
|
||||
.attr('progress', 7000)
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('Donations', buildObject)
|
||||
})
|
||||
|
||||
@ -327,13 +275,13 @@ const emailDefaults = {
|
||||
|
||||
Factory.define('emailAddress')
|
||||
.attrs(emailDefaults)
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('EmailAddress', buildObject)
|
||||
})
|
||||
|
||||
Factory.define('unverifiedEmailAddress')
|
||||
.attr(emailDefaults)
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('UnverifiedEmailAddress', buildObject)
|
||||
})
|
||||
|
||||
@ -346,7 +294,7 @@ const inviteCodeDefaults = {
|
||||
Factory.define('inviteCode')
|
||||
.attrs(inviteCodeDefaults)
|
||||
.option('groupId', null)
|
||||
.option('group', ['groupId'], async (groupId) => {
|
||||
.option('group', ['groupId'], (groupId) => {
|
||||
if (groupId) {
|
||||
return neode.find('Group', groupId)
|
||||
}
|
||||
@ -383,11 +331,11 @@ Factory.define('location')
|
||||
id: 'country.10743216036480410',
|
||||
type: 'country',
|
||||
})
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('Location', buildObject)
|
||||
})
|
||||
|
||||
Factory.define('report').after(async (buildObject, _options) => {
|
||||
Factory.define('report').after((buildObject, _options) => {
|
||||
return neode.create('Report', buildObject)
|
||||
})
|
||||
|
||||
@ -395,7 +343,7 @@ Factory.define('tag')
|
||||
.attrs({
|
||||
name: '#human-connection',
|
||||
})
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('Tag', buildObject)
|
||||
})
|
||||
|
||||
@ -403,7 +351,7 @@ Factory.define('socialMedia')
|
||||
.attrs({
|
||||
url: 'https://mastodon.social/@Gargron',
|
||||
})
|
||||
.after(async (buildObject, _options) => {
|
||||
.after((buildObject, _options) => {
|
||||
return neode.create('SocialMedia', buildObject)
|
||||
})
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
||||
import { getDriver, getNeode } from '@db/neo4j'
|
||||
|
||||
class Store {
|
||||
@ -84,7 +83,7 @@ class Store {
|
||||
const driver = getDriver()
|
||||
const session = driver.session()
|
||||
const { migrations } = set
|
||||
const writeTxResultPromise = session.writeTransaction(async (txc) => {
|
||||
const writeTxResultPromise = session.writeTransaction((txc) => {
|
||||
return Promise.all(
|
||||
migrations.map(async (migration) => {
|
||||
const { title, description, timestamp } = migration
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable import-x/no-extraneous-dependencies */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/* eslint-disable promise/prefer-await-to-callbacks */
|
||||
/* eslint-disable import-x/no-deprecated */
|
||||
import { throwError, concat } from 'rxjs'
|
||||
import { flatMap, mergeMap, map, catchError, filter } from 'rxjs/operators'
|
||||
|
||||
@ -72,7 +71,7 @@ export function up(next) {
|
||||
),
|
||||
)
|
||||
.subscribe({
|
||||
next: ({ user, email, _oldUser, oldEmail }) => {
|
||||
next: ({ user, email, _oldUser, oldEmail }) =>
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`
|
||||
Merged:
|
||||
@ -80,8 +79,7 @@ export function up(next) {
|
||||
userId: ${user.id}
|
||||
email: ${oldEmail} => ${email.email}
|
||||
=============================
|
||||
`)
|
||||
},
|
||||
`),
|
||||
complete: () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Merging of duplicate users completed')
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable import-x/no-extraneous-dependencies */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/* eslint-disable promise/prefer-await-to-callbacks */
|
||||
/* eslint-disable import-x/no-deprecated */
|
||||
import { throwError, concat } from 'rxjs'
|
||||
import { flatMap, mergeMap, map, catchError } from 'rxjs/operators'
|
||||
|
||||
@ -66,7 +65,7 @@ export function up(next) {
|
||||
),
|
||||
)
|
||||
.subscribe({
|
||||
next: ({ updatedLocation, location }) => {
|
||||
next: ({ updatedLocation, location }) =>
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`
|
||||
Merged:
|
||||
@ -74,8 +73,7 @@ export function up(next) {
|
||||
locationId: ${location.id}
|
||||
updatedLocation: ${location.id} => ${updatedLocation.id}
|
||||
=============================
|
||||
`)
|
||||
},
|
||||
`),
|
||||
complete: () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Merging of duplicate locations completed')
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
'use strict'
|
||||
|
||||
export async function up(_next) {}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/await-thenable */
|
||||
|
||||
import { open } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
|
||||
@ -13,7 +13,6 @@ export default {
|
||||
nameNL: { type: 'string' },
|
||||
namePL: { type: 'string' },
|
||||
nameRU: { type: 'string' },
|
||||
nameSQ: { type: 'string' },
|
||||
isIn: {
|
||||
type: 'relationship',
|
||||
relationship: 'IS_IN',
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable jest/valid-title */
|
||||
|
||||
import { cleanDatabase } from '@db/factories'
|
||||
import { getNeode, getDriver } from '@db/neo4j'
|
||||
@ -66,8 +65,8 @@ describe('slug', () => {
|
||||
})
|
||||
|
||||
describe('characters', () => {
|
||||
const createUser = async (attrs) => {
|
||||
return neode.create('User', attrs).then(async (user) => user.toJson())
|
||||
const createUser = (attrs) => {
|
||||
return neode.create('User', attrs).then((user) => user.toJson())
|
||||
}
|
||||
|
||||
it('-', async () => {
|
||||
@ -82,7 +81,7 @@ describe('slug', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('', async () => {
|
||||
it(' ', async () => {
|
||||
await expect(createUser({ slug: 'matt rider' })).rejects.toThrow('ERROR_VALIDATION')
|
||||
})
|
||||
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
/* eslint-disable import-x/no-named-as-default-member */
|
||||
import neo4j from 'neo4j-driver'
|
||||
/* eslint-disable import/no-named-as-default-member */
|
||||
import neo4j, { Driver } from 'neo4j-driver'
|
||||
import Neode from 'neode'
|
||||
|
||||
import CONFIG from '@config/index'
|
||||
import models from '@db/models/index'
|
||||
|
||||
import type { Driver } from 'neo4j-driver'
|
||||
|
||||
let driver: Driver
|
||||
const defaultOptions = {
|
||||
uri: CONFIG.NEO4J_URI,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
|
||||
/* eslint-disable n/no-process-exit */
|
||||
import CONFIG from '@config/index'
|
||||
|
||||
import { cleanDatabase } from './factories'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
|
||||
/* eslint-disable n/no-process-exit */
|
||||
import CONFIG from '@config/index'
|
||||
|
||||
import { cleanDatabase } from './factories'
|
||||
|
||||
@ -2,22 +2,19 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
/* eslint-disable n/no-unpublished-import */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
||||
|
||||
/* eslint-disable n/no-process-exit */
|
||||
import { faker } from '@faker-js/faker'
|
||||
import sample from 'lodash/sample'
|
||||
|
||||
import CONFIG from '@config/index'
|
||||
import { categories } from '@constants/categories'
|
||||
import CreateComment from '@graphql/queries/comments/CreateComment.gql'
|
||||
import ChangeGroupMemberRole from '@graphql/queries/groups/ChangeGroupMemberRole.gql'
|
||||
import CreateGroup from '@graphql/queries/groups/CreateGroup.gql'
|
||||
import JoinGroup from '@graphql/queries/groups/JoinGroup.gql'
|
||||
import CreateMessage from '@graphql/queries/messaging/CreateMessage.gql'
|
||||
import CreateRoom from '@graphql/queries/messaging/CreateRoom.gql'
|
||||
import CreatePost from '@graphql/queries/posts/CreatePost.gql'
|
||||
import { ChangeGroupMemberRole } from '@graphql/queries/ChangeGroupMemberRole'
|
||||
import { CreateComment } from '@graphql/queries/CreateComment'
|
||||
import { CreateGroup } from '@graphql/queries/CreateGroup'
|
||||
import { CreateMessage } from '@graphql/queries/CreateMessage'
|
||||
import { CreatePost } from '@graphql/queries/CreatePost'
|
||||
import { CreateRoom } from '@graphql/queries/CreateRoom'
|
||||
import { JoinGroup } from '@graphql/queries/JoinGroup'
|
||||
import { createApolloTestSetup } from '@root/test/helpers'
|
||||
|
||||
import Factory from './factories'
|
||||
@ -42,7 +39,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
||||
authenticatedUser,
|
||||
config: CONFIG,
|
||||
})
|
||||
const apolloSetup = await createApolloTestSetup({ context })
|
||||
const apolloSetup = createApolloTestSetup({ context })
|
||||
const { mutate, server, database } = apolloSetup
|
||||
const { neode } = database
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface CategoryDbProperties {
|
||||
createdAt: string
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface CommentDbProperties {
|
||||
content: string
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface EmailAddressDbProperties {
|
||||
createdAt: string
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { PostDbProperties } from './Post'
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
import { PostDbProperties } from './Post'
|
||||
|
||||
export interface EventDbProperties extends PostDbProperties {
|
||||
eventIsOnline: boolean
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface GroupDbProperties {
|
||||
about: string
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface ImageDbProperties {
|
||||
alt: string
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface InviteCodeDbProperties {
|
||||
code: string
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface LocationDbProperties {
|
||||
id: string
|
||||
@ -14,7 +14,6 @@ export interface LocationDbProperties {
|
||||
namePL: string
|
||||
namePT: string
|
||||
nameRU: string
|
||||
nameSQ: string
|
||||
type: string
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface MessageDbProperties {
|
||||
content: string
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface PostDbProperties {
|
||||
clickedCount: number
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface ReportDbProperties {
|
||||
closed: boolean
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface TagDbProperties {
|
||||
deleted: boolean
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Integer, Node } from 'neo4j-driver'
|
||||
import { Integer, Node } from 'neo4j-driver'
|
||||
|
||||
export interface UserDbProperties {
|
||||
allowEmbedIframes: boolean
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Notificación",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Rol en el grupo cambiado",
|
||||
"chatMessage": "Nuevo mensaje de chat",
|
||||
"commentedOnPost": "Nuevo comentario en una publicación",
|
||||
"followedUserPosted": "Nueva publicación de un usuario seguido",
|
||||
"mentionedInComment": "Mencionado en un comentario",
|
||||
"mentionedInPost": "Mencionado en una publicación",
|
||||
"newEmail": "Nueva dirección de correo electrónico",
|
||||
"removedUserFromGroup": "Eliminado del grupo",
|
||||
"postInGroup": "Nueva publicación en el grupo",
|
||||
"resetPassword": "Restablecer contraseña",
|
||||
"userJoinedGroup": "Un usuario se unió al grupo",
|
||||
"userLeftGroup": "Un usuario abandonó el grupo",
|
||||
"wrongEmail": "¿Correo electrónico incorrecto?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Gracias por registrarte – nos alegra tenerte con nosotros. Solo falta un pequeño paso antes de que podamos cambiar el mundo juntos … Por favor, confirma tu dirección de correo electrónico haciendo clic en el botón de abajo:",
|
||||
"codeHint": "Si el botón de arriba no funciona, también puedes copiar el siguiente código en la ventana de tu navegador: ",
|
||||
"codeHintException": "Sin embargo, esto solo funciona si te has registrado a través de nuestro sitio web.",
|
||||
"notYouStart": "Si no te has registrado en ",
|
||||
"notYouEnd": " te recomendamos que lo visites. Es una red social de personas para personas que quieren conectarse y cambiar el mundo juntas.",
|
||||
"ps": "PD: Si ignoras este correo electrónico, no crearemos una cuenta para ti. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Si el botón de arriba no funciona, también puedes copiar el siguiente código en la ventana de tu navegador: ",
|
||||
"introduction": "¿Quieres cambiar tu dirección de correo electrónico? ¡No hay problema! Simplemente haz clic en el botón de abajo para verificar tu nueva dirección:",
|
||||
"doNotChange": "Si no quieres cambiar tu dirección de correo electrónico, simplemente ignora este mensaje. "
|
||||
},
|
||||
"support": "Si tienes preguntas o problemas, no dudes en contactar con nuestro soporte: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Confirma tu dirección de correo electrónico",
|
||||
"resetPassword": "Restablecer contraseña",
|
||||
"tryAgain": "Probar con otro correo electrónico",
|
||||
"verifyEmail": "Verificar dirección de correo electrónico",
|
||||
"viewChat": "Ver chat",
|
||||
"viewComment": "Ver comentario",
|
||||
"viewGroup": "Ver grupo",
|
||||
"viewPost": "Ver publicación"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Hola",
|
||||
"seeYou": "¡Hasta pronto en ",
|
||||
"yourTeam": "– El equipo de {team}",
|
||||
"settingsHint": "PD: Si no quieres recibir más correos electrónicos, cambia tu ",
|
||||
"settingsName": "configuración de notificaciones",
|
||||
"welcome": "Bienvenido a"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Si el botón de arriba no funciona, también puedes copiar el siguiente código en la ventana de tu navegador: ",
|
||||
"ignore": "Si no has solicitado una nueva contraseña, simplemente ignora este correo electrónico.",
|
||||
"introduction": "¿Has olvidado tu contraseña? ¡No hay problema! Simplemente haz clic en el botón de abajo para restablecerla en las próximas 24 horas:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " o si no querías restablecer tu contraseña, simplemente ignora este correo electrónico.",
|
||||
"ignoreStart": "Si no tienes una cuenta en ",
|
||||
"introduction": "Has solicitado un restablecimiento de contraseña, pero lamentablemente no hemos encontrado ninguna cuenta asociada a tu dirección de correo electrónico. ¿Te registraste quizás con otra dirección?"
|
||||
},
|
||||
"changedGroupMemberRole": "tu rol en el grupo «{groupName}» ha sido cambiado. Haz clic en el botón para ver este grupo:",
|
||||
"chatMessageStart": "has recibido un nuevo mensaje de chat de ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " ha comentado en una publicación que sigues con el título «{postTitle}». Haz clic en el botón para ver este comentario:",
|
||||
"followedUserPosted": ", un usuario al que sigues, ha escrito una nueva publicación con el título «{postTitle}». Haz clic en el botón para ver esta publicación:",
|
||||
"mentionedInComment": " te ha mencionado en un comentario de la publicación con el título «{postTitle}». Haz clic en el botón para ver este comentario:",
|
||||
"mentionedInPost": " te ha mencionado en una publicación con el título «{postTitle}». Haz clic en el botón para ver esta publicación:",
|
||||
"removedUserFromGroup": "has sido eliminado del grupo «{groupName}».",
|
||||
"postInGroup": "alguien ha escrito una nueva publicación con el título «{postTitle}» en uno de tus grupos. Haz clic en el botón para ver esta publicación:",
|
||||
"userJoinedGroup": " se ha unido al grupo «{groupName}». Haz clic en el botón para ver este grupo:",
|
||||
"userLeftGroup": " ha abandonado el grupo «{groupName}». Haz clic en el botón para ver este grupo:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Notification",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Rôle dans le groupe modifié",
|
||||
"chatMessage": "Nouveau message de chat",
|
||||
"commentedOnPost": "Nouveau commentaire sur une publication",
|
||||
"followedUserPosted": "Nouvelle publication d'un utilisateur suivi",
|
||||
"mentionedInComment": "Mentionné dans un commentaire",
|
||||
"mentionedInPost": "Mentionné dans une publication",
|
||||
"newEmail": "Nouvelle adresse e-mail",
|
||||
"removedUserFromGroup": "Retiré du groupe",
|
||||
"postInGroup": "Nouvelle publication dans le groupe",
|
||||
"resetPassword": "Réinitialiser le mot de passe",
|
||||
"userJoinedGroup": "Un utilisateur a rejoint le groupe",
|
||||
"userLeftGroup": "Un utilisateur a quitté le groupe",
|
||||
"wrongEmail": "Mauvaise adresse e-mail ?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Merci de nous avoir rejoints – nous sommes ravis de vous compter parmi nous. Il ne reste plus qu'une petite étape avant de pouvoir changer le monde ensemble … Veuillez confirmer votre adresse e-mail en cliquant sur le bouton ci-dessous :",
|
||||
"codeHint": "Si le bouton ci-dessus ne fonctionne pas, vous pouvez aussi copier le code suivant dans votre navigateur : ",
|
||||
"codeHintException": "Cependant, cela ne fonctionne que si vous vous êtes inscrit via notre site web.",
|
||||
"notYouStart": "Si vous ne vous êtes pas inscrit sur ",
|
||||
"notYouEnd": " nous vous recommandons d'y jeter un œil ! C'est un réseau social de personnes pour des personnes qui veulent se connecter et changer le monde ensemble.",
|
||||
"ps": "PS : Si vous ignorez cet e-mail, nous ne créerons pas de compte pour vous. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Si le bouton ci-dessus ne fonctionne pas, vous pouvez aussi copier le code suivant dans votre navigateur : ",
|
||||
"introduction": "Vous souhaitez changer votre adresse e-mail ? Pas de problème ! Cliquez simplement sur le bouton ci-dessous pour vérifier votre nouvelle adresse :",
|
||||
"doNotChange": "Si vous ne souhaitez pas changer votre adresse e-mail, n'hésitez pas à ignorer ce message. "
|
||||
},
|
||||
"support": "Si vous avez des questions ou des problèmes, n'hésitez pas à contacter notre support : ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Confirmer votre adresse e-mail",
|
||||
"resetPassword": "Réinitialiser le mot de passe",
|
||||
"tryAgain": "Essayer une autre adresse e-mail",
|
||||
"verifyEmail": "Vérifier l'adresse e-mail",
|
||||
"viewChat": "Voir le chat",
|
||||
"viewComment": "Voir le commentaire",
|
||||
"viewGroup": "Voir le groupe",
|
||||
"viewPost": "Voir la publication"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Bonjour",
|
||||
"seeYou": "À bientôt sur ",
|
||||
"yourTeam": "– L'équipe {team}",
|
||||
"settingsHint": "PS : Si vous ne souhaitez plus recevoir d'e-mails, modifiez vos ",
|
||||
"settingsName": "paramètres de notification",
|
||||
"welcome": "Bienvenue sur"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Si le bouton ci-dessus ne fonctionne pas, vous pouvez aussi copier le code suivant dans votre navigateur : ",
|
||||
"ignore": "Si vous n'avez pas demandé de nouveau mot de passe, n'hésitez pas à ignorer cet e-mail.",
|
||||
"introduction": "Vous avez oublié votre mot de passe ? Pas de problème ! Cliquez simplement sur le bouton ci-dessous pour le réinitialiser dans les 24 prochaines heures :"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " ou si vous ne souhaitiez pas réinitialiser votre mot de passe, veuillez ignorer cet e-mail.",
|
||||
"ignoreStart": "Si vous n'avez pas de compte sur ",
|
||||
"introduction": "Vous avez demandé une réinitialisation de mot de passe, mais malheureusement nous n'avons trouvé aucun compte associé à votre adresse e-mail. Vous êtes-vous peut-être inscrit avec une autre adresse ?"
|
||||
},
|
||||
"changedGroupMemberRole": "votre rôle dans le groupe « {groupName} » a été modifié. Cliquez sur le bouton pour voir ce groupe :",
|
||||
"chatMessageStart": "vous avez reçu un nouveau message de chat de ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " a commenté une publication que vous suivez avec le titre « {postTitle} ». Cliquez sur le bouton pour voir ce commentaire :",
|
||||
"followedUserPosted": ", un utilisateur que vous suivez, a écrit une nouvelle publication avec le titre « {postTitle} ». Cliquez sur le bouton pour voir cette publication :",
|
||||
"mentionedInComment": " vous a mentionné dans un commentaire sur la publication avec le titre « {postTitle} ». Cliquez sur le bouton pour voir ce commentaire :",
|
||||
"mentionedInPost": " vous a mentionné dans une publication avec le titre « {postTitle} ». Cliquez sur le bouton pour voir cette publication :",
|
||||
"removedUserFromGroup": "vous avez été retiré du groupe « {groupName} ».",
|
||||
"postInGroup": "quelqu'un a écrit une nouvelle publication avec le titre « {postTitle} » dans l'un de vos groupes. Cliquez sur le bouton pour voir cette publication :",
|
||||
"userJoinedGroup": " a rejoint le groupe « {groupName} ». Cliquez sur le bouton pour voir ce groupe :",
|
||||
"userLeftGroup": " a quitté le groupe « {groupName} ». Cliquez sur le bouton pour voir ce groupe :"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Notifica",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Ruolo nel gruppo modificato",
|
||||
"chatMessage": "Nuovo messaggio in chat",
|
||||
"commentedOnPost": "Nuovo commento su un post",
|
||||
"followedUserPosted": "Nuovo post di un utente seguito",
|
||||
"mentionedInComment": "Menzionato in un commento",
|
||||
"mentionedInPost": "Menzionato in un post",
|
||||
"newEmail": "Nuovo indirizzo e-mail",
|
||||
"removedUserFromGroup": "Rimosso dal gruppo",
|
||||
"postInGroup": "Nuovo post nel gruppo",
|
||||
"resetPassword": "Reimposta la password",
|
||||
"userJoinedGroup": "Un utente si è unito al gruppo",
|
||||
"userLeftGroup": "Un utente ha lasciato il gruppo",
|
||||
"wrongEmail": "E-mail sbagliata?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Grazie per esserti registrato – siamo felici di averti con noi. Manca solo un piccolo passo prima di poter cambiare il mondo insieme … Per favore, conferma il tuo indirizzo e-mail cliccando sul pulsante qui sotto:",
|
||||
"codeHint": "Se il pulsante qui sopra non funziona, puoi anche copiare il seguente codice nella finestra del tuo browser: ",
|
||||
"codeHintException": "Tuttavia, questo funziona solo se ti sei registrato tramite il nostro sito web.",
|
||||
"notYouStart": "Se non ti sei registrato su ",
|
||||
"notYouEnd": " ti consigliamo di dargli un'occhiata! È un social network di persone per persone che vogliono connettersi e cambiare il mondo insieme.",
|
||||
"ps": "PS: Se ignori questa e-mail, non creeremo un account per te. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Se il pulsante qui sopra non funziona, puoi anche copiare il seguente codice nella finestra del tuo browser: ",
|
||||
"introduction": "Vuoi cambiare il tuo indirizzo e-mail? Nessun problema! Clicca semplicemente sul pulsante qui sotto per verificare il tuo nuovo indirizzo:",
|
||||
"doNotChange": "Se non vuoi cambiare il tuo indirizzo e-mail, puoi semplicemente ignorare questo messaggio. "
|
||||
},
|
||||
"support": "Se hai domande o problemi, non esitare a contattare il nostro supporto: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Conferma il tuo indirizzo e-mail",
|
||||
"resetPassword": "Reimposta la password",
|
||||
"tryAgain": "Prova con un altro indirizzo e-mail",
|
||||
"verifyEmail": "Verifica l'indirizzo e-mail",
|
||||
"viewChat": "Visualizza la chat",
|
||||
"viewComment": "Visualizza il commento",
|
||||
"viewGroup": "Visualizza il gruppo",
|
||||
"viewPost": "Visualizza il post"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Ciao",
|
||||
"seeYou": "A presto su ",
|
||||
"yourTeam": "– Il team {team}",
|
||||
"settingsHint": "PS: Se non vuoi più ricevere e-mail, modifica le tue ",
|
||||
"settingsName": "impostazioni di notifica",
|
||||
"welcome": "Benvenuto su"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Se il pulsante qui sopra non funziona, puoi anche copiare il seguente codice nella finestra del tuo browser: ",
|
||||
"ignore": "Se non hai richiesto una nuova password, puoi semplicemente ignorare questa e-mail.",
|
||||
"introduction": "Hai dimenticato la tua password? Nessun problema! Clicca semplicemente sul pulsante qui sotto per reimpostarla entro le prossime 24 ore:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " o se non volevi reimpostare la tua password, puoi semplicemente ignorare questa e-mail.",
|
||||
"ignoreStart": "Se non hai un account su ",
|
||||
"introduction": "Hai richiesto un ripristino della password, ma purtroppo non abbiamo trovato un account associato al tuo indirizzo e-mail. Ti sei forse registrato con un altro indirizzo?"
|
||||
},
|
||||
"changedGroupMemberRole": "il tuo ruolo nel gruppo \u201e{groupName}\u201c è stato modificato. Clicca sul pulsante per visualizzare questo gruppo:",
|
||||
"chatMessageStart": "hai ricevuto un nuovo messaggio in chat da ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " ha commentato un post che stai seguendo con il titolo \u201e{postTitle}\u201c. Clicca sul pulsante per visualizzare questo commento:",
|
||||
"followedUserPosted": ", un utente che segui, ha scritto un nuovo post con il titolo \u201e{postTitle}\u201c. Clicca sul pulsante per visualizzare questo post:",
|
||||
"mentionedInComment": " ti ha menzionato in un commento al post con il titolo \u201e{postTitle}\u201c. Clicca sul pulsante per visualizzare questo commento:",
|
||||
"mentionedInPost": " ti ha menzionato in un post con il titolo \u201e{postTitle}\u201c. Clicca sul pulsante per visualizzare questo post:",
|
||||
"removedUserFromGroup": "sei stato rimosso dal gruppo \u201e{groupName}\u201c.",
|
||||
"postInGroup": "qualcuno ha scritto un nuovo post con il titolo \u201e{postTitle}\u201c in uno dei tuoi gruppi. Clicca sul pulsante per visualizzare questo post:",
|
||||
"userJoinedGroup": " si è unito al gruppo \u201e{groupName}\u201c. Clicca sul pulsante per visualizzare questo gruppo:",
|
||||
"userLeftGroup": " ha lasciato il gruppo \u201e{groupName}\u201c. Clicca sul pulsante per visualizzare questo gruppo:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Melding",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Rol in groep gewijzigd",
|
||||
"chatMessage": "Nieuw chatbericht",
|
||||
"commentedOnPost": "Nieuwe reactie op bericht",
|
||||
"followedUserPosted": "Nieuw bericht van gevolgde gebruiker",
|
||||
"mentionedInComment": "Vermeld in reactie",
|
||||
"mentionedInPost": "Vermeld in bericht",
|
||||
"newEmail": "Nieuw e-mailadres",
|
||||
"removedUserFromGroup": "Uit groep verwijderd",
|
||||
"postInGroup": "Nieuw bericht in groep",
|
||||
"resetPassword": "Wachtwoord herstellen",
|
||||
"userJoinedGroup": "Gebruiker is lid geworden van groep",
|
||||
"userLeftGroup": "Gebruiker heeft groep verlaten",
|
||||
"wrongEmail": "Verkeerd e-mailadres?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Bedankt voor je aanmelding – fijn dat je erbij bent. Er is nog maar één klein stapje nodig voordat we samen de wereld kunnen verbeteren … Bevestig je e-mailadres door op de onderstaande knop te klikken:",
|
||||
"codeHint": "Als de bovenstaande knop niet werkt, kun je ook de volgende code in je browservenster kopiëren: ",
|
||||
"codeHintException": "Dit werkt echter alleen als je je via onze website hebt geregistreerd.",
|
||||
"notYouStart": "Als je je niet hebt aangemeld bij ",
|
||||
"notYouEnd": " raden we je aan om een kijkje te nemen! Het is een sociaal netwerk van mensen voor mensen die samen de wereld willen veranderen.",
|
||||
"ps": "PS: Als je deze e-mail negeert, maken we geen account voor je aan. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Als de bovenstaande knop niet werkt, kun je ook de volgende code in je browservenster kopiëren: ",
|
||||
"introduction": "Wil je je e-mailadres wijzigen? Geen probleem! Klik op de onderstaande knop om je nieuwe adres te verifiëren:",
|
||||
"doNotChange": "Als je je e-mailadres niet wilt wijzigen, kun je dit bericht gewoon negeren. "
|
||||
},
|
||||
"support": "Als je vragen of problemen hebt, neem dan gerust contact op met onze ondersteuning: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Bevestig je e-mailadres",
|
||||
"resetPassword": "Wachtwoord herstellen",
|
||||
"tryAgain": "Probeer een ander e-mailadres",
|
||||
"verifyEmail": "E-mailadres verifiëren",
|
||||
"viewChat": "Chat bekijken",
|
||||
"viewComment": "Reactie bekijken",
|
||||
"viewGroup": "Groep bekijken",
|
||||
"viewPost": "Bericht bekijken"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Hallo",
|
||||
"seeYou": "Tot snel bij ",
|
||||
"yourTeam": "– Het {team} Team",
|
||||
"settingsHint": "PS: Als je geen e-mails meer wilt ontvangen, wijzig dan je ",
|
||||
"settingsName": "meldingsinstellingen",
|
||||
"welcome": "Welkom bij"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Als de bovenstaande knop niet werkt, kun je ook de volgende code in je browservenster kopiëren: ",
|
||||
"ignore": "Als je geen nieuw wachtwoord hebt aangevraagd, kun je deze e-mail gewoon negeren.",
|
||||
"introduction": "Wachtwoord vergeten? Geen probleem! Klik op de onderstaande knop om het binnen 24 uur te herstellen:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " hebt of als je je wachtwoord niet wilde herstellen, kun je deze e-mail gewoon negeren.",
|
||||
"ignoreStart": "Als je geen account hebt bij ",
|
||||
"introduction": "Je hebt een wachtwoordherstel aangevraagd, maar we konden helaas geen account vinden dat aan je e-mailadres is gekoppeld. Heb je je misschien met een ander adres aangemeld?"
|
||||
},
|
||||
"changedGroupMemberRole": "je rol in de groep \u201e{groupName}\u201c is gewijzigd. Klik op de knop om deze groep te bekijken:",
|
||||
"chatMessageStart": "je hebt een nieuw chatbericht ontvangen van ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " heeft gereageerd op een bericht dat je volgt met de titel \u201e{postTitle}\u201c. Klik op de knop om deze reactie te bekijken:",
|
||||
"followedUserPosted": ", een gebruiker die je volgt, heeft een nieuw bericht geschreven met de titel \u201e{postTitle}\u201c. Klik op de knop om dit bericht te bekijken:",
|
||||
"mentionedInComment": " heeft je vermeld in een reactie op het bericht met de titel \u201e{postTitle}\u201c. Klik op de knop om deze reactie te bekijken:",
|
||||
"mentionedInPost": " heeft je vermeld in een bericht met de titel \u201e{postTitle}\u201c. Klik op de knop om dit bericht te bekijken:",
|
||||
"removedUserFromGroup": "je bent verwijderd uit de groep \u201e{groupName}\u201c.",
|
||||
"postInGroup": "iemand heeft een nieuw bericht geschreven met de titel \u201e{postTitle}\u201c in een van je groepen. Klik op de knop om dit bericht te bekijken:",
|
||||
"userJoinedGroup": " is lid geworden van de groep \u201e{groupName}\u201c. Klik op de knop om deze groep te bekijken:",
|
||||
"userLeftGroup": " heeft de groep \u201e{groupName}\u201c verlaten. Klik op de knop om deze groep te bekijken:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Powiadomienie",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Zmieniono rolę w grupie",
|
||||
"chatMessage": "Nowa wiadomość na czacie",
|
||||
"commentedOnPost": "Nowy komentarz do wpisu",
|
||||
"followedUserPosted": "Nowy wpis obserwowanego użytkownika",
|
||||
"mentionedInComment": "Wspomniano w komentarzu",
|
||||
"mentionedInPost": "Wspomniano we wpisie",
|
||||
"newEmail": "Nowy adres e-mail",
|
||||
"removedUserFromGroup": "Usunięto z grupy",
|
||||
"postInGroup": "Nowy wpis w grupie",
|
||||
"resetPassword": "Zresetuj hasło",
|
||||
"userJoinedGroup": "Użytkownik dołączył do grupy",
|
||||
"userLeftGroup": "Użytkownik opuścił grupę",
|
||||
"wrongEmail": "Nieprawidłowy e-mail?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Dziękujemy za rejestrację – cieszymy się, że jesteś z nami. Został jeszcze tylko jeden mały krok, zanim razem zaczniemy zmieniać świat … Potwierdź swój adres e-mail, klikając poniższy przycisk:",
|
||||
"codeHint": "Jeśli powyższy przycisk nie działa, możesz też skopiować następujący kod do okna przeglądarki: ",
|
||||
"codeHintException": "Działa to jednak tylko wtedy, gdy zarejestrowałeś się przez naszą stronę internetową.",
|
||||
"notYouStart": "Jeśli nie rejestrowałeś się w ",
|
||||
"notYouEnd": " polecamy zajrzeć! To sieć społecznościowa ludzi dla ludzi, którzy chcą się łączyć i wspólnie zmieniać świat.",
|
||||
"ps": "PS: Jeśli zignorujesz tego e-maila, nie utworzymy dla Ciebie konta. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Jeśli powyższy przycisk nie działa, możesz też skopiować następujący kod do okna przeglądarki: ",
|
||||
"introduction": "Chcesz zmienić swój adres e-mail? Żaden problem! Po prostu kliknij poniższy przycisk, aby zweryfikować nowy adres:",
|
||||
"doNotChange": "Jeśli nie chcesz zmieniać swojego adresu e-mail, po prostu zignoruj tę wiadomość. "
|
||||
},
|
||||
"support": "Jeśli masz pytania lub problemy, skontaktuj się z naszym wsparciem: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Potwierdź swój adres e-mail",
|
||||
"resetPassword": "Zresetuj hasło",
|
||||
"tryAgain": "Spróbuj z innym adresem e-mail",
|
||||
"verifyEmail": "Zweryfikuj adres e-mail",
|
||||
"viewChat": "Zobacz czat",
|
||||
"viewComment": "Zobacz komentarz",
|
||||
"viewGroup": "Zobacz grupę",
|
||||
"viewPost": "Zobacz wpis"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Cześć",
|
||||
"seeYou": "Do zobaczenia wkrótce na ",
|
||||
"yourTeam": "– Zespół {team}",
|
||||
"settingsHint": "PS: Jeśli nie chcesz już otrzymywać e-maili, zmień swoje ",
|
||||
"settingsName": "ustawienia powiadomień",
|
||||
"welcome": "Witamy w"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Jeśli powyższy przycisk nie działa, możesz też skopiować następujący kod do okna przeglądarki: ",
|
||||
"ignore": "Jeśli nie prosiłeś o nowe hasło, po prostu zignoruj tego e-maila.",
|
||||
"introduction": "Zapomniałeś hasła? Żaden problem! Po prostu kliknij poniższy przycisk, aby je zresetować w ciągu najbliższych 24 godzin:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " lub jeśli nie chciałeś resetować hasła, po prostu zignoruj tego e-maila.",
|
||||
"ignoreStart": "Jeśli nie masz konta w ",
|
||||
"introduction": "Poprosiłeś o zresetowanie hasła, ale niestety nie znaleźliśmy konta powiązanego z Twoim adresem e-mail. Czy może zarejestrowałeś się z innym adresem?"
|
||||
},
|
||||
"changedGroupMemberRole": "Twoja rola w grupie „{groupName}“ została zmieniona. Kliknij przycisk, aby zobaczyć tę grupę:",
|
||||
"chatMessageStart": "otrzymałeś nową wiadomość na czacie od ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " skomentował wpis, który obserwujesz, o tytule „{postTitle}“. Kliknij przycisk, aby zobaczyć ten komentarz:",
|
||||
"followedUserPosted": ", użytkownik, którego obserwujesz, napisał nowy wpis o tytule „{postTitle}“. Kliknij przycisk, aby zobaczyć ten wpis:",
|
||||
"mentionedInComment": " wspomniał o Tobie w komentarzu do wpisu o tytule „{postTitle}“. Kliknij przycisk, aby zobaczyć ten komentarz:",
|
||||
"mentionedInPost": " wspomniał o Tobie we wpisie o tytule „{postTitle}“. Kliknij przycisk, aby zobaczyć ten wpis:",
|
||||
"removedUserFromGroup": "zostałeś usunięty z grupy „{groupName}“.",
|
||||
"postInGroup": "ktoś napisał nowy wpis o tytule „{postTitle}“ w jednej z Twoich grup. Kliknij przycisk, aby zobaczyć ten wpis:",
|
||||
"userJoinedGroup": " dołączył do grupy „{groupName}“. Kliknij przycisk, aby zobaczyć tę grupę:",
|
||||
"userLeftGroup": " opuścił grupę „{groupName}“. Kliknij przycisk, aby zobaczyć tę grupę:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Notificação",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Função no grupo alterada",
|
||||
"chatMessage": "Nova mensagem no chat",
|
||||
"commentedOnPost": "Novo comentário numa publicação",
|
||||
"followedUserPosted": "Nova publicação de um utilizador seguido",
|
||||
"mentionedInComment": "Mencionado num comentário",
|
||||
"mentionedInPost": "Mencionado numa publicação",
|
||||
"newEmail": "Novo endereço de e-mail",
|
||||
"removedUserFromGroup": "Removido do grupo",
|
||||
"postInGroup": "Nova publicação no grupo",
|
||||
"resetPassword": "Redefinir palavra-passe",
|
||||
"userJoinedGroup": "Um utilizador juntou-se ao grupo",
|
||||
"userLeftGroup": "Um utilizador saiu do grupo",
|
||||
"wrongEmail": "E-mail errado?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Obrigado por te registares – é ótimo ter-te connosco. Falta apenas um pequeno passo antes de podermos mudar o mundo juntos … Por favor, confirma o teu endereço de e-mail clicando no botão abaixo:",
|
||||
"codeHint": "Se o botão acima não funcionar, também podes copiar o seguinte código na janela do teu navegador: ",
|
||||
"codeHintException": "No entanto, isto só funciona se te registaste através do nosso site.",
|
||||
"notYouStart": "Se não te registaste em ",
|
||||
"notYouEnd": " recomendamos que dês uma olhada! É uma rede social de pessoas para pessoas que querem conectar-se e mudar o mundo juntas.",
|
||||
"ps": "PS: Se ignorares este e-mail, não criaremos uma conta para ti. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Se o botão acima não funcionar, também podes copiar o seguinte código na janela do teu navegador: ",
|
||||
"introduction": "Queres alterar o teu endereço de e-mail? Sem problema! Basta clicar no botão abaixo para verificar o teu novo endereço:",
|
||||
"doNotChange": "Se não quiseres alterar o teu endereço de e-mail, podes simplesmente ignorar esta mensagem. "
|
||||
},
|
||||
"support": "Se tiveres dúvidas ou problemas, não hesites em contactar o nosso suporte: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Confirma o teu endereço de e-mail",
|
||||
"resetPassword": "Redefinir palavra-passe",
|
||||
"tryAgain": "Tentar outro endereço de e-mail",
|
||||
"verifyEmail": "Verificar endereço de e-mail",
|
||||
"viewChat": "Ver chat",
|
||||
"viewComment": "Ver comentário",
|
||||
"viewGroup": "Ver grupo",
|
||||
"viewPost": "Ver publicação"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Olá",
|
||||
"seeYou": "Até breve em ",
|
||||
"yourTeam": "– A equipa {team}",
|
||||
"settingsHint": "PS: Se não quiseres receber mais e-mails, altera as tuas ",
|
||||
"settingsName": "definições de notificação",
|
||||
"welcome": "Bem-vindo a"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Se o botão acima não funcionar, também podes copiar o seguinte código na janela do teu navegador: ",
|
||||
"ignore": "Se não solicitaste uma nova palavra-passe, podes simplesmente ignorar este e-mail.",
|
||||
"introduction": "Esqueceste a tua palavra-passe? Sem problema! Basta clicar no botão abaixo para a redefinir nas próximas 24 horas:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " ou se não querias redefinir a tua palavra-passe, podes simplesmente ignorar este e-mail.",
|
||||
"ignoreStart": "Se não tens uma conta em ",
|
||||
"introduction": "Solicitaste uma redefinição de palavra-passe, mas infelizmente não encontrámos nenhuma conta associada ao teu endereço de e-mail. Será que te registaste com outro endereço?"
|
||||
},
|
||||
"changedGroupMemberRole": "a tua função no grupo \u201e{groupName}\u201c foi alterada. Clica no botão para ver este grupo:",
|
||||
"chatMessageStart": "recebeste uma nova mensagem no chat de ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " comentou numa publicação que estás a seguir com o título \u201e{postTitle}\u201c. Clica no botão para ver este comentário:",
|
||||
"followedUserPosted": ", um utilizador que segues, escreveu uma nova publicação com o título \u201e{postTitle}\u201c. Clica no botão para ver esta publicação:",
|
||||
"mentionedInComment": " mencionou-te num comentário na publicação com o título \u201e{postTitle}\u201c. Clica no botão para ver este comentário:",
|
||||
"mentionedInPost": " mencionou-te numa publicação com o título \u201e{postTitle}\u201c. Clica no botão para ver esta publicação:",
|
||||
"removedUserFromGroup": "foste removido do grupo \u201e{groupName}\u201c.",
|
||||
"postInGroup": "alguém escreveu uma nova publicação com o título \u201e{postTitle}\u201c num dos teus grupos. Clica no botão para ver esta publicação:",
|
||||
"userJoinedGroup": " juntou-se ao grupo \u201e{groupName}\u201c. Clica no botão para ver este grupo:",
|
||||
"userLeftGroup": " saiu do grupo \u201e{groupName}\u201c. Clica no botão para ver este grupo:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Уведомление",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Роль в группе изменена",
|
||||
"chatMessage": "Новое сообщение в чате",
|
||||
"commentedOnPost": "Новый комментарий к публикации",
|
||||
"followedUserPosted": "Новая публикация от пользователя, на которого вы подписаны",
|
||||
"mentionedInComment": "Упоминание в комментарии",
|
||||
"mentionedInPost": "Упоминание в публикации",
|
||||
"newEmail": "Новый адрес электронной почты",
|
||||
"removedUserFromGroup": "Удалён из группы",
|
||||
"postInGroup": "Новая публикация в группе",
|
||||
"resetPassword": "Сброс пароля",
|
||||
"userJoinedGroup": "Пользователь присоединился к группе",
|
||||
"userLeftGroup": "Пользователь покинул группу",
|
||||
"wrongEmail": "Неверный адрес электронной почты?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Спасибо за регистрацию – мы рады, что вы с нами. Остался всего один маленький шаг, прежде чем мы сможем вместе менять мир … Пожалуйста, подтвердите свой адрес электронной почты, нажав на кнопку ниже:",
|
||||
"codeHint": "Если кнопка выше не работает, вы также можете скопировать следующий код в окно браузера: ",
|
||||
"codeHintException": "Однако это работает только в том случае, если вы зарегистрировались через наш сайт.",
|
||||
"notYouStart": "Если вы не регистрировались на ",
|
||||
"notYouEnd": " рекомендуем заглянуть! Это социальная сеть от людей для людей, которые хотят объединяться и вместе менять мир.",
|
||||
"ps": "PS: Если вы проигнорируете это письмо, мы не создадим для вас аккаунт. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Если кнопка выше не работает, вы также можете скопировать следующий код в окно браузера: ",
|
||||
"introduction": "Хотите изменить свой адрес электронной почты? Нет проблем! Просто нажмите на кнопку ниже, чтобы подтвердить новый адрес:",
|
||||
"doNotChange": "Если вы не хотите менять свой адрес электронной почты, просто проигнорируйте это сообщение. "
|
||||
},
|
||||
"support": "Если у вас есть вопросы или проблемы, обращайтесь в нашу службу поддержки: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Подтвердите свой адрес электронной почты",
|
||||
"resetPassword": "Сбросить пароль",
|
||||
"tryAgain": "Попробовать другой адрес электронной почты",
|
||||
"verifyEmail": "Подтвердить адрес электронной почты",
|
||||
"viewChat": "Открыть чат",
|
||||
"viewComment": "Посмотреть комментарий",
|
||||
"viewGroup": "Посмотреть группу",
|
||||
"viewPost": "Посмотреть публикацию"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Здравствуйте",
|
||||
"seeYou": "До скорой встречи на ",
|
||||
"yourTeam": "– Команда {team}",
|
||||
"settingsHint": "PS: Если вы больше не хотите получать электронные письма, измените свои ",
|
||||
"settingsName": "настройки уведомлений",
|
||||
"welcome": "Добро пожаловать в"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Если кнопка выше не работает, вы также можете скопировать следующий код в окно браузера: ",
|
||||
"ignore": "Если вы не запрашивали новый пароль, просто проигнорируйте это письмо.",
|
||||
"introduction": "Забыли пароль? Нет проблем! Просто нажмите на кнопку ниже, чтобы сбросить его в течение ближайших 24 часов:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " или если вы не хотели сбрасывать пароль, просто проигнорируйте это письмо.",
|
||||
"ignoreStart": "Если у вас нет аккаунта на ",
|
||||
"introduction": "Вы запросили сброс пароля, но, к сожалению, мы не нашли аккаунт, связанный с вашим адресом электронной почты. Возможно, вы зарегистрировались с другим адресом?"
|
||||
},
|
||||
"changedGroupMemberRole": "ваша роль в группе «{groupName}» была изменена. Нажмите на кнопку, чтобы посмотреть эту группу:",
|
||||
"chatMessageStart": "вы получили новое сообщение в чате от ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " прокомментировал публикацию, за которой вы следите, с заголовком «{postTitle}». Нажмите на кнопку, чтобы посмотреть этот комментарий:",
|
||||
"followedUserPosted": ", пользователь, на которого вы подписаны, написал новую публикацию с заголовком «{postTitle}». Нажмите на кнопку, чтобы посмотреть эту публикацию:",
|
||||
"mentionedInComment": " упомянул вас в комментарии к публикации с заголовком «{postTitle}». Нажмите на кнопку, чтобы посмотреть этот комментарий:",
|
||||
"mentionedInPost": " упомянул вас в публикации с заголовком «{postTitle}». Нажмите на кнопку, чтобы посмотреть эту публикацию:",
|
||||
"removedUserFromGroup": "вы были удалены из группы «{groupName}».",
|
||||
"postInGroup": "кто-то написал новую публикацию с заголовком «{postTitle}» в одной из ваших групп. Нажмите на кнопку, чтобы посмотреть эту публикацию:",
|
||||
"userJoinedGroup": " присоединился к группе «{groupName}». Нажмите на кнопку, чтобы посмотреть эту группу:",
|
||||
"userLeftGroup": " покинул группу «{groupName}». Нажмите на кнопку, чтобы посмотреть эту группу:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Njoftim",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Roli në grup u ndryshua",
|
||||
"chatMessage": "Mesazh i ri në chat",
|
||||
"commentedOnPost": "Koment i ri në postim",
|
||||
"followedUserPosted": "Postim i ri nga një përdorues i ndjekur",
|
||||
"mentionedInComment": "U përmend në koment",
|
||||
"mentionedInPost": "U përmend në postim",
|
||||
"newEmail": "Adresë e re e-mail",
|
||||
"removedUserFromGroup": "U hoq nga grupi",
|
||||
"postInGroup": "Postim i ri në grup",
|
||||
"resetPassword": "Rivendos fjalëkalimin",
|
||||
"userJoinedGroup": "Një përdorues u bashkua me grupin",
|
||||
"userLeftGroup": "Një përdorues u largua nga grupi",
|
||||
"wrongEmail": "E-mail e gabuar?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Faleminderit që u regjistruat – jemi të lumtur që jeni me ne. Mbetet vetëm një hap i vogël përpara se të ndryshojmë botën së bashku … Ju lutemi konfirmoni adresën tuaj të e-mailit duke klikuar butonin më poshtë:",
|
||||
"codeHint": "Nëse butoni më sipër nuk funksionon, mund të kopjoni kodin e mëposhtëm në dritaren e shfletuesit tuaj: ",
|
||||
"codeHintException": "Megjithatë, kjo funksionon vetëm nëse jeni regjistruar përmes faqes sonë të internetit.",
|
||||
"notYouStart": "Nëse nuk jeni regjistruar në ",
|
||||
"notYouEnd": " ju rekomandojmë ta shikoni! Është një rrjet social nga njerëz për njerëz që duan të lidhen dhe të ndryshojnë botën së bashku.",
|
||||
"ps": "PS: Nëse e injoroni këtë e-mail, nuk do të krijojmë një llogari për ju. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Nëse butoni më sipër nuk funksionon, mund të kopjoni kodin e mëposhtëm në dritaren e shfletuesit tuaj: ",
|
||||
"introduction": "Dëshironi të ndryshoni adresën tuaj të e-mailit? Asnjë problem! Thjesht klikoni butonin më poshtë për të verifikuar adresën tuaj të re:",
|
||||
"doNotChange": "Nëse nuk dëshironi të ndryshoni adresën tuaj të e-mailit, thjesht injoroni këtë mesazh. "
|
||||
},
|
||||
"support": "Nëse keni pyetje ose probleme, mos hezitoni të kontaktoni mbështetjen tonë: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Konfirmoni adresën tuaj të e-mailit",
|
||||
"resetPassword": "Rivendos fjalëkalimin",
|
||||
"tryAgain": "Provoni me një e-mail tjetër",
|
||||
"verifyEmail": "Verifiko adresën e e-mailit",
|
||||
"viewChat": "Shiko chatin",
|
||||
"viewComment": "Shiko komentin",
|
||||
"viewGroup": "Shiko grupin",
|
||||
"viewPost": "Shiko postimin"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Përshëndetje",
|
||||
"seeYou": "Shihemi së shpejti në ",
|
||||
"yourTeam": "– Ekipi {team}",
|
||||
"settingsHint": "PS: Nëse nuk dëshironi të merrni më e-mail, ndryshoni ",
|
||||
"settingsName": "cilësimet e njoftimeve",
|
||||
"welcome": "Mirë se vini në"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Nëse butoni më sipër nuk funksionon, mund të kopjoni kodin e mëposhtëm në dritaren e shfletuesit tuaj: ",
|
||||
"ignore": "Nëse nuk keni kërkuar një fjalëkalim të ri, thjesht injoroni këtë e-mail.",
|
||||
"introduction": "Keni harruar fjalëkalimin? Asnjë problem! Thjesht klikoni butonin më poshtë për ta rivendosur brenda 24 orëve të ardhshme:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " ose nëse nuk dëshironit të rivendosnit fjalëkalimin, ju lutemi injoroni këtë e-mail.",
|
||||
"ignoreStart": "Nëse nuk keni një llogari në ",
|
||||
"introduction": "Ju kërkuat një rivendosje të fjalëkalimit, por fatkeqësisht nuk gjetëm asnjë llogari të lidhur me adresën tuaj të e-mailit. A mund të jeni regjistruar me një adresë tjetër?"
|
||||
},
|
||||
"changedGroupMemberRole": "roli juaj në grupin \u201e{groupName}\u201c u ndryshua. Klikoni butonin për të parë këtë grup:",
|
||||
"chatMessageStart": "keni marrë një mesazh të ri në chat nga ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " komentoi në një postim që po ndiqni me titullin \u201e{postTitle}\u201c. Klikoni butonin për të parë këtë koment:",
|
||||
"followedUserPosted": ", një përdorues që ndiqni, shkroi një postim të ri me titullin \u201e{postTitle}\u201c. Klikoni butonin për të parë këtë postim:",
|
||||
"mentionedInComment": " ju përmendi në një koment te postimi me titullin \u201e{postTitle}\u201c. Klikoni butonin për të parë këtë koment:",
|
||||
"mentionedInPost": " ju përmendi në një postim me titullin \u201e{postTitle}\u201c. Klikoni butonin për të parë këtë postim:",
|
||||
"removedUserFromGroup": "jeni hequr nga grupi \u201e{groupName}\u201c.",
|
||||
"postInGroup": "dikush shkroi një postim të ri me titullin \u201e{postTitle}\u201c në një nga grupet tuaja. Klikoni butonin për të parë këtë postim:",
|
||||
"userJoinedGroup": " u bashkua me grupin \u201e{groupName}\u201c. Klikoni butonin për të parë këtë grup:",
|
||||
"userLeftGroup": " u largua nga grupi \u201e{groupName}\u201c. Klikoni butonin për të parë këtë grup:"
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
{
|
||||
"notification": "Сповіщення",
|
||||
"subjects": {
|
||||
"changedGroupMemberRole": "Роль у групі змінено",
|
||||
"chatMessage": "Нове повідомлення в чаті",
|
||||
"commentedOnPost": "Новий коментар до публікації",
|
||||
"followedUserPosted": "Нова публікація від користувача, на якого ви підписані",
|
||||
"mentionedInComment": "Згадка в коментарі",
|
||||
"mentionedInPost": "Згадка в публікації",
|
||||
"newEmail": "Нова адреса електронної пошти",
|
||||
"removedUserFromGroup": "Видалено з групи",
|
||||
"postInGroup": "Нова публікація в групі",
|
||||
"resetPassword": "Скинути пароль",
|
||||
"userJoinedGroup": "Користувач приєднався до групи",
|
||||
"userLeftGroup": "Користувач покинув групу",
|
||||
"wrongEmail": "Невірна адреса електронної пошти?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Дякуємо за реєстрацію – ми раді, що ви з нами. Залишився лише один маленький крок, перш ніж ми зможемо разом змінювати світ … Будь ласка, підтвердіть свою адресу електронної пошти, натиснувши кнопку нижче:",
|
||||
"codeHint": "Якщо кнопка вище не працює, ви також можете скопіювати наступний код у вікно браузера: ",
|
||||
"codeHintException": "Однак це працює лише в тому випадку, якщо ви зареєструвалися через наш сайт.",
|
||||
"notYouStart": "Якщо ви не реєструвалися на ",
|
||||
"notYouEnd": " рекомендуємо заглянути! Це соціальна мережа від людей для людей, які хочуть об'єднуватися і разом змінювати світ.",
|
||||
"ps": "PS: Якщо ви проігноруєте цей лист, ми не створимо для вас обліковий запис. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Якщо кнопка вище не працює, ви також можете скопіювати наступний код у вікно браузера: ",
|
||||
"introduction": "Хочете змінити свою адресу електронної пошти? Без проблем! Просто натисніть кнопку нижче, щоб підтвердити нову адресу:",
|
||||
"doNotChange": "Якщо ви не хочете змінювати свою адресу електронної пошти, просто проігноруйте це повідомлення. "
|
||||
},
|
||||
"support": "Якщо у вас є запитання або проблеми, зверніться до нашої служби підтримки: ",
|
||||
"buttons": {
|
||||
"confirmEmail": "Підтвердіть свою адресу електронної пошти",
|
||||
"resetPassword": "Скинути пароль",
|
||||
"tryAgain": "Спробувати іншу адресу електронної пошти",
|
||||
"verifyEmail": "Підтвердити адресу електронної пошти",
|
||||
"viewChat": "Відкрити чат",
|
||||
"viewComment": "Переглянути коментар",
|
||||
"viewGroup": "Переглянути групу",
|
||||
"viewPost": "Переглянути публікацію"
|
||||
},
|
||||
"general": {
|
||||
"greeting": "Вітаємо",
|
||||
"seeYou": "До зустрічі на ",
|
||||
"yourTeam": "– Команда {team}",
|
||||
"settingsHint": "PS: Якщо ви більше не хочете отримувати електронні листи, змініть свої ",
|
||||
"settingsName": "налаштування сповіщень",
|
||||
"welcome": "Ласкаво просимо до"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Якщо кнопка вище не працює, ви також можете скопіювати наступний код у вікно браузера: ",
|
||||
"ignore": "Якщо ви не запитували новий пароль, просто проігноруйте цей лист.",
|
||||
"introduction": "Забули пароль? Без проблем! Просто натисніть кнопку нижче, щоб скинути його протягом наступних 24 годин:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " або якщо ви не хотіли скидати пароль, просто проігноруйте цей лист.",
|
||||
"ignoreStart": "Якщо у вас немає облікового запису на ",
|
||||
"introduction": "Ви запросили скидання пароля, але, на жаль, ми не знайшли облікового запису, пов'язаного з вашою адресою електронної пошти. Можливо, ви зареєструвалися з іншою адресою?"
|
||||
},
|
||||
"changedGroupMemberRole": "вашу роль у групі «{groupName}» було змінено. Натисніть кнопку, щоб переглянути цю групу:",
|
||||
"chatMessageStart": "ви отримали нове повідомлення в чаті від ",
|
||||
"chatMessageEnd": ".",
|
||||
"commentedOnPost": " прокоментував публікацію, за якою ви стежите, з заголовком «{postTitle}». Натисніть кнопку, щоб переглянути цей коментар:",
|
||||
"followedUserPosted": ", користувач, на якого ви підписані, написав нову публікацію з заголовком «{postTitle}». Натисніть кнопку, щоб переглянути цю публікацію:",
|
||||
"mentionedInComment": " згадав вас у коментарі до публікації з заголовком «{postTitle}». Натисніть кнопку, щоб переглянути цей коментар:",
|
||||
"mentionedInPost": " згадав вас у публікації з заголовком «{postTitle}». Натисніть кнопку, щоб переглянути цю публікацію:",
|
||||
"removedUserFromGroup": "вас було видалено з групи «{groupName}».",
|
||||
"postInGroup": "хтось написав нову публікацію з заголовком «{postTitle}» в одній з ваших груп. Натисніть кнопку, щоб переглянути цю публікацію:",
|
||||
"userJoinedGroup": " приєднався до групи «{groupName}». Натисніть кнопку, щоб переглянути цю групу:",
|
||||
"userLeftGroup": " покинув групу «{groupName}». Натисніть кнопку, щоб переглянути цю групу:"
|
||||
}
|
||||
@ -2,7 +2,7 @@ import CONFIG from '@config/index'
|
||||
|
||||
CONFIG.SUPPORT_EMAIL = 'devops@ocelot.social'
|
||||
|
||||
// eslint-disable-next-line import-x/first
|
||||
// eslint-disable-next-line import/first
|
||||
import { sendChatMessageMail } from './sendEmail'
|
||||
|
||||
const senderUser = {
|
||||
|
||||
@ -12,8 +12,7 @@ import { createTransport } from 'nodemailer'
|
||||
import CONFIG, { nodemailerTransportOptions } from '@config/index'
|
||||
import logosWebapp from '@config/logosBranded'
|
||||
import metadata from '@config/metadata'
|
||||
|
||||
import type { UserDbProperties } from '@db/types/User'
|
||||
import { UserDbProperties } from '@db/types/User'
|
||||
|
||||
const welcomeImageUrl = new URL(logosWebapp.LOGO_WELCOME_PATH, CONFIG.CLIENT_URI)
|
||||
const settingsUrl = new URL('/settings/notifications', CONFIG.CLIENT_URI)
|
||||
@ -39,7 +38,7 @@ const email = new Email({
|
||||
},
|
||||
transport,
|
||||
i18n: {
|
||||
locales: ['en', 'de', 'nl', 'fr', 'it', 'es', 'pt', 'pl', 'ru', 'sq', 'uk'],
|
||||
locales: ['en', 'de'],
|
||||
defaultLocale: CONFIG.LANGUAGE_DEFAULT,
|
||||
retryInDefaultLocale: false,
|
||||
directory: path.join(__dirname, 'locales'),
|
||||
|
||||
@ -2,7 +2,7 @@ import CONFIG from '@config/index'
|
||||
|
||||
CONFIG.SUPPORT_EMAIL = 'devops@ocelot.social'
|
||||
|
||||
// eslint-disable-next-line import-x/first
|
||||
// eslint-disable-next-line import/first
|
||||
import { sendEmailVerification } from './sendEmail'
|
||||
|
||||
describe('sendEmailVerification', () => {
|
||||
|
||||
@ -2,7 +2,7 @@ import CONFIG from '@config/index'
|
||||
|
||||
CONFIG.SUPPORT_EMAIL = 'devops@ocelot.social'
|
||||
|
||||
// eslint-disable-next-line import-x/first
|
||||
// eslint-disable-next-line import/first
|
||||
import { sendNotificationMail } from './sendEmail'
|
||||
|
||||
describe('sendNotificationMail', () => {
|
||||
|
||||
@ -2,7 +2,7 @@ import CONFIG from '@config/index'
|
||||
|
||||
CONFIG.SUPPORT_EMAIL = 'devops@ocelot.social'
|
||||
|
||||
// eslint-disable-next-line import-x/first
|
||||
// eslint-disable-next-line import/first
|
||||
import { sendRegistrationMail } from './sendEmail'
|
||||
|
||||
describe('sendRegistrationMail', () => {
|
||||
|
||||
@ -2,7 +2,7 @@ import CONFIG from '@config/index'
|
||||
|
||||
CONFIG.SUPPORT_EMAIL = 'devops@ocelot.social'
|
||||
|
||||
// eslint-disable-next-line import-x/first
|
||||
// eslint-disable-next-line import/first
|
||||
import { sendResetPasswordMail } from './sendEmail'
|
||||
|
||||
describe('sendResetPasswordMail', () => {
|
||||
|
||||
@ -2,7 +2,7 @@ import CONFIG from '@config/index'
|
||||
|
||||
CONFIG.SUPPORT_EMAIL = 'devops@ocelot.social'
|
||||
|
||||
// eslint-disable-next-line import-x/first
|
||||
// eslint-disable-next-line import/first
|
||||
import { sendWrongEmail } from './sendEmail'
|
||||
|
||||
describe('sendWrongEmail', () => {
|
||||
|
||||
6
backend/src/graphql.d.ts
vendored
6
backend/src/graphql.d.ts
vendored
@ -1,6 +0,0 @@
|
||||
declare module '*.gql' {
|
||||
import type { DocumentNode } from 'graphql'
|
||||
|
||||
const value: DocumentNode
|
||||
export default value
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
import { GraphQLError } from 'graphql'
|
||||
|
||||
export class UserInputError extends GraphQLError {
|
||||
constructor(message: string) {
|
||||
super(message, { extensions: { code: 'BAD_USER_INPUT' } })
|
||||
}
|
||||
}
|
||||
|
||||
export class AuthenticationError extends GraphQLError {
|
||||
constructor(message: string) {
|
||||
super(message, { extensions: { code: 'UNAUTHENTICATED' } })
|
||||
}
|
||||
}
|
||||
|
||||
export class ForbiddenError extends GraphQLError {
|
||||
constructor(message: string) {
|
||||
super(message, { extensions: { code: 'FORBIDDEN' } })
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
/* eslint-disable n/no-sync, security/detect-non-literal-fs-filename */
|
||||
// Register a require hook for .gql files so they can be imported at runtime.
|
||||
// Jest uses its own graphqlTransform.ts for this; this hook covers tsx/node usage
|
||||
// (e.g. db:seed).
|
||||
import { readFileSync } from 'node:fs'
|
||||
import Module from 'node:module'
|
||||
|
||||
import { parse } from 'graphql'
|
||||
|
||||
// @ts-expect-error -- require.extensions is deprecated but still functional for CJS hooks
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
Module._extensions['.gql'] = function (_module: typeof module, filename: string) {
|
||||
const content = readFileSync(filename, 'utf-8')
|
||||
try {
|
||||
_module.exports = parse(content)
|
||||
} catch (error: unknown) {
|
||||
throw new Error(
|
||||
`Failed to parse ${filename}: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
11
backend/src/graphql/queries/AddEmailAddress.ts
Normal file
11
backend/src/graphql/queries/AddEmailAddress.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const AddEmailAddress = gql`
|
||||
mutation ($email: String!) {
|
||||
AddEmailAddress(email: $email) {
|
||||
email
|
||||
verifiedAt
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
`
|
||||
15
backend/src/graphql/queries/AddPostEmotions.ts
Normal file
15
backend/src/graphql/queries/AddPostEmotions.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const AddPostEmotions = gql`
|
||||
mutation ($to: _PostInput!, $data: _EMOTEDInput!) {
|
||||
AddPostEmotions(to: $to, data: $data) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
to {
|
||||
id
|
||||
}
|
||||
emotion
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -1,8 +0,0 @@
|
||||
query Category {
|
||||
Category {
|
||||
id
|
||||
slug
|
||||
name
|
||||
icon
|
||||
}
|
||||
}
|
||||
12
backend/src/graphql/queries/Category.ts
Normal file
12
backend/src/graphql/queries/Category.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const Category = gql`
|
||||
query {
|
||||
Category {
|
||||
id
|
||||
slug
|
||||
name
|
||||
icon
|
||||
}
|
||||
}
|
||||
`
|
||||
16
backend/src/graphql/queries/ChangeGroupMemberRole.ts
Normal file
16
backend/src/graphql/queries/ChangeGroupMemberRole.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const ChangeGroupMemberRole = gql`
|
||||
mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
|
||||
ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
|
||||
user {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
membership {
|
||||
role
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
15
backend/src/graphql/queries/CreateComment.ts
Normal file
15
backend/src/graphql/queries/CreateComment.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const CreateComment = gql`
|
||||
mutation ($id: ID, $postId: ID!, $content: String!) {
|
||||
CreateComment(id: $id, postId: $postId, content: $content) {
|
||||
id
|
||||
content
|
||||
author {
|
||||
name
|
||||
}
|
||||
isPostObservedByMe
|
||||
postObservingUsersCount
|
||||
}
|
||||
}
|
||||
`
|
||||
53
backend/src/graphql/queries/CreateGroup.ts
Normal file
53
backend/src/graphql/queries/CreateGroup.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const CreateGroup = gql`
|
||||
mutation (
|
||||
$id: ID
|
||||
$name: String!
|
||||
$slug: String
|
||||
$about: String
|
||||
$description: String!
|
||||
$groupType: GroupType!
|
||||
$actionRadius: GroupActionRadius!
|
||||
$categoryIds: [ID]
|
||||
$locationName: String # empty string '' sets it to null
|
||||
) {
|
||||
CreateGroup(
|
||||
id: $id
|
||||
name: $name
|
||||
slug: $slug
|
||||
about: $about
|
||||
description: $description
|
||||
groupType: $groupType
|
||||
actionRadius: $actionRadius
|
||||
categoryIds: $categoryIds
|
||||
locationName: $locationName
|
||||
) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
createdAt
|
||||
updatedAt
|
||||
disabled
|
||||
deleted
|
||||
about
|
||||
description
|
||||
descriptionExcerpt
|
||||
groupType
|
||||
actionRadius
|
||||
categories {
|
||||
id
|
||||
slug
|
||||
name
|
||||
icon
|
||||
}
|
||||
locationName
|
||||
location {
|
||||
name
|
||||
nameDE
|
||||
nameEN
|
||||
}
|
||||
myRole
|
||||
}
|
||||
}
|
||||
`
|
||||
22
backend/src/graphql/queries/CreateMessage.ts
Normal file
22
backend/src/graphql/queries/CreateMessage.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const CreateMessage = gql`
|
||||
mutation ($roomId: ID!, $content: String!, $files: [FileInput]) {
|
||||
CreateMessage(roomId: $roomId, content: $content, files: $files) {
|
||||
id
|
||||
content
|
||||
senderId
|
||||
username
|
||||
avatar
|
||||
date
|
||||
saved
|
||||
distributed
|
||||
seen
|
||||
files {
|
||||
url
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
51
backend/src/graphql/queries/CreatePost.ts
Normal file
51
backend/src/graphql/queries/CreatePost.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const CreatePost = gql`
|
||||
mutation (
|
||||
$id: ID
|
||||
$title: String!
|
||||
$slug: String
|
||||
$content: String!
|
||||
$categoryIds: [ID]
|
||||
$groupId: ID
|
||||
$postType: PostType
|
||||
$eventInput: _EventInput
|
||||
) {
|
||||
CreatePost(
|
||||
id: $id
|
||||
title: $title
|
||||
slug: $slug
|
||||
content: $content
|
||||
categoryIds: $categoryIds
|
||||
groupId: $groupId
|
||||
postType: $postType
|
||||
eventInput: $eventInput
|
||||
) {
|
||||
id
|
||||
slug
|
||||
title
|
||||
content
|
||||
disabled
|
||||
deleted
|
||||
postType
|
||||
author {
|
||||
name
|
||||
}
|
||||
categories {
|
||||
id
|
||||
}
|
||||
eventStart
|
||||
eventEnd
|
||||
eventLocationName
|
||||
eventVenue
|
||||
eventIsOnline
|
||||
eventLocation {
|
||||
lng
|
||||
lat
|
||||
}
|
||||
isObservedByMe
|
||||
observingUsersCount
|
||||
language
|
||||
}
|
||||
}
|
||||
`
|
||||
22
backend/src/graphql/queries/CreateRoom.ts
Normal file
22
backend/src/graphql/queries/CreateRoom.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const CreateRoom = gql`
|
||||
mutation ($userId: ID!) {
|
||||
CreateRoom(userId: $userId) {
|
||||
id
|
||||
roomId
|
||||
roomName
|
||||
lastMessageAt
|
||||
unreadCount
|
||||
#avatar
|
||||
users {
|
||||
_id
|
||||
id
|
||||
name
|
||||
avatar {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
14
backend/src/graphql/queries/CreateSocialMedia.ts
Normal file
14
backend/src/graphql/queries/CreateSocialMedia.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const CreateSocialMedia = gql`
|
||||
mutation ($url: String!) {
|
||||
CreateSocialMedia(url: $url) {
|
||||
id
|
||||
url
|
||||
url
|
||||
ownedBy {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
12
backend/src/graphql/queries/DeleteComment.ts
Normal file
12
backend/src/graphql/queries/DeleteComment.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const DeleteComment = gql`
|
||||
mutation ($id: ID!) {
|
||||
DeleteComment(id: $id) {
|
||||
id
|
||||
content
|
||||
contentExcerpt
|
||||
deleted
|
||||
}
|
||||
}
|
||||
`
|
||||
20
backend/src/graphql/queries/DeletePost.ts
Normal file
20
backend/src/graphql/queries/DeletePost.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const DeletePost = gql`
|
||||
mutation ($id: ID!) {
|
||||
DeletePost(id: $id) {
|
||||
id
|
||||
deleted
|
||||
content
|
||||
contentExcerpt
|
||||
image {
|
||||
url
|
||||
}
|
||||
comments {
|
||||
deleted
|
||||
content
|
||||
contentExcerpt
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
10
backend/src/graphql/queries/DeleteSocialMedia.ts
Normal file
10
backend/src/graphql/queries/DeleteSocialMedia.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const DeleteSocialMedia = gql`
|
||||
mutation ($id: ID!) {
|
||||
DeleteSocialMedia(id: $id) {
|
||||
id
|
||||
url
|
||||
}
|
||||
}
|
||||
`
|
||||
30
backend/src/graphql/queries/DeleteUser.ts
Normal file
30
backend/src/graphql/queries/DeleteUser.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const DeleteUser = gql`
|
||||
mutation ($id: ID!, $resource: [Deletable]) {
|
||||
DeleteUser(id: $id, resource: $resource) {
|
||||
id
|
||||
name
|
||||
about
|
||||
deleted
|
||||
contributions {
|
||||
id
|
||||
content
|
||||
contentExcerpt
|
||||
deleted
|
||||
comments {
|
||||
id
|
||||
content
|
||||
contentExcerpt
|
||||
deleted
|
||||
}
|
||||
}
|
||||
comments {
|
||||
id
|
||||
content
|
||||
contentExcerpt
|
||||
deleted
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
12
backend/src/graphql/queries/Donations.ts
Normal file
12
backend/src/graphql/queries/Donations.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const Donations = gql`
|
||||
query {
|
||||
Donations {
|
||||
id
|
||||
showDonations
|
||||
goal
|
||||
progress
|
||||
}
|
||||
}
|
||||
`
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user