@centia-io/sdk 0.0.43 → 0.0.45

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.
@@ -80,6 +80,12 @@ function getStorage() {
80
80
 
81
81
  //#endregion
82
82
  //#region src/util/utils.ts
83
+ /**
84
+ * @author Martin Høgh <mh@mapcentia.com>
85
+ * @copyright 2013-2026 MapCentia ApS
86
+ * @license https://opensource.org/license/mit The MIT License
87
+ *
88
+ */
83
89
  const generatePkceChallenge = async () => {
84
90
  const generateRandomString = () => {
85
91
  const array = new Uint32Array(28);
@@ -161,7 +167,8 @@ const setOptions = (options) => {
161
167
  getStorage().setItem("gc2_options", JSON.stringify({
162
168
  "clientId": options.clientId,
163
169
  "host": options.host,
164
- "redirectUri": options.redirectUri
170
+ "redirectUri": options.redirectUri,
171
+ "clientSecret": options.clientSecret || null
165
172
  }));
166
173
  };
167
174
  const getOptions = () => {
@@ -188,6 +195,12 @@ const clearNonce = () => {
188
195
 
189
196
  //#endregion
190
197
  //#region src/services/gc2.services.ts
198
+ /**
199
+ * @author Martin Høgh <mh@mapcentia.com>
200
+ * @copyright 2013-2026 MapCentia ApS
201
+ * @license https://opensource.org/license/mit The MIT License
202
+ *
203
+ */
191
204
  var Gc2Service = class {
192
205
  constructor(options) {
193
206
  this.options = options;
@@ -298,6 +311,7 @@ var Gc2Service = class {
298
311
  const path = `${this.host}/api/v4/oauth`;
299
312
  return this.request(this.buildUrl(path), "POST", {
300
313
  client_id: this.options.clientId,
314
+ client_secret: this.options.clientSecret,
301
315
  grant_type: "password",
302
316
  username,
303
317
  password,
@@ -323,6 +337,12 @@ var Gc2Service = class {
323
337
 
324
338
  //#endregion
325
339
  //#region src/CodeFlow.ts
340
+ /**
341
+ * @author Martin Høgh <mh@mapcentia.com>
342
+ * @copyright 2013-2026 MapCentia ApS
343
+ * @license https://opensource.org/license/mit The MIT License
344
+ *
345
+ */
326
346
  var CodeFlow = class {
327
347
  constructor(options) {
328
348
  this.options = options;
@@ -381,6 +401,12 @@ var CodeFlow = class {
381
401
 
382
402
  //#endregion
383
403
  //#region src/PasswordFlow.ts
404
+ /**
405
+ * @author Martin Høgh <mh@mapcentia.com>
406
+ * @copyright 2013-2026 MapCentia ApS
407
+ * @license https://opensource.org/license/mit The MIT License
408
+ *
409
+ */
384
410
  var PasswordFlow = class {
385
411
  constructor(options) {
386
412
  this.options = options;
@@ -395,7 +421,8 @@ var PasswordFlow = class {
395
421
  setOptions({
396
422
  clientId: this.options.clientId,
397
423
  host: this.options.host,
398
- redirectUri: ""
424
+ redirectUri: "",
425
+ clientSecret: this.options.clientSecret
399
426
  });
400
427
  }
401
428
  signOut() {
@@ -409,79 +436,242 @@ var PasswordFlow = class {
409
436
  };
410
437
 
411
438
  //#endregion
412
- //#region src/util/request-headers.ts
413
- const getHeaders = async (contentType = "application/json") => {
414
- if (!await isLogin(new Gc2Service(getOptions()))) return Promise.reject("Is not logged in");
415
- const { accessToken } = getTokens();
416
- const headers = {
417
- Accept: "application/json",
418
- Cookie: "XDEBUG_SESSION=XDEBUG_ECLIPSE",
419
- Authorization: accessToken ? "Bearer " + accessToken : null
420
- };
421
- if (contentType) headers["Content-Type"] = contentType;
422
- return headers;
439
+ //#region src/http/errors.ts
440
+ /**
441
+ * Normalized error thrown by all SDK HTTP operations.
442
+ * CLI and Web should catch this type for consistent error handling.
443
+ */
444
+ var CentiaApiError = class extends Error {
445
+ constructor(opts) {
446
+ super(opts.message);
447
+ this.name = "CentiaApiError";
448
+ if (opts.cause !== void 0) this.cause = opts.cause;
449
+ this.status = opts.status;
450
+ this.code = opts.code;
451
+ this.details = opts.details;
452
+ this.requestId = opts.requestId;
453
+ this.method = opts.method;
454
+ this.url = opts.url;
455
+ }
423
456
  };
424
- var request_headers_default = getHeaders;
457
+ /** Type guard for CentiaApiError. */
458
+ function isCentiaApiError(e) {
459
+ return e instanceof CentiaApiError;
460
+ }
425
461
 
426
462
  //#endregion
427
- //#region src/util/make-request.ts
428
- const make = async (version, resource, method, payload, contentType = "application/json") => {
429
- const options = getOptions();
430
- let request = {
431
- method,
432
- headers: await request_headers_default(contentType),
433
- redirect: "manual"
434
- };
435
- if (payload) request.body = contentType === "application/json" ? JSON.stringify(payload) : payload;
436
- return await fetch(options.host + `/api/v${version}/${resource}`, request);
463
+ //#region src/http/client.ts
464
+ /**
465
+ * Unified HTTP client for the Centia API.
466
+ * Works in both Node.js and browser environments.
467
+ */
468
+ var CentiaHttpClient = class {
469
+ constructor(config) {
470
+ this.baseUrl = config.baseUrl.replace(/\/+$/, "");
471
+ this.auth = config.auth ?? {};
472
+ this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
473
+ this.userAgent = config.userAgent;
474
+ }
475
+ /**
476
+ * Execute an HTTP request against the Centia API.
477
+ * Returns parsed JSON on success. Throws CentiaApiError on non-expected status.
478
+ */
479
+ async request(opts) {
480
+ return (await this.requestFull(opts)).body;
481
+ }
482
+ /**
483
+ * Execute an HTTP request and return the full response including headers.
484
+ * Useful for operations that return Location headers (POST 201, PATCH 303).
485
+ */
486
+ async requestFull(opts) {
487
+ const url = this.buildUrl(opts.path, opts.query);
488
+ const headers = await this.buildHeaders(opts);
489
+ const init = {
490
+ method: opts.method,
491
+ headers,
492
+ redirect: "manual"
493
+ };
494
+ if (opts.body !== void 0 && opts.body !== null) init.body = this.resolveContentType(opts.contentType) === "application/json" ? JSON.stringify(opts.body) : opts.body;
495
+ const response = await this.fetchFn(url, init);
496
+ if (response.type === "opaqueredirect") {
497
+ if ((opts.expectedStatus ?? 200) === 303) return {
498
+ body: null,
499
+ status: 303,
500
+ getHeader: (name) => name.toLowerCase() === "location" ? response.url : null
501
+ };
502
+ }
503
+ return {
504
+ body: await this.handleResponse(response, opts, url),
505
+ status: response.status,
506
+ getHeader: (name) => response.headers.get(name)
507
+ };
508
+ }
509
+ buildUrl(path, query) {
510
+ const cleanPath = path.replace(/^\/+/, "");
511
+ let url = `${this.baseUrl}/${cleanPath}`;
512
+ if (query) {
513
+ const params = new URLSearchParams(query);
514
+ url += `?${params.toString()}`;
515
+ }
516
+ return url;
517
+ }
518
+ async buildHeaders(opts) {
519
+ const headers = { "Accept": opts.accept ?? "application/json" };
520
+ if (this.auth.getAccessToken) {
521
+ const token = await this.auth.getAccessToken();
522
+ if (token) headers["Authorization"] = `Bearer ${token}`;
523
+ }
524
+ if (this.auth.getHeaders) {
525
+ const authHeaders = await this.auth.getHeaders();
526
+ Object.assign(headers, authHeaders);
527
+ }
528
+ if (this.userAgent && typeof navigator === "undefined") headers["User-Agent"] = this.userAgent;
529
+ const ct = this.resolveContentType(opts.contentType);
530
+ if (ct) headers["Content-Type"] = ct;
531
+ return headers;
532
+ }
533
+ resolveContentType(contentType) {
534
+ if (contentType === null) return null;
535
+ return contentType ?? "application/json";
536
+ }
537
+ async handleResponse(response, opts, url) {
538
+ const expectedStatus = opts.expectedStatus ?? 200;
539
+ let bodyText = "";
540
+ try {
541
+ bodyText = await response.text();
542
+ } catch {}
543
+ let parsed = null;
544
+ if (bodyText) try {
545
+ parsed = JSON.parse(bodyText);
546
+ } catch {}
547
+ if (response.status !== expectedStatus) throw new CentiaApiError({
548
+ message: (parsed?.message ?? parsed?.error ?? bodyText) || `Unexpected status ${response.status}`,
549
+ status: response.status,
550
+ code: parsed?.code,
551
+ details: parsed,
552
+ requestId: response.headers.get("x-request-id") ?? void 0,
553
+ method: opts.method,
554
+ url
555
+ });
556
+ return parsed ?? (bodyText || null);
557
+ }
437
558
  };
438
- var make_request_default = make;
559
+ /**
560
+ * Create a new Centia HTTP client.
561
+ *
562
+ * Node.js usage:
563
+ * ```ts
564
+ * const client = createCentiaClient({
565
+ * baseUrl: 'https://example.centia.io',
566
+ * auth: { getAccessToken: async () => process.env.CENTIA_TOKEN },
567
+ * });
568
+ * ```
569
+ *
570
+ * Browser usage:
571
+ * ```ts
572
+ * const client = createCentiaClient({
573
+ * baseUrl: 'https://example.centia.io',
574
+ * auth: { getAccessToken: async () => getStoredToken() },
575
+ * });
576
+ * ```
577
+ */
578
+ function createCentiaClient(config) {
579
+ return new CentiaHttpClient(config);
580
+ }
439
581
 
440
582
  //#endregion
441
- //#region src/util/get-response.ts
442
- const get = async (response, expectedCode) => {
443
- let res = null;
444
- let bodyText = "";
445
- try {
446
- bodyText = await response.text();
447
- } catch (e) {}
448
- if (bodyText) try {
449
- res = JSON.parse(bodyText);
450
- } catch (e) {}
451
- if (response.status !== expectedCode) {
452
- const msg = res && (res.message || res.error) || bodyText || `Unexpected status ${response.status}`;
453
- throw new Error(msg);
454
- }
455
- return res;
456
- };
457
- var get_response_default = get;
583
+ //#region src/http/legacy.ts
584
+ /**
585
+ * @author Martin Høgh <mh@mapcentia.com>
586
+ * @copyright 2013-2026 MapCentia ApS
587
+ * @license https://opensource.org/license/mit The MIT License
588
+ *
589
+ * Legacy bridge: creates a CentiaHttpClient from storage-based options/tokens.
590
+ * Used by existing SDK modules when no explicit client is provided.
591
+ */
592
+ /**
593
+ * Create a CentiaHttpClient backed by the legacy storage-based auth.
594
+ * The auth callback reads fresh tokens from storage on each request
595
+ * and auto-refreshes expired access tokens via the refresh token.
596
+ */
597
+ function getLegacyClient() {
598
+ return new CentiaHttpClient({
599
+ baseUrl: getOptions().host,
600
+ auth: { getAccessToken: async () => {
601
+ if (!await isLogin(new Gc2Service(getOptions()))) return;
602
+ return getTokens().accessToken || void 0;
603
+ } }
604
+ });
605
+ }
458
606
 
459
607
  //#endregion
460
608
  //#region src/Sql.ts
461
609
  var Sql = class {
610
+ constructor(client) {
611
+ this.client = client ?? getLegacyClient();
612
+ }
462
613
  async exec(request) {
463
- return await get_response_default(await make_request_default("4", `sql`, "POST", request), 200);
614
+ return this.client.request({
615
+ path: "api/v4/sql",
616
+ method: "POST",
617
+ body: request
618
+ });
464
619
  }
465
620
  };
466
621
 
467
622
  //#endregion
468
623
  //#region src/Rpc.ts
469
624
  var Rpc = class {
625
+ constructor(client) {
626
+ this.client = client ?? getLegacyClient();
627
+ }
470
628
  async call(request) {
471
- return await get_response_default(await make_request_default("4", `call`, "POST", request), 200);
629
+ return this.client.request({
630
+ path: "api/v4/call",
631
+ method: "POST",
632
+ body: request
633
+ });
634
+ }
635
+ };
636
+
637
+ //#endregion
638
+ //#region src/Gql.ts
639
+ var Gql = class {
640
+ constructor(schema, client) {
641
+ this.schema = schema;
642
+ this.client = client ?? getLegacyClient();
643
+ }
644
+ async request(request) {
645
+ return this.client.request({
646
+ path: `api/graphql/schema/${this.schema}`,
647
+ method: "POST",
648
+ body: request
649
+ });
472
650
  }
473
651
  };
474
652
 
475
653
  //#endregion
476
654
  //#region src/Meta.ts
477
655
  var Meta = class {
656
+ constructor(client) {
657
+ this.client = client ?? getLegacyClient();
658
+ }
478
659
  async query(rel) {
479
- return await get_response_default(await make_request_default("3", `meta/${rel}`, "GET", null), 200);
660
+ return this.client.request({
661
+ path: `api/v4/meta/${rel}`,
662
+ method: "GET"
663
+ });
480
664
  }
481
665
  };
482
666
 
483
667
  //#endregion
484
668
  //#region src/Status.ts
669
+ /**
670
+ * @author Martin Høgh <mh@mapcentia.com>
671
+ * @copyright 2013-2026 MapCentia ApS
672
+ * @license https://opensource.org/license/mit The MIT License
673
+ *
674
+ */
485
675
  var Status = class {
486
676
  isAuth() {
487
677
  const tokens = getTokens();
@@ -494,6 +684,12 @@ var Status = class {
494
684
 
495
685
  //#endregion
496
686
  //#region src/Claims.ts
687
+ /**
688
+ * @author Martin Høgh <mh@mapcentia.com>
689
+ * @copyright 2013-2026 MapCentia ApS
690
+ * @license https://opensource.org/license/mit The MIT License
691
+ *
692
+ */
497
693
  var Claims = class {
498
694
  get() {
499
695
  const tokens = getTokens().accessToken;
@@ -504,13 +700,25 @@ var Claims = class {
504
700
  //#endregion
505
701
  //#region src/Users.ts
506
702
  var Users = class {
703
+ constructor(client) {
704
+ this.client = client ?? getLegacyClient();
705
+ }
507
706
  async get(user) {
508
- return await get_response_default(await make_request_default("4", `users/${user}`, "GET", null), 200);
707
+ return this.client.request({
708
+ path: `api/v4/users/${user}`,
709
+ method: "GET"
710
+ });
509
711
  }
510
712
  };
511
713
 
512
714
  //#endregion
513
715
  //#region src/Ws.ts
716
+ /**
717
+ * @author Martin Høgh <mh@mapcentia.com>
718
+ * @copyright 2013-2026 MapCentia ApS
719
+ * @license https://opensource.org/license/mit The MIT License
720
+ *
721
+ */
514
722
  var Ws = class {
515
723
  constructor(options) {
516
724
  this.options = options;
@@ -548,25 +756,49 @@ var Ws = class {
548
756
  //#endregion
549
757
  //#region src/Stats.ts
550
758
  var Stats = class {
759
+ constructor(client) {
760
+ this.client = client ?? getLegacyClient();
761
+ }
551
762
  async get() {
552
- return await get_response_default(await make_request_default("4", `stats`, "GET", null), 200);
763
+ return this.client.request({
764
+ path: "api/v4/stats",
765
+ method: "GET"
766
+ });
553
767
  }
554
768
  };
555
769
 
556
770
  //#endregion
557
771
  //#region src/Tables.ts
558
772
  var Tables = class {
773
+ constructor(client) {
774
+ this.client = client ?? getLegacyClient();
775
+ }
559
776
  async get(schema, table) {
560
- return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "GET", null), 200);
777
+ return this.client.request({
778
+ path: `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`,
779
+ method: "GET"
780
+ });
561
781
  }
562
782
  async create(schema, table, payload) {
563
- return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "POST", payload), 200);
783
+ return this.client.request({
784
+ path: `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`,
785
+ method: "POST",
786
+ body: payload
787
+ });
564
788
  }
565
789
  async patch(schema, table, payload) {
566
- return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "PATCH", payload), 200);
790
+ return this.client.request({
791
+ path: `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`,
792
+ method: "PATCH",
793
+ body: payload
794
+ });
567
795
  }
568
796
  async delete(schema, table) {
569
- return await get_response_default(await make_request_default("4", `schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`, "DELETE", null), 204);
797
+ return this.client.request({
798
+ path: `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}`,
799
+ method: "DELETE",
800
+ expectedStatus: 204
801
+ });
570
802
  }
571
803
  };
572
804
 
@@ -593,26 +825,26 @@ function extractDataFromResponse(method, res) {
593
825
  if (!err || typeof err !== "object") throw new TypeError(`createApi: Invalid RPC error for method "${method}". Expected 'error' to be an object.`);
594
826
  const code = err.code;
595
827
  const message = err.message;
596
- const data$1 = err.data;
828
+ const data = err.data;
597
829
  const codeIsNum = typeof code === "number" && Number.isFinite(code);
598
830
  const details = typeof message === "string" && message.length > 0 ? message : "Unknown error";
599
831
  const e = /* @__PURE__ */ new Error(`createApi: RPC error for method "${method}"${codeIsNum ? ` (${code})` : ""}: ${details}`);
600
832
  e.code = code;
601
- if (data$1 !== void 0) e.data = data$1;
833
+ if (data !== void 0) e.data = data;
602
834
  e.method = method;
603
835
  e.name = "JsonRpcError";
604
836
  throw e;
605
837
  }
606
838
  const result = res.result;
607
839
  if (!result || typeof result !== "object") throw new TypeError(`createApi: Invalid RPC response for method "${method}". Missing result object.`);
608
- const data = result.data;
609
- if (!Array.isArray(data)) throw new TypeError(`createApi: Invalid RPC response for method "${method}". Expected result.data to be an array.`);
610
- return data;
840
+ const dataArr = result.data;
841
+ if (!Array.isArray(dataArr)) throw new TypeError(`createApi: Invalid RPC response for method "${method}". Expected result.data to be an array.`);
842
+ return dataArr;
611
843
  }
612
- async function dispatch(name, paramsLike) {
844
+ async function dispatch(name, paramsLike, client) {
613
845
  if (typeof name !== "string" || name.length === 0) throw new TypeError("createApi: RPC method name must be a non-empty string.");
614
846
  const params = validateParamsForMethod(String(name), paramsLike);
615
- const rpc = new Rpc();
847
+ const rpc = new Rpc(client);
616
848
  const request = {
617
849
  jsonrpc: "2.0",
618
850
  method: name,
@@ -622,17 +854,23 @@ async function dispatch(name, paramsLike) {
622
854
  const res = await rpc.call(request);
623
855
  return extractDataFromResponse(String(name), res);
624
856
  }
625
- function createApi() {
857
+ function createApi(client) {
626
858
  return new Proxy({}, { get(_target, prop) {
627
859
  if (typeof prop !== "string") return void 0;
628
860
  return (...args) => {
629
- return dispatch(prop, args.length === 0 ? {} : args.length === 1 ? args[0] : args);
861
+ return dispatch(prop, args.length === 0 ? {} : args.length === 1 ? args[0] : args, client);
630
862
  };
631
863
  } });
632
864
  }
633
865
 
634
866
  //#endregion
635
867
  //#region src/SignUp.ts
868
+ /**
869
+ * @author Martin Høgh <mh@mapcentia.com>
870
+ * @copyright 2013-2026 MapCentia ApS
871
+ * @license https://opensource.org/license/mit The MIT License
872
+ *
873
+ */
636
874
  var SignUp = class {
637
875
  constructor(options) {
638
876
  this.options = options;
@@ -1422,8 +1660,565 @@ function createSqlBuilder(schema) {
1422
1660
  }
1423
1661
 
1424
1662
  //#endregion
1663
+ //#region src/provisioning/Schemas.ts
1664
+ var Schemas = class {
1665
+ constructor(client) {
1666
+ this.client = client;
1667
+ }
1668
+ async getSchema(schema, opts) {
1669
+ const path = schema ? `api/v4/schemas/${encodeURIComponent(schema)}` : "api/v4/schemas";
1670
+ const query = {};
1671
+ if (opts?.namesOnly) query.namesOnly = "true";
1672
+ return this.client.request({
1673
+ path,
1674
+ method: "GET",
1675
+ query: Object.keys(query).length > 0 ? query : void 0
1676
+ });
1677
+ }
1678
+ async postSchema(body) {
1679
+ return { location: (await this.client.requestFull({
1680
+ path: "api/v4/schemas",
1681
+ method: "POST",
1682
+ body,
1683
+ expectedStatus: 201
1684
+ })).getHeader("Location") ?? "" };
1685
+ }
1686
+ async patchSchema(schema, body) {
1687
+ return { location: (await this.client.requestFull({
1688
+ path: `api/v4/schemas/${encodeURIComponent(schema)}`,
1689
+ method: "PATCH",
1690
+ body,
1691
+ expectedStatus: 303
1692
+ })).getHeader("Location") ?? "" };
1693
+ }
1694
+ async deleteSchema(schema) {
1695
+ await this.client.request({
1696
+ path: `api/v4/schemas/${encodeURIComponent(schema)}`,
1697
+ method: "DELETE",
1698
+ expectedStatus: 204
1699
+ });
1700
+ }
1701
+ };
1702
+
1703
+ //#endregion
1704
+ //#region src/provisioning/Columns.ts
1705
+ var Columns = class {
1706
+ constructor(client) {
1707
+ this.client = client;
1708
+ }
1709
+ basePath(schema, table) {
1710
+ return `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}/columns`;
1711
+ }
1712
+ async getColumn(schema, table, column) {
1713
+ const path = column ? `${this.basePath(schema, table)}/${encodeURIComponent(column)}` : this.basePath(schema, table);
1714
+ return this.client.request({
1715
+ path,
1716
+ method: "GET"
1717
+ });
1718
+ }
1719
+ async postColumn(schema, table, body) {
1720
+ return { location: (await this.client.requestFull({
1721
+ path: this.basePath(schema, table),
1722
+ method: "POST",
1723
+ body,
1724
+ expectedStatus: 201
1725
+ })).getHeader("Location") ?? "" };
1726
+ }
1727
+ async patchColumn(schema, table, column, body) {
1728
+ return { location: (await this.client.requestFull({
1729
+ path: `${this.basePath(schema, table)}/${encodeURIComponent(column)}`,
1730
+ method: "PATCH",
1731
+ body,
1732
+ expectedStatus: 303
1733
+ })).getHeader("Location") ?? "" };
1734
+ }
1735
+ async deleteColumn(schema, table, column) {
1736
+ await this.client.request({
1737
+ path: `${this.basePath(schema, table)}/${encodeURIComponent(column)}`,
1738
+ method: "DELETE",
1739
+ expectedStatus: 204
1740
+ });
1741
+ }
1742
+ };
1743
+
1744
+ //#endregion
1745
+ //#region src/provisioning/Constraints.ts
1746
+ var Constraints = class {
1747
+ constructor(client) {
1748
+ this.client = client;
1749
+ }
1750
+ basePath(schema, table) {
1751
+ return `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}/constraints`;
1752
+ }
1753
+ async getConstraint(schema, table, constraint) {
1754
+ const path = constraint ? `${this.basePath(schema, table)}/${encodeURIComponent(constraint)}` : this.basePath(schema, table);
1755
+ return this.client.request({
1756
+ path,
1757
+ method: "GET"
1758
+ });
1759
+ }
1760
+ async postConstraint(schema, table, body) {
1761
+ return { location: (await this.client.requestFull({
1762
+ path: this.basePath(schema, table),
1763
+ method: "POST",
1764
+ body,
1765
+ expectedStatus: 201
1766
+ })).getHeader("Location") ?? "" };
1767
+ }
1768
+ async deleteConstraint(schema, table, constraint) {
1769
+ await this.client.request({
1770
+ path: `${this.basePath(schema, table)}/${encodeURIComponent(constraint)}`,
1771
+ method: "DELETE",
1772
+ expectedStatus: 204
1773
+ });
1774
+ }
1775
+ };
1776
+
1777
+ //#endregion
1778
+ //#region src/provisioning/Indices.ts
1779
+ var Indices = class {
1780
+ constructor(client) {
1781
+ this.client = client;
1782
+ }
1783
+ basePath(schema, table) {
1784
+ return `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}/indices`;
1785
+ }
1786
+ async getIndex(schema, table, index) {
1787
+ const path = index ? `${this.basePath(schema, table)}/${encodeURIComponent(index)}` : this.basePath(schema, table);
1788
+ return this.client.request({
1789
+ path,
1790
+ method: "GET"
1791
+ });
1792
+ }
1793
+ async postIndex(schema, table, body) {
1794
+ return { location: (await this.client.requestFull({
1795
+ path: this.basePath(schema, table),
1796
+ method: "POST",
1797
+ body,
1798
+ expectedStatus: 201
1799
+ })).getHeader("Location") ?? "" };
1800
+ }
1801
+ async deleteIndex(schema, table, index) {
1802
+ await this.client.request({
1803
+ path: `${this.basePath(schema, table)}/${encodeURIComponent(index)}`,
1804
+ method: "DELETE",
1805
+ expectedStatus: 204
1806
+ });
1807
+ }
1808
+ };
1809
+
1810
+ //#endregion
1811
+ //#region src/provisioning/Sequences.ts
1812
+ var Sequences = class {
1813
+ constructor(client) {
1814
+ this.client = client;
1815
+ }
1816
+ basePath(schema) {
1817
+ return `api/v4/schemas/${encodeURIComponent(schema)}/sequences`;
1818
+ }
1819
+ async getSequence(schema, sequence) {
1820
+ const path = sequence ? `${this.basePath(schema)}/${encodeURIComponent(sequence)}` : this.basePath(schema);
1821
+ return this.client.request({
1822
+ path,
1823
+ method: "GET"
1824
+ });
1825
+ }
1826
+ async postSequence(schema, body) {
1827
+ return { location: (await this.client.requestFull({
1828
+ path: this.basePath(schema),
1829
+ method: "POST",
1830
+ body,
1831
+ expectedStatus: 201
1832
+ })).getHeader("Location") ?? "" };
1833
+ }
1834
+ async patchSequence(schema, sequence, body) {
1835
+ return { location: (await this.client.requestFull({
1836
+ path: `${this.basePath(schema)}/${encodeURIComponent(sequence)}`,
1837
+ method: "PATCH",
1838
+ body,
1839
+ expectedStatus: 303
1840
+ })).getHeader("Location") ?? "" };
1841
+ }
1842
+ async deleteSequence(schema, sequence) {
1843
+ await this.client.request({
1844
+ path: `${this.basePath(schema)}/${encodeURIComponent(sequence)}`,
1845
+ method: "DELETE",
1846
+ expectedStatus: 204
1847
+ });
1848
+ }
1849
+ };
1850
+
1851
+ //#endregion
1852
+ //#region src/provisioning/Tables.ts
1853
+ var ProvisioningTables = class {
1854
+ constructor(client) {
1855
+ this.client = client;
1856
+ }
1857
+ basePath(schema) {
1858
+ return `api/v4/schemas/${encodeURIComponent(schema)}/tables`;
1859
+ }
1860
+ async getTable(schema, table) {
1861
+ const path = table ? `${this.basePath(schema)}/${encodeURIComponent(table)}` : this.basePath(schema);
1862
+ return this.client.request({
1863
+ path,
1864
+ method: "GET"
1865
+ });
1866
+ }
1867
+ async postTable(schema, body) {
1868
+ return { location: (await this.client.requestFull({
1869
+ path: this.basePath(schema),
1870
+ method: "POST",
1871
+ body,
1872
+ expectedStatus: 201
1873
+ })).getHeader("Location") ?? "" };
1874
+ }
1875
+ async patchTable(schema, table, body) {
1876
+ return { location: (await this.client.requestFull({
1877
+ path: `${this.basePath(schema)}/${encodeURIComponent(table)}`,
1878
+ method: "PATCH",
1879
+ body,
1880
+ expectedStatus: 303
1881
+ })).getHeader("Location") ?? "" };
1882
+ }
1883
+ async deleteTable(schema, table) {
1884
+ await this.client.request({
1885
+ path: `${this.basePath(schema)}/${encodeURIComponent(table)}`,
1886
+ method: "DELETE",
1887
+ expectedStatus: 204
1888
+ });
1889
+ }
1890
+ };
1891
+
1892
+ //#endregion
1893
+ //#region src/provisioning/Users.ts
1894
+ var ProvisioningUsers = class {
1895
+ constructor(client) {
1896
+ this.client = client;
1897
+ }
1898
+ async getUser(name) {
1899
+ const path = name ? `api/v4/users/${encodeURIComponent(name)}` : "api/v4/users";
1900
+ return this.client.request({
1901
+ path,
1902
+ method: "GET"
1903
+ });
1904
+ }
1905
+ async postUser(body) {
1906
+ return { location: (await this.client.requestFull({
1907
+ path: "api/v4/users",
1908
+ method: "POST",
1909
+ body,
1910
+ expectedStatus: 201
1911
+ })).getHeader("Location") ?? "" };
1912
+ }
1913
+ async patchUser(name, body) {
1914
+ return { location: (await this.client.requestFull({
1915
+ path: `api/v4/users/${encodeURIComponent(name)}`,
1916
+ method: "PATCH",
1917
+ body,
1918
+ expectedStatus: 303
1919
+ })).getHeader("Location") ?? "" };
1920
+ }
1921
+ async deleteUser(name) {
1922
+ await this.client.request({
1923
+ path: `api/v4/users/${encodeURIComponent(name)}`,
1924
+ method: "DELETE",
1925
+ expectedStatus: 204
1926
+ });
1927
+ }
1928
+ };
1929
+
1930
+ //#endregion
1931
+ //#region src/provisioning/Clients.ts
1932
+ var ProvisioningClients = class {
1933
+ constructor(client) {
1934
+ this.client = client;
1935
+ }
1936
+ async getClient(id) {
1937
+ const path = id ? `api/v4/clients/${encodeURIComponent(id)}` : "api/v4/clients";
1938
+ return this.client.request({
1939
+ path,
1940
+ method: "GET"
1941
+ });
1942
+ }
1943
+ async postClient(body) {
1944
+ const res = await this.client.requestFull({
1945
+ path: "api/v4/clients",
1946
+ method: "POST",
1947
+ body,
1948
+ expectedStatus: 201
1949
+ });
1950
+ return {
1951
+ location: res.getHeader("Location") ?? "",
1952
+ secret: res.body.secret
1953
+ };
1954
+ }
1955
+ async patchClient(id, body) {
1956
+ return { location: (await this.client.requestFull({
1957
+ path: `api/v4/clients/${encodeURIComponent(id)}`,
1958
+ method: "PATCH",
1959
+ body,
1960
+ expectedStatus: 303
1961
+ })).getHeader("Location") ?? "" };
1962
+ }
1963
+ async deleteClient(id) {
1964
+ await this.client.request({
1965
+ path: `api/v4/clients/${encodeURIComponent(id)}`,
1966
+ method: "DELETE",
1967
+ expectedStatus: 204
1968
+ });
1969
+ }
1970
+ };
1971
+
1972
+ //#endregion
1973
+ //#region src/provisioning/Rules.ts
1974
+ var Rules = class {
1975
+ constructor(client) {
1976
+ this.client = client;
1977
+ }
1978
+ async getRule(id) {
1979
+ const path = id != null ? `api/v4/rules/${encodeURIComponent(id)}` : "api/v4/rules";
1980
+ return this.client.request({
1981
+ path,
1982
+ method: "GET"
1983
+ });
1984
+ }
1985
+ async postRule(body) {
1986
+ return this.client.request({
1987
+ path: "api/v4/rules",
1988
+ method: "POST",
1989
+ body,
1990
+ expectedStatus: 201
1991
+ });
1992
+ }
1993
+ async patchRule(id, body) {
1994
+ return this.client.request({
1995
+ path: `api/v4/rules/${encodeURIComponent(id)}`,
1996
+ method: "PATCH",
1997
+ body
1998
+ });
1999
+ }
2000
+ async deleteRule(id) {
2001
+ await this.client.request({
2002
+ path: `api/v4/rules/${encodeURIComponent(id)}`,
2003
+ method: "DELETE",
2004
+ expectedStatus: 204
2005
+ });
2006
+ }
2007
+ };
2008
+
2009
+ //#endregion
2010
+ //#region src/provisioning/Privileges.ts
2011
+ var Privileges = class {
2012
+ constructor(client) {
2013
+ this.client = client;
2014
+ }
2015
+ async getPrivileges(schema, table) {
2016
+ return this.client.request({
2017
+ path: `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}/privileges`,
2018
+ method: "GET"
2019
+ });
2020
+ }
2021
+ async patchPrivileges(schema, table, body) {
2022
+ return this.client.request({
2023
+ path: `api/v4/schemas/${encodeURIComponent(schema)}/tables/${encodeURIComponent(table)}/privileges`,
2024
+ method: "PATCH",
2025
+ body
2026
+ });
2027
+ }
2028
+ };
2029
+
2030
+ //#endregion
2031
+ //#region src/provisioning/RpcMethods.ts
2032
+ var RpcMethods = class {
2033
+ constructor(client) {
2034
+ this.client = client;
2035
+ }
2036
+ async getRpc(method) {
2037
+ const path = method ? `api/v4/methods/${encodeURIComponent(method)}` : "api/v4/methods";
2038
+ return this.client.request({
2039
+ path,
2040
+ method: "GET"
2041
+ });
2042
+ }
2043
+ async postRpc(body) {
2044
+ return { location: (await this.client.requestFull({
2045
+ path: "api/v4/methods",
2046
+ method: "POST",
2047
+ body,
2048
+ expectedStatus: 201
2049
+ })).getHeader("Location") ?? "" };
2050
+ }
2051
+ async patchRpc(method, body) {
2052
+ return { location: (await this.client.requestFull({
2053
+ path: `api/v4/methods/${encodeURIComponent(method)}`,
2054
+ method: "PATCH",
2055
+ body,
2056
+ expectedStatus: 303
2057
+ })).getHeader("Location") ?? "" };
2058
+ }
2059
+ async deleteRpc(method) {
2060
+ await this.client.request({
2061
+ path: `api/v4/methods/${encodeURIComponent(method)}`,
2062
+ method: "DELETE",
2063
+ expectedStatus: 204
2064
+ });
2065
+ }
2066
+ async postCallDry(body) {
2067
+ return this.client.request({
2068
+ path: "api/v4/call/dry",
2069
+ method: "POST",
2070
+ body
2071
+ });
2072
+ }
2073
+ };
2074
+
2075
+ //#endregion
2076
+ //#region src/provisioning/MetadataWrite.ts
2077
+ var MetadataWrite = class {
2078
+ constructor(client) {
2079
+ this.client = client;
2080
+ }
2081
+ async patchMetaData(body) {
2082
+ return this.client.request({
2083
+ path: "api/v4/meta",
2084
+ method: "PATCH",
2085
+ body
2086
+ });
2087
+ }
2088
+ };
2089
+
2090
+ //#endregion
2091
+ //#region src/provisioning/TypeScriptInterfaces.ts
2092
+ var TypeScriptInterfaces = class {
2093
+ constructor(client) {
2094
+ this.client = client;
2095
+ }
2096
+ async getTypeScript() {
2097
+ return this.client.request({
2098
+ path: "api/v4/interfaces",
2099
+ method: "GET",
2100
+ accept: "text/plain"
2101
+ });
2102
+ }
2103
+ };
2104
+
2105
+ //#endregion
2106
+ //#region src/provisioning/FileImport.ts
2107
+ var FileImport = class {
2108
+ constructor(client) {
2109
+ this.client = client;
2110
+ }
2111
+ /**
2112
+ * Upload a file via multipart/form-data.
2113
+ * In Node.js, pass a FormData instance. In browsers, pass a native FormData.
2114
+ */
2115
+ async postFileUpload(formData) {
2116
+ return this.client.request({
2117
+ path: "api/v4/file/upload",
2118
+ method: "POST",
2119
+ body: formData,
2120
+ contentType: null,
2121
+ expectedStatus: 201
2122
+ });
2123
+ }
2124
+ async postFileProcess(body) {
2125
+ return this.client.request({
2126
+ path: "api/v4/file/process",
2127
+ method: "POST",
2128
+ body,
2129
+ expectedStatus: 201
2130
+ });
2131
+ }
2132
+ };
2133
+
2134
+ //#endregion
2135
+ //#region src/provisioning/GitCommit.ts
2136
+ var GitCommit = class {
2137
+ constructor(client) {
2138
+ this.client = client;
2139
+ }
2140
+ async postCommit(body) {
2141
+ return this.client.request({
2142
+ path: "api/v4/commit",
2143
+ method: "POST",
2144
+ body
2145
+ });
2146
+ }
2147
+ };
2148
+
2149
+ //#endregion
2150
+ //#region src/provisioning/SqlNoToken.ts
2151
+ var SqlNoToken = class {
2152
+ constructor(client) {
2153
+ this.client = client;
2154
+ }
2155
+ async postSqlNoToken(database, body) {
2156
+ return this.client.request({
2157
+ path: `api/v4/sql/database/${encodeURIComponent(database)}`,
2158
+ method: "POST",
2159
+ body
2160
+ });
2161
+ }
2162
+ };
2163
+
2164
+ //#endregion
2165
+ //#region src/admin.ts
2166
+ /**
2167
+ * @author Martin Høgh <mh@mapcentia.com>
2168
+ * @copyright 2013-2026 MapCentia ApS
2169
+ * @license https://opensource.org/license/mit The MIT License
2170
+ */
2171
+ /**
2172
+ * Create a Centia admin client with access to provisioning operations.
2173
+ *
2174
+ * ```ts
2175
+ * const client = createCentiaAdminClient({
2176
+ * baseUrl: 'https://example.centia.io',
2177
+ * auth: { getAccessToken: async () => token },
2178
+ * });
2179
+ *
2180
+ * await client.provisioning.schemas.postSchema({ name: 'myschema' });
2181
+ * ```
2182
+ */
2183
+ function createCentiaAdminClient(config) {
2184
+ const http = new CentiaHttpClient(config);
2185
+ return {
2186
+ http,
2187
+ provisioning: {
2188
+ schemas: new Schemas(http),
2189
+ tables: new ProvisioningTables(http),
2190
+ columns: new Columns(http),
2191
+ constraints: new Constraints(http),
2192
+ indices: new Indices(http),
2193
+ sequences: new Sequences(http),
2194
+ users: new ProvisioningUsers(http),
2195
+ clients: new ProvisioningClients(http),
2196
+ rules: new Rules(http),
2197
+ privileges: new Privileges(http),
2198
+ rpcMethods: new RpcMethods(http),
2199
+ metadata: new MetadataWrite(http),
2200
+ typeScript: new TypeScriptInterfaces(http),
2201
+ fileImport: new FileImport(http),
2202
+ gitCommit: new GitCommit(http),
2203
+ sqlNoToken: new SqlNoToken(http)
2204
+ }
2205
+ };
2206
+ }
2207
+
2208
+ //#endregion
2209
+ //#region src/index.ts
2210
+ /**
2211
+ * @author Martin Høgh <mh@mapcentia.com>
2212
+ * @copyright 2013-2026 MapCentia ApS
2213
+ * @license https://opensource.org/license/mit The MIT License
2214
+ *
2215
+ */
2216
+
2217
+ //#endregion
2218
+ exports.CentiaApiError = CentiaApiError;
1425
2219
  exports.Claims = Claims;
1426
2220
  exports.CodeFlow = CodeFlow;
2221
+ exports.Gql = Gql;
1427
2222
  exports.Meta = Meta;
1428
2223
  exports.PasswordFlow = PasswordFlow;
1429
2224
  exports.Rpc = Rpc;
@@ -1435,4 +2230,7 @@ exports.Tables = Tables;
1435
2230
  exports.Users = Users;
1436
2231
  exports.Ws = Ws;
1437
2232
  exports.createApi = createApi;
1438
- exports.createSqlBuilder = createSqlBuilder;
2233
+ exports.createCentiaAdminClient = createCentiaAdminClient;
2234
+ exports.createCentiaClient = createCentiaClient;
2235
+ exports.createSqlBuilder = createSqlBuilder;
2236
+ exports.isCentiaApiError = isCentiaApiError;