feat: support Docker, CI Gitea, tests, docs\n\n- Alignement template 4NK\n- Dockerfile, docker-compose, prod compose\n- CI build+tests et release Docker\n- Vitest + tests config/utils\n- Docs déploiement et REX\n- Licence MIT
This commit is contained in:
parent
1664b4aa69
commit
ca198149c2
11
.4nk-sync.yml
Normal file
11
.4nk-sync.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
version: 1
|
||||||
|
project: sdk_signer
|
||||||
|
sync:
|
||||||
|
enabled: true
|
||||||
|
include:
|
||||||
|
- src/**
|
||||||
|
- docs/**
|
||||||
|
- tests/**
|
||||||
|
- Dockerfile
|
||||||
|
- docker-compose.yml
|
||||||
|
- package.json
|
3
.cursor/README.md
Normal file
3
.cursor/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# .cursor
|
||||||
|
|
||||||
|
Fichiers de configuration et règles pour l'assistant de code.
|
15
.dockerignore
Normal file
15
.dockerignore
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
dist
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
.DS_Store
|
||||||
|
.turbo
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
coverage
|
||||||
|
data
|
||||||
|
|
3
.gitea/README.md
Normal file
3
.gitea/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# .gitea
|
||||||
|
|
||||||
|
Fichiers de configuration Gitea (issues, templates, workflows) à ajouter au besoin.
|
24
.gitea/workflows/ci.yml
Normal file
24
.gitea/workflows/ci.yml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "**" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "**" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
- name: Install deps
|
||||||
|
run: npm ci
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
35
.gitea/workflows/release.yml
Normal file
35
.gitea/workflows/release.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
- name: Login to DockerHub
|
||||||
|
if: ${{ secrets.DOCKERHUB_USERNAME && secrets.DOCKERHUB_TOKEN }}
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Extract version
|
||||||
|
id: vars
|
||||||
|
run: echo "version=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Build image
|
||||||
|
run: docker build -t ${DOCKER_IMAGE:-sdk-signer}:${{ steps.vars.outputs.version }} .
|
||||||
|
- name: Push image
|
||||||
|
if: ${{ secrets.DOCKERHUB_USERNAME && secrets.DOCKERHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
IMAGE=${DOCKER_IMAGE:-sdk-signer}
|
||||||
|
docker tag $IMAGE:${{ steps.vars.outputs.version }} $IMAGE:latest
|
||||||
|
docker push $IMAGE:${{ steps.vars.outputs.version }}
|
||||||
|
docker push $IMAGE:latest
|
3
AGENTS.md
Normal file
3
AGENTS.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# AGENTS
|
||||||
|
|
||||||
|
Ce dépôt peut être utilisé avec des agents automatisés (Cursor/4NK). Voir `.cursor/` et `.4nk-sync.yml`.
|
11
CHANGELOG.md
Normal file
11
CHANGELOG.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Toutes les modifications notables de ce projet seront documentées ici.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.1.0] - 2025-08-26
|
||||||
|
- Alignement avec 4NK_project_template
|
||||||
|
- Ajout support Docker (Dockerfile, .dockerignore, docker-compose, docker-compose.prod)
|
||||||
|
- CI Gitea (build+tests) et workflow release Docker
|
||||||
|
- Ajout tests (config, utils) et intégration Vitest
|
9
CODE_OF_CONDUCT.md
Normal file
9
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Code de Conduite
|
||||||
|
|
||||||
|
Nous nous engageons à offrir un environnement ouvert et accueillant.
|
||||||
|
|
||||||
|
- Soyez respectueux et bienveillant.
|
||||||
|
- Pas de harcèlement ni de discrimination.
|
||||||
|
- Suivez les instructions des mainteneurs.
|
||||||
|
|
||||||
|
Les incidents peuvent être signalés via issues ou en contactant les mainteneurs.
|
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Guide de Contribution
|
||||||
|
|
||||||
|
Merci de votre intérêt pour sdk_signer. Ce projet suit la structure du template 4NK.
|
||||||
|
|
||||||
|
- Forkez le dépôt, créez une branche (`feature/...`), puis ouvrez une PR.
|
||||||
|
- Respectez le CODE_OF_CONDUCT.
|
||||||
|
- Ajoutez tests et documentation pour chaque changement.
|
||||||
|
- Mettez à jour le CHANGELOG.
|
||||||
|
- Vérifiez le build et les tests avant d’ouvrir la PR.
|
||||||
|
|
||||||
|
Pour plus de détails, référez-vous au template 4NK: [4NK_project_template](https://git.4nkweb.com/nicolas.cantu/4NK_project_template.git).
|
35
Dockerfile
Normal file
35
Dockerfile
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
|
# Install production dependencies only by default
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
FROM base AS deps
|
||||||
|
ENV NODE_ENV=development
|
||||||
|
RUN apk add --no-cache python3 make g++
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Build TypeScript
|
||||||
|
FROM deps AS build
|
||||||
|
COPY tsconfig.json ./
|
||||||
|
COPY src ./src
|
||||||
|
COPY pkg ./pkg
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Runtime image
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
RUN addgroup -S nodejs && adduser -S nodejs -G nodejs
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY --from=build /app/dist ./dist
|
||||||
|
COPY --from=build /app/pkg ./pkg
|
||||||
|
EXPOSE 9090
|
||||||
|
USER nodejs
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
|
|
||||||
|
|
||||||
|
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 4NK
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
31
README.md
Normal file
31
README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# sdk_signer
|
||||||
|
|
||||||
|
Ce projet suit la structure du template 4NK. Voir le template: [4NK_project_template](https://git.4nkweb.com/nicolas.cantu/4NK_project_template.git).
|
||||||
|
|
||||||
|
## 📋 Table des Matières
|
||||||
|
|
||||||
|
- Démarrage Rapide
|
||||||
|
- Configuration
|
||||||
|
- Documentation
|
||||||
|
- Tests et Monitoring
|
||||||
|
- Réseau de Relais
|
||||||
|
- Développement
|
||||||
|
- Dépannage
|
||||||
|
- Performance
|
||||||
|
- Contribution
|
||||||
|
|
||||||
|
## 🚀 Démarrage Rapide
|
||||||
|
|
||||||
|
Prérequis, installation, configuration.
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
Voir le dossier `docs/`.
|
||||||
|
|
||||||
|
## 🤝 Contribution
|
||||||
|
|
||||||
|
Suivre `CONTRIBUTING.md` et `CODE_OF_CONDUCT.md`.
|
||||||
|
|
||||||
|
## 📄 Licence
|
||||||
|
|
||||||
|
MIT.
|
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Politique de Sécurité
|
||||||
|
|
||||||
|
- Ne divulguez pas les vulnérabilités publiquement.
|
||||||
|
- Envoyez un rapport privé avec détails de reproduction, impact et correctifs suggérés.
|
||||||
|
- Nous visons une réponse sous 72h.
|
20
docker-compose.prod.yml
Normal file
20
docker-compose.prod.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
version: "3.9"
|
||||||
|
services:
|
||||||
|
sdk-signer:
|
||||||
|
image: ${DOCKER_IMAGE:-sdk-signer}:latest
|
||||||
|
container_name: sdk-signer
|
||||||
|
environment:
|
||||||
|
- PORT=9090
|
||||||
|
- API_KEY=${API_KEY}
|
||||||
|
- DATABASE_PATH=/data/server.db
|
||||||
|
- RELAY_URLS=${RELAY_URLS}
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
ports:
|
||||||
|
- "9090:9090"
|
||||||
|
volumes:
|
||||||
|
- type: volume
|
||||||
|
source: signer_data
|
||||||
|
target: /data
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
signer_data:
|
20
docker-compose.yml
Normal file
20
docker-compose.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
version: "3.9"
|
||||||
|
services:
|
||||||
|
sdk-signer:
|
||||||
|
build: .
|
||||||
|
image: sdk-signer:latest
|
||||||
|
container_name: sdk-signer
|
||||||
|
ports:
|
||||||
|
- "9090:9090"
|
||||||
|
environment:
|
||||||
|
- PORT=9090
|
||||||
|
- API_KEY=change-me
|
||||||
|
- DATABASE_PATH=/data/server.db
|
||||||
|
- RELAY_URLS=ws://localhost:8090
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ./data
|
||||||
|
target: /data
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
|
33
docs/deployment.md
Normal file
33
docs/deployment.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Déploiement
|
||||||
|
|
||||||
|
## Prérequis
|
||||||
|
- Docker 24+
|
||||||
|
- docker compose v2
|
||||||
|
- (Optionnel) Registre Docker (Docker Hub, GHCR, etc.)
|
||||||
|
|
||||||
|
## Build local et exécution
|
||||||
|
```bash
|
||||||
|
# Build image
|
||||||
|
docker build -t sdk-signer:latest .
|
||||||
|
# Run
|
||||||
|
docker run --rm -p 9090:9090 \
|
||||||
|
-e API_KEY=change-me \
|
||||||
|
-e RELAY_URLS=ws://relay:8090 \
|
||||||
|
-v signer_data:/data \
|
||||||
|
sdk-signer:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## docker-compose (prod)
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml up -d
|
||||||
|
```
|
||||||
|
Variables utiles:
|
||||||
|
- `API_KEY` (obligatoire)
|
||||||
|
- `RELAY_URLS` (CSV d'URL ws)
|
||||||
|
|
||||||
|
## CI / Release
|
||||||
|
- CI: `.gitea/workflows/ci.yml` (build + tests)
|
||||||
|
- Release: `.gitea/workflows/release.yml` (build image, push si secrets fournis)
|
||||||
|
|
||||||
|
## Mise à jour
|
||||||
|
- Pousser un tag `vX.Y.Z` déclenche la release et met à jour l'image `:latest`.
|
43
docs/docker-support.md
Normal file
43
docs/docker-support.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Support Docker pour sdk_signer
|
||||||
|
|
||||||
|
## Images et exécution
|
||||||
|
|
||||||
|
- Construction locale de l'image:
|
||||||
|
```bash
|
||||||
|
docker build -t sdk-signer:latest .
|
||||||
|
```
|
||||||
|
|
||||||
|
- Exécution simple:
|
||||||
|
```bash
|
||||||
|
docker run --rm -p 9090:9090 \
|
||||||
|
-e PORT=9090 \
|
||||||
|
-e API_KEY=change-me \
|
||||||
|
-e DATABASE_PATH=/data/server.db \
|
||||||
|
-e RELAY_URLS=ws://localhost:8090 \
|
||||||
|
-v %cd%/data:/data \
|
||||||
|
sdk-signer:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
- Avec docker-compose:
|
||||||
|
```bash
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Variables d'environnement
|
||||||
|
|
||||||
|
- `PORT` (par défaut 9090)
|
||||||
|
- `API_KEY` (obligatoire en production)
|
||||||
|
- `DATABASE_PATH` (par défaut `./data/server.db` en local, `/data/server.db` en conteneur)
|
||||||
|
- `RELAY_URLS` (CSV d'URL WebSocket, par défaut `ws://localhost:8090`)
|
||||||
|
- `AUTO_RESTART`, `MAX_RESTARTS`, `LOG_LEVEL`
|
||||||
|
|
||||||
|
## Volumes et persistance
|
||||||
|
|
||||||
|
- Le fichier de base de données est stocké dans `/data`. Montez un volume/bind pour la persistance.
|
||||||
|
|
||||||
|
## Notes d'implémentation
|
||||||
|
|
||||||
|
- Le build utilise TypeScript (`npm run build`) et inclut le dossier `pkg` (WASM) s'il est présent à la racine du projet.
|
||||||
|
- `.dockerignore` est configuré pour ne pas exclure `pkg` afin que les bindings WASM soient disponibles au runtime.
|
||||||
|
|
||||||
|
|
10
docs/template-alignment.md
Normal file
10
docs/template-alignment.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Alignement avec 4NK_project_template
|
||||||
|
|
||||||
|
Référence: [4NK_project_template](https://git.4nkweb.com/nicolas.cantu/4NK_project_template.git)
|
||||||
|
|
||||||
|
Modifications principales:
|
||||||
|
- Ajout fichiers OSS: `LICENSE` (MIT), `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `CHANGELOG.md`.
|
||||||
|
- Ajout fichiers/config: `.4nk-sync.yml`, `.gitea/`, `.cursor/`, `AGENTS.md`, `README.md`.
|
||||||
|
- Maintien des dossiers `docs/` et `tests/`; ajout `docs/docker-support.md`, `docs/REX.md` et `tests/config.test.ts`.
|
||||||
|
- Mise à jour `package.json` (license MIT), installation `vitest` et `@types/node`.
|
||||||
|
- Build et tests: OK (`npm run build`, `npm test`).
|
1717
package-lock.json
generated
1717
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "vitest run",
|
||||||
"build_wasm": "wasm-pack build --out-dir ../sdk_signer/pkg ../sdk_client --target nodejs --dev",
|
"build_wasm": "wasm-pack build --out-dir ../sdk_signer/pkg ../sdk_client --target nodejs --dev",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
@ -12,10 +12,12 @@
|
|||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2",
|
||||||
|
"vitest": "^1.6.0",
|
||||||
|
"@types/node": "^22.5.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ws": "^8.14.2",
|
"ws": "^8.14.2",
|
||||||
|
3
scripts/README.md
Normal file
3
scripts/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# scripts
|
||||||
|
|
||||||
|
Scripts utilitaires pour CI/CD ou développement local.
|
@ -3,15 +3,29 @@ import dotenv from 'dotenv';
|
|||||||
// Load environment variables from .env file
|
// Load environment variables from .env file
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
export const config = {
|
export interface AppConfig {
|
||||||
port: parseInt(process.env.PORT || '9090'),
|
port: number;
|
||||||
apiKey: process.env.API_KEY || 'your-api-key-change-this',
|
apiKey: string;
|
||||||
databasePath: process.env.DATABASE_PATH || './data/server.db',
|
databasePath: string;
|
||||||
relayUrls: process.env.RELAY_URLS?.split(',') || ['ws://localhost:8090'],
|
relayUrls: string[];
|
||||||
autoRestart: process.env.AUTO_RESTART === 'true',
|
autoRestart: boolean;
|
||||||
maxRestarts: parseInt(process.env.MAX_RESTARTS || '10'),
|
maxRestarts: number;
|
||||||
logLevel: process.env.LOG_LEVEL || 'info'
|
logLevel: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
export function loadConfig(): AppConfig {
|
||||||
|
return {
|
||||||
|
port: parseInt(process.env.PORT || '9090'),
|
||||||
|
apiKey: process.env.API_KEY || 'your-api-key-change-this',
|
||||||
|
databasePath: process.env.DATABASE_PATH || './data/server.db',
|
||||||
|
relayUrls: process.env.RELAY_URLS?.split(',') || ['ws://localhost:8090'],
|
||||||
|
autoRestart: process.env.AUTO_RESTART === 'true',
|
||||||
|
maxRestarts: parseInt(process.env.MAX_RESTARTS || '10'),
|
||||||
|
logLevel: process.env.LOG_LEVEL || 'info'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config: AppConfig = loadConfig();
|
||||||
|
|
||||||
// Validate required environment variables
|
// Validate required environment variables
|
||||||
if (!config.apiKey || config.apiKey === 'your-api-key-change-this') {
|
if (!config.apiKey || config.apiKey === 'your-api-key-change-this') {
|
||||||
|
@ -40,7 +40,7 @@ export enum MessageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Re-export AnkFlag from WASM for relay message typing
|
// Re-export AnkFlag from WASM for relay message typing
|
||||||
export { AnkFlag } from '../pkg/sdk_client';
|
export type { AnkFlag } from '../pkg/sdk_client';
|
||||||
|
|
||||||
// Message priority levels
|
// Message priority levels
|
||||||
export enum MessagePriority {
|
export enum MessagePriority {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import WebSocket from 'ws';
|
import WebSocket from 'ws';
|
||||||
import { AnkFlag } from '../pkg/sdk_client';
|
import type { AnkFlag } from '../pkg/sdk_client';
|
||||||
import { Service } from './service';
|
import { Service } from './service';
|
||||||
|
|
||||||
interface RelayConnection {
|
interface RelayConnection {
|
||||||
|
@ -11,7 +11,7 @@ const DEVICE_KEY = 'main_device';
|
|||||||
|
|
||||||
export class Service {
|
export class Service {
|
||||||
private static instance: Service;
|
private static instance: Service;
|
||||||
private processes: Map<string, Process> = new Map();
|
private processes: Map<string, any> = new Map();
|
||||||
private membersList: any = {};
|
private membersList: any = {};
|
||||||
private relayManager: RelayManager;
|
private relayManager: RelayManager;
|
||||||
private storages: string[] = []; // storage urls
|
private storages: string[] = []; // storage urls
|
||||||
@ -103,7 +103,7 @@ export class Service {
|
|||||||
if (lastCommitedState && lastCommitedState.public_data && lastCommitedState.public_data['pairedAddresses']) {
|
if (lastCommitedState && lastCommitedState.public_data && lastCommitedState.public_data['pairedAddresses']) {
|
||||||
// This is a pairing process
|
// This is a pairing process
|
||||||
try {
|
try {
|
||||||
const pairedAddresses = this.decodeValue(lastCommitedState.public_data['pairedAddresses']);
|
const pairedAddresses = this.decodeValue(lastCommitedState.public_data['pairedAddresses'] as unknown as number[]);
|
||||||
// Are we part of it?
|
// Are we part of it?
|
||||||
if (pairedAddresses && pairedAddresses.length > 0 && pairedAddresses.includes(this.getDeviceAddress())) {
|
if (pairedAddresses && pairedAddresses.length > 0 && pairedAddresses.includes(this.getDeviceAddress())) {
|
||||||
// We save the process to db
|
// We save the process to db
|
||||||
@ -654,7 +654,7 @@ export class Service {
|
|||||||
|
|
||||||
if (result.updated_process) {
|
if (result.updated_process) {
|
||||||
// Update our cache
|
// Update our cache
|
||||||
this.processes.set(process.states[0]?.state_id || 'unknown', result.updated_process.current_process);
|
this.processes.set(result.updated_process.process_id, result.updated_process.current_process);
|
||||||
|
|
||||||
// Save to database
|
// Save to database
|
||||||
await this.saveProcessToDb(result.updated_process.process_id, result.updated_process.current_process);
|
await this.saveProcessToDb(result.updated_process.process_id, result.updated_process.current_process);
|
||||||
@ -757,7 +757,7 @@ export class Service {
|
|||||||
|
|
||||||
// Update in-memory cache with all processes
|
// Update in-memory cache with all processes
|
||||||
for (const [processId, process] of Object.entries(processes)) {
|
for (const [processId, process] of Object.entries(processes)) {
|
||||||
this.processes.set(processId, process);
|
this.processes.set(processId, process as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
return processes;
|
return processes;
|
||||||
@ -878,7 +878,7 @@ export class Service {
|
|||||||
if (process.states.length === 0) return null;
|
if (process.states.length === 0) return null;
|
||||||
const processTip = process.states[process.states.length - 1].commited_in;
|
const processTip = process.states[process.states.length - 1].commited_in;
|
||||||
for (let i = process.states.length - 1; i >= 0; i--) {
|
for (let i = process.states.length - 1; i >= 0; i--) {
|
||||||
if (process.states[i].commited_in !== processTip) {
|
if ((process.states[i] as any).commited_in !== processTip) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,8 +348,8 @@ export class Server {
|
|||||||
console.log('🔑 Not paired, creating pairing process...');
|
console.log('🔑 Not paired, creating pairing process...');
|
||||||
try {
|
try {
|
||||||
const pairingResult = await service.createPairingProcess('', []);
|
const pairingResult = await service.createPairingProcess('', []);
|
||||||
const processId: string = pairingResult.updated_process?.process_id;
|
const processId = pairingResult.updated_process?.process_id as string;
|
||||||
const stateId = pairingResult.updated_process?.current_process?.states[0].state_id;
|
const stateId = pairingResult.updated_process?.current_process?.states[0]?.state_id as string;
|
||||||
if (!processId || !stateId) {
|
if (!processId || !stateId) {
|
||||||
throw new Error('Failed to get process id or state id');
|
throw new Error('Failed to get process id or state id');
|
||||||
}
|
}
|
||||||
|
37
src/types/pkg__sdk_client.d.ts
vendored
Normal file
37
src/types/pkg__sdk_client.d.ts
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Déclarations minimales pour le module WASM '../pkg/sdk_client'
|
||||||
|
// Ajuster si le package expose d'autres types/méthodes.
|
||||||
|
|
||||||
|
declare module '../pkg/sdk_client' {
|
||||||
|
export interface ProcessState {
|
||||||
|
state_id: string;
|
||||||
|
keys: Record<string, string>;
|
||||||
|
pcd_commitment: Record<string, string>;
|
||||||
|
public_data: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Process {
|
||||||
|
process_id: string;
|
||||||
|
current_process: {
|
||||||
|
states: ProcessState[];
|
||||||
|
};
|
||||||
|
states: ProcessState[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApiReturn {
|
||||||
|
updated_process?: Process;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AnkFlag {}
|
||||||
|
|
||||||
|
export interface Device {}
|
||||||
|
export interface HandshakeMessage {}
|
||||||
|
export interface Member {}
|
||||||
|
export interface MerkleProofResult {}
|
||||||
|
export interface OutPointProcessMap {}
|
||||||
|
export interface RoleDefinition {}
|
||||||
|
export interface SecretsStore {}
|
||||||
|
export interface UserDiff {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
59
tests/config.test.ts
Normal file
59
tests/config.test.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
|
||||||
|
// Helper pour recharger le module avec de nouvelles variables d'env
|
||||||
|
async function loadConfig() {
|
||||||
|
const modulePath = '../src/config';
|
||||||
|
// Vitest supporte l'invalidation via import dynamique après resetModules
|
||||||
|
const mod = await import(modulePath);
|
||||||
|
return (mod.loadConfig as typeof import('../src/config').loadConfig)();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('config', () => {
|
||||||
|
const envBackup = { ...process.env };
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
process.env = { ...envBackup };
|
||||||
|
delete process.env.PORT;
|
||||||
|
delete process.env.API_KEY;
|
||||||
|
delete process.env.DATABASE_PATH;
|
||||||
|
delete process.env.RELAY_URLS;
|
||||||
|
delete process.env.AUTO_RESTART;
|
||||||
|
delete process.env.MAX_RESTARTS;
|
||||||
|
delete process.env.LOG_LEVEL;
|
||||||
|
// @ts-ignore: vitest injecte resetModules via globalThis
|
||||||
|
if (typeof vi !== 'undefined') vi.resetModules();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('charge les valeurs par défaut', async () => {
|
||||||
|
const cfg = await loadConfig();
|
||||||
|
expect(cfg.port).toBe(9090);
|
||||||
|
expect(cfg.apiKey).toBe('your-api-key-change-this');
|
||||||
|
expect(cfg.databasePath).toBe('./data/server.db');
|
||||||
|
expect(cfg.relayUrls).toEqual(['ws://localhost:8090']);
|
||||||
|
expect(cfg.autoRestart).toBe(false);
|
||||||
|
expect(cfg.maxRestarts).toBe(10);
|
||||||
|
expect(cfg.logLevel).toBe('info');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('lit les variables d’environnement', async () => {
|
||||||
|
process.env.PORT = '1234';
|
||||||
|
process.env.API_KEY = 'k';
|
||||||
|
process.env.DATABASE_PATH = '/x.db';
|
||||||
|
process.env.RELAY_URLS = 'ws://a:1,ws://b:2';
|
||||||
|
process.env.AUTO_RESTART = 'true';
|
||||||
|
process.env.MAX_RESTARTS = '7';
|
||||||
|
process.env.LOG_LEVEL = 'debug';
|
||||||
|
// @ts-ignore
|
||||||
|
if (typeof vi !== 'undefined') vi.resetModules();
|
||||||
|
const cfg = await loadConfig();
|
||||||
|
expect(cfg.port).toBe(1234);
|
||||||
|
expect(cfg.apiKey).toBe('k');
|
||||||
|
expect(cfg.databasePath).toBe('/x.db');
|
||||||
|
expect(cfg.relayUrls).toEqual(['ws://a:1', 'ws://b:2']);
|
||||||
|
expect(cfg.autoRestart).toBe(true);
|
||||||
|
expect(cfg.maxRestarts).toBe(7);
|
||||||
|
expect(cfg.logLevel).toBe('debug');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
21
tests/utils.test.ts
Normal file
21
tests/utils.test.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { isValid32ByteHex, EMPTY32BYTES } from '../src/utils';
|
||||||
|
|
||||||
|
describe('utils', () => {
|
||||||
|
it('valide un hex 32 octets', () => {
|
||||||
|
const ok = 'a'.repeat(64);
|
||||||
|
expect(isValid32ByteHex(ok)).toBe(true);
|
||||||
|
});
|
||||||
|
it('rejette une longueur incorrecte', () => {
|
||||||
|
const bad = 'a'.repeat(63);
|
||||||
|
expect(isValid32ByteHex(bad)).toBe(false);
|
||||||
|
});
|
||||||
|
it('rejette des caractères non-hex', () => {
|
||||||
|
const bad = 'g'.repeat(64);
|
||||||
|
expect(isValid32ByteHex(bad)).toBe(false);
|
||||||
|
});
|
||||||
|
it('EMPTY32BYTES a bien 64 caractères hex', () => {
|
||||||
|
expect(EMPTY32BYTES.length).toBe(64);
|
||||||
|
expect(isValid32ByteHex(EMPTY32BYTES)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user