|
|
1 месяц назад | |
|---|---|---|
| docs | 1 месяц назад | |
| migrations | 1 месяц назад | |
| scripts | 1 месяц назад | |
| src | 1 месяц назад | |
| test | 1 месяц назад | |
| .env.example | 1 месяц назад | |
| .gitignore | 1 месяц назад | |
| .nvmrc | 1 месяц назад | |
| README.md | 1 месяц назад | |
| TASKS.md | 1 месяц назад | |
| compose.yaml | 1 месяц назад | |
| package-lock.json | 1 месяц назад | |
| package.json | 1 месяц назад | |
| tsconfig.json | 1 месяц назад |
Independent backend template for the domestic ecommerce VOC product. The first case workspace is Demashi on JD. This repository does not connect to the cross-border production database and does not contain any Fmode, Parse, PostgreSQL, or supplier credential.
Completed through 2026-07-24:
GET /health database readiness check.POST /api/domestic-voc/sync idempotent manual-sync queue entry.GET /api/domestic-voc/jobs/:id sync-job status.GET /api/domestic-voc/snapshot response compatible with the frontend DomesticDataset interface.owner / admin / analyst / viewer authorization.Voc* class schemas, resumable bounded imports, direct count verification, and a Parse-backed sync worker.The current case resolves to 2,817 operating products, 37 mapped competitor products, 9,717 daily metrics, 40 relations, and 355 first-page competitor review samples. All 37 competitor product details and review requests were persisted through the company relay on 2026-07-24. The PostgreSQL importer may create internal relation_stub rows to preserve foreign keys; the Parse REST model stores denormalized relation identities and therefore does not create those extra catalog products.
The worker calls JD product-detail and review paths only through the company /api/voc-e-commerce gateway. It never sends a browser request to a supplier endpoint and never returns raw gateway errors or credentials.
Saas-voc frontend
-> saas-voc-server
-> shared API and authorization contract
-> local in-memory repository (development)
-> dedicated PostgreSQL repository (production, voc schema)
-> external Parse REST repository (shared development or managed Parse)
-> dedicated Parse application (production authentication)
-> sync queue
-> existing /api/voc-e-commerce gateway
The browser only calls this service. FMODE_API_KEY is used in the server-side Authorization header and is never returned to the browser or included in a request URL.
Registered JD gateway contracts:
GET /api/voc-e-commerce/jd/get-item-detail/v1?itemId={productId}
GET /api/voc-e-commerce/jd/get-item-comments/v1?itemId={productId}&page={page}
The first worker run defaults to one review page. JD_REVIEW_MAX_PAGES can raise the bounded limit after quota and response validation.
Use Node.js 22.13 or newer within the Node 22 release line. The repository intentionally pins Node 22 because Parse Server publishes explicit supported runtime ranges.
Required configuration is listed in .env.example. Empty secrets are rejected before the HTTP server starts. STORAGE_DRIVER=parse_rest requires the external Parse URL, application id, and master key but no direct database connection. STORAGE_DRIVER=postgres additionally requires DATABASE_URL, a maintenance key, and optionally a separate MIGRATION_DATABASE_URL. Never commit live credentials.
Use this mode when PostgreSQL is not exposed and the project must connect through an existing Parse Server REST API:
$env:STORAGE_DRIVER = 'parse_rest'
$env:PARSE_SERVER_URL = 'https://parse.example.com/parse'
$env:PARSE_APP_ID = '<application-id>'
$env:PARSE_MASTER_KEY = '<process-only-master-key>'
$env:API_AUTH_MODE = 'disabled' # isolated local development only
$env:FMODE_API_KEY = '<process-only-company-gateway-key>'
npm run bootstrap:parse-rest -- "E:\workspace\Saas-voc\src\assets\data\demashi-summary.json" demashi
npm run import:workbook:parse-rest -- "E:\path\to\德玛仕产品及竟品收集0721.xlsx" demashi
npm run sync:competitors:parse-rest -- demashi --concurrency=3 --reviews --review-pages=1
npm run verify:parse-rest -- demashi jd
npm run dev
The bootstrap command creates or reconciles 14 isolated Voc* classes, seeds the workspace/member/source records, imports the normalized case in request-size-bounded batches, and is idempotent for the same source hash and verified counts. The workbook command performs the same bounded import directly from Excel using a streaming reader. Competitor sync creates all mapped competitor records first, then skips already completed details on later runs. The verification command checks the schema set, class-level permissions, workspace/import readiness, exact own/competitor/detail counts, and denial of app-id-only reads. See docs/parse-rest-schema.md for the class contract.
The local demo runtime has no PostgreSQL, Parse, or gateway credential dependency. From this repository run:
npm ci
npm run start:local
It loads ../../Saas-voc/src/assets/data/demashi-summary.json by default and listens on http://127.0.0.1:4400. Override the source only when the repositories are stored elsewhere:
$env:LOCAL_DATASET_PATH = 'E:\path\to\demashi-summary.json'
npm run start:local
Local demo sync requests create queryable in-memory completion records that validate whether requested products exist in the packaged dataset. They do not collect external data or persist anything. Production collection and persistence remain in npm run dev.
Local mode injects the fixed local-admin owner. It is intentionally database-free and must not be internet-facing.
Set LOCAL_WORKSPACE_ID when using a packaged dataset under a workspace other than demashi; omitted API workspace ids then resolve to that configured default.
Local database:
$env:POSTGRES_PASSWORD = '<local-only-password>'
docker compose up -d postgres
The compose database listens only on 127.0.0.1:54329. A local DATABASE_URL therefore uses database saas_voc on port 54329.
Install, migrate, and run:
npm ci
npm run migrate
npm run dev
Import the current normalized case after migration:
npm run import:dataset -- "E:\workspace\Saas-voc\src\assets\data\demashi-summary.json"
001_initial_domain.sql creates the domestic VOC catalog and sync tables. 002_saas_platform.sql adds members, analysis runs, actions, alerts, and audit history. The migration runner records each file in voc.schema_migration and executes each unapplied migration in its own transaction.
Use API_AUTH_MODE=parse in production. API clients send either X-Parse-Session-Token or Authorization: Bearer <session-token>. The backend validates the session through PARSE_SERVER_URL/users/me and never sends a Parse master or maintenance key to the browser.
For the first production start, set SAAS_BOOTSTRAP_ADMIN_USER_ID to the Parse user object id and optionally set its email and display name. The service upserts that user as owner of SAAS_DEFAULT_WORKSPACE_ID. Clear the bootstrap variables after successful verification so a later restart cannot silently restore that account's owner role.
API_AUTH_MODE=disabled is available for isolated database-backed development only. It uses LOCAL_AUTH_USER_ID, LOCAL_AUTH_USER_EMAIL, and LOCAL_AUTH_USER_NAME, and must not be enabled in a public environment.
Default local API address:
http://127.0.0.1:4400
Queue a JD product and review sync:
POST /api/domestic-voc/sync
Idempotency-Key: optional-client-key
Content-Type: application/json
{
"workspaceId": "demashi",
"platform": "jd",
"productIds": ["11266507445"],
"scopes": ["product", "reviews"]
}
When Idempotency-Key is absent, the service derives a stable key from workspace, platform, products, scopes, and UTC date. The same daily request returns the same job.
Read status and frontend data:
GET /api/domestic-voc/jobs/{jobId}
POST /api/domestic-voc/jobs/{jobId}/retry
POST /api/domestic-voc/jobs/{jobId}/cancel
GET /api/domestic-voc/snapshot?workspaceId=demashi&platform=jd
Catalog and operational APIs:
GET /api/domestic-voc/products
GET /api/domestic-voc/products/{productId}
GET /api/domestic-voc/products/{productId}/reviews
GET /api/domestic-voc/relations
GET /api/domestic-voc/jobs
GET /api/domestic-voc/jobs/{jobId}/events
GET /api/saas/context
GET /api/saas/workspaces
GET|PUT /api/saas/workspaces/{workspaceId}/members[/userId]
GET /api/saas/workspaces/{workspaceId}/data-sources
GET /api/saas/workspaces/{workspaceId}/imports
GET|POST /api/saas/workspaces/{workspaceId}/analyses
GET|POST|PATCH /api/saas/workspaces/{workspaceId}/actions[/actionId]
GET|POST|PATCH /api/saas/workspaces/{workspaceId}/alerts[/alertId]
GET /api/saas/workspaces/{workspaceId}/audit
List endpoints use opaque cursor pagination (limit plus optional cursor). Analysis creation returns a truthful pending record; an analysis worker is not included yet.
An empty database returns a valid empty dataset. It does not invent reviews, ratings, sentiment, pain points, or AI output.
INSERT ... ON CONFLICT in batches.FOR UPDATE SKIP LOCKED.SYNC_JOB_STALE_AFTER_MS; exhausted jobs become failed and eligible jobs return to the queue.Voc* class schemas at startup through the schema REST API.When the dedicated database and server are available, no route or frontend contract rewrite is required:
DATABASE_URL to the least-privilege runtime role and MIGRATION_DATABASE_URL to the schema owner.PARSE_SERVER_URL, and API_AUTH_MODE=parse.CORS_ORIGINS.npm ci, npm run migrate, then npm run import:dataset -- <dataset-path>./health, /api/saas/context, snapshot totals, and one bounded sync job./parse and /api.parse-server@9.10.0 replaces the initially evaluated v8 line, removing all high and critical audit findings. A ws@8.21.0 override is retained because Parse currently pins an older vulnerable patch. The remaining 14 audit findings are moderate transitive dependencies in Parse push/Firebase and redirect support plus ExcelJS's nested UUID package; push and LiveQuery are not configured in this template. Re-run npm audit --omit=dev before each deployment and do not use npm audit fix --force, which currently proposes breaking Parse/ExcelJS downgrades.
npm run build
npm test
npm run verify:parse-rest -- demashi jd
npm audit --omit=dev
Current result:
11266507445; the adapter extracted the product id, title, and brand from the live double-data envelope.Voc* schemas present, master-key-only access confirmed, 2,817 own products, 37 competitor products with 37 details ready, 9,717 metrics, 40 relations, and 355 competitor reviews./health, SaaS context, full snapshot, frontend proxy, desktop navigation, and 390x844 responsive rendering passed against the Parse REST store.See TASKS.md for the implementation sequence and acceptance boundary.