@abyss-project/tools 1.2.0 → 1.4.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.
Files changed (34) hide show
  1. package/.eslintrc.js +33 -33
  2. package/.prettierrc +5 -5
  3. package/README.md +32 -32
  4. package/dist/api/beam.api.d.ts +2 -1
  5. package/dist/api/beam.api.js +10 -4
  6. package/dist/api/beam.api.js.map +1 -1
  7. package/dist/api/extraction.api.d.ts +5 -5
  8. package/dist/api/extraction.api.js +21 -4
  9. package/dist/api/extraction.api.js.map +1 -1
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.js +3 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/types/enum/beam.enum.d.ts +4 -0
  14. package/dist/types/enum/beam.enum.js +6 -1
  15. package/dist/types/enum/beam.enum.js.map +1 -1
  16. package/dist/types/interface/api/requests/beam.request.d.ts +17 -0
  17. package/dist/types/interface/api/requests/extraction.request.d.ts +12 -0
  18. package/dist/types/interface/api/responses/beam.response.d.ts +23 -1
  19. package/dist/types/interface/api/responses/extraction.response.d.ts +6 -0
  20. package/dist/types/interface/models/beam.dto.d.ts +13 -1
  21. package/dist/types/interface/models/extraction.dto.d.ts +10 -1
  22. package/dist/types/interface/models/extraction.dto.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/api/beam.api.ts +29 -4
  25. package/src/api/extraction.api.ts +57 -17
  26. package/src/api/tests/beam.api.spec.ts +64 -0
  27. package/src/index.ts +9 -0
  28. package/src/types/enum/beam.enum.ts +8 -0
  29. package/src/types/interface/api/requests/beam.request.ts +31 -3
  30. package/src/types/interface/api/requests/extraction.request.ts +28 -0
  31. package/src/types/interface/api/responses/beam.response.ts +30 -1
  32. package/src/types/interface/api/responses/extraction.response.ts +19 -2
  33. package/src/types/interface/models/beam.dto.ts +20 -1
  34. package/src/types/interface/models/extraction.dto.ts +31 -6
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  import { ExtractionMode, ExtractionFeedbackIssueType, ExtractionFeedbackStatus, ProcessingMode, IExtractionBankHint } from '../../models/extraction.dto';
4
+ import { DocumentType } from '../../../enum/document-type.enum';
4
5
  import type { IExtractionPlan } from '../../models/extraction-plan.dto';
5
6
  export interface IExtractionScopeQuery {
6
7
  organization_id?: string;
@@ -90,19 +91,30 @@ export interface IAsyncExportExtractionBody {
90
91
  format: 'csv' | 'json';
91
92
  delimiter?: ',' | ';' | '\t';
92
93
  }
94
+ export interface IListTemplatesQuery {
95
+ kind?: 'spatial' | 'dsl';
96
+ archived?: 'true' | 'false' | 'all';
97
+ document_type?: DocumentType;
98
+ }
93
99
  export interface ICreateTemplateBody {
94
100
  name: string;
95
101
  description?: string;
102
+ document_type?: DocumentType | null;
96
103
  template_json: Record<string, unknown>;
97
104
  comment?: string;
105
+ witness_pdf_base64?: string;
106
+ witness_filename?: string;
98
107
  }
99
108
  export interface IUpdateTemplateBody {
100
109
  template_json: Record<string, unknown>;
101
110
  comment?: string;
111
+ witness_pdf_base64?: string;
112
+ witness_filename?: string;
102
113
  }
103
114
  export interface IPatchTemplateMetaBody {
104
115
  name?: string;
105
116
  description?: string | null;
117
+ document_type?: DocumentType | null;
106
118
  is_active?: boolean;
107
119
  }
108
120
  export interface ISubmitFeedbackExtractionBody {
@@ -2,7 +2,7 @@ import { BasePaginate } from '../type-message/base-paginate';
2
2
  import { IResponse } from '../type-message/response';
3
3
  import { IBeamTransfer, IBeamFile, IBeamRecipient } from '../../models/beam.dto';
4
4
  import { IContentShare } from '../../models/content-share.dto';
5
- import { BeamVisibility, BeamServeDenyReasonCode } from '../../../enum/beam.enum';
5
+ import { BeamVisibility, BeamServeDenyReasonCode, BeamDownloadKind } from '../../../enum/beam.enum';
6
6
  export interface IGetBeamData {
7
7
  beamTransfer: IBeamTransfer;
8
8
  }
@@ -90,3 +90,25 @@ export interface IListRecipientsBeamData {
90
90
  recipients: IBeamRecipient[];
91
91
  }
92
92
  export type IListRecipientsBeamResponse = IResponse<IListRecipientsBeamData>;
93
+ export interface IBeamStatsDayBucket {
94
+ day: string;
95
+ count: number;
96
+ zipCount: number;
97
+ }
98
+ export interface IBeamStatsRecentEvent {
99
+ downloadedAt: string;
100
+ kind: BeamDownloadKind;
101
+ fileId: string | null;
102
+ fileName: string | null;
103
+ userId: string | null;
104
+ ipHash: string;
105
+ }
106
+ export interface IGetBeamStatsData {
107
+ byDay: IBeamStatsDayBucket[];
108
+ recent: IBeamStatsRecentEvent[];
109
+ totals: {
110
+ downloadCount: number;
111
+ lastDownloadedAt: string | null;
112
+ };
113
+ }
114
+ export type IGetBeamStatsResponse = IResponse<IGetBeamStatsData>;
@@ -169,6 +169,12 @@ export interface IGetTemplateData {
169
169
  }
170
170
  export type IGetTemplateResponse = IResponse<IGetTemplateData>;
171
171
  export type IListTemplateVersionsResponse = IResponse<IExtractionTemplateVersion[]>;
172
+ export interface IGetTemplateWitnessUrlData {
173
+ url: string;
174
+ filename: string | null;
175
+ size_bytes: number | null;
176
+ }
177
+ export type IGetTemplateWitnessUrlResponse = IResponse<IGetTemplateWitnessUrlData>;
172
178
  export interface IExtractionTemplateCollection {
173
179
  $schema: 'abyss-rcb-template-collection/v1';
174
180
  exported_at: string;
@@ -1,7 +1,7 @@
1
1
  import { IOrganization } from './organization.dto';
2
2
  import { IUser } from './user.dto';
3
3
  import { IProject } from './project.dto';
4
- import { BeamVisibility } from '../../enum/beam.enum';
4
+ import { BeamVisibility, BeamDownloadKind } from '../../enum/beam.enum';
5
5
  export interface IBeamTransfer {
6
6
  id: string;
7
7
  slug: string;
@@ -56,3 +56,15 @@ export interface IBeamRecipient {
56
56
  createdAt?: Date;
57
57
  transfer?: IBeamTransfer;
58
58
  }
59
+ export interface IBeamDownloadEvent {
60
+ id: string;
61
+ transferId: string;
62
+ fileId: string | null;
63
+ kind: BeamDownloadKind;
64
+ ipHash: string;
65
+ userId: string | null;
66
+ downloadedAt: Date;
67
+ createdAt?: Date;
68
+ transfer?: IBeamTransfer;
69
+ file?: IBeamFile | null;
70
+ }
@@ -1,5 +1,6 @@
1
1
  import { ExtractionWarningCode } from '../../../types/enum/extraction-warning.enum';
2
2
  import { ExtractionFeedbackIssueType } from '../../../types/enum/extraction-feedback-issue-type.enum';
3
+ import { DocumentType } from '../../../types/enum/document-type.enum';
3
4
  import type { IFieldValue, IExecutionManifest, IGlobalConfidence } from './extraction-plan.dto';
4
5
  export { ExtractionFeedbackIssueType };
5
6
  export type ExtractionMode = 'auto' | 'hint' | 'template';
@@ -101,10 +102,15 @@ export interface IExtraction {
101
102
  }
102
103
  export interface IExtractionTemplate {
103
104
  id: string;
104
- userId: string;
105
+ userId: string | null;
106
+ organizationId: string | null;
107
+ projectId: string | null;
108
+ createdByUserId: string | null;
105
109
  name: string;
106
110
  description: string | null;
111
+ documentType: DocumentType | null;
107
112
  isActive: boolean;
113
+ lastUsedAt: string | null;
108
114
  createdAt: string;
109
115
  updatedAt: string;
110
116
  }
@@ -141,6 +147,9 @@ export interface IExtractionTemplateVersion {
141
147
  version: number;
142
148
  templateJson: Record<string, unknown>;
143
149
  comment: string | null;
150
+ witnessFileId: string | null;
151
+ witnessSizeBytes: number | null;
152
+ witnessFilename: string | null;
144
153
  createdAt: string;
145
154
  }
146
155
  export interface IExtractionFeedback {
@@ -1 +1 @@
1
- {"version":3,"file":"extraction.dto.js","sourceRoot":"","sources":["../../../../src/types/interface/models/extraction.dto.ts"],"names":[],"mappings":";;;AAKA,yFAAoF;AA+E3E,sGA/EA,+CAAqB,OA+EA;AA9E9B,iHAAsG;AAQ7F,4GARA,iEAA2B,OAQA;AAwOpC,IAAY,sBAYX;AAZD,WAAY,sBAAsB;IAChC,qEAA2C,CAAA;IAC3C,+DAAqC,CAAA;IACrC,+EAAqD,CAAA;IACrD,uEAA6C,CAAA;IAC7C,6DAAmC,CAAA;IACnC,2DAAiC,CAAA;IACjC,6DAAmC,CAAA;IACnC,uEAA6C,CAAA;IAC7C,uDAA6B,CAAA;IAC7B,mEAAyC,CAAA;IACzC,6DAAmC,CAAA;AACrC,CAAC,EAZW,sBAAsB,sCAAtB,sBAAsB,QAYjC;AAEY,QAAA,yBAAyB,GACpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAuCxC,IAAY,2BAGX;AAHD,WAAY,2BAA2B;IACrC,4CAAa,CAAA;IACb,0CAAW,CAAA;AACb,CAAC,EAHW,2BAA2B,2CAA3B,2BAA2B,QAGtC"}
1
+ {"version":3,"file":"extraction.dto.js","sourceRoot":"","sources":["../../../../src/types/interface/models/extraction.dto.ts"],"names":[],"mappings":";;;AAKA,yFAAoF;AA4E3E,sGA5EA,+CAAqB,OA4EA;AA3E9B,iHAAsG;AAK7F,4GALA,iEAA2B,OAKA;AAoQpC,IAAY,sBAYX;AAZD,WAAY,sBAAsB;IAChC,qEAA2C,CAAA;IAC3C,+DAAqC,CAAA;IACrC,+EAAqD,CAAA;IACrD,uEAA6C,CAAA;IAC7C,6DAAmC,CAAA;IACnC,2DAAiC,CAAA;IACjC,6DAAmC,CAAA;IACnC,uEAA6C,CAAA;IAC7C,uDAA6B,CAAA;IAC7B,mEAAyC,CAAA;IACzC,6DAAmC,CAAA;AACrC,CAAC,EAZW,sBAAsB,sCAAtB,sBAAsB,QAYjC;AAEY,QAAA,yBAAyB,GACpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAuCxC,IAAY,2BAGX;AAHD,WAAY,2BAA2B;IACrC,4CAAa,CAAA;IACb,0CAAW,CAAA;AACb,CAAC,EAHW,2BAA2B,2CAA3B,2BAA2B,QAGtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abyss-project/tools",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Core package to interact with Abyss-Project Tools",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -42,6 +42,9 @@ import type {
42
42
  IAddRecipientsBeamBody,
43
43
  IAddRecipientsBeamResponse,
44
44
  IListRecipientsBeamResponse,
45
+ IGetBeamStatsParams,
46
+ IGetBeamStatsQuery,
47
+ IGetBeamStatsResponse,
45
48
  } from '../types';
46
49
  import { BEAM_MANAGE_TOKEN_HEADER } from '../constants/beam.constants';
47
50
 
@@ -51,6 +54,10 @@ import { BEAM_MANAGE_TOKEN_HEADER } from '../constants/beam.constants';
51
54
  const manageTokenHeader = (manageToken?: string): { headers?: Record<string, string> } =>
52
55
  manageToken ? { headers: { [BEAM_MANAGE_TOKEN_HEADER]: manageToken } } : {};
53
56
 
57
+ // renew/reactivate POST body: only carry `days` when the caller requested a
58
+ // specific extension window (the API clamps it to the tier cap; default 7).
59
+ const renewalBody = (days?: number): { days?: number } => (days !== undefined ? { days } : {});
60
+
54
61
  export const beamApi = {
55
62
  get: async (params: IGetBeamParams): Promise<IGetBeamResponse> => {
56
63
  const response = await AbyssToolsCore.axios.get<IGetBeamResponse>(`/beam/${params.beamId}`);
@@ -138,13 +145,31 @@ export const beamApi = {
138
145
 
139
146
  renew: async (params: IRenewBeamParams): Promise<IRenewBeamResponse> => {
140
147
  return (
141
- await AbyssToolsCore.axios.post<IRenewBeamResponse>(`/beam/${params.beamId}/renew`)
148
+ await AbyssToolsCore.axios.post<IRenewBeamResponse>(
149
+ `/beam/${params.beamId}/renew`,
150
+ renewalBody(params.days),
151
+ )
142
152
  ).data;
143
153
  },
144
154
 
145
155
  reactivate: async (params: IReactivateBeamParams): Promise<IReactivateBeamResponse> => {
146
156
  return (
147
- await AbyssToolsCore.axios.post<IReactivateBeamResponse>(`/beam/${params.beamId}/reactivate`)
157
+ await AbyssToolsCore.axios.post<IReactivateBeamResponse>(
158
+ `/beam/${params.beamId}/reactivate`,
159
+ renewalBody(params.days),
160
+ )
161
+ ).data;
162
+ },
163
+
164
+ // Owner download stats (MANAGE-gated): per-day series + recent events + totals.
165
+ stats: async (
166
+ params: IGetBeamStatsParams,
167
+ query?: IGetBeamStatsQuery,
168
+ ): Promise<IGetBeamStatsResponse> => {
169
+ return (
170
+ await AbyssToolsCore.axios.get<IGetBeamStatsResponse>(`/beam/${params.beamId}/stats`, {
171
+ params: query,
172
+ })
148
173
  ).data;
149
174
  },
150
175
 
@@ -258,7 +283,7 @@ export const beamApi = {
258
283
  return (
259
284
  await AbyssToolsCore.axios.post<IRenewBeamResponse>(
260
285
  `/beam/${params.beamId}/renew`,
261
- undefined,
286
+ renewalBody(params.days),
262
287
  manageTokenHeader(params.manageToken),
263
288
  )
264
289
  ).data;
@@ -269,7 +294,7 @@ export const beamApi = {
269
294
  return (
270
295
  await AbyssToolsCore.axios.post<IReactivateBeamResponse>(
271
296
  `/beam/${params.beamId}/reactivate`,
272
- undefined,
297
+ renewalBody(params.days),
273
298
  manageTokenHeader(params.manageToken),
274
299
  )
275
300
  ).data;
@@ -42,6 +42,7 @@ import {
42
42
  IListTemplatesResponse,
43
43
  IGetTemplateResponse,
44
44
  IListTemplateVersionsResponse,
45
+ IGetTemplateWitnessUrlResponse,
45
46
  IExtractionTemplateCollection,
46
47
  IImportTemplateCollectionResponse,
47
48
  IGetJobResponse,
@@ -62,6 +63,7 @@ import {
62
63
  ICreateTemplateBody,
63
64
  IUpdateTemplateBody,
64
65
  IPatchTemplateMetaBody,
66
+ IListTemplatesQuery,
65
67
  ISubmitFeedbackExtractionBody,
66
68
  IPatchFeedbackBody,
67
69
  IListFeedbackQuery,
@@ -478,7 +480,7 @@ export const toggleExtractionTraining = async (
478
480
  // ─── TEMPLATES ───────────────────────────────
479
481
 
480
482
  export const listTemplates = async (
481
- query: { kind?: 'spatial' | 'dsl' } & IExtractionTemplateScopeQuery = {},
483
+ query: IListTemplatesQuery & IExtractionTemplateScopeQuery = {},
482
484
  apiKey?: string,
483
485
  ): Promise<IListTemplatesResponse> => {
484
486
  return (
@@ -566,19 +568,58 @@ export const listTemplateVersions = async (
566
568
  ).data;
567
569
  };
568
570
 
571
+ /**
572
+ * Presigned download URL for a template version's witness PDF.
573
+ * 404 when the version has no witness.
574
+ * GET /extract/templates/:id/versions/:version/witness-url
575
+ */
576
+ export const getTemplateWitnessUrl = async (
577
+ templateId: string,
578
+ version: number,
579
+ scope: IExtractionTemplateScopeQuery = {},
580
+ apiKey?: string,
581
+ ): Promise<IGetTemplateWitnessUrlResponse> => {
582
+ return (
583
+ await AbyssToolsCore.axios.get<IGetTemplateWitnessUrlResponse>(
584
+ `extract/templates/${templateId}/versions/${version}/witness-url`,
585
+ { params: serializeParams(scope), headers: authHeader(apiKey) },
586
+ )
587
+ ).data;
588
+ };
589
+
590
+ /**
591
+ * Delete a template version's witness PDF (frees the billed storage).
592
+ * 404 when the version has no witness. Allowed on archived templates.
593
+ * DELETE /extract/templates/:id/versions/:version/witness
594
+ */
595
+ export const deleteTemplateWitness = async (
596
+ templateId: string,
597
+ version: number,
598
+ scope: IExtractionTemplateScopeQuery = {},
599
+ apiKey?: string,
600
+ ): Promise<void> => {
601
+ await AbyssToolsCore.axios.delete(`extract/templates/${templateId}/versions/${version}/witness`, {
602
+ params: serializeParams(scope),
603
+ headers: authHeader(apiKey),
604
+ });
605
+ };
606
+
569
607
  export const exportTemplateCollection = async (
570
608
  ids: string[] | null,
571
609
  scope: IExtractionTemplateScopeQuery = {},
572
610
  apiKey?: string,
573
611
  ): Promise<IExtractionTemplateCollection> => {
574
- const res = await AbyssToolsCore.axios.get<IExtractionTemplateCollection>(`extract/templates/export`, {
575
- params: {
576
- ...(ids && ids.length ? { ids: ids.join(',') } : {}),
577
- ...serializeParams(scope),
612
+ const res = await AbyssToolsCore.axios.get<IExtractionTemplateCollection>(
613
+ `extract/templates/export`,
614
+ {
615
+ params: {
616
+ ...(ids && ids.length ? { ids: ids.join(',') } : {}),
617
+ ...serializeParams(scope),
618
+ },
619
+ headers: authHeader(apiKey),
620
+ responseType: 'json',
578
621
  },
579
- headers: authHeader(apiKey),
580
- responseType: 'json',
581
- });
622
+ );
582
623
  return res.data;
583
624
  };
584
625
 
@@ -792,10 +833,10 @@ export const getExtractionWebhook = async (
792
833
  apiKey?: string,
793
834
  ): Promise<IGetExtractionWebhookResponse> =>
794
835
  (
795
- await AbyssToolsCore.axios.get<IGetExtractionWebhookResponse>(
796
- `extract/webhook/${webhookId}`,
797
- { params: serializeParams(scope), headers: authHeader(apiKey) },
798
- )
836
+ await AbyssToolsCore.axios.get<IGetExtractionWebhookResponse>(`extract/webhook/${webhookId}`, {
837
+ params: serializeParams(scope),
838
+ headers: authHeader(apiKey),
839
+ })
799
840
  ).data;
800
841
 
801
842
  export const createExtractionWebhook = async (
@@ -804,11 +845,10 @@ export const createExtractionWebhook = async (
804
845
  apiKey?: string,
805
846
  ): Promise<ICreateExtractionWebhookResponse> =>
806
847
  (
807
- await AbyssToolsCore.axios.post<ICreateExtractionWebhookResponse>(
808
- `extract/webhook`,
809
- body,
810
- { params: serializeParams(scope), headers: authHeader(apiKey) },
811
- )
848
+ await AbyssToolsCore.axios.post<ICreateExtractionWebhookResponse>(`extract/webhook`, body, {
849
+ params: serializeParams(scope),
850
+ headers: authHeader(apiKey),
851
+ })
812
852
  ).data;
813
853
 
814
854
  export const updateExtractionWebhook = async (
@@ -39,4 +39,68 @@ describe('beamApi', () => {
39
39
  expect(get).toHaveBeenCalledWith('/b/abcdefghij');
40
40
  get.mockRestore();
41
41
  });
42
+
43
+ it('renew posts an empty body by default and { days } when a window is requested', async () => {
44
+ const post = jest
45
+ .spyOn(AbyssToolsCore.axios, 'post')
46
+ .mockResolvedValue({ data: { data: { beamTransfer: { id: 't1' } } } });
47
+
48
+ await AbyssToolsCore.sdk.beam.renew({ beamId: 't1' });
49
+ expect(post).toHaveBeenCalledWith('/beam/t1/renew', {});
50
+
51
+ await AbyssToolsCore.sdk.beam.renew({ beamId: 't1', days: 30 });
52
+ expect(post).toHaveBeenCalledWith('/beam/t1/renew', { days: 30 });
53
+ post.mockRestore();
54
+ });
55
+
56
+ it('reactivate posts an empty body by default and { days } when a window is requested', async () => {
57
+ const post = jest
58
+ .spyOn(AbyssToolsCore.axios, 'post')
59
+ .mockResolvedValue({ data: { data: { beamTransfer: { id: 't1' } } } });
60
+
61
+ await AbyssToolsCore.sdk.beam.reactivate({ beamId: 't1' });
62
+ expect(post).toHaveBeenCalledWith('/beam/t1/reactivate', {});
63
+
64
+ await AbyssToolsCore.sdk.beam.reactivate({ beamId: 't1', days: 14 });
65
+ expect(post).toHaveBeenCalledWith('/beam/t1/reactivate', { days: 14 });
66
+ post.mockRestore();
67
+ });
68
+
69
+ it('public.renew carries the manage token header AND the optional days body', async () => {
70
+ const post = jest
71
+ .spyOn(AbyssToolsCore.axios, 'post')
72
+ .mockResolvedValue({ data: { data: { beamTransfer: { id: 't1' } } } });
73
+
74
+ await AbyssToolsCore.sdk.beam.public.renew({ beamId: 't1', manageToken: 'tok', days: 7 });
75
+
76
+ expect(post).toHaveBeenCalledWith(
77
+ '/beam/t1/renew',
78
+ { days: 7 },
79
+ { headers: { 'x-beam-manage-token': 'tok' } },
80
+ );
81
+ post.mockRestore();
82
+ });
83
+
84
+ it('stats reads /beam/:beamId/stats with the window/pagination query', async () => {
85
+ const get = jest.spyOn(AbyssToolsCore.axios, 'get').mockResolvedValue({
86
+ data: {
87
+ data: {
88
+ byDay: [{ day: '2026-07-09', count: 2, zipCount: 1 }],
89
+ recent: [],
90
+ totals: { downloadCount: 2, lastDownloadedAt: null },
91
+ },
92
+ },
93
+ });
94
+
95
+ const res = await AbyssToolsCore.sdk.beam.stats(
96
+ { beamId: 't1' },
97
+ { days: 7, limit: 10, offset: 0 },
98
+ );
99
+
100
+ expect(get).toHaveBeenCalledWith('/beam/t1/stats', {
101
+ params: { days: 7, limit: 10, offset: 0 },
102
+ });
103
+ expect(res.data.byDay[0].zipCount).toBe(1);
104
+ get.mockRestore();
105
+ });
42
106
  });
package/src/index.ts CHANGED
@@ -286,6 +286,7 @@ type AbyssToolsCoreSDK = {
286
286
  delete: typeof beamApiModule.beamApi.delete;
287
287
  renew: typeof beamApiModule.beamApi.renew;
288
288
  reactivate: typeof beamApiModule.beamApi.reactivate;
289
+ stats: typeof beamApiModule.beamApi.stats;
289
290
  share: {
290
291
  create: typeof beamApiModule.beamApi.share.create;
291
292
  list: typeof beamApiModule.beamApi.share.list;
@@ -362,8 +363,13 @@ type AbyssToolsCoreSDK = {
362
363
  create: typeof extractionApi.createTemplate;
363
364
  update: typeof extractionApi.updateTemplate;
364
365
  patchMeta: typeof extractionApi.patchTemplateMeta;
366
+ /** DESTRUCTIVE: template + versions + witness PDFs. Archive via patchMeta instead. */
365
367
  delete: typeof extractionApi.deleteTemplate;
366
368
  listVersions: typeof extractionApi.listTemplateVersions;
369
+ /** Presigned download URL for a version's witness PDF (404 when none). */
370
+ getWitnessUrl: typeof extractionApi.getTemplateWitnessUrl;
371
+ /** Delete a version's witness PDF and free the billed storage. */
372
+ deleteWitness: typeof extractionApi.deleteTemplateWitness;
367
373
  exportCollection: typeof extractionApi.exportTemplateCollection;
368
374
  importCollection: typeof extractionApi.importTemplateCollection;
369
375
  };
@@ -671,6 +677,7 @@ export class AbyssToolsCore {
671
677
  delete: beamApiModule.beamApi.delete,
672
678
  renew: beamApiModule.beamApi.renew,
673
679
  reactivate: beamApiModule.beamApi.reactivate,
680
+ stats: beamApiModule.beamApi.stats,
674
681
  share: {
675
682
  create: beamApiModule.beamApi.share.create,
676
683
  list: beamApiModule.beamApi.share.list,
@@ -748,6 +755,8 @@ export class AbyssToolsCore {
748
755
  patchMeta: extractionApi.patchTemplateMeta,
749
756
  delete: extractionApi.deleteTemplate,
750
757
  listVersions: extractionApi.listTemplateVersions,
758
+ getWitnessUrl: extractionApi.getTemplateWitnessUrl,
759
+ deleteWitness: extractionApi.deleteTemplateWitness,
751
760
  exportCollection: extractionApi.exportTemplateCollection,
752
761
  importCollection: extractionApi.importTemplateCollection,
753
762
  },
@@ -22,3 +22,11 @@ export enum BeamServeDenyReasonCode {
22
22
  SCAN_PENDING = 'scan_pending',
23
23
  SCAN_INFECTED = 'scan_infected',
24
24
  }
25
+
26
+ // What a beam_download_events row counted: a single-file download (/b/:slug/
27
+ // file/:fileId) or the whole-transfer zip (/b/:slug/zip). Inline embeds (/raw)
28
+ // and thumbnails (/thumb) are deliberately NOT download events (spec §17.6).
29
+ export enum BeamDownloadKind {
30
+ FILE = 'file',
31
+ ZIP = 'zip',
32
+ }
@@ -42,12 +42,15 @@ export type ICreateBeamBody = {
42
42
  };
43
43
 
44
44
  // Anonymous draft creation (POST /beam/public). Same metadata as the owned
45
- // create minus expiresInDays — anonymous TTL is fixed at 7 days by createDraft.
45
+ // create. `expiresInDays` is an optional 1..7 lifetime (integer) the anonymous
46
+ // creator may pick; absent = the fixed 7-day anonymous TTL, and createDraft caps
47
+ // it at 7 days.
46
48
  export type ICreateBeamPublicBody = {
47
49
  title?: string;
48
50
  message?: string;
49
51
  visibility?: BeamVisibility;
50
52
  password?: string;
53
+ expiresInDays?: number;
51
54
  maxDownloads?: number;
52
55
  recipients?: { email: string; locale?: string }[];
53
56
  };
@@ -105,14 +108,26 @@ export interface IUnlockBeamPublicBody {
105
108
  password: string;
106
109
  }
107
110
 
108
- // Management lifecycle (B4): renew/reactivate take only the transfer id. Both
109
- // push expiresAt forward and reactivate the transfer server-side.
111
+ // Management lifecycle (B4): renew/reactivate push expiresAt forward and
112
+ // reactivate the transfer server-side. `days` optionally requests the extension
113
+ // window; the API clamps it to the tier cap (7 days for anonymous transfers,
114
+ // the plan's TOOLS_BEAM_EXPIRY_MAX_DAYS for owned ones; default 7).
110
115
  export interface IRenewBeamParams {
111
116
  beamId: string;
117
+ days?: number;
118
+ }
119
+
120
+ export interface IRenewBeamBody {
121
+ days?: number;
112
122
  }
113
123
 
114
124
  export interface IReactivateBeamParams {
115
125
  beamId: string;
126
+ days?: number;
127
+ }
128
+
129
+ export interface IReactivateBeamBody {
130
+ days?: number;
116
131
  }
117
132
 
118
133
  // Sharing (B4): a MANAGE holder grants a content_share (BEAM content type) on the
@@ -150,3 +165,16 @@ export interface IAddRecipientsBeamBody {
150
165
  export interface IListRecipientsBeamParams {
151
166
  beamId: string;
152
167
  }
168
+
169
+ // Download stats (owner view): per-day series over the last `days` days plus the
170
+ // paginated recent-event feed (limit/offset, newest first). Defaults are applied
171
+ // server-side (days=30, limit=50, offset=0).
172
+ export interface IGetBeamStatsParams {
173
+ beamId: string;
174
+ }
175
+
176
+ export interface IGetBeamStatsQuery {
177
+ days?: number;
178
+ limit?: number;
179
+ offset?: number;
180
+ }
@@ -9,6 +9,7 @@ import {
9
9
  ProcessingMode,
10
10
  IExtractionBankHint,
11
11
  } from '../../models/extraction.dto';
12
+ import { DocumentType } from '../../../enum/document-type.enum';
12
13
  import type { IExtractionPlan } from '../../models/extraction-plan.dto';
13
14
 
14
15
  // ─── SCOPE ───────────────────────────────────
@@ -150,21 +151,48 @@ export interface IAsyncExportExtractionBody {
150
151
 
151
152
  // ─── TEMPLATES ───────────────────────────────
152
153
 
154
+ /**
155
+ * Query for GET /extract/templates.
156
+ * `archived`: 'false' (default) = active templates, 'true' = the archive,
157
+ * 'all' = everything.
158
+ */
159
+ export interface IListTemplatesQuery {
160
+ kind?: 'spatial' | 'dsl';
161
+ archived?: 'true' | 'false' | 'all';
162
+ /** Filter to templates targeting a given document type. */
163
+ document_type?: DocumentType;
164
+ }
165
+
153
166
  export interface ICreateTemplateBody {
154
167
  name: string;
155
168
  description?: string;
169
+ /** Kind of document the template targets (DocumentType). */
170
+ document_type?: DocumentType | null;
156
171
  template_json: Record<string, unknown>;
157
172
  comment?: string;
173
+ /**
174
+ * Optional witness (sample) PDF, base64-encoded (max 25 MB decoded).
175
+ * Stored per version, billed to the owner's storage pool.
176
+ */
177
+ witness_pdf_base64?: string;
178
+ witness_filename?: string;
158
179
  }
159
180
 
160
181
  export interface IUpdateTemplateBody {
161
182
  template_json: Record<string, unknown>;
162
183
  comment?: string;
184
+ /**
185
+ * Optional witness (sample) PDF, base64-encoded (max 25 MB decoded).
186
+ * Stored per version, billed to the owner's storage pool.
187
+ */
188
+ witness_pdf_base64?: string;
189
+ witness_filename?: string;
163
190
  }
164
191
 
165
192
  export interface IPatchTemplateMetaBody {
166
193
  name?: string;
167
194
  description?: string | null;
195
+ document_type?: DocumentType | null;
168
196
  is_active?: boolean;
169
197
  }
170
198
 
@@ -2,7 +2,7 @@ import { BasePaginate } from '../type-message/base-paginate';
2
2
  import { IResponse } from '../type-message/response';
3
3
  import { IBeamTransfer, IBeamFile, IBeamRecipient } from '../../models/beam.dto';
4
4
  import { IContentShare } from '../../models/content-share.dto';
5
- import { BeamVisibility, BeamServeDenyReasonCode } from '../../../enum/beam.enum';
5
+ import { BeamVisibility, BeamServeDenyReasonCode, BeamDownloadKind } from '../../../enum/beam.enum';
6
6
 
7
7
  export interface IGetBeamData {
8
8
  beamTransfer: IBeamTransfer;
@@ -120,3 +120,32 @@ export interface IListRecipientsBeamData {
120
120
  recipients: IBeamRecipient[];
121
121
  }
122
122
  export type IListRecipientsBeamResponse = IResponse<IListRecipientsBeamData>;
123
+
124
+ // Download stats (owner view, MANAGE-gated): a per-day series (SQL date_trunc,
125
+ // UTC buckets; days with zero downloads are omitted), the paginated recent-event
126
+ // feed (newest first) and the denormalized transfer totals. `fileName` is null
127
+ // for a zip event and after the downloaded file was deleted (FK SET NULL).
128
+ export interface IBeamStatsDayBucket {
129
+ day: string; // 'YYYY-MM-DD'
130
+ count: number;
131
+ zipCount: number;
132
+ }
133
+
134
+ export interface IBeamStatsRecentEvent {
135
+ downloadedAt: string;
136
+ kind: BeamDownloadKind;
137
+ fileId: string | null;
138
+ fileName: string | null;
139
+ userId: string | null;
140
+ ipHash: string;
141
+ }
142
+
143
+ export interface IGetBeamStatsData {
144
+ byDay: IBeamStatsDayBucket[];
145
+ recent: IBeamStatsRecentEvent[];
146
+ totals: {
147
+ downloadCount: number;
148
+ lastDownloadedAt: string | null;
149
+ };
150
+ }
151
+ export type IGetBeamStatsResponse = IResponse<IGetBeamStatsData>;