mirror of
https://github.com/sinanyuntu/trade-message-center.git
synced 2026-09-17 13:22:11 +08:00
docs: format OneTalk DOM card collection plan
This commit is contained in:
@@ -23,21 +23,32 @@
|
||||
### Task 1: DOM reader and legacy reader removal
|
||||
|
||||
**Files:**
|
||||
|
||||
- Create: `apps/chrome-extension/src/onetalk/main-page/card-observer/dom-card-reader.ts`
|
||||
- Delete: `apps/chrome-extension/src/onetalk/main-page/card-observer/react-card-reader.ts`
|
||||
- Modify: `apps/chrome-extension/src/onetalk/main-page/card-observer/entry.ts`
|
||||
- Test: `apps/chrome-extension/test/onetalk-rendered-card-reader.test.js`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Produces: `readOneTalkRenderedCardFromDom(pageWindow, card): OneTalkRenderedCardObservation | null`.
|
||||
- Consumes: `readConversationSelection`, `normalizeOneTalkProductUrl`, rendered-card validators and fingerprint creator.
|
||||
|
||||
- [ ] **Step 1: Replace Fiber fixtures with DOM fixtures and red tests.**
|
||||
|
||||
```js
|
||||
assert.equal(readOneTalkRenderedCardFromDom(page, cardWith({ cardMessageId: "m-1", wrapperMessageId: "m-2" })), null);
|
||||
assert.equal(
|
||||
readOneTalkRenderedCardFromDom(
|
||||
page,
|
||||
cardWith({ cardMessageId: "m-1", wrapperMessageId: "m-2" }),
|
||||
),
|
||||
null,
|
||||
);
|
||||
assert.equal(readOneTalkRenderedCardFromDom(page, quoteCard({ cardType: 8 })), null);
|
||||
assert.equal(readOneTalkRenderedCardFromDom(page, productCard({ rawUrl: "https://bad.example" })), null);
|
||||
assert.equal(
|
||||
readOneTalkRenderedCardFromDom(page, productCard({ rawUrl: "https://bad.example" })),
|
||||
null,
|
||||
);
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the focused reader test and confirm the missing DOM reader fails.**
|
||||
@@ -50,7 +61,8 @@ node --experimental-strip-types --test apps/chrome-extension/test/onetalk-render
|
||||
|
||||
```ts
|
||||
const messageId = cardMessageId ?? wrapperMessageId;
|
||||
if (!messageId || (cardMessageId && wrapperMessageId && cardMessageId !== wrapperMessageId)) return null;
|
||||
if (!messageId || (cardMessageId && wrapperMessageId && cardMessageId !== wrapperMessageId))
|
||||
return null;
|
||||
if (!sameOptionalConversation(cardInfo, wrapperInfo)) return null;
|
||||
```
|
||||
|
||||
@@ -59,8 +71,14 @@ Construct only exact `rendered_inquiry`, `rendered_product`, or `rendered_order`
|
||||
- [ ] **Step 4: Rewrite entry to scan cards and react only to DOM mutations.**
|
||||
|
||||
```ts
|
||||
for (const card of cardsForMutation(record)) publish(readOneTalkRenderedCardFromDom(pageWindow, card));
|
||||
observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-expinfo", "src", "style"] });
|
||||
for (const card of cardsForMutation(record))
|
||||
publish(readOneTalkRenderedCardFromDom(pageWindow, card));
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
attributeFilter: ["data-expinfo", "src", "style"],
|
||||
});
|
||||
```
|
||||
|
||||
Remove `setInterval`, wrapper rescans, React imports, and the deleted reader file.
|
||||
@@ -74,18 +92,23 @@ node --experimental-strip-types --test apps/chrome-extension/test/onetalk-render
|
||||
### Task 2: Remove Fiber-only base evidence from local boundaries
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `apps/chrome-extension/src/onetalk/page-bridge/{main.ts,model.ts}`
|
||||
- Modify: `apps/chrome-extension/src/onetalk/service-worker/{rendered-card-coordinator.ts,storage.ts}`
|
||||
- Test: `apps/chrome-extension/test/{onetalk-page-bridge,onetalk-rendered-card-coordinator,onetalk-sync-storage}.test.js`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- `onetalk.page.rendered-card-observed` contains `{ channelAccountId, observations }` only.
|
||||
- `OneTalkRenderedCardCoordinator.observe(observations)` persists and flushes observations without base evidence.
|
||||
|
||||
- [ ] **Step 1: Add bridge and ledger tests that accept an observation-only message and reject legacy base-evidence fields.**
|
||||
|
||||
```js
|
||||
assert.deepEqual(decodeOneTalkPageMessage({ source, version, type, channelAccountId, observations }), expected);
|
||||
assert.deepEqual(
|
||||
decodeOneTalkPageMessage({ source, version, type, channelAccountId, observations }),
|
||||
expected,
|
||||
);
|
||||
assert.equal("baseDirection" in pendingRecord, false);
|
||||
```
|
||||
|
||||
@@ -113,12 +136,14 @@ node --experimental-strip-types --test apps/chrome-extension/test/onetalk-page-b
|
||||
### Task 3: Remove approved server audit columns without data cleanup
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `apps/server/src/database/schema/onetalk.ts`
|
||||
- Modify: `apps/server/src/onetalk/rendered-card-{model,repository,service}.ts`
|
||||
- Create: generated `apps/server/drizzle/0015_*.sql` and matching `drizzle/meta` files
|
||||
- Test: `apps/server/test/onetalk-rendered-card-{migration,repository,flow}.test.ts`
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Stored row retains key, `renderedCardContent`, `renderedCardContentFingerprint`, `renderedCardObservedAtMs`, and `conflictCount`.
|
||||
- Same content stays duplicate; different content increments `conflictCount` and returns conflict without overwriting JSON.
|
||||
|
||||
@@ -157,6 +182,7 @@ pnpm --filter @trade-message-center/server db:check
|
||||
### Task 4: Contract-preserving integration verification
|
||||
|
||||
**Files:**
|
||||
|
||||
- Test: existing contract, read-projection, extension and server suites
|
||||
|
||||
- [ ] **Step 1: Add read projection regressions for all three base kinds and reject mismatched supplement kinds.**
|
||||
|
||||
Reference in New Issue
Block a user