@offscript/sdk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -2
- package/dist/adapters/nuxt.cjs +16 -0
- package/dist/adapters/nuxt.cjs.map +1 -0
- package/dist/adapters/nuxt.d.ts +10 -0
- package/dist/adapters/nuxt.js +14 -0
- package/dist/adapters/nuxt.js.map +1 -0
- package/dist/adapters/vanilla.cjs +18 -0
- package/dist/adapters/vanilla.cjs.map +1 -0
- package/dist/adapters/vanilla.d.ts +6 -0
- package/dist/adapters/vanilla.js +5 -0
- package/dist/adapters/vanilla.js.map +1 -0
- package/dist/adapters/vue.cjs +24 -0
- package/dist/adapters/vue.cjs.map +1 -0
- package/dist/adapters/vue.d.ts +18 -0
- package/dist/adapters/vue.js +21 -0
- package/dist/adapters/vue.js.map +1 -0
- package/dist/chunk-3NX2AGXM.cjs +2671 -0
- package/dist/chunk-3NX2AGXM.cjs.map +1 -0
- package/dist/chunk-3OSCH7J2.js +2658 -0
- package/dist/chunk-3OSCH7J2.js.map +1 -0
- package/dist/chunk-B6GO5FE5.cjs +442 -0
- package/dist/chunk-B6GO5FE5.cjs.map +1 -0
- package/dist/chunk-HAPNSHFG.cjs +20 -0
- package/dist/chunk-HAPNSHFG.cjs.map +1 -0
- package/dist/chunk-LFXHB4PN.js +426 -0
- package/dist/chunk-LFXHB4PN.js.map +1 -0
- package/dist/chunk-MBYNQSKA.js +17 -0
- package/dist/chunk-MBYNQSKA.js.map +1 -0
- package/dist/core/ApiClient.d.ts +24 -0
- package/dist/core/LifecycleManager.d.ts +26 -0
- package/dist/core/OffscriptSDK.d.ts +98 -0
- package/dist/core/SessionManager.d.ts +44 -0
- package/dist/core/config.d.ts +2 -0
- package/dist/index.cjs +98 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/playwright/ActionNormalizer.d.ts +37 -0
- package/dist/playwright/PlaywrightDataContract.d.ts +88 -0
- package/dist/playwright/SelectorGenerator.d.ts +26 -0
- package/dist/playwright/index.d.ts +3 -0
- package/dist/playwright.cjs +56 -0
- package/dist/playwright.cjs.map +1 -0
- package/dist/playwright.js +3 -0
- package/dist/playwright.js.map +1 -0
- package/dist/privacy/DataSanitizer.d.ts +32 -0
- package/dist/privacy/PrivacyConfig.d.ts +4 -0
- package/dist/recorders/ActionRecorder.d.ts +46 -0
- package/dist/recorders/ContextRecorder.d.ts +23 -0
- package/dist/recorders/ErrorRecorder.d.ts +20 -0
- package/dist/recorders/HTTPRecorder.d.ts +28 -0
- package/dist/recorders/IframeRecorder.d.ts +19 -0
- package/dist/recorders/RRWebRecorder.d.ts +29 -0
- package/dist/recorders/types.d.ts +25 -0
- package/dist/transport/EventQueue.d.ts +28 -0
- package/dist/transport/EventTransport.d.ts +84 -0
- package/dist/transport/PersistentBuffer.d.ts +60 -0
- package/dist/transport/RetryManager.d.ts +9 -0
- package/dist/types/config.d.ts +115 -0
- package/dist/types/events.d.ts +185 -0
- package/dist/types/session.d.ts +77 -0
- package/dist/utils/errors.d.ts +41 -0
- package/dist/utils/id.d.ts +1 -0
- package/dist/utils/misc.d.ts +20 -0
- package/docs/api-contract.md +56 -0
- package/docs/architecture.md +38 -0
- package/docs/event-contract.md +26 -0
- package/docs/playwright-contract.md +39 -0
- package/package.json +78 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const now: () => number;
|
|
2
|
+
export declare function safe<T>(fn: () => T, fallback?: T): T | undefined;
|
|
3
|
+
export declare function throttle<A extends unknown[]>(fn: (...a: A) => void, ms: number): ((...a: A) => void) & {
|
|
4
|
+
cancel(): void;
|
|
5
|
+
};
|
|
6
|
+
export declare function debounce<A extends unknown[]>(fn: (...a: A) => void, ms: number): ((...a: A) => void) & {
|
|
7
|
+
cancel(): void;
|
|
8
|
+
flush(): void;
|
|
9
|
+
};
|
|
10
|
+
/** Estimativa barata do tamanho serializado (bytes ≈ chars). */
|
|
11
|
+
export declare function approxSize(value: unknown): number;
|
|
12
|
+
export declare function deepMerge<T extends object>(base: T, patch?: Partial<T>): T;
|
|
13
|
+
export type Listener = () => void;
|
|
14
|
+
/** Registro de listeners com remoção em lote. */
|
|
15
|
+
export declare class Disposer {
|
|
16
|
+
private fns;
|
|
17
|
+
add(fn: Listener): void;
|
|
18
|
+
listen(target: EventTarget, type: string, handler: (e: any) => void, opts?: boolean | AddEventListenerOptions): void;
|
|
19
|
+
dispose(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Contrato da API Offscript (SDK ↔ backend)
|
|
2
|
+
|
|
3
|
+
Todos os endpoints exigem `Authorization: Bearer <sessionToken>` (token de curta duração, escopo: plataforma + execução + sessão). Respostas em JSON. CORS: o backend deve permitir os headers `Authorization, Content-Type, Content-Encoding, Idempotency-Key, X-Offscript-Sdk` (um `*` **não** cobre `Authorization`).
|
|
4
|
+
|
|
5
|
+
| Método | Caminho | Finalidade |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| POST | `/sdk/sessions` | Cria (ou obtém, idempotente por `executionId`) a sessão |
|
|
8
|
+
| POST | `/sdk/sessions/{id}/events` | Recebe um lote de eventos |
|
|
9
|
+
| POST | `/sdk/sessions/{id}/heartbeat` | Mantém a sessão viva; informa desativação remota |
|
|
10
|
+
| POST | `/sdk/sessions/{id}/complete` | Encerra a sessão |
|
|
11
|
+
| GET | `/sdk/sessions/{id}/status` | Estado da sessão (usado ao retomar após reload) |
|
|
12
|
+
|
|
13
|
+
## POST /sdk/sessions
|
|
14
|
+
Request: `{ platformId, testCaseId, executionId, tabId, sdkVersion, appVersion?, context }`
|
|
15
|
+
|
|
16
|
+
Response `200`:
|
|
17
|
+
```json
|
|
18
|
+
{ "sessionId": "ses_1", "recording": { "enabled": true, "reason": null },
|
|
19
|
+
"expiresAt": 1790000000000, "heartbeatIntervalMs": 30000,
|
|
20
|
+
"sessionToken": "(opcional) token renovado",
|
|
21
|
+
"limits": { "maxBatchBytes": 524288, "maxBatchEvents": 200 } }
|
|
22
|
+
```
|
|
23
|
+
Se `recording.enabled = false` o SDK **não grava** e lança `SessionDisabledError`.
|
|
24
|
+
O backend deve validar que a plataforma, o caso de teste e a execução pertencem ao escopo do token.
|
|
25
|
+
|
|
26
|
+
## POST /sdk/sessions/{id}/events
|
|
27
|
+
Headers: `Idempotency-Key: <batchId>`; opcionalmente `Content-Encoding: gzip` (se `transport.compress`).
|
|
28
|
+
|
|
29
|
+
Body (`EventBatch`):
|
|
30
|
+
```json
|
|
31
|
+
{ "schemaVersion": "1.0", "batchId": "ses_1.tab_x.1-200.200", "sessionId": "ses_1",
|
|
32
|
+
"executionId": "exec", "tabId": "tab_x", "sequenceStart": 1, "sequenceEnd": 200,
|
|
33
|
+
"createdAt": 1790000000000, "sdkVersion": "0.1.0", "events": [ /* OffscriptEvent */ ] }
|
|
34
|
+
```
|
|
35
|
+
Response `200`: `{ "batchId": "...", "accepted": 200, "duplicate": false, "persistedThrough": 200 }`
|
|
36
|
+
|
|
37
|
+
Requisitos do backend:
|
|
38
|
+
- **Idempotência**: deduplicar por `event.id` (e/ou `batchId`). Reenvios devem responder `200` com `duplicate: true`. O SDK reenvia lotes que não recebeu ACK, inclusive após reload e após o envio `keepalive` do encerramento da página.
|
|
39
|
+
- **Ordenação lógica**: chunk por `(sessionId, tabId, sequenceStart)`; a ordem canônica é `(tabId, sequence)`; eventos podem chegar fora de ordem.
|
|
40
|
+
- Armazenar em múltiplos chunks (um registro por lote), nunca um JSON único por sessão.
|
|
41
|
+
- Códigos: `401/403` → `AuthError` (SDK para e vai para `error`); `410` → `SessionExpiredError`; `413` → o SDK divide o lote e reenvia; `408/429/5xx` e falhas de rede → retry com backoff exponencial + jitter (respeita `Retry-After`); outros `4xx` não são reenviados.
|
|
42
|
+
- Rate limiting e validação de payload (`schemaVersion`, tamanhos, sequências) são responsabilidade do backend.
|
|
43
|
+
|
|
44
|
+
## POST /sdk/sessions/{id}/heartbeat
|
|
45
|
+
Request: `{ tabId, pageId, status, pending, lastSequence }` → Response: `{ "status": "active" | "disabled" | "expired", "sessionToken"?, "expiresAt"? }`.
|
|
46
|
+
`disabled` = desativação remota: o SDK faz flush de melhor esforço, para e emite `disabled`. `expired` → `SessionExpiredError`.
|
|
47
|
+
|
|
48
|
+
## POST /sdk/sessions/{id}/complete
|
|
49
|
+
Request: `{ tabId, lastSequence, eventCount, pages }` → Response: `{ "completed": true }`.
|
|
50
|
+
|
|
51
|
+
## GET /sdk/sessions/{id}/status
|
|
52
|
+
Response: `{ "status": "active" | "disabled" | "expired", "sessionToken"?, "expiresAt"? }`.
|
|
53
|
+
|
|
54
|
+
## Retenção / LGPD
|
|
55
|
+
- Local: eventos não confirmados ficam no IndexedDB até o ACK ou até `privacy.localRetentionMs` (24 h por padrão); ao encerrar com sucesso o buffer da sessão é apagado.
|
|
56
|
+
- Servidor: a política de retenção, base legal e direito de exclusão são do backend; o SDK só envia dados já sanitizados e permite desativação remota via `recording.enabled`/`heartbeat`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Decisões de arquitetura
|
|
2
|
+
|
|
3
|
+
## Contexto do repositório
|
|
4
|
+
O repositório `soffact/offscript-sdk` estava **vazio** (nenhum painel, backend, tabela, endpoint ou player). Portanto:
|
|
5
|
+
- o SDK foi criado como pacote independente (`packages/offscript-sdk`), sem acoplamento a framework;
|
|
6
|
+
- não existe backend a reutilizar: os contratos HTTP estão em [api-contract.md](./api-contract.md) e há um **servidor de referência** (`tests/helpers/referenceServer.ts`) que implementa esse contrato para testar o cliente de ponta a ponta. Ele **não** substitui o backend real da Offscript, que precisa implementar o mesmo contrato.
|
|
7
|
+
|
|
8
|
+
## Dois fluxos independentes
|
|
9
|
+
```
|
|
10
|
+
Session Manager + autorização
|
|
11
|
+
├─ Visual Recorder (rrweb: DOM, snapshots, mutações) → replay histórico
|
|
12
|
+
├─ Semantic Recorder (ações + seletores + contexto) → Playwright futuro
|
|
13
|
+
├─ Observability (HTTP, console, erros, iframes)
|
|
14
|
+
└─ Event Transport → API Offscript (lotes idempotentes, IndexedDB, retry)
|
|
15
|
+
```
|
|
16
|
+
- `RRWebRecorder` nunca produz ações; `ActionRecorder` nunca lê eventos rrweb. Ambos só falam com o núcleo via `EventSink.emit(kind, data)`.
|
|
17
|
+
- Eventos brutos (`action`) ≠ passos normalizados (`ActionNormalizer`) ≠ contrato Playwright (`PlaywrightDataContract`). A normalização é função pura e roda fora do caminho de captura (no navegador via `exportPlaywrightData()` ou no backend com `buildPlaywrightContract`).
|
|
18
|
+
|
|
19
|
+
## Envelope e ordenação
|
|
20
|
+
Todo evento tem `(sessionId, tabId, sequence, timestamp, pageId)`. A sequência é monotônica **por aba**, persistida em `sessionStorage` a cada evento, e continua entre páginas (MPA). O `id` do evento é `${tabId}:${sequence}` — determinístico, o que torna reenvios idempotentes. Entre abas a ordenação é por `timestamp`.
|
|
21
|
+
|
|
22
|
+
## Política multi-aba
|
|
23
|
+
Cada aba grava de forma independente na **mesma sessão/execução**, com `tabId` e sequência próprios. O estado da sessão fica em `sessionStorage` (escopo de aba). Abas abertas por `window.open` herdam uma cópia do `sessionStorage`; quando `navigator.locks` existe, um Web Lock por `tabId` detecta o clone e atribui um novo `tabId`.
|
|
24
|
+
|
|
25
|
+
## Segurança por padrão
|
|
26
|
+
- Token de sessão de **curta duração**, emitido pelo backend; o SDK nunca recebe chaves administrativas. O token vai em `Authorization: Bearer` com `credentials: "omit"`.
|
|
27
|
+
- Sanitização **antes** de qualquer persistência (IndexedDB) ou envio — inclusive atributos de URL e textos dentro dos eventos rrweb.
|
|
28
|
+
- Valores digitados viram `valueRef` (referência opaca com sal por aba), exceto campos na allowlist (`data-offscript-allow`). Senhas nunca.
|
|
29
|
+
- Bodies HTTP desligados por padrão.
|
|
30
|
+
|
|
31
|
+
## Transporte
|
|
32
|
+
- Fila em memória (staging) → IndexedDB (`PersistentBuffer`, com fallback para memória) → lotes por aba.
|
|
33
|
+
- Um evento só sai do buffer depois do ACK do backend (`200` com o `batchId`).
|
|
34
|
+
- Backpressure por prioridade: `low` (mousemove, scroll, console) é descartado antes de `normal` e `critical` (snapshots rrweb, lifecycle). Se incrementais do rrweb forem descartados, o SDK força novo snapshot completo assim que houver folga.
|
|
35
|
+
- Encerramento da página: `pagehide` → evento `page-end` + `fetch(..., {keepalive:true})` do que ainda está em staging (≤ 60 KB). **Não há ACK nesse caminho**; os eventos continuam no IndexedDB e são reenviados na próxima página (idempotente). `sendBeacon` não é usado porque não permite o header `Authorization`.
|
|
36
|
+
|
|
37
|
+
## Carregamento sob demanda
|
|
38
|
+
`rrweb` é carregado com `import("rrweb")` apenas quando `recording.rrweb` está ligado; o pacote tem `sideEffects: false` e entradas separadas para adaptadores e para o contrato Playwright.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Contrato de eventos (schemaVersion 1.0)
|
|
2
|
+
|
|
3
|
+
Envelope (`OffscriptEvent`): `id`, `kind`, `sessionId`, `executionId`, `tabId`, `pageId`, `sequence`, `timestamp`, `relatedActionId?`, `relatedActionDeltaMs?`, `data`.
|
|
4
|
+
|
|
5
|
+
`relatedActionId` liga `http`, `console`, `error` e `iframe` à ação mais recente do usuário dentro de `correlationWindowMs` (3 s por padrão). Para `http`, o `timestamp` é o **início** da requisição.
|
|
6
|
+
|
|
7
|
+
| kind | `data` | Observações |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `rrweb` | evento rrweb nativo (`type`: 2 snapshot, 3 incremental, 4 meta…) | URLs em atributos e textos sensíveis redigidos. Um `type 2` abre cada página. |
|
|
10
|
+
| `action` | `RecordedAction` | `schemaVersion` próprio (`ACTION_SCHEMA_VERSION`), `sequence` = sequência do envelope |
|
|
11
|
+
| `http` | `HttpEventData` | um evento por requisição, na conclusão |
|
|
12
|
+
| `console` | `ConsoleEventData` | níveis configuráveis; argumentos serializados e sanitizados |
|
|
13
|
+
| `error` | `ErrorEventData` | `window.onerror`, `unhandledrejection`, falha de recurso |
|
|
14
|
+
| `context` | `ContextEventData` | `reason`: `page-load`, `viewport`, `navigation`… |
|
|
15
|
+
| `iframe` | `IframeEventData` | presença/geometria/foco; **sem** conteúdo interno |
|
|
16
|
+
| `lifecycle` | `LifecycleEventData` | `session-start/resume`, `page-start/end`, `pause/resume`, `stop`, `navigation`, `recorder-error` |
|
|
17
|
+
|
|
18
|
+
Tipos completos: `src/types/events.ts`. Alterações compatíveis (campos opcionais novos) mantêm `1.x`; remoção/renomeação exige `2.0`.
|
|
19
|
+
|
|
20
|
+
## Ações (`RecordedAction.type`)
|
|
21
|
+
`click`, `dblclick`, `hover` (`payload.phase`: enter/leave), `mousemove` (trajetória amostrada; desligado por padrão), `drag`, `input`, `keydown` (somente teclas relevantes: Enter, Esc, Tab, setas, F-keys, atalhos com Ctrl/Meta/Alt), `select`, `check`, `scroll` (from/to), `navigate`, `reload`, `focus`, `blur`.
|
|
22
|
+
|
|
23
|
+
Valores de `input` **não** são gravados por padrão: `payload = { valueCaptured: false, valueRef, length, fieldType }`. Em campos com `data-offscript-allow` (ou seletor em `privacy.allowedInputSelectors`): `{ valueCaptured: true, value }`. Senhas nunca.
|
|
24
|
+
|
|
25
|
+
## Seletores
|
|
26
|
+
`selector` é o primeiro candidato único na ordem: `testid` → `attribute` (name/data-id) → `role` (`role=button[name="Salvar"]`) → `label` → `placeholder` → `id` estável → `css` estrutural. Todos os candidatos são enviados em `selectorCandidates` com `unique`/`matches` no momento da ação. Classes geradas (CSS-in-JS, hashes) e ids dinâmicos são ignorados.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Playwright Data Contract (v1.0)
|
|
2
|
+
|
|
3
|
+
O SDK **não executa Playwright**. Ele produz, a partir das ações gravadas, um documento versionado para um serviço externo converter em testes. Uma reprodução bem-sucedida **não** significa aprovação: as assertions pertencem aos casos de teste no painel.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { buildPlaywrightContract, validatePlaywrightContract } from "@offscript/sdk/playwright"; // sem puxar o runtime de gravação
|
|
7
|
+
const contract = buildPlaywrightContract({ session, actions, contexts }); // backend ou navegador
|
|
8
|
+
validatePlaywrightContract(contract); // [] = válido
|
|
9
|
+
// ou, no navegador, com as ações da página atual:
|
|
10
|
+
offscript.exportPlaywrightData();
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```jsonc
|
|
14
|
+
{
|
|
15
|
+
"contractVersion": "1.0", "kind": "offscript.playwright-recording",
|
|
16
|
+
"session": { "sessionId", "executionId", "testCaseId", "platformId" },
|
|
17
|
+
"initialConditions": { "url", "viewport", "userAgent", "language", "timezone", "deviceScaleFactor", "browser" },
|
|
18
|
+
"steps": [{
|
|
19
|
+
"index": 0, "type": "click|dblclick|fill|press|select|check|uncheck|hover|drag|scroll|navigate|reload",
|
|
20
|
+
"timestamp": 1790000000000, "waitBeforeMs": 420, "url": "…",
|
|
21
|
+
"selector": "role=button[name=\"Salvar\"]", "selectorUnique": true,
|
|
22
|
+
"selectorCandidates": [{ "strategy": "testid", "selector": "[data-testid=\"save\"]", "unique": true, "matches": 1 }],
|
|
23
|
+
"element": { "tag": "button", "role": "button", "name": "Salvar", "testId": "save" },
|
|
24
|
+
"args": { "value": "…" } /* ou { "valueRef", "valueCaptured": false } */,
|
|
25
|
+
"expectsNavigation": { "to": "https://app/x" },
|
|
26
|
+
"sourceActionIds": ["tab_x:12"], "causedByActionId": "…"
|
|
27
|
+
}],
|
|
28
|
+
"stats": { "rawActions": 40, "steps": 14, "merged": 26 },
|
|
29
|
+
"limitations": ["…"], "extensions": {}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Normalização (`ActionNormalizer`)
|
|
34
|
+
`click,click,dblclick` → `dblclick` · `click` + `check` → `check/uncheck` · vários `input` no mesmo campo → um `fill` · `keydown` → `press` (`Control+s`) · scrolls consecutivos → um `scroll` · `navigate` logo após um clique/Enter → `expectsNavigation` do passo causador · `focus`, `blur`, `mousemove` e `hover` isolado são descartados (permanecem nos eventos brutos). Cada passo mantém `sourceActionIds` para rastreabilidade.
|
|
35
|
+
|
|
36
|
+
## O que o motor externo deve fazer
|
|
37
|
+
Resolver seletores (tentando `selectorCandidates` em ordem), pedir valores para `valueRef` (campos não autorizados não são reproduzíveis), aplicar esperas inteligentes (`waitBeforeMs` é só dica), validar assertions do caso de teste e produzir o resultado de regressão.
|
|
38
|
+
|
|
39
|
+
Versionamento: `contractVersion` `MAJOR.MINOR`; `validatePlaywrightContract` recusa `MAJOR` diferente.
|
package/package.json
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@offscript/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Offscript SDK - grava\u00e7\u00e3o de sess\u00f5es de teste QA (rrweb, a\u00e7\u00f5es, rede, erros)",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./vue": {
|
|
18
|
+
"types": "./dist/adapters/vue.d.ts",
|
|
19
|
+
"import": "./dist/adapters/vue.js",
|
|
20
|
+
"require": "./dist/adapters/vue.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./nuxt": {
|
|
23
|
+
"types": "./dist/adapters/nuxt.d.ts",
|
|
24
|
+
"import": "./dist/adapters/nuxt.js",
|
|
25
|
+
"require": "./dist/adapters/nuxt.cjs"
|
|
26
|
+
},
|
|
27
|
+
"./vanilla": {
|
|
28
|
+
"types": "./dist/adapters/vanilla.d.ts",
|
|
29
|
+
"import": "./dist/adapters/vanilla.js",
|
|
30
|
+
"require": "./dist/adapters/vanilla.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./playwright": {
|
|
33
|
+
"types": "./dist/playwright/index.d.ts",
|
|
34
|
+
"import": "./dist/playwright.js",
|
|
35
|
+
"require": "./dist/playwright.cjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md",
|
|
41
|
+
"docs"
|
|
42
|
+
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup && tsc -p tsconfig.build.json",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build",
|
|
49
|
+
"test:e2e": "node e2e/build.mjs && playwright test",
|
|
50
|
+
"verify": "npm run typecheck && npm test && npm run build && npm run test:e2e"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"rrweb": "^2.0.0-alpha.18"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@playwright/test": "^1.64.1",
|
|
57
|
+
"@types/node": "^26.6.5",
|
|
58
|
+
"esbuild": "^0.28.2",
|
|
59
|
+
"fake-indexeddb": "^6.2.6",
|
|
60
|
+
"jsdom": "^30.1.3",
|
|
61
|
+
"tsup": "^9.0.0",
|
|
62
|
+
"tsx": "^4.23.15",
|
|
63
|
+
"typescript": "^7.0.2",
|
|
64
|
+
"vitest": "^5.0.5"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=18"
|
|
71
|
+
},
|
|
72
|
+
"repository": {
|
|
73
|
+
"type": "git",
|
|
74
|
+
"url": "git+https://github.com/soffact/offscript-sdk.git",
|
|
75
|
+
"directory": "packages/offscript-sdk"
|
|
76
|
+
},
|
|
77
|
+
"bugs": {
|
|
78
|
+
"url": "https://github.com/soffact/offscript-sdk/issues"
|
|
79
|
+
},
|
|
80
|
+
"homepage": "https://github.com/soffact/offscript-sdk#readme"
|
|
6
81
|
}
|