@forgezero/providers 0.1.21 → 0.1.23
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 +66 -159
- package/dist/binance.js +1 -1
- package/dist/chain.js +1 -1
- package/dist/database.js +1 -1
- package/dist/email.js +1 -1
- package/dist/git.d.ts +124 -0
- package/dist/git.js +400 -0
- package/dist/http.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pool.js +1 -1
- package/dist/storage.js +1 -1
- package/dist/translation.js +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Send through whichever provider is up. Priority and failover, reordered live.
|
|
|
11
11
|
|
|
12
12
|
## Package overview
|
|
13
13
|
|
|
14
|
-
Anyone calling somebody else's API who needs the failure classified rather than guessed. Provider capabilities stay independent from application-owned services, which attach named methods by priority with health tracking. Supported runtimes: bun, node, workers, deno. Package root: @forgezero/providers.
|
|
14
|
+
Anyone calling somebody else's API who needs the failure classified rather than guessed. Provider capabilities stay independent from application-owned services, which attach named methods by priority with health tracking. Supported runtimes: bun, node, workers, deno. Package root: @forgezero/providers. Consumer documentation is curated with each module's explicit public flag; the complete internal/export inventory remains in the typed SSOT and declaration files.
|
|
15
15
|
|
|
16
16
|
```text
|
|
17
17
|
bun add @forgezero/providers
|
|
@@ -29,9 +29,9 @@ The five packages are installation boundaries. Choose a package by who installs
|
|
|
29
29
|
| @forgezero/runtime | Portable runtime primitives for queries, jobs, events, schemas and finance. | bun, node | [Open](https://www.forgezero.net/docs/runtime) |
|
|
30
30
|
| @forgezero/agent | Operator CLI and managed-node agent for bootstrap, deploy and lifecycle. | bun, node | [Open](https://www.forgezero.net/docs/agent) |
|
|
31
31
|
|
|
32
|
-
## @forgezero/providers
|
|
32
|
+
## @forgezero/providers supported imports and commands
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
These are supported consumer entry points, not every internal module shipped for ForgeZero managed installation. Each row links to its task-oriented usage.
|
|
35
35
|
|
|
36
36
|
| public entry | short description | runtime | details |
|
|
37
37
|
|---|---|---|---|
|
|
@@ -45,6 +45,7 @@ Every row links to the detailed explanation and named-import/example area below.
|
|
|
45
45
|
| @forgezero/providers/storage | S3-compatible object storage, SigV4 signed with Web Crypto and no vendor SDK. | portable | [Reference + usage](#forgezero-providers-storage) |
|
|
46
46
|
| @forgezero/providers/translation | Google AI Studio translation with strict batch alignment and classified quota failures. | portable | [Reference + usage](#forgezero-providers-translation) |
|
|
47
47
|
| @forgezero/providers/realtime | Cloudflare KV node-directory and Durable Object fan-out clients for project-defined realtime services. | portable | [Reference + usage](#forgezero-providers-realtime) |
|
|
48
|
+
| @forgezero/providers/git | Versioned Git Connect contracts for accounts, repositories, branches, webhooks and short-lived clone credentials; GitHub, GitLab and private forges attach without changing the service. | portable | [Reference + usage](#forgezero-providers-git) |
|
|
48
49
|
|
|
49
50
|
## Commands
|
|
50
51
|
|
|
@@ -59,61 +60,11 @@ bun test
|
|
|
59
60
|
<a id="forgezero-providers"></a>
|
|
60
61
|
## @forgezero/providers
|
|
61
62
|
|
|
62
|
-
The registry: priority, health, and a terminal-versus-retryable verdict per failure. This
|
|
63
|
+
The registry: priority, health, and a terminal-versus-retryable verdict per failure. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
63
64
|
|
|
64
65
|
```text
|
|
65
66
|
import {
|
|
66
67
|
ProviderError,
|
|
67
|
-
STRIKES_TO_OFFLINE,
|
|
68
|
-
VERSION,
|
|
69
|
-
chainCredentials,
|
|
70
|
-
chainScopedCredentials,
|
|
71
|
-
createRegistry,
|
|
72
|
-
createService,
|
|
73
|
-
defineProvider,
|
|
74
|
-
defineProviderMethod,
|
|
75
|
-
defineProviderMethodBranches,
|
|
76
|
-
defineService,
|
|
77
|
-
defineSingleMethodProvider,
|
|
78
|
-
envCredentials,
|
|
79
|
-
nextHealth,
|
|
80
|
-
scopeCredentials,
|
|
81
|
-
serviceMethod,
|
|
82
|
-
staticConfig,
|
|
83
|
-
} from '@forgezero/providers';
|
|
84
|
-
|
|
85
|
-
import type {
|
|
86
|
-
AnyProviderMethod,
|
|
87
|
-
Attempt,
|
|
88
|
-
CallOptions,
|
|
89
|
-
CallResult,
|
|
90
|
-
ConfigSource,
|
|
91
|
-
CredentialSource,
|
|
92
|
-
DirectAttempt,
|
|
93
|
-
DirectCallResult,
|
|
94
|
-
DirectServiceAttachment,
|
|
95
|
-
DirectServiceConfig,
|
|
96
|
-
DirectServiceOptions,
|
|
97
|
-
EmailBatch,
|
|
98
|
-
EmailBatchItemResult,
|
|
99
|
-
EmailBatchResult,
|
|
100
|
-
EmailMessage,
|
|
101
|
-
FailureKind,
|
|
102
|
-
InvokeContext,
|
|
103
|
-
ProviderDefinition,
|
|
104
|
-
ProviderHealth,
|
|
105
|
-
ProviderInstanceConfig,
|
|
106
|
-
ProviderMethodBranches,
|
|
107
|
-
ProviderMethodEntry,
|
|
108
|
-
ProviderMethodSpec,
|
|
109
|
-
ProviderMethods,
|
|
110
|
-
RegistryOptions,
|
|
111
|
-
ScopedCredentialSource,
|
|
112
|
-
ServiceDefinition,
|
|
113
|
-
ServiceMethodAttachment,
|
|
114
|
-
ServiceMethodContract,
|
|
115
|
-
ServiceMethods,
|
|
116
|
-
StaticRegistryConfig,
|
|
117
68
|
} from '@forgezero/providers';
|
|
118
69
|
```
|
|
119
70
|
|
|
@@ -189,19 +140,11 @@ const credentials = chainScopedCredentials(
|
|
|
189
140
|
<a id="forgezero-providers-email"></a>
|
|
190
141
|
## @forgezero/providers/email
|
|
191
142
|
|
|
192
|
-
JetEmail (`send`, `sendBatch`), SMTP (`send` only), and the typed email service contract; SMTP transport is injected. This
|
|
143
|
+
JetEmail (`send`, `sendBatch`), SMTP (`send` only), and the typed email service contract; SMTP transport is injected. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
193
144
|
|
|
194
145
|
```text
|
|
195
146
|
import {
|
|
196
147
|
emailProviders,
|
|
197
|
-
emailService,
|
|
198
|
-
jetemail,
|
|
199
|
-
smtp,
|
|
200
|
-
} from '@forgezero/providers/email';
|
|
201
|
-
|
|
202
|
-
import type {
|
|
203
|
-
JetEmailConfig,
|
|
204
|
-
SmtpTransport,
|
|
205
148
|
} from '@forgezero/providers/email';
|
|
206
149
|
```
|
|
207
150
|
|
|
@@ -250,27 +193,11 @@ console.log(outcome.result, outcome.attempts);
|
|
|
250
193
|
<a id="forgezero-providers-database"></a>
|
|
251
194
|
## @forgezero/providers/database
|
|
252
195
|
|
|
253
|
-
ArangoDB in the registry for credential rotation and health — with failover off by default. This
|
|
196
|
+
ArangoDB in the registry for credential rotation and health — with failover off by default. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
254
197
|
|
|
255
198
|
```text
|
|
256
199
|
import {
|
|
257
200
|
ARANGO_COMMUNITY_VERSION,
|
|
258
|
-
ARANGO_SERVER_MODE_PATH,
|
|
259
|
-
MAX_ARANGO_COORDINATORS,
|
|
260
|
-
arangoCoordinatorUrls,
|
|
261
|
-
arangodb,
|
|
262
|
-
databaseProviders,
|
|
263
|
-
resetPools,
|
|
264
|
-
} from '@forgezero/providers/database';
|
|
265
|
-
|
|
266
|
-
import type {
|
|
267
|
-
ArangoConfig,
|
|
268
|
-
ArangoConnectOptions,
|
|
269
|
-
ArangoCoordinatorMember,
|
|
270
|
-
ArangoLike,
|
|
271
|
-
ArangoMembershipSnapshot,
|
|
272
|
-
ArangoMembershipVerifier,
|
|
273
|
-
Query,
|
|
274
201
|
} from '@forgezero/providers/database';
|
|
275
202
|
```
|
|
276
203
|
|
|
@@ -289,27 +216,11 @@ export const selectedCapability = ARANGO_COMMUNITY_VERSION;
|
|
|
289
216
|
<a id="forgezero-providers-http"></a>
|
|
290
217
|
## @forgezero/providers/http
|
|
291
218
|
|
|
292
|
-
Outbound HTTP with a per-host weight budget reserved before the call and settled from the response. This
|
|
219
|
+
Outbound HTTP with a per-host weight budget reserved before the call and settled from the response. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
293
220
|
|
|
294
221
|
```text
|
|
295
222
|
import {
|
|
296
223
|
BudgetExhausted,
|
|
297
|
-
binanceWeight,
|
|
298
|
-
budgetState,
|
|
299
|
-
createHttpClient,
|
|
300
|
-
http,
|
|
301
|
-
httpProviders,
|
|
302
|
-
resetBudgets,
|
|
303
|
-
settle,
|
|
304
|
-
spend,
|
|
305
|
-
} from '@forgezero/providers/http';
|
|
306
|
-
|
|
307
|
-
import type {
|
|
308
|
-
HostBudget,
|
|
309
|
-
HttpClient,
|
|
310
|
-
HttpConfig,
|
|
311
|
-
HttpRequest,
|
|
312
|
-
HttpResponse,
|
|
313
224
|
} from '@forgezero/providers/http';
|
|
314
225
|
```
|
|
315
226
|
|
|
@@ -328,20 +239,11 @@ export const selectedCapability = BudgetExhausted;
|
|
|
328
239
|
<a id="forgezero-providers-pool"></a>
|
|
329
240
|
## @forgezero/providers/pool
|
|
330
241
|
|
|
331
|
-
Which outbound address a request leaves by, sticky per key, over the same budget as everything else. This
|
|
242
|
+
Which outbound address a request leaves by, sticky per key, over the same budget as everything else. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
332
243
|
|
|
333
244
|
```text
|
|
334
245
|
import {
|
|
335
246
|
PoolEmpty,
|
|
336
|
-
PoolExhausted,
|
|
337
|
-
createAddressPool,
|
|
338
|
-
} from '@forgezero/providers/pool';
|
|
339
|
-
|
|
340
|
-
import type {
|
|
341
|
-
AddressPool,
|
|
342
|
-
Lease,
|
|
343
|
-
PoolAddress,
|
|
344
|
-
PoolOptions,
|
|
345
247
|
} from '@forgezero/providers/pool';
|
|
346
248
|
```
|
|
347
249
|
|
|
@@ -360,19 +262,12 @@ export const selectedCapability = PoolEmpty;
|
|
|
360
262
|
<a id="forgezero-providers-chain"></a>
|
|
361
263
|
## @forgezero/providers/chain
|
|
362
264
|
|
|
363
|
-
An EVM node behind the same failover as any other service: read logs, broadcast, and never stop scanning because one endpoint rate-limited. This
|
|
265
|
+
An EVM node behind the same failover as any other service: read logs, broadcast, and never stop scanning because one endpoint rate-limited. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
364
266
|
|
|
365
267
|
```text
|
|
366
268
|
import {
|
|
367
269
|
evmRpc,
|
|
368
270
|
} from '@forgezero/providers/chain';
|
|
369
|
-
|
|
370
|
-
import type {
|
|
371
|
-
ChainCall,
|
|
372
|
-
ChainLog,
|
|
373
|
-
ChainReceipt,
|
|
374
|
-
ChainResult,
|
|
375
|
-
} from '@forgezero/providers/chain';
|
|
376
271
|
```
|
|
377
272
|
|
|
378
273
|
## @forgezero/providers/chain — Use this entry point
|
|
@@ -390,19 +285,11 @@ export const selectedCapability = evmRpc;
|
|
|
390
285
|
<a id="forgezero-providers-binance"></a>
|
|
391
286
|
## @forgezero/providers/binance
|
|
392
287
|
|
|
393
|
-
Binance behind the venue adapter: three hosts, one weight budget, signed over the exact string that is sent. This
|
|
288
|
+
Binance behind the venue adapter: three hosts, one weight budget, signed over the exact string that is sent. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
394
289
|
|
|
395
290
|
```text
|
|
396
291
|
import {
|
|
397
292
|
binanceSymbol,
|
|
398
|
-
createBinanceAdapter,
|
|
399
|
-
readBinanceError,
|
|
400
|
-
toOrderStatus,
|
|
401
|
-
} from '@forgezero/providers/binance';
|
|
402
|
-
|
|
403
|
-
import type {
|
|
404
|
-
BinanceCredentials,
|
|
405
|
-
BinanceOptions,
|
|
406
293
|
} from '@forgezero/providers/binance';
|
|
407
294
|
```
|
|
408
295
|
|
|
@@ -421,29 +308,11 @@ export const selectedCapability = binanceSymbol;
|
|
|
421
308
|
<a id="forgezero-providers-storage"></a>
|
|
422
309
|
## @forgezero/providers/storage
|
|
423
310
|
|
|
424
|
-
S3-compatible object storage, SigV4 signed with Web Crypto and no vendor SDK. This
|
|
311
|
+
S3-compatible object storage, SigV4 signed with Web Crypto and no vendor SDK. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
425
312
|
|
|
426
313
|
```text
|
|
427
314
|
import {
|
|
428
315
|
MAX_SINGLE_PUT_BYTES,
|
|
429
|
-
StorageError,
|
|
430
|
-
amzDate,
|
|
431
|
-
createS3Client,
|
|
432
|
-
encodeSegment,
|
|
433
|
-
parseListXml,
|
|
434
|
-
s3,
|
|
435
|
-
signRequest,
|
|
436
|
-
storageProviders,
|
|
437
|
-
} from '@forgezero/providers/storage';
|
|
438
|
-
|
|
439
|
-
import type {
|
|
440
|
-
ObjectSummary,
|
|
441
|
-
PutObjectArgs,
|
|
442
|
-
S3Client,
|
|
443
|
-
S3Config,
|
|
444
|
-
S3Credentials,
|
|
445
|
-
SignedRequest,
|
|
446
|
-
StorageRequest,
|
|
447
316
|
} from '@forgezero/providers/storage';
|
|
448
317
|
```
|
|
449
318
|
|
|
@@ -462,20 +331,11 @@ export const selectedCapability = MAX_SINGLE_PUT_BYTES;
|
|
|
462
331
|
<a id="forgezero-providers-translation"></a>
|
|
463
332
|
## @forgezero/providers/translation
|
|
464
333
|
|
|
465
|
-
Google AI Studio translation with strict batch alignment and classified quota failures. This
|
|
334
|
+
Google AI Studio translation with strict batch alignment and classified quota failures. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
466
335
|
|
|
467
336
|
```text
|
|
468
337
|
import {
|
|
469
338
|
TranslationError,
|
|
470
|
-
googleAiStudio,
|
|
471
|
-
parseStrings,
|
|
472
|
-
translationProviders,
|
|
473
|
-
} from '@forgezero/providers/translation';
|
|
474
|
-
|
|
475
|
-
import type {
|
|
476
|
-
TranslateRequest,
|
|
477
|
-
TranslateResult,
|
|
478
|
-
TranslationProvider,
|
|
479
339
|
} from '@forgezero/providers/translation';
|
|
480
340
|
```
|
|
481
341
|
|
|
@@ -494,16 +354,11 @@ export const selectedCapability = TranslationError;
|
|
|
494
354
|
<a id="forgezero-providers-realtime"></a>
|
|
495
355
|
## @forgezero/providers/realtime
|
|
496
356
|
|
|
497
|
-
Cloudflare KV node-directory and Durable Object fan-out clients for project-defined realtime services. This
|
|
357
|
+
Cloudflare KV node-directory and Durable Object fan-out clients for project-defined realtime services. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
498
358
|
|
|
499
359
|
```text
|
|
500
360
|
import {
|
|
501
361
|
RealtimeProviderError,
|
|
502
|
-
cloudflareRealtime,
|
|
503
|
-
} from '@forgezero/providers/realtime';
|
|
504
|
-
|
|
505
|
-
import type {
|
|
506
|
-
RealtimeProviderOptions,
|
|
507
362
|
} from '@forgezero/providers/realtime';
|
|
508
363
|
```
|
|
509
364
|
|
|
@@ -519,11 +374,40 @@ import {
|
|
|
519
374
|
export const selectedCapability = RealtimeProviderError;
|
|
520
375
|
```
|
|
521
376
|
|
|
377
|
+
<a id="forgezero-providers-git"></a>
|
|
378
|
+
## @forgezero/providers/git
|
|
379
|
+
|
|
380
|
+
Versioned Git Connect contracts for accounts, repositories, branches, webhooks and short-lived clone credentials; GitHub, GitLab and private forges attach without changing the service. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
|
|
381
|
+
|
|
382
|
+
```text
|
|
383
|
+
import {
|
|
384
|
+
defineGitConnectProvider,
|
|
385
|
+
} from '@forgezero/providers/git';
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## @forgezero/providers/git — Use this entry point
|
|
389
|
+
|
|
390
|
+
This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
|
|
391
|
+
|
|
392
|
+
```text
|
|
393
|
+
import {
|
|
394
|
+
defineGitConnectProvider,
|
|
395
|
+
} from '@forgezero/providers/git';
|
|
396
|
+
|
|
397
|
+
export const selectedCapability = defineGitConnectProvider;
|
|
398
|
+
```
|
|
399
|
+
|
|
522
400
|
## Built-in provider capabilities
|
|
523
401
|
|
|
524
402
|
A provider owns versioned capabilities; it does not own a service. A service method attaches an exact provider, method and version in an ordered array. Current, legacy and deprecated branches can coexist; retired branches never run.
|
|
525
403
|
|
|
526
404
|
```text
|
|
405
|
+
github-app
|
|
406
|
+
- listAccounts
|
|
407
|
+
- listRepositories
|
|
408
|
+
- listBranches
|
|
409
|
+
- ensureWebhook
|
|
410
|
+
- cloneCredential
|
|
527
411
|
evm-rpc
|
|
528
412
|
- request
|
|
529
413
|
jetemail
|
|
@@ -541,6 +425,29 @@ google-ai-studio
|
|
|
541
425
|
- translate
|
|
542
426
|
```
|
|
543
427
|
|
|
428
|
+
## GitHub App (github-app)
|
|
429
|
+
|
|
430
|
+
Import: @forgezero/providers/git. Each method below is a provider capability that a service attaches by exact version. User OAuth verifies an email and is discarded before the mandatory passkey. App installation credentials are minted on demand, limited to one selected repository, and expire rather than being stored. GitLab or a private forge implements the same Git Connect service without pretending to be GitHub.
|
|
431
|
+
|
|
432
|
+
```text
|
|
433
|
+
importPath: '@forgezero/providers/git'
|
|
434
|
+
providerId: 'github-app'
|
|
435
|
+
methods:
|
|
436
|
+
- listAccounts
|
|
437
|
+
- listRepositories
|
|
438
|
+
- listBranches
|
|
439
|
+
- ensureWebhook
|
|
440
|
+
- cloneCredential
|
|
441
|
+
credentials:
|
|
442
|
+
- clientSecret
|
|
443
|
+
- privateKey
|
|
444
|
+
- webhookSecret
|
|
445
|
+
config:
|
|
446
|
+
- clientId
|
|
447
|
+
- appId
|
|
448
|
+
- slug
|
|
449
|
+
```
|
|
450
|
+
|
|
544
451
|
## EVM JSON-RPC node (evm-rpc)
|
|
545
452
|
|
|
546
453
|
Import: @forgezero/providers/chain. Each method below is a provider capability that a service attaches by exact version. Several endpoints per chain is the normal case, not a luxury: public RPC is rate-limited and paid gateways have outages, and a scanner that stops when one is down stops crediting deposits while the money sits on the chain. "Already known" and "nonce too low" are TERMINAL — the transaction is already in flight, so rebroadcasting through another node is how a sweep gets sent twice.
|
package/dist/binance.js
CHANGED
package/dist/chain.js
CHANGED
package/dist/database.js
CHANGED
package/dist/email.js
CHANGED
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { type FailureKind, type InvokeContext, type ProviderDefinition } from './index';
|
|
2
|
+
export interface GitAccount {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
kind: 'user' | 'organization' | 'group' | 'other';
|
|
6
|
+
}
|
|
7
|
+
export interface GitRepository {
|
|
8
|
+
id: string;
|
|
9
|
+
fullName: string;
|
|
10
|
+
private: boolean;
|
|
11
|
+
defaultBranch: string;
|
|
12
|
+
cloneUrl: string;
|
|
13
|
+
}
|
|
14
|
+
export interface GitBranch {
|
|
15
|
+
name: string;
|
|
16
|
+
protected?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface GitCloneCredential {
|
|
19
|
+
username: string;
|
|
20
|
+
token: string;
|
|
21
|
+
expiresAtTs: number;
|
|
22
|
+
}
|
|
23
|
+
export interface GitAccountRequest {
|
|
24
|
+
cursor?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface GitRepositoryRequest {
|
|
27
|
+
accountId: string;
|
|
28
|
+
cursor?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface GitBranchRequest {
|
|
31
|
+
accountId: string;
|
|
32
|
+
repository: string;
|
|
33
|
+
cursor?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface GitWebhookRequest {
|
|
36
|
+
accountId: string;
|
|
37
|
+
repository: string;
|
|
38
|
+
callbackUrl: string;
|
|
39
|
+
secret: string;
|
|
40
|
+
events: readonly ['push'];
|
|
41
|
+
}
|
|
42
|
+
export interface GitCloneCredentialRequest {
|
|
43
|
+
accountId: string;
|
|
44
|
+
repository: string;
|
|
45
|
+
}
|
|
46
|
+
export declare const githubAppConfigSchema: {
|
|
47
|
+
readonly type: "object";
|
|
48
|
+
readonly properties: {
|
|
49
|
+
readonly clientId: {
|
|
50
|
+
readonly type: "string";
|
|
51
|
+
readonly minLength: 10;
|
|
52
|
+
readonly maxLength: 128;
|
|
53
|
+
};
|
|
54
|
+
readonly appId: {
|
|
55
|
+
readonly type: "string";
|
|
56
|
+
readonly pattern: "^[1-9][0-9]{0,19}$";
|
|
57
|
+
};
|
|
58
|
+
readonly slug: {
|
|
59
|
+
readonly type: "string";
|
|
60
|
+
readonly pattern: "^[a-z0-9][a-z0-9-]{0,99}$";
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
readonly required: readonly ["clientId", "appId", "slug"];
|
|
64
|
+
readonly additionalProperties: false;
|
|
65
|
+
};
|
|
66
|
+
export declare const githubAppCredentialSchema: {
|
|
67
|
+
readonly type: "object";
|
|
68
|
+
readonly properties: {
|
|
69
|
+
readonly clientSecret: {
|
|
70
|
+
readonly type: "string";
|
|
71
|
+
readonly minLength: 20;
|
|
72
|
+
readonly maxLength: 512;
|
|
73
|
+
readonly writeOnly: true;
|
|
74
|
+
};
|
|
75
|
+
readonly privateKey: {
|
|
76
|
+
readonly type: "string";
|
|
77
|
+
readonly minLength: 800;
|
|
78
|
+
readonly maxLength: 32768;
|
|
79
|
+
readonly writeOnly: true;
|
|
80
|
+
};
|
|
81
|
+
readonly webhookSecret: {
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
readonly minLength: 32;
|
|
84
|
+
readonly maxLength: 256;
|
|
85
|
+
readonly writeOnly: true;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
readonly required: readonly ["clientSecret", "privateKey", "webhookSecret"];
|
|
89
|
+
readonly additionalProperties: false;
|
|
90
|
+
};
|
|
91
|
+
export declare const gitConnectService: import("./index").ServiceDefinition<"git-connect", {
|
|
92
|
+
listAccounts: import("./index").ServiceMethodContract<GitAccountRequest, readonly GitAccount[]>;
|
|
93
|
+
listRepositories: import("./index").ServiceMethodContract<GitRepositoryRequest, readonly GitRepository[]>;
|
|
94
|
+
listBranches: import("./index").ServiceMethodContract<GitBranchRequest, readonly GitBranch[]>;
|
|
95
|
+
ensureWebhook: import("./index").ServiceMethodContract<GitWebhookRequest, {
|
|
96
|
+
webhookId: string;
|
|
97
|
+
created: boolean;
|
|
98
|
+
}>;
|
|
99
|
+
cloneCredential: import("./index").ServiceMethodContract<GitCloneCredentialRequest, GitCloneCredential>;
|
|
100
|
+
}>;
|
|
101
|
+
export interface GitConnectAdapter {
|
|
102
|
+
listAccounts(context: InvokeContext, args: GitAccountRequest): Promise<readonly GitAccount[]>;
|
|
103
|
+
listRepositories(context: InvokeContext, args: GitRepositoryRequest): Promise<readonly GitRepository[]>;
|
|
104
|
+
listBranches(context: InvokeContext, args: GitBranchRequest): Promise<readonly GitBranch[]>;
|
|
105
|
+
ensureWebhook(context: InvokeContext, args: GitWebhookRequest): Promise<{
|
|
106
|
+
webhookId: string;
|
|
107
|
+
created: boolean;
|
|
108
|
+
}>;
|
|
109
|
+
cloneCredential(context: InvokeContext, args: GitCloneCredentialRequest): Promise<GitCloneCredential>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Define one Git forge without coupling it to ForgeZero Vault or API storage.
|
|
113
|
+
* A GitHub App, GitLab OAuth application, self-hosted forge, or future provider
|
|
114
|
+
* supplies this adapter; the service keeps the same five typed operations.
|
|
115
|
+
*/
|
|
116
|
+
export declare function defineGitConnectProvider(args: {
|
|
117
|
+
id: string;
|
|
118
|
+
label: string;
|
|
119
|
+
version: string;
|
|
120
|
+
adapter: GitConnectAdapter;
|
|
121
|
+
credentials?: Record<string, unknown>;
|
|
122
|
+
config?: Record<string, unknown>;
|
|
123
|
+
classify?: (error: unknown) => FailureKind;
|
|
124
|
+
}): ProviderDefinition;
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
class ProviderError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
details;
|
|
5
|
+
constructor(code, message, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.details = details;
|
|
9
|
+
this.name = "ProviderError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function envCredentials(env) {
|
|
13
|
+
return {
|
|
14
|
+
name: "env",
|
|
15
|
+
async get(reference, field) {
|
|
16
|
+
const key = `${reference}_${field}`.replace(/[.-]/g, "_").toUpperCase();
|
|
17
|
+
const value = env[key];
|
|
18
|
+
if (value === undefined) {
|
|
19
|
+
throw new ProviderError("CREDENTIAL_MISSING", `Set ${key} in the environment.`);
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function chainCredentials(...sources) {
|
|
26
|
+
return {
|
|
27
|
+
name: sources.map((source) => source.name).join("+"),
|
|
28
|
+
async get(reference, field) {
|
|
29
|
+
let last;
|
|
30
|
+
for (const source of sources) {
|
|
31
|
+
try {
|
|
32
|
+
return await source.get(reference, field);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
last = error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
throw last instanceof Error ? last : new ProviderError("CREDENTIAL_MISSING", `No source held ${reference}.${field}.`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function scopeCredentials(source, reference) {
|
|
42
|
+
return {
|
|
43
|
+
name: `${source.name}:${reference}`,
|
|
44
|
+
get: (field) => source.get(reference, field)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function chainScopedCredentials(...sources) {
|
|
48
|
+
return {
|
|
49
|
+
name: sources.map((source) => source.name).join("+"),
|
|
50
|
+
async get(field) {
|
|
51
|
+
let last;
|
|
52
|
+
for (const source of sources) {
|
|
53
|
+
try {
|
|
54
|
+
return await source.get(field);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
last = error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
throw last instanceof Error ? last : new ProviderError("CREDENTIAL_MISSING", `No scoped source held field "${field}".`);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function staticConfig(config) {
|
|
64
|
+
const providers = new Map(config.providers.map((provider) => [provider.instanceKey, provider]));
|
|
65
|
+
if (providers.size !== config.providers.length) {
|
|
66
|
+
throw new ProviderError("CONFIG_DUPLICATE_INSTANCE", "Provider instance keys must be unique.");
|
|
67
|
+
}
|
|
68
|
+
const health = new Map;
|
|
69
|
+
return {
|
|
70
|
+
name: "static",
|
|
71
|
+
async provider(instanceKey) {
|
|
72
|
+
const provider = providers.get(instanceKey);
|
|
73
|
+
return provider ? { ...provider, config: { ...provider.config } } : undefined;
|
|
74
|
+
},
|
|
75
|
+
async list(serviceKey, methodKey) {
|
|
76
|
+
return (config.services[serviceKey]?.[methodKey] ?? []).map((attachment) => ({
|
|
77
|
+
...attachment,
|
|
78
|
+
health: health.get(`${serviceKey}:${methodKey}:${attachment.instanceKey}:${attachment.providerMethod}:${attachment.providerMethodVersion ?? "current"}`) ?? (attachment.providerMethodVersion === undefined ? [...health.entries()].find(([key]) => key.startsWith(`${serviceKey}:${methodKey}:${attachment.instanceKey}:${attachment.providerMethod}:`))?.[1] : undefined) ?? attachment.health
|
|
79
|
+
}));
|
|
80
|
+
},
|
|
81
|
+
async recordHealth(serviceKey, methodKey, instanceKey, providerMethod, providerMethodVersion, next) {
|
|
82
|
+
health.set(`${serviceKey}:${methodKey}:${instanceKey}:${providerMethod}:${providerMethodVersion}`, next);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function defineProviderMethod(method) {
|
|
87
|
+
return method;
|
|
88
|
+
}
|
|
89
|
+
function defineProviderMethodBranches(branches) {
|
|
90
|
+
const entries = Object.entries(branches.versions);
|
|
91
|
+
if (entries.length === 0 || !branches.versions[branches.currentVersion]) {
|
|
92
|
+
throw new ProviderError("PROVIDER_METHOD_VERSION", "A versioned provider method needs a current branch.");
|
|
93
|
+
}
|
|
94
|
+
for (const [version, method] of entries) {
|
|
95
|
+
if (method.version !== version) {
|
|
96
|
+
throw new ProviderError("PROVIDER_METHOD_VERSION", `Provider method branch "${version}" declares version "${method.version}".`);
|
|
97
|
+
}
|
|
98
|
+
if (version === branches.currentVersion && method.lifecycle !== "current") {
|
|
99
|
+
throw new ProviderError("PROVIDER_METHOD_VERSION", `Current provider method branch "${version}" must have lifecycle current.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return branches;
|
|
103
|
+
}
|
|
104
|
+
var methodBranch = (provider, methodName, version) => {
|
|
105
|
+
const entry = provider?.methods[methodName];
|
|
106
|
+
if (!entry)
|
|
107
|
+
return;
|
|
108
|
+
if ("versions" in entry)
|
|
109
|
+
return entry.versions[version ?? entry.currentVersion];
|
|
110
|
+
return version === undefined || version === entry.version ? entry : undefined;
|
|
111
|
+
};
|
|
112
|
+
function defineProvider(spec) {
|
|
113
|
+
for (const [name, entry] of Object.entries(spec.methods)) {
|
|
114
|
+
if ("versions" in entry)
|
|
115
|
+
defineProviderMethodBranches(entry);
|
|
116
|
+
else if (!entry.version || !["current", "legacy", "deprecated", "retired"].includes(entry.lifecycle)) {
|
|
117
|
+
throw new ProviderError("PROVIDER_METHOD_VERSION", `Provider method "${spec.id}.${name}" needs a version and lifecycle.`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return spec;
|
|
121
|
+
}
|
|
122
|
+
function defineSingleMethodProvider(spec) {
|
|
123
|
+
const { method, version = "v1", lifecycle = "current", invoke, classify, ...identity } = spec;
|
|
124
|
+
return defineProvider({
|
|
125
|
+
...identity,
|
|
126
|
+
methods: { [method]: defineProviderMethod({ version, lifecycle, invoke, classify }) }
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
var STRIKES_TO_OFFLINE = 3;
|
|
130
|
+
function serviceMethod() {
|
|
131
|
+
return Object.freeze({});
|
|
132
|
+
}
|
|
133
|
+
function defineService(definition) {
|
|
134
|
+
return definition;
|
|
135
|
+
}
|
|
136
|
+
function nextHealth(current, kind) {
|
|
137
|
+
if (kind === "success")
|
|
138
|
+
return { strikes: 0, status: "ok" };
|
|
139
|
+
if (kind === "backoff")
|
|
140
|
+
return current ?? { strikes: 0, status: "ok" };
|
|
141
|
+
const strikes = (current?.strikes ?? 0) + 1;
|
|
142
|
+
return {
|
|
143
|
+
strikes,
|
|
144
|
+
status: strikes >= STRIKES_TO_OFFLINE ? "offline" : "degraded",
|
|
145
|
+
lastFailureAtTs: Date.now()
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function createRegistry(options) {
|
|
149
|
+
const byId = new Map(options.providers.map((provider) => [provider.id, provider]));
|
|
150
|
+
async function call(serviceKey, methodKey, args, callOptions = {}) {
|
|
151
|
+
const configured = [...await options.config.list(serviceKey, methodKey)].filter((attachment) => attachment.enabled).sort((a, b) => a.priority - b.priority);
|
|
152
|
+
const attempts = [];
|
|
153
|
+
for (const attachment of configured) {
|
|
154
|
+
const requestedVersion = attachment.providerMethodVersion;
|
|
155
|
+
if (callOptions.signal?.aborted) {
|
|
156
|
+
const cancelled = {
|
|
157
|
+
ok: false,
|
|
158
|
+
fallbackUsed: attempts.length > 0,
|
|
159
|
+
attempts,
|
|
160
|
+
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}.${methodKey}" call was cancelled.`)
|
|
161
|
+
};
|
|
162
|
+
await options.after?.(cancelled);
|
|
163
|
+
return cancelled;
|
|
164
|
+
}
|
|
165
|
+
const instance = await options.config.provider(attachment.instanceKey);
|
|
166
|
+
if (!instance) {
|
|
167
|
+
attempts.push({ providerId: "unknown", instanceKey: attachment.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: requestedVersion ?? "current", outcome: "skipped", error: "instance not registered" });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const spec = byId.get(instance.providerId);
|
|
171
|
+
const method = methodBranch(spec, attachment.providerMethod, requestedVersion);
|
|
172
|
+
if (!spec || !method) {
|
|
173
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: requestedVersion ?? "current", outcome: "skipped", error: !spec ? "provider not registered" : "method version not supported" });
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (method.lifecycle === "retired") {
|
|
177
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: method.version, outcome: "skipped", error: "method version retired" });
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (!instance.enabled) {
|
|
181
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: method.version, outcome: "skipped", error: "instance disabled" });
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (attachment.health?.status === "offline") {
|
|
185
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: method.version, outcome: "skipped", error: "offline" });
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
await options.before?.({ service: serviceKey, method: methodKey, provider: instance.providerId, instance: instance.instanceKey });
|
|
189
|
+
const startedAt = performance.now();
|
|
190
|
+
try {
|
|
191
|
+
const result = await method.invoke({
|
|
192
|
+
config: instance.config,
|
|
193
|
+
secret: (field) => options.credentials.get(instance.secretRef, field),
|
|
194
|
+
signal: callOptions.signal
|
|
195
|
+
}, args);
|
|
196
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: method.version, outcome: "sent", durationMs: performance.now() - startedAt });
|
|
197
|
+
await options.config.recordHealth(serviceKey, methodKey, instance.instanceKey, attachment.providerMethod, method.version, nextHealth(attachment.health, "success"));
|
|
198
|
+
const sent = {
|
|
199
|
+
ok: true,
|
|
200
|
+
result,
|
|
201
|
+
provider: instance.providerId,
|
|
202
|
+
instance: instance.instanceKey,
|
|
203
|
+
method: attachment.providerMethod,
|
|
204
|
+
selected: { providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, providerMethodVersion: method.version },
|
|
205
|
+
fallbackUsed: attempts.length > 1,
|
|
206
|
+
attempts
|
|
207
|
+
};
|
|
208
|
+
await options.after?.(sent);
|
|
209
|
+
return sent;
|
|
210
|
+
} catch (error) {
|
|
211
|
+
if (callOptions.signal?.aborted) {
|
|
212
|
+
const cancelled = {
|
|
213
|
+
ok: false,
|
|
214
|
+
fallbackUsed: attempts.length > 0,
|
|
215
|
+
attempts,
|
|
216
|
+
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}.${methodKey}" call was cancelled.`)
|
|
217
|
+
};
|
|
218
|
+
await options.after?.(cancelled);
|
|
219
|
+
return cancelled;
|
|
220
|
+
}
|
|
221
|
+
const kind = method.classify(error);
|
|
222
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
223
|
+
const code = error instanceof ProviderError ? error.code : typeof error?.code === "string" ? error.code : undefined;
|
|
224
|
+
attempts.push({
|
|
225
|
+
providerId: instance.providerId,
|
|
226
|
+
instanceKey: instance.instanceKey,
|
|
227
|
+
providerMethod: attachment.providerMethod,
|
|
228
|
+
providerMethodVersion: method.version,
|
|
229
|
+
outcome: "failed",
|
|
230
|
+
kind,
|
|
231
|
+
durationMs: performance.now() - startedAt,
|
|
232
|
+
failure: { kind, ...code ? { code } : {}, message },
|
|
233
|
+
error: message
|
|
234
|
+
});
|
|
235
|
+
await options.config.recordHealth(serviceKey, methodKey, instance.instanceKey, attachment.providerMethod, method.version, nextHealth(attachment.health, kind));
|
|
236
|
+
if (kind === "terminal") {
|
|
237
|
+
const refused = {
|
|
238
|
+
ok: false,
|
|
239
|
+
fallbackUsed: attempts.length > 1,
|
|
240
|
+
attempts,
|
|
241
|
+
error: new ProviderError("PAYLOAD_REJECTED", "The request was refused as malformed; no provider will accept it.")
|
|
242
|
+
};
|
|
243
|
+
await options.after?.(refused);
|
|
244
|
+
return refused;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const failed = {
|
|
249
|
+
ok: false,
|
|
250
|
+
fallbackUsed: attempts.length > 1,
|
|
251
|
+
attempts,
|
|
252
|
+
error: new ProviderError(attempts.length === 0 ? "NO_PROVIDER" : "ALL_PROVIDERS_FAILED", attempts.length === 0 ? `No provider method is configured for "${serviceKey}.${methodKey}".` : `Every provider method for "${serviceKey}.${methodKey}" failed or was skipped.`)
|
|
253
|
+
};
|
|
254
|
+
await options.after?.(failed);
|
|
255
|
+
return failed;
|
|
256
|
+
}
|
|
257
|
+
function service(definition) {
|
|
258
|
+
return {
|
|
259
|
+
call(method, args, callOptions) {
|
|
260
|
+
return call(definition.key, method, args, callOptions);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
return { call, service };
|
|
265
|
+
}
|
|
266
|
+
function createService(definition, methods, options = {}) {
|
|
267
|
+
const providers = new Map;
|
|
268
|
+
const credentials = new Map;
|
|
269
|
+
const instances = [];
|
|
270
|
+
const serviceMethods = {};
|
|
271
|
+
for (const methodKey of Object.keys(definition.methods)) {
|
|
272
|
+
const attachments = methods[methodKey];
|
|
273
|
+
if (!Array.isArray(attachments)) {
|
|
274
|
+
throw new ProviderError("CONFIG_METHOD_MISSING", `Service method "${definition.key}.${methodKey}" needs an attachment array.`);
|
|
275
|
+
}
|
|
276
|
+
const priorities = new Set;
|
|
277
|
+
serviceMethods[methodKey] = attachments.map((attachment, index) => {
|
|
278
|
+
if (!Number.isInteger(attachment.priority) || attachment.priority < 1 || attachment.priority > 1000) {
|
|
279
|
+
throw new ProviderError("CONFIG_PRIORITY", `Priority for "${definition.key}.${methodKey}" must be an integer from 1 to 1000.`);
|
|
280
|
+
}
|
|
281
|
+
if (priorities.has(attachment.priority)) {
|
|
282
|
+
throw new ProviderError("CONFIG_PRIORITY_DUPLICATE", `Priorities for "${definition.key}.${methodKey}" must be unique.`);
|
|
283
|
+
}
|
|
284
|
+
priorities.add(attachment.priority);
|
|
285
|
+
const branch = methodBranch(attachment.provider, attachment.method, attachment.version);
|
|
286
|
+
if (!branch || branch.lifecycle === "retired") {
|
|
287
|
+
throw new ProviderError("CONFIG_METHOD_UNSUPPORTED", `Provider "${attachment.provider.id}" does not support active method "${attachment.method}@${attachment.version ?? "current"}".`);
|
|
288
|
+
}
|
|
289
|
+
const existing = providers.get(attachment.provider.id);
|
|
290
|
+
if (existing && existing !== attachment.provider) {
|
|
291
|
+
throw new ProviderError("CONFIG_PROVIDER_DUPLICATE", `Provider id "${attachment.provider.id}" has more than one definition.`);
|
|
292
|
+
}
|
|
293
|
+
providers.set(attachment.provider.id, attachment.provider);
|
|
294
|
+
const internalKey = `${definition.key}:${methodKey}:${index}`;
|
|
295
|
+
credentials.set(internalKey, attachment.credentials);
|
|
296
|
+
instances.push({
|
|
297
|
+
instanceKey: internalKey,
|
|
298
|
+
providerId: attachment.provider.id,
|
|
299
|
+
enabled: attachment.enabled ?? true,
|
|
300
|
+
config: { ...attachment.config ?? {} },
|
|
301
|
+
secretRef: internalKey
|
|
302
|
+
});
|
|
303
|
+
return {
|
|
304
|
+
instanceKey: internalKey,
|
|
305
|
+
providerMethod: attachment.method,
|
|
306
|
+
providerMethodVersion: branch.version,
|
|
307
|
+
priority: attachment.priority,
|
|
308
|
+
enabled: attachment.enabled ?? true
|
|
309
|
+
};
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
const registry = createRegistry({
|
|
313
|
+
providers: [...providers.values()],
|
|
314
|
+
config: staticConfig({ providers: instances, services: { [definition.key]: serviceMethods } }),
|
|
315
|
+
credentials: {
|
|
316
|
+
name: [...new Set([...credentials.values()].map((source) => source.name))].join("+"),
|
|
317
|
+
async get(reference, field) {
|
|
318
|
+
const source = credentials.get(reference);
|
|
319
|
+
if (!source)
|
|
320
|
+
throw new ProviderError("CREDENTIAL_SOURCE_MISSING", "The provider credential source is unavailable.");
|
|
321
|
+
return source.get(field);
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
...options
|
|
325
|
+
});
|
|
326
|
+
const dynamic = registry.service(definition);
|
|
327
|
+
return {
|
|
328
|
+
async call(method, args, callOptions) {
|
|
329
|
+
const result = await dynamic.call(method, args, callOptions);
|
|
330
|
+
const { instance: _instance, selected, attempts, ...rest } = result;
|
|
331
|
+
return {
|
|
332
|
+
...rest,
|
|
333
|
+
...selected ? { selected: { providerId: selected.providerId, providerMethod: selected.providerMethod, providerMethodVersion: selected.providerMethodVersion } } : {},
|
|
334
|
+
attempts: attempts.map(({ instanceKey: _instanceKey, ...attempt }) => attempt)
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
var VERSION = "0.1.23";
|
|
340
|
+
|
|
341
|
+
// src/git.ts
|
|
342
|
+
var githubAppConfigSchema = {
|
|
343
|
+
type: "object",
|
|
344
|
+
properties: {
|
|
345
|
+
clientId: { type: "string", minLength: 10, maxLength: 128 },
|
|
346
|
+
appId: { type: "string", pattern: "^[1-9][0-9]{0,19}$" },
|
|
347
|
+
slug: { type: "string", pattern: "^[a-z0-9][a-z0-9-]{0,99}$" }
|
|
348
|
+
},
|
|
349
|
+
required: ["clientId", "appId", "slug"],
|
|
350
|
+
additionalProperties: false
|
|
351
|
+
};
|
|
352
|
+
var githubAppCredentialSchema = {
|
|
353
|
+
type: "object",
|
|
354
|
+
properties: {
|
|
355
|
+
clientSecret: { type: "string", minLength: 20, maxLength: 512, writeOnly: true },
|
|
356
|
+
privateKey: { type: "string", minLength: 800, maxLength: 32768, writeOnly: true },
|
|
357
|
+
webhookSecret: { type: "string", minLength: 32, maxLength: 256, writeOnly: true }
|
|
358
|
+
},
|
|
359
|
+
required: ["clientSecret", "privateKey", "webhookSecret"],
|
|
360
|
+
additionalProperties: false
|
|
361
|
+
};
|
|
362
|
+
var gitConnectService = defineService({
|
|
363
|
+
key: "git-connect",
|
|
364
|
+
methods: {
|
|
365
|
+
listAccounts: serviceMethod(),
|
|
366
|
+
listRepositories: serviceMethod(),
|
|
367
|
+
listBranches: serviceMethod(),
|
|
368
|
+
ensureWebhook: serviceMethod(),
|
|
369
|
+
cloneCredential: serviceMethod()
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
function defineGitConnectProvider(args) {
|
|
373
|
+
const classify = args.classify ?? (() => "retryable");
|
|
374
|
+
const branch = (invoke) => defineProviderMethodBranches({
|
|
375
|
+
currentVersion: args.version,
|
|
376
|
+
versions: {
|
|
377
|
+
[args.version]: { version: args.version, lifecycle: "current", invoke, classify }
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
return defineProvider({
|
|
381
|
+
id: args.id,
|
|
382
|
+
label: args.label,
|
|
383
|
+
multiInstance: true,
|
|
384
|
+
credentials: args.credentials,
|
|
385
|
+
config: args.config,
|
|
386
|
+
methods: {
|
|
387
|
+
listAccounts: branch(args.adapter.listAccounts),
|
|
388
|
+
listRepositories: branch(args.adapter.listRepositories),
|
|
389
|
+
listBranches: branch(args.adapter.listBranches),
|
|
390
|
+
ensureWebhook: branch(args.adapter.ensureWebhook),
|
|
391
|
+
cloneCredential: branch(args.adapter.cloneCredential)
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
export {
|
|
396
|
+
githubAppCredentialSchema,
|
|
397
|
+
githubAppConfigSchema,
|
|
398
|
+
gitConnectService,
|
|
399
|
+
defineGitConnectProvider
|
|
400
|
+
};
|
package/dist/http.js
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/pool.js
CHANGED
package/dist/storage.js
CHANGED
package/dist/translation.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgezero/providers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"./realtime": {
|
|
47
47
|
"types": "./dist/realtime.d.ts",
|
|
48
48
|
"default": "./dist/realtime.js"
|
|
49
|
+
},
|
|
50
|
+
"./git": {
|
|
51
|
+
"types": "./dist/git.d.ts",
|
|
52
|
+
"default": "./dist/git.js"
|
|
49
53
|
}
|
|
50
54
|
},
|
|
51
55
|
"scripts": {
|
|
@@ -85,6 +89,6 @@
|
|
|
85
89
|
"LICENSE"
|
|
86
90
|
],
|
|
87
91
|
"dependencies": {
|
|
88
|
-
"@forgezero/runtime": "^0.1.
|
|
92
|
+
"@forgezero/runtime": "^0.1.14"
|
|
89
93
|
}
|
|
90
94
|
}
|