chore: migrate to pnpm workspaces monorepo with Turborepo

- Restructure directories: apps/api, apps/admin, apps/website
- Add root pnpm-workspace.yaml, turbo.json, .prettierrc, .gitignore
- Rename packages to @inkreach/api, @inkreach/admin, @inkreach/website
- Add shared packages: packages/tsconfig, packages/shared-types
- Add pnpm.onlyBuiltDependencies for native builds
- Update docs: README.md, structs.md
- All three projects build successfully
This commit is contained in:
yeuimu
2026-07-11 16:54:05 +08:00
parent 69945b8749
commit 7e04877bb6
155 changed files with 20134 additions and 14393 deletions
+102
View File
@@ -0,0 +1,102 @@
import { Injectable, Logger } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { firstValueFrom } from 'rxjs';
const POD_HEADERS = {
'Content-Type': 'application/json;charset=UTF-8',
Origin: 'https://inkpod.vip',
Referer: 'https://inkpod.vip/',
} as const;
export interface SdsCategoryTreeNode {
id: number | string | null;
name?: string;
icon?: string;
children?: SdsCategoryTreeNode[];
[key: string]: unknown;
}
export interface SdsProduct {
id: number | string;
name?: string;
title?: string;
pic?: string;
image?: string;
psd_img_url?: string;
thumbImgUrl?: string;
blankDesignUrl?: string;
img_url?: string;
show_img?: string;
price?: number | string;
currentPrice?: number | string;
categoryId?: number | string;
[key: string]: unknown;
}
export interface SdsProductsPage {
items?: SdsProduct[];
content?: SdsProduct[];
totalCount?: number;
totalElements?: number;
total?: number;
page?: number;
size?: number;
[key: string]: unknown;
}
/**
* Thin wrapper around the SDS (mapi.sdspod.com) endpoints that the
* `SyncService` consumes.
*
* Exposed as its own service so it can be mocked cleanly in unit tests.
*/
@Injectable()
export class SdsClientService {
private readonly logger = new Logger(SdsClientService.name);
private readonly baseUrl: string;
constructor(
private readonly http: HttpService,
config: ConfigService,
) {
this.baseUrl =
config.get<string>('SDS_API_BASE')?.replace(/\/$/, '') ??
'https://mapi.sdspod.com';
}
/**
* Fetches the SDS category tree of type 3 (products category).
* Body matches the legacy inkpod client.
*/
async fetchCategoryTree(): Promise<SdsCategoryTreeNode[]> {
const url = `${this.baseUrl}/category/tree/3`;
const body = {
withActivityArea: true,
withPrivate: true,
onlyHaveProduct: true,
};
const { data } = await firstValueFrom(
this.http.post<SdsCategoryTreeNode[]>(url, body, { headers: POD_HEADERS }),
);
return Array.isArray(data) ? data : [];
}
/**
* Fetches one page of products for a given SDS category.
*/
async fetchProductsPage(
categoryId: string | number,
page = 1,
size = 50,
): Promise<SdsProductsPage> {
const url = `${this.baseUrl}/products/page`;
const { data } = await firstValueFrom(
this.http.get<SdsProductsPage>(url, {
headers: POD_HEADERS,
params: { categoryId, page, size },
}),
);
return data ?? {};
}
}