@bpmnkit/profiles 0.0.5

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 ADDED
@@ -0,0 +1,139 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/bpmn-sdk/monorepo/main/doc/logos/logo-2-gateway.svg" width="72" height="72" alt="BPMN Kit logo">
3
+ <h1>@bpmnkit/profiles</h1>
4
+ <p>Shared auth, profile storage, and client factories for the BPMN Kit CLI and proxy server</p>
5
+
6
+ [![npm](https://img.shields.io/npm/v/@bpmnkit/profiles?style=flat-square&color=6244d7)](https://www.npmjs.com/package/@bpmnkit/profiles)
7
+ [![license](https://img.shields.io/npm/l/@bpmnkit/profiles?style=flat-square)](https://github.com/bpmnkit/monorepo/blob/main/LICENSE)
8
+ [![typescript](https://img.shields.io/badge/TypeScript-strict-6244d7?style=flat-square&logo=typescript&logoColor=white)](https://github.com/bpmnkit/monorepo)
9
+
10
+ [Documentation](https://bpmn-sdk-docs.pages.dev) · [GitHub](https://github.com/bpmnkit/monorepo) · [Changelog](https://github.com/bpmnkit/monorepo/blob/main/packages/profiles/CHANGELOG.md)
11
+ </div>
12
+
13
+ ---
14
+
15
+ ## Overview
16
+
17
+ `@bpmnkit/profiles` is the shared layer that connects the `casen` CLI with the local proxy server. It handles profile CRUD (read/write to `~/.config/casen/config.json`), creates typed `CamundaClient` instances from stored profiles, and resolves Authorization headers for any supported auth type.
18
+
19
+ You do not need this package if you are connecting directly to Camunda using `@bpmnkit/api`. It is intended for tooling that needs to share authentication state with the CLI.
20
+
21
+ ## Features
22
+
23
+ - **Profile CRUD** — list, get, save, delete, and activate named profiles stored in `~/.config/casen/config.json`
24
+ - **Client factory** — `createClientFromProfile(name?)` creates a ready-to-use `CamundaClient` from the active or named profile
25
+ - **Auth header resolution** — `getAuthHeader(config)` returns the correct `Authorization` header string for Bearer, Basic, and OAuth2 auth types
26
+ - **OAuth2 token caching** — tokens are cached in memory and refreshed 60 seconds before expiry; no extra files written
27
+ - **XDG-aware** — profile file path resolves to the correct platform directory (Linux XDG, macOS, Windows AppData)
28
+ - **Zero UI dependencies** — no TUI or CLI dependencies; plain Node.js
29
+
30
+ ## Installation
31
+
32
+ ```sh
33
+ npm install @bpmnkit/profiles
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ### Create a `CamundaClient` from the active profile
39
+
40
+ ```typescript
41
+ import { createClientFromProfile } from "@bpmnkit/profiles"
42
+
43
+ // Uses the currently active profile from ~/.config/casen/config.json
44
+ const client = createClientFromProfile()
45
+
46
+ const instances = await client.processInstance.searchProcessInstances({})
47
+ console.log(instances.page.totalItems)
48
+ ```
49
+
50
+ ### Use a named profile
51
+
52
+ ```typescript
53
+ const client = createClientFromProfile("production")
54
+ ```
55
+
56
+ ### Resolve an auth header directly
57
+
58
+ ```typescript
59
+ import { getActiveProfile, getAuthHeader } from "@bpmnkit/profiles"
60
+
61
+ const profile = getActiveProfile()
62
+ if (profile) {
63
+ const header = await getAuthHeader(profile.config)
64
+ // "Bearer eyJ..." or "Basic dXNlcjpwYXNz" or ""
65
+ }
66
+ ```
67
+
68
+ ### Manage profiles programmatically
69
+
70
+ ```typescript
71
+ import { listProfiles, saveProfile, useProfile, deleteProfile } from "@bpmnkit/profiles"
72
+
73
+ // List all profiles
74
+ const profiles = listProfiles()
75
+
76
+ // Save a new profile
77
+ saveProfile({
78
+ name: "local",
79
+ apiType: "self-managed",
80
+ config: {
81
+ baseUrl: "http://localhost:8080/v2",
82
+ auth: { type: "basic", username: "admin", password: "admin" },
83
+ },
84
+ })
85
+
86
+ // Activate a profile
87
+ useProfile("local")
88
+
89
+ // Delete a profile
90
+ deleteProfile("old-profile")
91
+ ```
92
+
93
+ ## API Reference
94
+
95
+ ### Profile Management
96
+
97
+ | Export | Description |
98
+ |--------|-------------|
99
+ | `listProfiles()` | Returns all stored profiles |
100
+ | `getProfile(name)` | Returns a profile by name, or `undefined` |
101
+ | `getActiveProfile()` | Returns the currently active profile |
102
+ | `getActiveName()` | Returns the active profile name |
103
+ | `saveProfile(profile)` | Create or update a profile |
104
+ | `deleteProfile(name)` | Remove a profile |
105
+ | `useProfile(name)` | Set the active profile |
106
+ | `getConfigFilePath()` | Returns the full path to the config file |
107
+
108
+ ### Client Factories
109
+
110
+ | Export | Description |
111
+ |--------|-------------|
112
+ | `createClientFromProfile(name?)` | `CamundaClient` from the active or named profile |
113
+ | `createAdminClientFromProfile(name?)` | `AdminApiClient` from the active or named profile |
114
+
115
+ ### Auth
116
+
117
+ | Export | Description |
118
+ |--------|-------------|
119
+ | `getAuthHeader(config)` | Resolves an `Authorization` header string for any auth type |
120
+
121
+ ---
122
+
123
+ ## Related Packages
124
+
125
+ | Package | Description |
126
+ |---------|-------------|
127
+ | [`@bpmnkit/core`](https://www.npmjs.com/package/@bpmnkit/core) | BPMN/DMN/Form parser, builder, layout engine |
128
+ | [`@bpmnkit/canvas`](https://www.npmjs.com/package/@bpmnkit/canvas) | Zero-dependency SVG BPMN viewer |
129
+ | [`@bpmnkit/editor`](https://www.npmjs.com/package/@bpmnkit/editor) | Full-featured interactive BPMN editor |
130
+ | [`@bpmnkit/engine`](https://www.npmjs.com/package/@bpmnkit/engine) | Lightweight BPMN process execution engine |
131
+ | [`@bpmnkit/feel`](https://www.npmjs.com/package/@bpmnkit/feel) | FEEL expression language parser & evaluator |
132
+ | [`@bpmnkit/plugins`](https://www.npmjs.com/package/@bpmnkit/plugins) | 22 composable canvas plugins |
133
+ | [`@bpmnkit/api`](https://www.npmjs.com/package/@bpmnkit/api) | Camunda 8 REST API TypeScript client |
134
+ | [`@bpmnkit/ascii`](https://www.npmjs.com/package/@bpmnkit/ascii) | Render BPMN diagrams as Unicode ASCII art |
135
+ | [`@bpmnkit/operate`](https://www.npmjs.com/package/@bpmnkit/operate) | Monitoring & operations frontend for Camunda clusters |
136
+
137
+ ## License
138
+
139
+ [MIT](https://github.com/bpmnkit/monorepo/blob/main/LICENSE) © bpmn-sdk
@@ -0,0 +1,4 @@
1
+ import { AdminApiClient, CamundaClient } from "@bpmnkit/api";
2
+ export declare function createClientFromProfile(profileName?: string): CamundaClient;
3
+ export declare function createAdminClientFromProfile(profileName?: string): AdminApiClient;
4
+ //# sourceMappingURL=client.d.ts.map
package/dist/client.js ADDED
@@ -0,0 +1,19 @@
1
+ import { AdminApiClient, CamundaClient } from "@bpmnkit/api";
2
+ import { getActiveProfile, getProfile } from "./profile.js";
3
+ function requireProfile(profileName) {
4
+ const profile = profileName ? getProfile(profileName) : getActiveProfile();
5
+ if (!profile) {
6
+ if (profileName) {
7
+ throw new Error(`Profile "${profileName}" not found. Run \`casen profile list\` to see available profiles.`);
8
+ }
9
+ throw new Error("No active profile. Create one with:\n\n casen profile create <name> --base-url <url> --auth-type bearer --token <token>\n");
10
+ }
11
+ return profile;
12
+ }
13
+ export function createClientFromProfile(profileName) {
14
+ return new CamundaClient(requireProfile(profileName).config);
15
+ }
16
+ export function createAdminClientFromProfile(profileName) {
17
+ return new AdminApiClient(requireProfile(profileName).config);
18
+ }
19
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,6 @@
1
+ export type { ApiType, AuditEntry, Profile, Settings } from "./profile.js";
2
+ export { listModelerProfiles } from "./modeler.js";
3
+ export { appendAuditEntry, clearAuditLog, deleteProfile, getActiveProfile, getActiveName, getAuditLog, getConfigFilePath, getProfile, getSettings, listProfiles, saveProfile, saveSettings, useProfile, } from "./profile.js";
4
+ export { createAdminClientFromProfile, createClientFromProfile } from "./client.js";
5
+ export { getAuthHeader } from "./token.js";
6
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { listModelerProfiles } from "./modeler.js";
2
+ export { appendAuditEntry, clearAuditLog, deleteProfile, getActiveProfile, getActiveName, getAuditLog, getConfigFilePath, getProfile, getSettings, listProfiles, saveProfile, saveSettings, useProfile, } from "./profile.js";
3
+ export { createAdminClientFromProfile, createClientFromProfile } from "./client.js";
4
+ export { getAuthHeader } from "./token.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import type { Profile } from "./profile.js";
2
+ export declare function listModelerProfiles(): Profile[];
3
+ //# sourceMappingURL=modeler.d.ts.map
@@ -0,0 +1,95 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { homedir, platform } from "node:os";
3
+ import { join } from "node:path";
4
+ // ─── Modeler config directory ─────────────────────────────────────────────────
5
+ function modelerConfigDir() {
6
+ const p = platform();
7
+ if (p === "win32")
8
+ return join(process.env.APPDATA ?? homedir(), "camunda-modeler");
9
+ if (p === "darwin")
10
+ return join(homedir(), "Library", "Application Support", "camunda-modeler");
11
+ return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "camunda-modeler");
12
+ }
13
+ // ─── Auth mapping ─────────────────────────────────────────────────────────────
14
+ function toAuth(conn) {
15
+ const targetType = typeof conn.targetType === "string" ? conn.targetType : "";
16
+ const authType = typeof conn.authType === "string" ? conn.authType : "";
17
+ // Camunda Cloud (SaaS): use OAuth2 with cloud token endpoint when credentials present
18
+ if (targetType === "camundaCloud" &&
19
+ typeof conn.camundaCloudClientId === "string" &&
20
+ conn.camundaCloudClientId &&
21
+ typeof conn.camundaCloudClientSecret === "string" &&
22
+ conn.camundaCloudClientSecret) {
23
+ return {
24
+ type: "oauth2",
25
+ clientId: conn.camundaCloudClientId,
26
+ clientSecret: conn.camundaCloudClientSecret,
27
+ tokenUrl: "https://login.cloud.camunda.io/oauth/token",
28
+ audience: "zeebe.camunda.io",
29
+ };
30
+ }
31
+ // Self-managed OAuth2
32
+ if ((authType === "clientCredentials" || authType === "oauth2") &&
33
+ typeof conn.clientId === "string" &&
34
+ conn.clientId &&
35
+ typeof conn.clientSecret === "string" &&
36
+ conn.clientSecret) {
37
+ return {
38
+ type: "oauth2",
39
+ clientId: conn.clientId,
40
+ clientSecret: conn.clientSecret,
41
+ tokenUrl: typeof conn.tokenUrl === "string" ? conn.tokenUrl : "",
42
+ audience: typeof conn.audience === "string" ? conn.audience : undefined,
43
+ };
44
+ }
45
+ // Bearer token
46
+ if (authType === "bearer" && typeof conn.bearerToken === "string" && conn.bearerToken) {
47
+ return { type: "bearer", token: conn.bearerToken };
48
+ }
49
+ // Basic auth
50
+ if (authType === "basic" &&
51
+ typeof conn.username === "string" &&
52
+ conn.username &&
53
+ typeof conn.password === "string") {
54
+ return { type: "basic", username: conn.username, password: conn.password };
55
+ }
56
+ return { type: "none" };
57
+ }
58
+ function toProfile(conn) {
59
+ const name = typeof conn.name === "string" && conn.name ? conn.name : null;
60
+ if (!name)
61
+ return null;
62
+ const baseUrl = typeof conn.contactPoint === "string" && conn.contactPoint ? conn.contactPoint : undefined;
63
+ return {
64
+ name,
65
+ apiType: "c8",
66
+ config: { baseUrl, auth: toAuth(conn) },
67
+ createdAt: null,
68
+ source: "modeler",
69
+ };
70
+ }
71
+ // ─── Public ───────────────────────────────────────────────────────────────────
72
+ export function listModelerProfiles() {
73
+ try {
74
+ const raw = readFileSync(join(modelerConfigDir(), "settings.json"), "utf8");
75
+ const settings = JSON.parse(raw);
76
+ if (!settings || typeof settings !== "object")
77
+ return [];
78
+ const connections = settings["connectionManagerPlugin.c8connections"];
79
+ if (!Array.isArray(connections))
80
+ return [];
81
+ const profiles = [];
82
+ for (const conn of connections) {
83
+ if (!conn || typeof conn !== "object")
84
+ continue;
85
+ const profile = toProfile(conn);
86
+ if (profile)
87
+ profiles.push(profile);
88
+ }
89
+ return profiles;
90
+ }
91
+ catch {
92
+ return [];
93
+ }
94
+ }
95
+ //# sourceMappingURL=modeler.js.map
@@ -0,0 +1,35 @@
1
+ import type { CamundaClientInput } from "@bpmnkit/api";
2
+ export type ApiType = "c8" | "admin";
3
+ export interface Profile {
4
+ name: string;
5
+ apiType: ApiType;
6
+ config: CamundaClientInput;
7
+ createdAt: string | null;
8
+ source?: "modeler";
9
+ }
10
+ export interface AuditEntry {
11
+ timestamp: string;
12
+ group: string;
13
+ command: string;
14
+ positional: string[];
15
+ flags: Record<string, string | boolean | number>;
16
+ status: "ok" | "error";
17
+ error?: string;
18
+ }
19
+ export interface Settings {
20
+ auditLogSize: number;
21
+ }
22
+ export declare function listProfiles(): Profile[];
23
+ export declare function getProfile(name: string): Profile | undefined;
24
+ export declare function getActiveProfile(): Profile | undefined;
25
+ export declare function getActiveName(): string | null;
26
+ export declare function saveProfile(name: string, config: CamundaClientInput, apiType?: ApiType): void;
27
+ export declare function deleteProfile(name: string): boolean;
28
+ export declare function useProfile(name: string): boolean;
29
+ export declare function getConfigFilePath(): string;
30
+ export declare function getSettings(): Settings;
31
+ export declare function saveSettings(settings: Partial<Settings>): void;
32
+ export declare function appendAuditEntry(profile: string, entry: Omit<AuditEntry, "timestamp">): void;
33
+ export declare function getAuditLog(profile?: string): AuditEntry[];
34
+ export declare function clearAuditLog(profile?: string): void;
35
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1,153 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir, platform } from "node:os";
3
+ import { join } from "node:path";
4
+ import { listModelerProfiles } from "./modeler.js";
5
+ const DEFAULT_AUDIT_LOG_SIZE = 15;
6
+ // ─── Config directory ─────────────────────────────────────────────────────────
7
+ function configDir() {
8
+ const p = platform();
9
+ if (p === "win32")
10
+ return join(process.env.APPDATA ?? homedir(), "casen");
11
+ if (p === "darwin")
12
+ return join(homedir(), "Library", "Application Support", "casen");
13
+ return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "casen");
14
+ }
15
+ function configFilePath() {
16
+ return join(configDir(), "config.json");
17
+ }
18
+ // ─── Read / write ─────────────────────────────────────────────────────────────
19
+ function readStore() {
20
+ try {
21
+ const raw = readFileSync(configFilePath(), "utf8");
22
+ const store = JSON.parse(raw);
23
+ if (!store.meta)
24
+ store.meta = {};
25
+ return store;
26
+ }
27
+ catch {
28
+ return { profiles: {}, active: null, meta: {} };
29
+ }
30
+ }
31
+ function writeStore(store) {
32
+ const dir = configDir();
33
+ mkdirSync(dir, { recursive: true });
34
+ writeFileSync(configFilePath(), JSON.stringify(store, null, 2), "utf8");
35
+ }
36
+ // ─── Public API ───────────────────────────────────────────────────────────────
37
+ export function listProfiles() {
38
+ const store = readStore();
39
+ const own = Object.entries(store.profiles).map(([name, config]) => ({
40
+ name,
41
+ apiType: store.meta[name]?.apiType ?? "c8",
42
+ config,
43
+ createdAt: store.meta[name]?.createdAt ?? null,
44
+ }));
45
+ // Merge Camunda Modeler connections; own profiles take precedence by name
46
+ const ownNames = new Set(own.map((p) => p.name));
47
+ const modeler = listModelerProfiles().filter((p) => !ownNames.has(p.name));
48
+ return [...own, ...modeler];
49
+ }
50
+ export function getProfile(name) {
51
+ const store = readStore();
52
+ const config = store.profiles[name];
53
+ if (!config)
54
+ return undefined;
55
+ return {
56
+ name,
57
+ apiType: store.meta[name]?.apiType ?? "c8",
58
+ config,
59
+ createdAt: store.meta[name]?.createdAt ?? null,
60
+ };
61
+ }
62
+ export function getActiveProfile() {
63
+ const store = readStore();
64
+ if (!store.active)
65
+ return undefined;
66
+ return getProfile(store.active);
67
+ }
68
+ export function getActiveName() {
69
+ return readStore().active;
70
+ }
71
+ export function saveProfile(name, config, apiType = "c8") {
72
+ const store = readStore();
73
+ store.profiles[name] = config;
74
+ if (!store.meta[name]) {
75
+ store.meta[name] = { createdAt: new Date().toISOString(), apiType };
76
+ }
77
+ else {
78
+ store.meta[name].apiType = apiType;
79
+ }
80
+ // Auto-activate if this is the first profile
81
+ if (store.active === null)
82
+ store.active = name;
83
+ writeStore(store);
84
+ }
85
+ export function deleteProfile(name) {
86
+ const store = readStore();
87
+ if (!(name in store.profiles))
88
+ return false;
89
+ const { [name]: _removed, ...rest } = store.profiles;
90
+ store.profiles = rest;
91
+ if (store.active === name) {
92
+ const remaining = Object.keys(store.profiles);
93
+ store.active = remaining.length > 0 ? (remaining[0] ?? null) : null;
94
+ }
95
+ writeStore(store);
96
+ return true;
97
+ }
98
+ export function useProfile(name) {
99
+ const store = readStore();
100
+ if (!(name in store.profiles))
101
+ return false;
102
+ store.active = name;
103
+ writeStore(store);
104
+ return true;
105
+ }
106
+ export function getConfigFilePath() {
107
+ return configFilePath();
108
+ }
109
+ // ─── Settings ─────────────────────────────────────────────────────────────────
110
+ export function getSettings() {
111
+ const store = readStore();
112
+ return { auditLogSize: store.settings?.auditLogSize ?? DEFAULT_AUDIT_LOG_SIZE };
113
+ }
114
+ export function saveSettings(settings) {
115
+ const store = readStore();
116
+ store.settings = { ...store.settings, ...settings };
117
+ writeStore(store);
118
+ }
119
+ // ─── Audit log ────────────────────────────────────────────────────────────────
120
+ export function appendAuditEntry(profile, entry) {
121
+ const store = readStore();
122
+ const size = store.settings?.auditLogSize ?? DEFAULT_AUDIT_LOG_SIZE;
123
+ const log = store.auditLog ?? {};
124
+ const existing = log[profile] ?? [];
125
+ const updated = [...existing, { ...entry, timestamp: new Date().toISOString() }];
126
+ log[profile] = updated.slice(-size);
127
+ store.auditLog = log;
128
+ writeStore(store);
129
+ }
130
+ export function getAuditLog(profile) {
131
+ const store = readStore();
132
+ if (!store.auditLog)
133
+ return [];
134
+ if (profile)
135
+ return store.auditLog[profile] ?? [];
136
+ return Object.values(store.auditLog)
137
+ .flat()
138
+ .sort((a, b) => a.timestamp.localeCompare(b.timestamp));
139
+ }
140
+ export function clearAuditLog(profile) {
141
+ const store = readStore();
142
+ if (!store.auditLog)
143
+ return;
144
+ if (profile) {
145
+ const { [profile]: _removed, ...rest } = store.auditLog;
146
+ store.auditLog = rest;
147
+ }
148
+ else {
149
+ store.auditLog = {};
150
+ }
151
+ writeStore(store);
152
+ }
153
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1,9 @@
1
+ import type { CamundaClientInput } from "@bpmnkit/api";
2
+ /**
3
+ * Returns an Authorization header value for the given client config.
4
+ * Returns an empty string for `auth.type === "none"` or if auth is unset.
5
+ *
6
+ * For OAuth2, tokens are cached in memory and refreshed 60 seconds before expiry.
7
+ */
8
+ export declare function getAuthHeader(config: CamundaClientInput): Promise<string>;
9
+ //# sourceMappingURL=token.d.ts.map
package/dist/token.js ADDED
@@ -0,0 +1,51 @@
1
+ // Simple in-memory token cache keyed by clientId
2
+ const tokenCache = new Map();
3
+ /**
4
+ * Returns an Authorization header value for the given client config.
5
+ * Returns an empty string for `auth.type === "none"` or if auth is unset.
6
+ *
7
+ * For OAuth2, tokens are cached in memory and refreshed 60 seconds before expiry.
8
+ */
9
+ export async function getAuthHeader(config) {
10
+ const auth = config.auth;
11
+ if (!auth || auth.type === "none")
12
+ return "";
13
+ if (auth.type === "bearer")
14
+ return `Bearer ${auth.token}`;
15
+ if (auth.type === "basic") {
16
+ const encoded = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
17
+ return `Basic ${encoded}`;
18
+ }
19
+ if (auth.type === "oauth2") {
20
+ const token = await fetchOAuth2Token(auth.clientId, auth.clientSecret, auth.tokenUrl, auth.audience, auth.scope);
21
+ return `Bearer ${token}`;
22
+ }
23
+ return "";
24
+ }
25
+ async function fetchOAuth2Token(clientId, clientSecret, tokenUrl, audience, scope) {
26
+ const cached = tokenCache.get(clientId);
27
+ if (cached && cached.expiresAt > Date.now() + 60_000)
28
+ return cached.token;
29
+ const body = new URLSearchParams({
30
+ grant_type: "client_credentials",
31
+ client_id: clientId,
32
+ client_secret: clientSecret,
33
+ });
34
+ if (audience)
35
+ body.set("audience", audience);
36
+ if (scope)
37
+ body.set("scope", scope);
38
+ const res = await fetch(tokenUrl, {
39
+ method: "POST",
40
+ body,
41
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
42
+ });
43
+ if (!res.ok) {
44
+ throw new Error(`OAuth2 token request failed: ${res.status} ${res.statusText}`);
45
+ }
46
+ const json = (await res.json());
47
+ const expiresIn = json.expires_in ?? 3600;
48
+ tokenCache.set(clientId, { token: json.access_token, expiresAt: Date.now() + expiresIn * 1000 });
49
+ return json.access_token;
50
+ }
51
+ //# sourceMappingURL=token.js.map
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@bpmnkit/profiles",
3
+ "version": "0.0.5",
4
+ "description": "Shared profile storage and auth client factory for @bpmn-sdk CLI and proxy server",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": ["dist/**/*.js", "dist/**/*.d.ts"],
15
+ "engines": {
16
+ "node": ">=20"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "typecheck": "tsc --noEmit",
21
+ "check": "biome check ."
22
+ },
23
+ "dependencies": {
24
+ "@bpmnkit/api": "workspace:*"
25
+ },
26
+ "keywords": ["bpmn", "camunda", "profiles", "authentication", "oauth2", "cli", "typescript"],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/bpmnkit/monorepo"
33
+ }
34
+ }