@bpmnkit/api 0.0.8

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 (48) hide show
  1. package/README.md +150 -0
  2. package/dist/generated/admin-resources.d.ts +199 -0
  3. package/dist/generated/admin-resources.js +381 -0
  4. package/dist/generated/admin-types.d.ts +283 -0
  5. package/dist/generated/admin-types.js +4 -0
  6. package/dist/generated/resources.d.ts +1519 -0
  7. package/dist/generated/resources.js +2650 -0
  8. package/dist/generated/types.d.ts +11946 -0
  9. package/dist/generated/types.js +4 -0
  10. package/dist/index.d.ts +11 -0
  11. package/dist/index.js +10 -0
  12. package/dist/runtime/auth.d.ts +31 -0
  13. package/dist/runtime/auth.js +136 -0
  14. package/dist/runtime/cache.d.ts +13 -0
  15. package/dist/runtime/cache.js +48 -0
  16. package/dist/runtime/cache.test.d.ts +2 -0
  17. package/dist/runtime/cache.test.js +38 -0
  18. package/dist/runtime/client.d.ts +25 -0
  19. package/dist/runtime/client.js +33 -0
  20. package/dist/runtime/config.d.ts +15 -0
  21. package/dist/runtime/config.js +371 -0
  22. package/dist/runtime/errors.d.ts +53 -0
  23. package/dist/runtime/errors.js +101 -0
  24. package/dist/runtime/errors.test.d.ts +2 -0
  25. package/dist/runtime/errors.test.js +40 -0
  26. package/dist/runtime/events.d.ts +12 -0
  27. package/dist/runtime/events.js +48 -0
  28. package/dist/runtime/events.test.d.ts +2 -0
  29. package/dist/runtime/events.test.js +57 -0
  30. package/dist/runtime/http.d.ts +15 -0
  31. package/dist/runtime/http.js +210 -0
  32. package/dist/runtime/logger.d.ts +9 -0
  33. package/dist/runtime/logger.js +34 -0
  34. package/dist/runtime/relations.d.ts +43 -0
  35. package/dist/runtime/relations.js +54 -0
  36. package/dist/runtime/retry.d.ts +14 -0
  37. package/dist/runtime/retry.js +41 -0
  38. package/dist/runtime/retry.test.d.ts +2 -0
  39. package/dist/runtime/retry.test.js +46 -0
  40. package/dist/runtime/token-cache.d.ts +42 -0
  41. package/dist/runtime/token-cache.js +104 -0
  42. package/dist/runtime/types.d.ts +191 -0
  43. package/dist/runtime/types.js +2 -0
  44. package/dist/runtime/yaml.d.ts +14 -0
  45. package/dist/runtime/yaml.js +234 -0
  46. package/dist/runtime/yaml.test.d.ts +2 -0
  47. package/dist/runtime/yaml.test.js +93 -0
  48. package/package.json +31 -0
@@ -0,0 +1,4 @@
1
+ // This file is auto-generated by scripts/generate.mjs
2
+ // Do not edit manually. Run `pnpm --filter @bpmnkit/api generate` to regenerate.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,11 @@
1
+ export type { CamundaClientConfig, CamundaClientInput, AuthConfig, RetryConfig, CacheConfig, LoggerConfig, LogLevel, CachedToken, TokenStore, TokenCacheConfig, } from "./runtime/types.js";
2
+ export type { ClientEventMap, RequestEvent, ResponseEvent, RawResponseEvent, ErrorEvent, RetryEvent, TokenRefreshEvent, CacheEvent, } from "./runtime/types.js";
3
+ export { CamundaError, CamundaHttpError, CamundaValidationError, CamundaAuthError, CamundaForbiddenError, CamundaNotFoundError, CamundaConflictError, CamundaRateLimitError, CamundaServerError, CamundaNetworkError, CamundaTimeoutError, } from "./runtime/errors.js";
4
+ export { FileTokenStore, NullTokenStore, defaultTokenCachePath } from "./runtime/token-cache.js";
5
+ export { CamundaClient } from "./generated/resources.js";
6
+ export type * from "./generated/types.js";
7
+ export { AdminApiClient } from "./generated/admin-resources.js";
8
+ export type * from "./generated/admin-types.js";
9
+ export type { Relation, RelationSource } from "./runtime/relations.js";
10
+ export { buildRelations } from "./runtime/relations.js";
11
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // Runtime — errors
2
+ export { CamundaError, CamundaHttpError, CamundaValidationError, CamundaAuthError, CamundaForbiddenError, CamundaNotFoundError, CamundaConflictError, CamundaRateLimitError, CamundaServerError, CamundaNetworkError, CamundaTimeoutError, } from "./runtime/errors.js";
3
+ // Runtime — token store implementations
4
+ export { FileTokenStore, NullTokenStore, defaultTokenCachePath } from "./runtime/token-cache.js";
5
+ // Generated C8 client (the main export)
6
+ export { CamundaClient } from "./generated/resources.js";
7
+ // Generated Admin API client
8
+ export { AdminApiClient } from "./generated/admin-resources.js";
9
+ export { buildRelations } from "./runtime/relations.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,31 @@
1
+ import type { AuthConfig, TokenStore } from "./types.js";
2
+ export interface AuthProvider {
3
+ /** Returns a value for the Authorization header, or null if not applicable. */
4
+ getAuthorizationHeader(): Promise<string | null>;
5
+ /** Called after a 401 to allow token refresh. Returns true if a retry may succeed. */
6
+ handleUnauthorized(): Promise<boolean>;
7
+ }
8
+ export declare class NoAuthProvider implements AuthProvider {
9
+ getAuthorizationHeader(): Promise<null>;
10
+ handleUnauthorized(): Promise<boolean>;
11
+ }
12
+ export declare class BearerAuthProvider implements AuthProvider {
13
+ private token;
14
+ constructor(token: string);
15
+ getAuthorizationHeader(): Promise<string>;
16
+ handleUnauthorized(): Promise<boolean>;
17
+ }
18
+ export declare class BasicAuthProvider implements AuthProvider {
19
+ #private;
20
+ constructor(username: string, password: string);
21
+ getAuthorizationHeader(): Promise<string>;
22
+ handleUnauthorized(): Promise<boolean>;
23
+ }
24
+ export declare class OAuth2Provider implements AuthProvider {
25
+ #private;
26
+ constructor(clientId: string, clientSecret: string, tokenUrl: string, scope?: string, audience?: string, store?: TokenStore, onRefresh?: () => void);
27
+ getAuthorizationHeader(): Promise<string>;
28
+ handleUnauthorized(): Promise<boolean>;
29
+ }
30
+ export declare function createAuthProvider(config: AuthConfig, store?: TokenStore, onRefresh?: () => void): AuthProvider;
31
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1,136 @@
1
+ import { CamundaAuthError } from "./errors.js";
2
+ import { buildTokenCacheKey, resolveTokenStore } from "./token-cache.js";
3
+ export class NoAuthProvider {
4
+ async getAuthorizationHeader() {
5
+ return null;
6
+ }
7
+ async handleUnauthorized() {
8
+ return false;
9
+ }
10
+ }
11
+ export class BearerAuthProvider {
12
+ token;
13
+ constructor(token) {
14
+ this.token = token;
15
+ }
16
+ async getAuthorizationHeader() {
17
+ return `Bearer ${this.token}`;
18
+ }
19
+ async handleUnauthorized() {
20
+ return false;
21
+ }
22
+ }
23
+ export class BasicAuthProvider {
24
+ #encoded;
25
+ constructor(username, password) {
26
+ this.#encoded = btoa(`${username}:${password}`);
27
+ }
28
+ async getAuthorizationHeader() {
29
+ return `Basic ${this.#encoded}`;
30
+ }
31
+ async handleUnauthorized() {
32
+ return false;
33
+ }
34
+ }
35
+ export class OAuth2Provider {
36
+ #clientId;
37
+ #clientSecret;
38
+ #tokenUrl;
39
+ #scope;
40
+ #audience;
41
+ /** In-memory token for the current process. */
42
+ #memoryToken = null;
43
+ #memoryExpiresAt = 0;
44
+ /** Persistent store (file / custom). */
45
+ #store;
46
+ #cacheKey;
47
+ /** Deduplicates concurrent refresh calls. */
48
+ #refreshing = null;
49
+ #onRefresh;
50
+ constructor(clientId, clientSecret, tokenUrl, scope, audience, store, onRefresh) {
51
+ this.#clientId = clientId;
52
+ this.#clientSecret = clientSecret;
53
+ this.#tokenUrl = tokenUrl;
54
+ this.#scope = scope;
55
+ this.#audience = audience;
56
+ this.#store = store ?? resolveTokenStore(undefined); // default: FileTokenStore
57
+ this.#cacheKey = buildTokenCacheKey(clientId, tokenUrl, scope, audience);
58
+ this.#onRefresh = onRefresh;
59
+ }
60
+ async getAuthorizationHeader() {
61
+ const token = await this.#getToken();
62
+ return `Bearer ${token}`;
63
+ }
64
+ async handleUnauthorized() {
65
+ // Invalidate both in-memory and persistent cache so next call fetches fresh
66
+ this.#memoryToken = null;
67
+ this.#memoryExpiresAt = 0;
68
+ await this.#store.set(this.#cacheKey, { accessToken: "", expiresAt: 0 });
69
+ return true;
70
+ }
71
+ async #getToken() {
72
+ // 1. Check in-memory token first (fastest path)
73
+ if (this.#memoryToken && Date.now() < this.#memoryExpiresAt - 30_000) {
74
+ return this.#memoryToken;
75
+ }
76
+ // 2. Check persistent store
77
+ const cached = await this.#store.get(this.#cacheKey);
78
+ if (cached?.accessToken) {
79
+ this.#memoryToken = cached.accessToken;
80
+ this.#memoryExpiresAt = cached.expiresAt;
81
+ return cached.accessToken;
82
+ }
83
+ // 3. Fetch a new token — deduplicate concurrent calls
84
+ if (this.#refreshing) {
85
+ return this.#refreshing;
86
+ }
87
+ this.#refreshing = this.#fetchToken().finally(() => {
88
+ this.#refreshing = null;
89
+ });
90
+ return this.#refreshing;
91
+ }
92
+ async #fetchToken() {
93
+ this.#onRefresh?.();
94
+ const params = new URLSearchParams({
95
+ grant_type: "client_credentials",
96
+ client_id: this.#clientId,
97
+ client_secret: this.#clientSecret,
98
+ });
99
+ if (this.#scope)
100
+ params.set("scope", this.#scope);
101
+ if (this.#audience)
102
+ params.set("audience", this.#audience);
103
+ const response = await fetch(this.#tokenUrl, {
104
+ method: "POST",
105
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
106
+ body: params.toString(),
107
+ });
108
+ if (!response.ok) {
109
+ throw new CamundaAuthError(`OAuth2 token request failed: ${response.status}`, response.status, await response.text(), this.#tokenUrl);
110
+ }
111
+ const data = (await response.json());
112
+ const expiresAt = Date.now() + (data.expires_in ?? 3600) * 1000;
113
+ // Update in-memory state
114
+ this.#memoryToken = data.access_token;
115
+ this.#memoryExpiresAt = expiresAt;
116
+ // Persist to store (fire and forget — failure is non-fatal)
117
+ this.#store.set(this.#cacheKey, {
118
+ accessToken: data.access_token,
119
+ expiresAt,
120
+ });
121
+ return data.access_token;
122
+ }
123
+ }
124
+ export function createAuthProvider(config, store, onRefresh) {
125
+ switch (config.type) {
126
+ case "bearer":
127
+ return new BearerAuthProvider(config.token);
128
+ case "basic":
129
+ return new BasicAuthProvider(config.username, config.password);
130
+ case "oauth2":
131
+ return new OAuth2Provider(config.clientId, config.clientSecret, config.tokenUrl, config.scope, config.audience, store, onRefresh);
132
+ case "none":
133
+ return new NoAuthProvider();
134
+ }
135
+ }
136
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Simple LRU cache with TTL expiry. No external dependencies.
3
+ */
4
+ export declare class Cache {
5
+ #private;
6
+ constructor(ttl: number, maxSize: number);
7
+ get<T>(key: string): T | undefined;
8
+ set(key: string, value: unknown, ttlOverride?: number): void;
9
+ delete(key: string): void;
10
+ clear(): void;
11
+ get size(): number;
12
+ }
13
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Simple LRU cache with TTL expiry. No external dependencies.
3
+ */
4
+ export class Cache {
5
+ #store = new Map();
6
+ #ttl;
7
+ #maxSize;
8
+ constructor(ttl, maxSize) {
9
+ this.#ttl = ttl;
10
+ this.#maxSize = maxSize;
11
+ }
12
+ get(key) {
13
+ const entry = this.#store.get(key);
14
+ if (!entry)
15
+ return undefined;
16
+ if (Date.now() > entry.expiresAt) {
17
+ this.#store.delete(key);
18
+ return undefined;
19
+ }
20
+ // LRU: move to end by re-inserting
21
+ this.#store.delete(key);
22
+ this.#store.set(key, entry);
23
+ return entry.value;
24
+ }
25
+ set(key, value, ttlOverride) {
26
+ if (this.#store.size >= this.#maxSize) {
27
+ // Evict oldest entry (first in insertion order)
28
+ const oldest = this.#store.keys().next().value;
29
+ if (oldest !== undefined) {
30
+ this.#store.delete(oldest);
31
+ }
32
+ }
33
+ this.#store.set(key, {
34
+ value,
35
+ expiresAt: Date.now() + (ttlOverride ?? this.#ttl),
36
+ });
37
+ }
38
+ delete(key) {
39
+ this.#store.delete(key);
40
+ }
41
+ clear() {
42
+ this.#store.clear();
43
+ }
44
+ get size() {
45
+ return this.#store.size;
46
+ }
47
+ }
48
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { Cache } from "./cache.js";
3
+ describe("Cache", () => {
4
+ it("stores and retrieves values", () => {
5
+ const cache = new Cache(60_000, 100);
6
+ cache.set("key", { value: 42 });
7
+ expect(cache.get("key")).toEqual({ value: 42 });
8
+ });
9
+ it("returns undefined for missing keys", () => {
10
+ const cache = new Cache(60_000, 100);
11
+ expect(cache.get("missing")).toBeUndefined();
12
+ });
13
+ it("expires entries after TTL", () => {
14
+ vi.useFakeTimers();
15
+ const cache = new Cache(100, 100);
16
+ cache.set("key", "value");
17
+ vi.advanceTimersByTime(200);
18
+ expect(cache.get("key")).toBeUndefined();
19
+ vi.useRealTimers();
20
+ });
21
+ it("evicts oldest entry when maxSize is exceeded", () => {
22
+ const cache = new Cache(60_000, 2);
23
+ cache.set("a", 1);
24
+ cache.set("b", 2);
25
+ cache.set("c", 3); // should evict "a"
26
+ expect(cache.get("a")).toBeUndefined();
27
+ expect(cache.get("b")).toBe(2);
28
+ expect(cache.get("c")).toBe(3);
29
+ });
30
+ it("clear removes all entries", () => {
31
+ const cache = new Cache(60_000, 100);
32
+ cache.set("a", 1);
33
+ cache.set("b", 2);
34
+ cache.clear();
35
+ expect(cache.size).toBe(0);
36
+ });
37
+ });
38
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1,25 @@
1
+ import { TypedEventEmitter } from "./events.js";
2
+ import { HttpClient } from "./http.js";
3
+ import type { CamundaClientConfig, CamundaClientInput, ClientEventMap } from "./types.js";
4
+ /**
5
+ * Base class for CamundaClient. The generated subclass adds all resource
6
+ * properties (processInstance, job, userTask, …).
7
+ */
8
+ export declare class CamundaBaseClient extends TypedEventEmitter<ClientEventMap> {
9
+ readonly http: HttpClient;
10
+ /** The fully resolved configuration used by this client. */
11
+ readonly config: CamundaClientConfig;
12
+ constructor(input?: CamundaClientInput);
13
+ /**
14
+ * Clears the in-memory response cache (if caching is enabled).
15
+ */
16
+ clearCache(): void;
17
+ }
18
+ /**
19
+ * Base class for all generated resource classes.
20
+ */
21
+ export declare class ResourceBase {
22
+ protected readonly _http: HttpClient;
23
+ constructor(_http: HttpClient);
24
+ }
25
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,33 @@
1
+ import { resolveConfig } from "./config.js";
2
+ import { TypedEventEmitter } from "./events.js";
3
+ import { HttpClient } from "./http.js";
4
+ /**
5
+ * Base class for CamundaClient. The generated subclass adds all resource
6
+ * properties (processInstance, job, userTask, …).
7
+ */
8
+ export class CamundaBaseClient extends TypedEventEmitter {
9
+ http;
10
+ /** The fully resolved configuration used by this client. */
11
+ config;
12
+ constructor(input = {}) {
13
+ super();
14
+ this.config = resolveConfig(input);
15
+ this.http = new HttpClient(this.config, this);
16
+ }
17
+ /**
18
+ * Clears the in-memory response cache (if caching is enabled).
19
+ */
20
+ clearCache() {
21
+ this.http.cache?.clear();
22
+ }
23
+ }
24
+ /**
25
+ * Base class for all generated resource classes.
26
+ */
27
+ export class ResourceBase {
28
+ _http;
29
+ constructor(_http) {
30
+ this._http = _http;
31
+ }
32
+ }
33
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,15 @@
1
+ import type { CamundaClientConfig, CamundaClientInput } from "./types.js";
2
+ declare function loadFromEnv(): CamundaClientInput;
3
+ declare function loadFromFile(filePath: string): CamundaClientInput;
4
+ /**
5
+ * Resolve the final `CamundaClientConfig` from three layers (lowest → highest):
6
+ * 1. Environment variables (CAMUNDA_*)
7
+ * 2. YAML config file (path from `input.configFile` or `CAMUNDA_CONFIG_FILE`)
8
+ * 3. Values passed directly to the constructor (`input`)
9
+ *
10
+ * Throws `CamundaError` if `baseUrl` or `auth` cannot be resolved.
11
+ */
12
+ export declare function resolveConfig(input: CamundaClientInput): CamundaClientConfig;
13
+ /** Exported for testing. */
14
+ export { loadFromEnv, loadFromFile };
15
+ //# sourceMappingURL=config.d.ts.map