eptaadmin-sdk 0.1.2

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,93 @@
1
+ # eptaadmin-sdk
2
+
3
+ A minimal JavaScript/TypeScript client for reading data out of your EptaAdmin workspaces from your own project — a script, a backend, a frontend build step, anywhere Node.js 18+ or a browser's `fetch` is available.
4
+
5
+ This SDK is currently **read-only**: it fetches workspaces, data sources, and their values. It does not create, update, or delete data.
6
+
7
+ ## Install
8
+
9
+ This package isn't published to the npm registry yet. Install it directly from the EptaAdmin repository, e.g. by copying `sdk/js/` into your project or adding it as a local/git dependency:
10
+
11
+ ```json
12
+ {
13
+ "dependencies": {
14
+ "eptaadmin-sdk": "file:../path/to/EptaAdmin/sdk/js"
15
+ }
16
+ }
17
+ ```
18
+
19
+ ## Getting an API key
20
+
21
+ 1. Log into your EptaAdmin instance.
22
+ 2. Go to **Mon profil** (top-right avatar menu).
23
+ 3. In the **Clés API** section, give the key a name and click **Générer une clé**.
24
+ 4. Copy the key immediately — it's shown once and cannot be recovered afterwards. If you lose it, revoke it and generate a new one.
25
+
26
+ The key inherits exactly the same permissions as your account: it can only read workspaces and data sources you're already a member of.
27
+
28
+ ## Quick start
29
+
30
+ ```js
31
+ import { EptaAdminClient } from "eptaadmin-sdk";
32
+
33
+ const client = new EptaAdminClient({
34
+ apiKey: process.env.EPTAADMIN_API_KEY,
35
+ baseUrl: "https://your-eptaadmin-instance.example.com", // defaults to http://localhost:8080
36
+ });
37
+
38
+ const workspaces = await client.listWorkspaces();
39
+ // [{ name: "Acme", slug: "acme", role: "owner" }]
40
+
41
+ const dataSources = await client.listDataSources("acme");
42
+ // [{ name: "Clients", slug: "clients" }]
43
+
44
+ const clients = await client.getDataSource("acme", "clients");
45
+ // { name: "Clients", slug: "clients", columns: { nom: ["Jean Dupont"], email: ["jean@example.com"] } }
46
+
47
+ // Shortcut when you already know exactly what you want, addressed as a
48
+ // single slash-separated path instead of separate arguments:
49
+ const names = await client.getValue("acme/clients/nom");
50
+ // ["Jean Dupont", "Marie Curie"]
51
+
52
+ const firstName = await client.getValue("acme/clients/nom/0");
53
+ // "Jean Dupont"
54
+ ```
55
+
56
+ ## Data model: independent columns
57
+
58
+ EptaAdmin stores each column of a data source as its own independent list of values — there's no assumed row-to-row correspondence between columns. `getDataSource()` returns that shape directly:
59
+
60
+ ```js
61
+ {
62
+ "columns": {
63
+ "nom": ["Jean Dupont", "Marie Curie"],
64
+ "email": ["jean@example.com", "marie@example.com"]
65
+ }
66
+ }
67
+ ```
68
+
69
+ If your project needs row-aligned records, build them yourself from the columns you know are meant to line up (e.g. by index), since EptaAdmin itself doesn't guarantee that alignment.
70
+
71
+ ## Error handling
72
+
73
+ Failed requests reject with an `EptaAdminError` carrying the HTTP status and the server's error message:
74
+
75
+ ```js
76
+ import { EptaAdminClient, EptaAdminError } from "eptaadmin-sdk";
77
+
78
+ try {
79
+ await client.getDataSource("acme", "does-not-exist");
80
+ } catch (err) {
81
+ if (err instanceof EptaAdminError) {
82
+ console.error(err.status, err.message); // 404 "Source de données introuvable."
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## API reference
88
+
89
+ - `new EptaAdminClient({ apiKey, baseUrl? })`
90
+ - `client.listWorkspaces(): Promise<{ name, slug, role }[]>`
91
+ - `client.listDataSources(workspaceSlug): Promise<{ name, slug }[]>`
92
+ - `client.getDataSource(workspaceSlug, dataSourceSlug): Promise<{ name, slug, columns }>`
93
+ - `client.getValue(path): Promise<unknown>` — `path` is `"wsSlug/dsSlug/column"` (returns that column's full array) or `"wsSlug/dsSlug/column/index"` (returns one value)
package/index.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ export interface Workspace {
2
+ name: string;
3
+ slug: string;
4
+ role: string;
5
+ }
6
+
7
+ export interface DataSourceSummary {
8
+ name: string;
9
+ slug: string;
10
+ }
11
+
12
+ export interface DataSourceContent {
13
+ name: string;
14
+ slug: string;
15
+ /** Each column is an independent list of values — index i of one column has no assumed relation to index i of another. */
16
+ columns: Record<string, unknown[]>;
17
+ }
18
+
19
+ export declare class EptaAdminError extends Error {
20
+ status: number;
21
+ constructor(message: string, status: number);
22
+ }
23
+
24
+ export interface EptaAdminClientOptions {
25
+ /** A personal API key generated from the EptaAdmin profile page. */
26
+ apiKey: string;
27
+ /** The URL of your EptaAdmin instance. Defaults to http://localhost:8080. */
28
+ baseUrl?: string;
29
+ }
30
+
31
+ export declare class EptaAdminClient {
32
+ constructor(options: EptaAdminClientOptions);
33
+ listWorkspaces(): Promise<Workspace[]>;
34
+ listDataSources(workspaceSlug: string): Promise<DataSourceSummary[]>;
35
+ getDataSource(workspaceSlug: string, dataSourceSlug: string): Promise<DataSourceContent>;
36
+ /**
37
+ * One-parameter shortcut addressed by a slash-separated path:
38
+ * - "wsSlug/dsSlug/column" -> that column's full value[] list.
39
+ * - "wsSlug/dsSlug/column/index" -> exactly one value at that index.
40
+ */
41
+ getValue(path: string): Promise<unknown>;
42
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "eptaadmin-sdk",
3
+ "version": "0.1.2",
4
+ "description": "Client SDK for reading your EptaAdmin workspace data from your own project.",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./src/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "src",
16
+ "index.d.ts",
17
+ "README.md"
18
+ ],
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "license": "MIT"
23
+ }
package/src/index.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * EptaAdmin SDK — a minimal client for the EptaAdmin public read-only API.
3
+ * Works in Node.js (18+, for global fetch) and in browsers.
4
+ */
5
+
6
+ export class EptaAdminError extends Error {
7
+ constructor(message, status) {
8
+ super(message);
9
+ this.name = "EptaAdminError";
10
+ this.status = status;
11
+ }
12
+ }
13
+
14
+ export class EptaAdminClient {
15
+ /**
16
+ * @param {{ apiKey: string, baseUrl?: string }} options
17
+ * apiKey — a personal API key generated from the EptaAdmin profile page.
18
+ * baseUrl — the URL of your EptaAdmin instance (default: http://localhost:8080).
19
+ */
20
+ constructor({ apiKey, baseUrl = "http://localhost:8080" } = {}) {
21
+ if (!apiKey) {
22
+ throw new Error("EptaAdminClient requires an apiKey");
23
+ }
24
+ this.apiKey = apiKey;
25
+ this.baseUrl = baseUrl.replace(/\/$/, "");
26
+ }
27
+
28
+ async _request(path) {
29
+ const res = await fetch(this.baseUrl + path, {
30
+ headers: { Authorization: `Bearer ${this.apiKey}` },
31
+ });
32
+ const body = await res.json().catch(() => null);
33
+ if (!res.ok) {
34
+ const message = (body && body.error) || `Request failed with status ${res.status}`;
35
+ throw new EptaAdminError(message, res.status);
36
+ }
37
+ return body;
38
+ }
39
+
40
+ /** Lists the workspaces this API key's user can access. */
41
+ listWorkspaces() {
42
+ return this._request("/api/v1/workspaces");
43
+ }
44
+
45
+ /** Lists the data sources in a workspace. */
46
+ listDataSources(workspaceSlug) {
47
+ return this._request(`/api/v1/workspaces/${encodeURIComponent(workspaceSlug)}/datasources`);
48
+ }
49
+
50
+ /**
51
+ * Fetches a data source's content. EptaAdmin stores each column as an
52
+ * independent list of values (no assumed row-to-row correspondence
53
+ * between columns), so the response mirrors that: `columns` is a plain
54
+ * object of `{ [columnKey]: value[] }`.
55
+ */
56
+ getDataSource(workspaceSlug, dataSourceSlug) {
57
+ return this._request(
58
+ `/api/v1/workspaces/${encodeURIComponent(workspaceSlug)}/datasources/${encodeURIComponent(dataSourceSlug)}`
59
+ );
60
+ }
61
+
62
+ /**
63
+ * One-parameter shortcut to a single column or a single value, addressed
64
+ * by a slash-separated path instead of separate arguments:
65
+ * - `"wsSlug/dsSlug/column"` -> that column's full value[] list.
66
+ * - `"wsSlug/dsSlug/column/index"` -> exactly one value at that index.
67
+ *
68
+ * @param {string} path
69
+ */
70
+ async getValue(path) {
71
+ const segments = String(path).split("/").filter(Boolean);
72
+ if (segments.length !== 3 && segments.length !== 4) {
73
+ throw new Error(
74
+ `getValue expects "workspace/dataSource/column" or "workspace/dataSource/column/index", got "${path}"`
75
+ );
76
+ }
77
+ const [workspaceSlug, dataSourceSlug, column, index] = segments;
78
+ let url =
79
+ `/api/v1/workspaces/${encodeURIComponent(workspaceSlug)}` +
80
+ `/datasources/${encodeURIComponent(dataSourceSlug)}` +
81
+ `/columns/${encodeURIComponent(column)}`;
82
+ if (index !== undefined) {
83
+ url += `/${encodeURIComponent(index)}`;
84
+ }
85
+ const body = await this._request(url);
86
+ return index !== undefined ? body.value : body.values;
87
+ }
88
+ }