@repome/api 0.1.9 → 0.3.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 (3) hide show
  1. package/dist/index.d.mts +1312 -148
  2. package/dist/index.mjs +111 -69
  3. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,11 +1,18 @@
1
1
  import * as z from "zod";
2
2
  import { oc } from "@orpc/contract";
3
+ //#region package.json
4
+ var version = "0.3.0";
5
+ //#endregion
3
6
  //#region src/base.ts
7
+ const validationIssueSchema = z.object({
8
+ path: z.array(z.union([z.string(), z.number()])).optional(),
9
+ message: z.string()
10
+ });
4
11
  const commonErrors = {
5
12
  BAD_REQUEST: {
6
13
  status: 400,
7
14
  message: "Bad request",
8
- data: z.object({}).optional()
15
+ data: z.object({ issues: z.array(validationIssueSchema).optional() }).optional()
9
16
  },
10
17
  UNAUTHENTICATED: {
11
18
  status: 401,
@@ -134,68 +141,70 @@ const commonErrors = {
134
141
  status: 502,
135
142
  message: "Repo import failed",
136
143
  data: z.object({ name: z.string() })
144
+ },
145
+ ORG_LAST_OWNED: {
146
+ status: 409,
147
+ message: "Cannot delete your last owned organization",
148
+ data: z.object({ slug: z.string() })
149
+ },
150
+ ORG_HAS_REPOS: {
151
+ status: 409,
152
+ message: "Cannot delete an organization that still owns repos",
153
+ data: z.object({
154
+ slug: z.string(),
155
+ repoCount: z.number().int().nonnegative()
156
+ })
137
157
  }
138
158
  };
139
159
  const ocBase = oc.errors(commonErrors);
140
- //#endregion
141
- //#region src/orgs.ts
142
- const orgSlugHint = "Lowercase, alphanumeric, - only.";
143
- const orgSlugSchema = z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, orgSlugHint);
144
- const PERSONAL_ORG_SLUG = "~";
145
- const repoScopeSchema = z.object({ orgSlug: z.union([orgSlugSchema, z.literal("~")]).optional() });
146
- const orgIdOrSlugSchema = z.object({ idOrSlug: z.string().min(1) });
147
- const orgCreateInputSchema = z.object({
148
- slug: orgSlugSchema,
149
- name: z.string().min(1).max(80)
150
- });
151
- const orgViewSchema = z.object({
152
- id: z.string(),
153
- slug: z.string(),
154
- name: z.string(),
155
- logo: z.string().nullable(),
156
- metadata: z.string().nullable(),
157
- createdAt: z.number()
158
- });
159
- const orgListOutputSchema = z.object({ items: z.array(orgViewSchema) });
160
- const orgs = {
161
- create: ocBase.input(orgCreateInputSchema).output(orgViewSchema),
162
- list: ocBase.output(orgListOutputSchema),
163
- get: ocBase.input(orgIdOrSlugSchema).output(orgViewSchema),
164
- delete: ocBase.input(orgIdOrSlugSchema).output(z.object({ deleted: z.literal(true) }))
165
- };
160
+ const ocPublic = ocBase.route({ spec: (operation) => ({
161
+ ...operation,
162
+ security: []
163
+ }) });
166
164
  //#endregion
167
165
  //#region src/pagination.ts
168
166
  const cursorSchema = z.string().optional().describe("Opaque pagination cursor from a previous page. Lenient: an undecodable cursor restarts from the first page; a stale cursor (pointing at a removed item) yields an empty page on git listings and continues past the cursor position on catalog listings. Never an error.");
169
167
  //#endregion
170
168
  //#region src/repos.ts
171
- const repoNameHint = "Lowercase, alphanumeric, ._- only.";
169
+ const repoNameHint = "Lowercase, alphanumeric, ._- only; \"..\" is not allowed.";
172
170
  const CLONE_TOKEN_SCOPE = "read";
173
- const repoNameSchema = z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9._-]*$/, repoNameHint);
171
+ const repoNameSchema = z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9._-]*$/, repoNameHint).refine((value) => !value.includes(".."), repoNameHint);
174
172
  function parseRepoName(value) {
175
173
  return repoNameSchema.parse(value);
176
174
  }
177
- const repoIdentSchema = repoScopeSchema.extend({ name: repoNameSchema });
175
+ const defaultBranchHint = "Branch name (\"main\") or refs/heads/-qualified; other refs/ namespaces are not branches.";
176
+ const REFS_HEADS_PREFIX = "refs/heads/";
177
+ /**
178
+ * The one normalizer for default-branch spellings: a refs/heads/-qualified
179
+ * value becomes the short name, anything else passes through. Persisted rows
180
+ * hold the short shape only — the default-branch guards, headOid, and
181
+ * clone/view templates all build `refs/heads/${defaultBranch}` from it, so a
182
+ * qualified spelling would silently fall outside them.
183
+ */
184
+ function normalizeDefaultBranch(branch) {
185
+ return branch.startsWith(REFS_HEADS_PREFIX) ? branch.slice(11) : branch;
186
+ }
187
+ const defaultBranchSchema = z.string().min(1).max(139).transform(normalizeDefaultBranch).pipe(z.string().min(1).max(128).refine((value) => !value.startsWith("refs/"), defaultBranchHint));
188
+ const repoIdentSchema = z.object({ name: repoNameSchema });
178
189
  const repoCreateInputSchema = repoIdentSchema.extend({
179
190
  description: z.string().max(512).optional(),
180
- defaultBranch: z.string().min(1).max(128).default("main")
191
+ defaultBranch: defaultBranchSchema.default("main")
181
192
  });
182
193
  const repoEnsureInputSchema = repoCreateInputSchema;
183
194
  const repoImportInputSchema = repoCreateInputSchema.extend({ remote: z.url() });
184
195
  const repoUpdateInputSchema = repoIdentSchema.extend({
185
196
  description: z.string().max(512).nullable().optional(),
186
- defaultBranch: z.string().min(1).max(128).optional()
197
+ defaultBranch: defaultBranchSchema.optional()
187
198
  });
188
- const repoListInputSchema = repoScopeSchema.extend({
199
+ const repoListInputSchema = z.object({
189
200
  cursor: cursorSchema,
190
201
  limit: z.number().int().min(1).max(100).default(50)
191
202
  });
192
203
  const repoSchema = z.object({
193
- orgId: z.string(),
194
204
  name: z.string(),
195
205
  ownerId: z.string(),
196
206
  description: z.string().nullable(),
197
207
  defaultBranch: z.string(),
198
- artifactName: z.string(),
199
208
  artifactId: z.string().nullable(),
200
209
  remote: z.string().nullable(),
201
210
  readOnly: z.boolean(),
@@ -229,20 +238,20 @@ const repos = {
229
238
  };
230
239
  //#endregion
231
240
  //#region src/git.ts
232
- const pageInputSchema = repoScopeSchema.extend({
241
+ const pageInputSchema = z.object({
233
242
  name: repoNameSchema,
234
243
  cursor: cursorSchema,
235
244
  limit: z.number().int().min(1).max(100).default(50)
236
245
  });
237
- const refInputSchema = repoScopeSchema.extend({
246
+ const refInputSchema = z.object({
238
247
  name: repoNameSchema,
239
248
  ref: z.string().min(1)
240
249
  });
241
- const oidInputSchema = repoScopeSchema.extend({
250
+ const oidInputSchema = z.object({
242
251
  name: repoNameSchema,
243
252
  oid: z.string().min(1)
244
253
  });
245
- const treeInputSchema = repoScopeSchema.extend({
254
+ const treeInputSchema = z.object({
246
255
  name: repoNameSchema,
247
256
  ref: z.string().min(1).default("HEAD"),
248
257
  path: z.string().optional(),
@@ -250,7 +259,7 @@ const treeInputSchema = repoScopeSchema.extend({
250
259
  cursor: cursorSchema,
251
260
  limit: z.number().int().min(1).max(100).default(50)
252
261
  });
253
- const blobInputSchema = repoScopeSchema.extend({
262
+ const blobInputSchema = z.object({
254
263
  name: repoNameSchema,
255
264
  oid: z.string().min(1)
256
265
  });
@@ -260,12 +269,12 @@ const signatureSchema$1 = z.object({
260
269
  timestamp: z.number().int().optional(),
261
270
  timezoneOffset: z.number().int().optional()
262
271
  });
263
- const branchCreateInputSchema = repoScopeSchema.extend({
272
+ const branchCreateInputSchema = z.object({
264
273
  name: repoNameSchema,
265
274
  branch: z.string().min(1),
266
275
  fromRef: z.string().min(1)
267
276
  });
268
- const branchUpdateInputSchema = repoScopeSchema.extend({
277
+ const branchUpdateInputSchema = z.object({
269
278
  name: repoNameSchema,
270
279
  ref: z.string().min(1),
271
280
  oid: z.string().min(1),
@@ -273,23 +282,23 @@ const branchUpdateInputSchema = repoScopeSchema.extend({
273
282
  force: z.boolean().optional(),
274
283
  allowDefaultBranchRewrite: z.boolean().optional()
275
284
  });
276
- const branchDeleteInputSchema = repoScopeSchema.extend({
285
+ const branchDeleteInputSchema = z.object({
277
286
  name: repoNameSchema,
278
287
  ref: z.string().min(1),
279
288
  expectedOid: z.string().min(1).optional()
280
289
  });
281
- const tagCreateInputSchema = repoScopeSchema.extend({
290
+ const tagCreateInputSchema = z.object({
282
291
  name: repoNameSchema,
283
292
  tag: z.string().min(1),
284
293
  oid: z.string().min(1),
285
294
  message: z.string().min(1).optional(),
286
295
  tagger: signatureSchema$1.optional()
287
296
  });
288
- const tagDeleteInputSchema = repoScopeSchema.extend({
297
+ const tagDeleteInputSchema = z.object({
289
298
  name: repoNameSchema,
290
299
  ref: z.string().min(1)
291
300
  });
292
- const commitCreateInputSchema = repoScopeSchema.extend({
301
+ const commitCreateInputSchema = z.object({
293
302
  name: repoNameSchema,
294
303
  ref: z.string().min(1),
295
304
  message: z.string().min(1),
@@ -304,7 +313,7 @@ const workspaceFileSchema$1 = z.object({
304
313
  content: z.string(),
305
314
  encoding: z.literal("base64").default("base64")
306
315
  });
307
- const workspaceCommitInputSchema = repoScopeSchema.extend({
316
+ const workspaceCommitInputSchema = z.object({
308
317
  name: repoNameSchema,
309
318
  ref: z.string().min(1).default("refs/heads/main"),
310
319
  message: z.string().min(1),
@@ -317,14 +326,14 @@ const workspaceCommitInputSchema = repoScopeSchema.extend({
317
326
  message: "workspace.commit requires at least one file or remove",
318
327
  path: ["files"]
319
328
  });
320
- const compareInputSchema = repoScopeSchema.extend({
329
+ const compareInputSchema = z.object({
321
330
  name: repoNameSchema,
322
331
  base: z.string().min(1),
323
332
  head: z.string().min(1),
324
333
  cursor: cursorSchema,
325
334
  limit: z.number().int().min(1).max(250).default(250)
326
335
  });
327
- const diffInputSchema = repoScopeSchema.extend({
336
+ const diffInputSchema = z.object({
328
337
  name: repoNameSchema,
329
338
  base: z.string().min(1),
330
339
  head: z.string().min(1),
@@ -451,13 +460,23 @@ const git = {
451
460
  //#endregion
452
461
  //#region src/tokens.ts
453
462
  const tokenScopeSchema = z.enum(["read", "write"]);
454
- const tokenMintInputSchema = repoScopeSchema.extend({
463
+ const TOKEN_OPS = [
464
+ "refs",
465
+ "object",
466
+ "merge",
467
+ "seed",
468
+ "clone",
469
+ "agent"
470
+ ];
471
+ const tokenOpSchema = z.enum(TOKEN_OPS).describe("Token op selecting the TTL cap: refs 60s, object 300s, merge 600s, seed 600s, clone 900s, agent 1800s. Defaults to `refs` (60s) when omitted. The effective TTL is min(requested ttlSeconds, op cap, server hard cap), floored at 60s.");
472
+ const gitRemoteOpSchema = z.string().min(1).max(32).describe("Git operation from the credential helper (e.g. `push`, `fetch`). `push` and `receive-pack` mint write-scope tokens; anything else mints read scope. Values outside the token op set (refs, object, merge, seed, clone, agent) use the default refs 60s TTL cap.");
473
+ const tokenMintInputSchema = z.object({
455
474
  name: repoNameSchema,
456
475
  scope: tokenScopeSchema,
457
476
  ttlSeconds: z.number().int().positive().optional(),
458
- op: z.string().min(1).max(32).optional()
477
+ op: tokenOpSchema.optional()
459
478
  });
460
- const tokenIdentInputSchema = repoScopeSchema.extend({
479
+ const tokenIdentInputSchema = z.object({
461
480
  name: repoNameSchema,
462
481
  id: z.string().min(1)
463
482
  });
@@ -467,7 +486,7 @@ const tokenMintForGitRemoteInputSchema = z.object({
467
486
  host: z.string().min(1),
468
487
  path: z.string().min(1),
469
488
  ttlSeconds: z.number().int().positive().optional(),
470
- op: z.string().min(1).max(32).optional()
489
+ op: gitRemoteOpSchema.optional()
471
490
  });
472
491
  const tokenViewSchema = z.object({
473
492
  id: z.string(),
@@ -482,7 +501,7 @@ const tokenViewSchema = z.object({
482
501
  revokedAt: z.string().nullable()
483
502
  });
484
503
  const tokenMintOutputSchema = tokenViewSchema.extend({ token: z.string() });
485
- const tokenListInputSchema = repoScopeSchema.extend({ name: repoNameSchema });
504
+ const tokenListInputSchema = z.object({ name: repoNameSchema });
486
505
  const tokenListOutputSchema = z.object({ items: z.array(tokenViewSchema) });
487
506
  const tokenRevokeOutputSchema = z.object({ revoked: z.boolean() });
488
507
  const tokenValidateOutputSchema = z.object({
@@ -521,7 +540,7 @@ const anonBlobInputSchema = anonRepoIdentSchema.extend({ oid: z.string().min(1)
521
540
  const anonRepoCreateInputSchema = z.object({
522
541
  name: repoNameSchema.optional(),
523
542
  description: z.string().max(512).optional(),
524
- defaultBranch: z.string().min(1).max(128).default("main"),
543
+ defaultBranch: defaultBranchSchema.default("main"),
525
544
  ttlSeconds: z.number().int().min(60).max(3600 * 72).optional()
526
545
  });
527
546
  const anonRepoSchema = repoSchema.extend({
@@ -542,7 +561,7 @@ const anonTokenMintForGitRemoteInputSchema = z.object({
542
561
  host: z.string().min(1),
543
562
  path: z.string().min(1),
544
563
  ttlSeconds: z.number().int().positive().optional(),
545
- op: z.string().min(1).max(32).optional()
564
+ op: gitRemoteOpSchema.optional()
546
565
  });
547
566
  const signatureSchema = z.object({
548
567
  name: z.string().min(1),
@@ -576,21 +595,21 @@ function pageOf(item) {
576
595
  }
577
596
  const anon = {
578
597
  repos: {
579
- create: ocBase.input(anonRepoCreateInputSchema).output(anonRepoCreateOutputSchema),
580
- get: ocBase.input(anonRepoIdentSchema).output(anonRepoSchema),
581
- list: ocBase.input(anonRepoListInputSchema).output(anonRepoListOutputSchema),
582
- delete: ocBase.input(anonRepoIdentSchema).output(z.object({ deleted: z.literal(true) }))
598
+ create: ocPublic.input(anonRepoCreateInputSchema).output(anonRepoCreateOutputSchema),
599
+ get: ocPublic.input(anonRepoIdentSchema).output(anonRepoSchema),
600
+ list: ocPublic.input(anonRepoListInputSchema).output(anonRepoListOutputSchema),
601
+ delete: ocPublic.input(anonRepoIdentSchema).output(z.object({ deleted: z.literal(true) }))
583
602
  },
584
- tokens: { mintForGitRemote: ocBase.input(anonTokenMintForGitRemoteInputSchema).output(tokenMintOutputSchema) },
603
+ tokens: { mintForGitRemote: ocPublic.input(anonTokenMintForGitRemoteInputSchema).output(tokenMintOutputSchema) },
585
604
  git: {
586
605
  refs: {
587
- list: ocBase.input(anonPageInputSchema).output(pageOf(gitRefSchema)),
588
- get: ocBase.input(anonRefInputSchema).output(gitRefSchema)
606
+ list: ocPublic.input(anonPageInputSchema).output(pageOf(gitRefSchema)),
607
+ get: ocPublic.input(anonRefInputSchema).output(gitRefSchema)
589
608
  },
590
- commits: { list: ocBase.input(anonPageInputSchema.extend({ ref: z.string().optional() })).output(pageOf(gitCommitSchema)) },
591
- tree: { get: ocBase.input(anonTreeInputSchema).output(pageOf(gitTreeEntrySchema)) },
592
- blob: { get: ocBase.input(anonBlobInputSchema).output(z.union([gitBlobSchema, gitBlobTooLargeSchema])) },
593
- workspace: { commit: ocBase.input(anonWorkspaceCommitInputSchema).output(z.object({
609
+ commits: { list: ocPublic.input(anonPageInputSchema.extend({ ref: z.string().optional() })).output(pageOf(gitCommitSchema)) },
610
+ tree: { get: ocPublic.input(anonTreeInputSchema).output(pageOf(gitTreeEntrySchema)) },
611
+ blob: { get: ocPublic.input(anonBlobInputSchema).output(z.union([gitBlobSchema, gitBlobTooLargeSchema])) },
612
+ workspace: { commit: ocPublic.input(anonWorkspaceCommitInputSchema).output(z.object({
594
613
  commit: gitCommitSchema,
595
614
  ref: gitRefSchema
596
615
  })) }
@@ -598,7 +617,7 @@ const anon = {
598
617
  };
599
618
  //#endregion
600
619
  //#region src/health.ts
601
- const health = { ping: ocBase.input(z.void()).output(z.object({
620
+ const health = { ping: ocPublic.input(z.void()).output(z.object({
602
621
  ok: z.literal(true),
603
622
  ts: z.number()
604
623
  })) };
@@ -648,6 +667,27 @@ const keys = {
648
667
  delete: ocBase.input(apiKeyDeleteInputSchema).output(apiKeyDeleteOutputSchema)
649
668
  };
650
669
  //#endregion
670
+ //#region src/orgs.ts
671
+ const orgSlugHint = "Lowercase, alphanumeric, - only.";
672
+ const orgSlugSchema = z.string().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, orgSlugHint);
673
+ const orgIdOrSlugSchema = z.object({ idOrSlug: z.string().min(1) });
674
+ const orgCreateInputSchema = z.object({ name: z.string().min(1).max(80).optional() });
675
+ const orgViewSchema = z.object({
676
+ id: z.string(),
677
+ slug: z.string(),
678
+ name: z.string(),
679
+ logo: z.string().nullable(),
680
+ metadata: z.string().nullable(),
681
+ createdAt: z.number()
682
+ });
683
+ const orgListOutputSchema = z.object({ items: z.array(orgViewSchema) });
684
+ const orgs = {
685
+ create: ocBase.input(orgCreateInputSchema).output(orgViewSchema),
686
+ list: ocBase.output(orgListOutputSchema),
687
+ get: ocBase.input(orgIdOrSlugSchema).output(orgViewSchema),
688
+ delete: ocBase.input(orgIdOrSlugSchema).output(z.object({ deleted: z.literal(true) }))
689
+ };
690
+ //#endregion
651
691
  //#region src/members.ts
652
692
  const memberRoleSchema = z.enum([
653
693
  "owner",
@@ -739,6 +779,8 @@ function serializeAnonIdRecord(record) {
739
779
  }
740
780
  //#endregion
741
781
  //#region src/index.ts
782
+ /** Contract package version; propagated into OpenAPI `info.version` (ISSUE-0057 V10-D2). */
783
+ const apiVersion = version;
742
784
  const contract = {
743
785
  anon,
744
786
  health,
@@ -751,4 +793,4 @@ const contract = {
751
793
  tokens
752
794
  };
753
795
  //#endregion
754
- export { ANON_ID_STORE_VERSION, CLONE_TOKEN_SCOPE, PERSONAL_ORG_SLUG, anonRepoSchema, apiKeyViewSchema, commonErrors, compareViewSchema, contract, cursorSchema, diffFileSchema, diffViewSchema, gitBlobSchema, gitCommitSchema, gitRefSchema, gitTreeEntrySchema, invitationListItemSchema, invitationViewSchema, meViewSchema, memberRoleSchema, memberViewSchema, mutableMemberRoleSchema, orgSlugHint, orgSlugSchema, orgViewSchema, parseAnonIdFile, parseRepoName, repoNameHint, repoNameSchema, repoSchema, scopeSchema, serializeAnonIdRecord, tokenScopeSchema, tokenViewSchema };
796
+ export { ANON_ID_STORE_VERSION, CLONE_TOKEN_SCOPE, TOKEN_OPS, anonRepoSchema, apiKeyViewSchema, apiVersion, commonErrors, compareViewSchema, contract, cursorSchema, defaultBranchHint, defaultBranchSchema, diffFileSchema, diffViewSchema, gitBlobSchema, gitCommitSchema, gitRefSchema, gitTreeEntrySchema, invitationListItemSchema, invitationViewSchema, meViewSchema, memberRoleSchema, memberViewSchema, mutableMemberRoleSchema, normalizeDefaultBranch, orgSlugHint, orgSlugSchema, orgViewSchema, parseAnonIdFile, parseRepoName, repoNameHint, repoNameSchema, repoSchema, scopeSchema, serializeAnonIdRecord, tokenOpSchema, tokenScopeSchema, tokenViewSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repome/api",
3
- "version": "0.1.9",
3
+ "version": "0.3.0",
4
4
  "description": "Agent-native, GitHub-shaped forge — shared oRPC contract (zod schemas + procedure shapes).",
5
5
  "keywords": [
6
6
  "agent",