@cloudpdf/contract 3.0.0-next.5 → 3.0.0-next.6

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/dist/openapi.js CHANGED
@@ -1,10 +1,9 @@
1
1
  // src/openapi.ts
2
- import { zodToJsonSchema } from "zod-to-json-schema";
3
- import { z as z2 } from "zod";
4
2
  import { EngineErrorPayloadSchema as EngineErrorPayloadSchema2 } from "@embedpdf/engine-core/wire";
3
+ import { z as z2 } from "zod";
4
+ import { zodToJsonSchema } from "zod-to-json-schema";
5
5
 
6
6
  // src/index.ts
7
- import { z } from "zod";
8
7
  import {
9
8
  AnnotationListPageSnapshotSchema,
10
9
  DocumentHeadSchema,
@@ -16,6 +15,7 @@ import {
16
15
  PageTextSnapshotSchema,
17
16
  wireTemplates
18
17
  } from "@embedpdf/engine-core/wire";
18
+ import { z } from "zod";
19
19
  var sha256Hex = /^[0-9a-f]{64}$/i;
20
20
  var docIdPattern = /^[A-Za-z0-9_-]+$/;
21
21
  var tenantIdPattern = /^[A-Za-z0-9_-]+$/;
@@ -32,6 +32,7 @@ var adminWirePaths = {
32
32
  tenant: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}`,
33
33
  documents: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/documents`,
34
34
  documentsInit: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/documents/init`,
35
+ documentsImport: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/documents/import`,
35
36
  document: (tenantId, docId) => `/v1/tenants/${encodeURIComponent(tenantId)}/documents/${encodeURIComponent(docId)}`,
36
37
  documentCommit: (tenantId, docId) => `/v1/tenants/${encodeURIComponent(tenantId)}/documents/${encodeURIComponent(docId)}/commit`,
37
38
  documentUploadProxy: (tenantId, docId) => `/v1/tenants/${encodeURIComponent(tenantId)}/documents/${encodeURIComponent(docId)}/upload-proxy`,
@@ -123,6 +124,59 @@ var AdminDocumentCommitRequestSchema = z.object({
123
124
  var AdminDocumentCommitResponseSchema = z.object({
124
125
  document: AdminDocumentRecordSchema
125
126
  });
127
+ var utf8ByteLength = (s) => new TextEncoder().encode(s).length;
128
+ var AdminImportSourceSchema = z.discriminatedUnion("kind", [
129
+ z.object({
130
+ kind: z.literal("url"),
131
+ url: z.string().url().max(8192)
132
+ }),
133
+ z.object({
134
+ kind: z.literal("connection"),
135
+ connectionId: z.string().min(1).max(128),
136
+ key: z.string().min(1).refine((k) => !k.includes("\0"), "key must not contain NUL").refine((k) => utf8ByteLength(k) <= 1024, "key must be at most 1024 UTF-8 bytes"),
137
+ revision: z.string().min(1).max(1024).optional()
138
+ })
139
+ ]);
140
+ var AdminDocumentImportRequestSchema = z.object({
141
+ source: AdminImportSourceSchema,
142
+ /**
143
+ * Optional integrity pins, enforced when present: `sizeBytes`
144
+ * against the source's declared Content-Length before the transfer,
145
+ * `sha256` against the server-observed digest after it. When absent
146
+ * the server-observed values become authoritative.
147
+ * `dedupMode=reuse-existing` REQUIRES `sha256` — without a declared
148
+ * hash the server cannot know what content to reuse.
149
+ */
150
+ expected: z.object({
151
+ sizeBytes: z.number().int().min(1).optional(),
152
+ sha256: z.string().regex(sha256Hex).optional()
153
+ }).optional(),
154
+ metadata: z.record(z.string(), z.unknown()).optional(),
155
+ idempotencyKey: z.string().optional(),
156
+ dedupMode: DedupModeSchema.optional(),
157
+ docId: z.string().regex(docIdPattern).optional(),
158
+ /**
159
+ * `sync` (default) holds the response open for the whole transfer.
160
+ * `async` accepts the request (202, document `pending`), transfers
161
+ * in the background, and the caller polls the document. Async
162
+ * requires a `connection` source (URLs are secrets and expire, so
163
+ * they cannot sit in a durable job); filesystem connections
164
+ * additionally require `expected.sha256`, since they have no
165
+ * revisions to pin retries to.
166
+ */
167
+ mode: z.enum(["sync", "async"]).optional()
168
+ });
169
+ var AdminDocumentImportResponseSchema = z.object({
170
+ /**
171
+ * `imported` — bytes were pulled, verified, and committed (sync).
172
+ * `deduped` — an existing document satisfied the request without a
173
+ * transfer (content dedup or idempotent replay).
174
+ * `accepted` — async: the job is queued (HTTP 202); poll the
175
+ * document until `ready` or `failed`.
176
+ */
177
+ tag: z.enum(["imported", "deduped", "accepted"]),
178
+ document: AdminDocumentRecordSchema
179
+ });
126
180
  var AdminDocumentResponseSchema = z.object({
127
181
  document: AdminDocumentRecordSchema
128
182
  });
@@ -480,6 +534,25 @@ var adminOperations = {
480
534
  },
481
535
  notes: "This bounded origin-mediated fallback must only be used after documents.init returns upload.kind=proxy. Auto mode prefers a presigned object-store PUT whenever available."
482
536
  },
537
+ "documents.importFrom": {
538
+ operationId: "documents.importFrom",
539
+ title: "Import document",
540
+ summary: "Server-side pull: fetch a PDF from a caller-supplied URL (e.g. a presigned object-store GET) or an operator-registered storage connection into CloudPDF-owned storage, verify it, and commit it.",
541
+ method: "POST",
542
+ path: "/v1/tenants/:tenantId/documents/import",
543
+ credentials: ["api-token", "tenant-jwt"],
544
+ scope: ["docs.create"],
545
+ params: AdminTenantParamsSchema,
546
+ body: { contentType: "application/json", schema: AdminDocumentImportRequestSchema },
547
+ responses: {
548
+ 200: { contentType: "application/json", schema: AdminDocumentImportResponseSchema },
549
+ 202: { contentType: "application/json", schema: AdminDocumentImportResponseSchema },
550
+ 400: { contentType: "application/json", schema: AdminErrorPayloadSchema },
551
+ 403: { contentType: "application/json", schema: AdminErrorPayloadSchema },
552
+ 502: { contentType: "application/json", schema: AdminErrorPayloadSchema }
553
+ },
554
+ notes: "Default mode is synchronous and bounded: the response returns only after the transfer verified and committed (or failed). mode=async (connection sources only) answers 202 immediately and an in-process worker performs the transfer with leased, fenced retries; poll the document until ready/failed. The deployment import policy gates scheme, network range, and size; sources must declare a length. CloudPDF copies and owns the bytes \u2014 the source is never referenced in place. A 502 marks a retryable upstream failure: retry with the same idempotencyKey to resume the same document. URL sources are capabilities and never echoed back. Connection sources name operator-registered storage (bucket/prefix scope, allowed credential classes, and tenant bindings are deployment configuration); `revision` is provider-interpreted (S3 VersionId, GCS generation, Azure version id)."
555
+ },
483
556
  "documents.list": {
484
557
  operationId: "documents.list",
485
558
  title: "List documents",
@@ -1231,12 +1304,54 @@ function operationObject(op, schemas) {
1231
1304
  };
1232
1305
  return out;
1233
1306
  }
1307
+ var RESERVED_SDK_SEGMENTS = [
1308
+ [
1309
+ "Java",
1310
+ /* @__PURE__ */ new Set([
1311
+ ...["abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class"],
1312
+ ...["const", "continue", "default", "do", "double", "else", "enum", "extends", "final"],
1313
+ ...["finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int"],
1314
+ ...["interface", "long", "native", "new", "package", "private", "protected", "public"],
1315
+ ...["return", "short", "static", "strictfp", "super", "switch", "synchronized", "this"],
1316
+ ...["throw", "throws", "transient", "try", "void", "volatile", "while"],
1317
+ ...["true", "false", "null"]
1318
+ ])
1319
+ ],
1320
+ [
1321
+ "Python",
1322
+ /* @__PURE__ */ new Set([
1323
+ ...["False", "None", "True", "and", "as", "assert", "async", "await", "break", "class"],
1324
+ ...["continue", "def", "del", "elif", "else", "except", "finally", "for", "from"],
1325
+ ...["global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass"],
1326
+ ...["raise", "return", "try", "while", "with", "yield"]
1327
+ ])
1328
+ ],
1329
+ [
1330
+ "Ruby",
1331
+ /* @__PURE__ */ new Set([
1332
+ ...["alias", "and", "begin", "break", "case", "class", "def", "do", "else", "elsif"],
1333
+ ...["end", "ensure", "false", "for", "if", "in", "module", "next", "nil", "not", "or"],
1334
+ ...["redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef"],
1335
+ ...["unless", "until", "when", "while", "yield"]
1336
+ ])
1337
+ ]
1338
+ ];
1234
1339
  function sdkOperationName(operationId) {
1235
1340
  const parts = operationId.split(".");
1236
1341
  const method = parts.pop();
1237
1342
  if (!method || parts.length === 0) {
1238
1343
  throw new Error(`Operation ID must use resource.method form: ${operationId}`);
1239
1344
  }
1345
+ for (const segment of [...parts, method]) {
1346
+ const collisions = RESERVED_SDK_SEGMENTS.filter(([, words]) => words.has(segment)).map(
1347
+ ([language]) => language
1348
+ );
1349
+ if (collisions.length > 0) {
1350
+ throw new Error(
1351
+ `Operation "${operationId}" cannot use "${segment}" as an SDK name segment: it is a reserved word in ${collisions.join(" and ")}, so SDK generators would rename or reject it. Pick a compound name instead (e.g. importFrom rather than import).`
1352
+ );
1353
+ }
1354
+ }
1240
1355
  return { groups: parts, method };
1241
1356
  }
1242
1357
  function headerParameters(op) {
@@ -1376,6 +1491,7 @@ function sortKeys(obj) {
1376
1491
  return Object.fromEntries(Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)));
1377
1492
  }
1378
1493
  export {
1379
- buildAdminOpenApiDocument
1494
+ buildAdminOpenApiDocument,
1495
+ sdkOperationName
1380
1496
  };
1381
1497
  //# sourceMappingURL=openapi.js.map