Each startSync request takes the Postgres advisory lock on its own
connection (its own session), so it already refuses concurrent calls on
the same instance: the in-process syncInProgress flag and its
isSyncInProgress getter were redundant and are removed. syncAll becomes
private: syncs start only through startSync.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Validate the environment at startup (src/config): required variables
must be present, HIBOUTIK_BASE_URL must be HTTPS.
- Global ValidationPipe (whitelist, forbidNonWhitelisted, transform).
- Helmet, CORS disabled unless CORS_ORIGINS is set, TRUST_PROXY support,
HTTP header/request timeouts, shutdown hooks.
- Rate limiting: 60 req/min/IP globally, 5 req/min on POST /sync.
- AllExceptionsFilter: unexpected errors are logged (message + stack,
never the raw error object) and answered with a generic 500.
- Postgres advisory lock (dedicated connection) so only one
synchronization runs at a time across all instances; released by
Postgres itself if the process dies.
- Fix the Jest moduleNameMapper (unescaped dot also matched .cjs files).
- Document the input validation and security rules in CLAUDE.md.
- Add class-validator, class-transformer, helmet and @nestjs/throttler;
npm audit fix refreshed package-lock.json.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A successful (2xx) answer from Hiboutik is now the truth, even an empty
list: records missing from it are deleted. The "empty list means API
issue" safety nets are removed.
Deletion stays safe because a failed call deletes nothing: HTTP errors
throw, and the new HiboutikClient.getList (used by getAllPages and the
non-paginated lists) also throws on a 2xx body that is not a list, so a
malformed answer is never mistaken for an empty list. A 2xx without body
is an empty list.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
## Summary
- Add `CLAUDE.md`: project description (K-pop shop backend, buffer in front of Hiboutik), architecture, domain notes, git workflow.
- Add shared `.claude/settings.json` (allowed dev commands, `.env` read protection).
- Pin the Prisma agent skills in `skills-lock.json` (restore with `npx skills experimental_install`, documented in the README).
- Update `.gitignore` (generated skills, local settings, Postman skills) and add `.gitattributes` (LF line endings).
## Note
This branch is based on `feat/customer-addresses-orders`, so the PR also contains the 3 feature commits (addresses, company details, orders) that `CLAUDE.md` describes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: MastersGame <quentin.duwa1210@gmail.com>
Reviewed-on: #2
POST /sync starts the full synchronization in the background (202, or 409 when one is already running). Entities are synced in dependency order: brands, categories, suppliers, products (with versions and stocks), customers. Each row is synced independently so that a failure is logged without stopping the rest. Replaces the default AppService.
Models mirror Hiboutik entities (categories tree, brands, suppliers, products and their versions, customers) plus addresses and orders for the upcoming sync. Every synced model is matched with Hiboutik through a unique hiboutikId. The generated client is ignored by git and env files other than .env.example are ignored.
Generate the Prisma client on postinstall. Jest now transpiles the ESM-only @nestjs/config and maps the .js imports of the generated Prisma client, in both the unit and e2e configurations.