chore(build): add switchable bytelyst package source
This commit is contained in:
parent
eac07dc3d9
commit
1bd0297066
1
.npmrc
1
.npmrc
@ -1,4 +1,5 @@
|
||||
@bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
||||
//gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN}
|
||||
# Used only when BYTELYST_PACKAGE_SOURCE=gitea.
|
||||
# Gitea returns Docker-internal tarball URLs (172.17.0.1:3300); rewrite host to the public URL
|
||||
replace-registry-host=always
|
||||
|
||||
116
.pnpmfile.cjs
Normal file
116
.pnpmfile.cjs
Normal file
@ -0,0 +1,116 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const PACKAGE_SCOPE = '@bytelyst/';
|
||||
const PACKAGE_SOURCE = process.env.BYTELYST_PACKAGE_SOURCE || 'vendor';
|
||||
const COMMON_PLAT_ROOT = process.env.BYTELYST_COMMON_PLAT_ROOT || '/opt/bytelyst/learning_ai_common_plat';
|
||||
const COMMON_PLAT_PACKAGES_ROOT = path.join(COMMON_PLAT_ROOT, 'packages');
|
||||
const VENDOR_PACKAGES_ROOT = path.join(__dirname, 'vendor', 'bytelyst');
|
||||
const VERSION_CACHE = new Map();
|
||||
let loggedSource = false;
|
||||
|
||||
function packageDirFor(name) {
|
||||
return name.startsWith(PACKAGE_SCOPE) ? name.slice(PACKAGE_SCOPE.length) : null;
|
||||
}
|
||||
|
||||
function pathIfPackageExists(rootDir, name) {
|
||||
const packageDir = packageDirFor(name);
|
||||
if (!packageDir) return null;
|
||||
|
||||
const candidate = path.join(rootDir, packageDir);
|
||||
return fs.existsSync(path.join(candidate, 'package.json')) ? candidate : null;
|
||||
}
|
||||
|
||||
function readPackageVersion(packagePath) {
|
||||
if (VERSION_CACHE.has(packagePath)) {
|
||||
return VERSION_CACHE.get(packagePath);
|
||||
}
|
||||
|
||||
try {
|
||||
const packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'));
|
||||
const version = packageJson.version || null;
|
||||
VERSION_CACHE.set(packagePath, version);
|
||||
return version;
|
||||
} catch {
|
||||
VERSION_CACHE.set(packagePath, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveRegistryVersion(name) {
|
||||
const commonPlatPath = pathIfPackageExists(COMMON_PLAT_PACKAGES_ROOT, name);
|
||||
if (commonPlatPath) {
|
||||
const version = readPackageVersion(commonPlatPath);
|
||||
if (version) return version;
|
||||
}
|
||||
|
||||
const vendorPath = pathIfPackageExists(VENDOR_PACKAGES_ROOT, name);
|
||||
if (vendorPath) {
|
||||
const version = readPackageVersion(vendorPath);
|
||||
if (version) return version;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveSpecifier(name) {
|
||||
if (!name.startsWith(PACKAGE_SCOPE)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (PACKAGE_SOURCE === 'common-plat') {
|
||||
const packagePath = pathIfPackageExists(COMMON_PLAT_PACKAGES_ROOT, name);
|
||||
return packagePath ? `file:${packagePath}` : null;
|
||||
}
|
||||
|
||||
if (PACKAGE_SOURCE === 'gitea') {
|
||||
const version = resolveRegistryVersion(name);
|
||||
return version ?? null;
|
||||
}
|
||||
|
||||
const vendorPath = pathIfPackageExists(VENDOR_PACKAGES_ROOT, name);
|
||||
if (vendorPath) {
|
||||
return `file:${vendorPath}`;
|
||||
}
|
||||
|
||||
const commonPlatPath = pathIfPackageExists(COMMON_PLAT_PACKAGES_ROOT, name);
|
||||
if (commonPlatPath) {
|
||||
return `file:${commonPlatPath}`;
|
||||
}
|
||||
|
||||
const version = resolveRegistryVersion(name);
|
||||
return version ?? null;
|
||||
}
|
||||
|
||||
function rewriteDependencySet(dependencies = {}) {
|
||||
for (const dependencyName of Object.keys(dependencies)) {
|
||||
const rewrittenSpecifier = resolveSpecifier(dependencyName);
|
||||
if (rewrittenSpecifier) {
|
||||
dependencies[dependencyName] = rewrittenSpecifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function logSourceOnce() {
|
||||
if (loggedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
loggedSource = true;
|
||||
process.stderr.write(
|
||||
`[bytelyst] pnpm package source=${PACKAGE_SOURCE} commonPlatRoot=${COMMON_PLAT_ROOT}\n`,
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hooks: {
|
||||
readPackage(packageJson) {
|
||||
logSourceOnce();
|
||||
rewriteDependencySet(packageJson.dependencies);
|
||||
rewriteDependencySet(packageJson.devDependencies);
|
||||
rewriteDependencySet(packageJson.optionalDependencies);
|
||||
rewriteDependencySet(packageJson.peerDependencies);
|
||||
return packageJson;
|
||||
},
|
||||
},
|
||||
};
|
||||
23
README.md
23
README.md
@ -23,7 +23,7 @@ web dashboard, and Expo mobile app under a single pnpm workspace.
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm run install:common-plat
|
||||
cp .env.example .env # root — used by Docker Compose and CI
|
||||
cp backend/.env.example backend/.env # backend — fill in Cosmos, exchange, and AI credentials
|
||||
cp web/.env.example web/.env.local # web — Vite build-time API URLs
|
||||
@ -139,8 +139,25 @@ uses redacted URL helpers for any future FMP log output.
|
||||
|
||||
## Shared Dependencies
|
||||
|
||||
Common-platform packages are vendored from `../learning_ai_common_plat/packages/*`
|
||||
and linked via `vendor/` at install time. See `pnpm-workspace.yaml` for the link strategy.
|
||||
Package resolution is controlled by `BYTELYST_PACKAGE_SOURCE` through
|
||||
`.pnpmfile.cjs`.
|
||||
|
||||
- `vendor` (default): prefer `vendor/bytelyst/*`, then fall back to a local
|
||||
`learning_ai_common_plat` checkout if present, then registry versions.
|
||||
- `common-plat`: resolve `@bytelyst/*` directly from
|
||||
`/opt/bytelyst/learning_ai_common_plat/packages/*`.
|
||||
- `gitea`: resolve `@bytelyst/*` from the Gitea npm registry using
|
||||
`GITEA_NPM_TOKEN`.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
pnpm run install:common-plat
|
||||
pnpm run install:gitea
|
||||
pnpm run install:vendor
|
||||
```
|
||||
|
||||
Override the sibling repo location with `BYTELYST_COMMON_PLAT_ROOT=/path/to/learning_ai_common_plat`.
|
||||
|
||||
## Release Checklist
|
||||
|
||||
|
||||
@ -9,7 +9,9 @@ RUN corepack enable && corepack prepare pnpm@10.6.5 --activate
|
||||
WORKDIR /app
|
||||
|
||||
ARG GITEA_NPM_TOKEN
|
||||
ARG BYTELYST_PACKAGE_SOURCE=vendor
|
||||
ENV GITEA_NPM_TOKEN=${GITEA_NPM_TOKEN}
|
||||
ENV BYTELYST_PACKAGE_SOURCE=${BYTELYST_PACKAGE_SOURCE}
|
||||
|
||||
# Copy workspace root files first (layer cache)
|
||||
COPY .npmrc pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||
@ -36,7 +38,9 @@ RUN corepack enable && corepack prepare pnpm@10.6.5 --activate
|
||||
WORKDIR /app
|
||||
|
||||
ARG GITEA_NPM_TOKEN
|
||||
ARG BYTELYST_PACKAGE_SOURCE=vendor
|
||||
ENV GITEA_NPM_TOKEN=${GITEA_NPM_TOKEN}
|
||||
ENV BYTELYST_PACKAGE_SOURCE=${BYTELYST_PACKAGE_SOURCE}
|
||||
|
||||
COPY .npmrc pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||
COPY package.json ./package.json
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#
|
||||
# Both services mount local source directories so edits are reflected immediately
|
||||
# without rebuilding the image. Requires node_modules to exist locally
|
||||
# (run `pnpm install` at repo root first).
|
||||
# (run the matching root install first, for example `pnpm run install:common-plat`).
|
||||
|
||||
version: '3.9'
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#
|
||||
# Requires:
|
||||
# - backend/.env populated (copy from backend/.env.example)
|
||||
# - GITEA_NPM_TOKEN env var set for private @bytelyst/* registry build args
|
||||
# - GITEA_NPM_TOKEN env var set when BYTELYST_PACKAGE_SOURCE=gitea
|
||||
#
|
||||
# For hot-reload dev mode use:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up
|
||||
@ -21,6 +21,7 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/Dockerfile
|
||||
args:
|
||||
BYTELYST_PACKAGE_SOURCE: ${BYTELYST_PACKAGE_SOURCE:-vendor}
|
||||
GITEA_NPM_TOKEN: ${GITEA_NPM_TOKEN:-}
|
||||
container_name: invttrdg-backend
|
||||
env_file:
|
||||
@ -46,6 +47,7 @@ services:
|
||||
context: .
|
||||
dockerfile: web/Dockerfile
|
||||
args:
|
||||
BYTELYST_PACKAGE_SOURCE: ${BYTELYST_PACKAGE_SOURCE:-vendor}
|
||||
GITEA_NPM_TOKEN: ${GITEA_NPM_TOKEN:-}
|
||||
VITE_PRODUCT_ID: ${VITE_PRODUCT_ID:-invttrdg}
|
||||
VITE_PLATFORM_URL: ${VITE_PLATFORM_URL:-https://api.bytelyst.com/platform/api}
|
||||
|
||||
@ -46,16 +46,21 @@ doesn't reflect them yet**. The previous session installed those via
|
||||
issue, which left stray `web/package-lock.json` etc. — those are now
|
||||
git-ignored (commit `255bb07`).
|
||||
|
||||
**Action required before CI green**: on a workstation with
|
||||
`GITEA_NPM_TOKEN` exported, run:
|
||||
**Action required before CI green**: regenerate the root lockfile from a
|
||||
consistent package source, then commit the result. For a sibling
|
||||
`learning_ai_common_plat` checkout on this host, run:
|
||||
|
||||
```bash
|
||||
pnpm install -r --no-frozen-lockfile
|
||||
pnpm run install:common-plat -- --no-frozen-lockfile
|
||||
git add pnpm-lock.yaml
|
||||
git commit -m "chore(E2): regen root lockfile with new web deps"
|
||||
git push
|
||||
```
|
||||
|
||||
If you need the registry path instead, run
|
||||
`BYTELYST_PACKAGE_SOURCE=gitea pnpm install -r --no-frozen-lockfile` with
|
||||
`GITEA_NPM_TOKEN` exported.
|
||||
|
||||
This is **item E2** in `docs/AUDIT_REDESIGN.md`. CI will fail until it lands.
|
||||
|
||||
### 2. Pre-existing test failures (NOT my regressions)
|
||||
|
||||
@ -29,11 +29,14 @@ It covers:
|
||||
### Workspace bootstrap
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm run install:common-plat
|
||||
cp .env.example .env
|
||||
pnpm verify
|
||||
```
|
||||
|
||||
If you need the registry path instead, use `pnpm run install:gitea`. The active
|
||||
resolver is controlled by `BYTELYST_PACKAGE_SOURCE` in `.pnpmfile.cjs`.
|
||||
|
||||
### Core commands
|
||||
|
||||
```bash
|
||||
@ -60,9 +63,13 @@ pnpm docker:down
|
||||
|
||||
Prerequisites for Docker:
|
||||
- `.env` at repo root filled in (copy from `.env.example`)
|
||||
- `GITEA_NPM_TOKEN` set in `.env` for private `@bytelyst/*` registry
|
||||
- `GITEA_NPM_TOKEN` set when `BYTELYST_PACKAGE_SOURCE=gitea`
|
||||
- `VITE_PLATFORM_URL` and `VITE_TRADING_API_URL` set if not using localhost defaults
|
||||
- For dev mode: run `pnpm install` locally first (node_modules mounted as volume)
|
||||
- For dev mode: run the matching local install first (for example `pnpm run install:common-plat`)
|
||||
|
||||
Docker note: `common-plat` mode targets `/opt/bytelyst/learning_ai_common_plat`
|
||||
on the host, so container builds should stay on `vendor` or `gitea` unless the
|
||||
build context is expanded to include the sibling repo.
|
||||
|
||||
### Surface-specific commands
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ import { chatSuggestions } from '@/constants/mockData';
|
||||
import PressableScale from '@/components/PressableScale';
|
||||
import { useMobileAuth } from '@/providers/MobileAuthProvider';
|
||||
import { mobileRuntime } from '@/lib/runtime';
|
||||
import { createRequestId } from '../../../shared/request-id.js';
|
||||
import { createRequestId } from '../../shared/request-id.js';
|
||||
|
||||
interface ChatMessage {
|
||||
id: string;
|
||||
|
||||
@ -10,7 +10,7 @@ import PillBadge from '@/components/PillBadge';
|
||||
import PressableScale from '@/components/PressableScale';
|
||||
import { useMobileAuth } from '@/providers/MobileAuthProvider';
|
||||
import { mobileRuntime } from '@/lib/runtime';
|
||||
import { createRequestId } from '../../../shared/request-id.js';
|
||||
import { createRequestId } from '../../shared/request-id.js';
|
||||
|
||||
interface MarketplacePreset {
|
||||
id: string;
|
||||
|
||||
@ -52,7 +52,8 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "~19.1.10",
|
||||
"@types/react": "^19.2.0",
|
||||
"@types/react-dom": "^19.2.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-expo": "~10.0.0",
|
||||
"typescript": "~5.9.2"
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm --filter @bytelyst/trading-backend build && pnpm --filter @bytelyst/trading-web build && pnpm --filter @bytelyst/trading-mobile typecheck",
|
||||
"install:common-plat": "BYTELYST_PACKAGE_SOURCE=common-plat pnpm install -r",
|
||||
"install:gitea": "BYTELYST_PACKAGE_SOURCE=gitea pnpm install -r",
|
||||
"install:vendor": "BYTELYST_PACKAGE_SOURCE=vendor pnpm install -r",
|
||||
"lint": "pnpm --filter @bytelyst/trading-backend lint && pnpm --filter @bytelyst/trading-web lint && pnpm --filter @bytelyst/trading-mobile lint",
|
||||
"smoke:release": "sh ./scripts/smoke-release.sh",
|
||||
"test": "pnpm --filter @bytelyst/trading-backend test && pnpm --filter @bytelyst/trading-web test",
|
||||
@ -18,6 +21,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@bytelyst/kill-switch-client": "file:./vendor/bytelyst/kill-switch-client",
|
||||
"@bytelyst/react-native-platform-sdk": "^1.0.0",
|
||||
"@bytelyst/react-auth": "file:./vendor/bytelyst/react-auth",
|
||||
"@bytelyst/telemetry-client": "file:./vendor/bytelyst/telemetry-client"
|
||||
},
|
||||
|
||||
1525
pnpm-lock.yaml
generated
1525
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,9 @@ RUN corepack enable && corepack prepare pnpm@10.6.5 --activate
|
||||
WORKDIR /app
|
||||
|
||||
ARG GITEA_NPM_TOKEN
|
||||
ARG BYTELYST_PACKAGE_SOURCE=vendor
|
||||
ENV GITEA_NPM_TOKEN=${GITEA_NPM_TOKEN}
|
||||
ENV BYTELYST_PACKAGE_SOURCE=${BYTELYST_PACKAGE_SOURCE}
|
||||
|
||||
COPY .npmrc pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||
COPY package.json ./package.json
|
||||
|
||||
Loading…
Reference in New Issue
Block a user