@centia-io/sdk 0.2.12 → 0.2.14

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.
@@ -346,6 +346,9 @@
346
346
  isSignUpOptions(options) {
347
347
  return "parentDb" in options;
348
348
  }
349
+ isGuestFlowOptions(options) {
350
+ return "database" in options && !("username" in options);
351
+ }
349
352
  buildUrl(path) {
350
353
  if (path.startsWith("http://") || path.startsWith("https://")) return path;
351
354
  return `${this.host}${path}`;
@@ -458,12 +461,24 @@
458
461
  database
459
462
  });
460
463
  }
461
- async getRefreshToken(token) {
464
+ async getGuestToken() {
462
465
  var _this5 = this;
463
- var _this$options$tokenUr3;
464
- const path = (_this$options$tokenUr3 = _this5.options.tokenUri) !== null && _this$options$tokenUr3 !== void 0 ? _this$options$tokenUr3 : `${_this5.host}/api/v4/oauth`;
466
+ let database;
467
+ if (_this5.isGuestFlowOptions(_this5.options)) database = _this5.options.database;
468
+ else throw new Error("GuestFlow options required for this operation");
469
+ const path = `${_this5.host}/api/v4/oauth/guest`;
465
470
  return _this5.request(_this5.buildUrl(path), "POST", {
471
+ database,
466
472
  client_id: _this5.options.clientId,
473
+ client_secret: _this5.options.clientSecret
474
+ });
475
+ }
476
+ async getRefreshToken(token) {
477
+ var _this6 = this;
478
+ var _this$options$tokenUr3;
479
+ const path = (_this$options$tokenUr3 = _this6.options.tokenUri) !== null && _this$options$tokenUr3 !== void 0 ? _this$options$tokenUr3 : `${_this6.host}/api/v4/oauth`;
480
+ return _this6.request(_this6.buildUrl(path), "POST", {
481
+ client_id: _this6.options.clientId,
467
482
  grant_type: "refresh_token",
468
483
  refresh_token: token
469
484
  });
@@ -581,6 +596,48 @@
581
596
  }
582
597
  };
583
598
 
599
+ //#endregion
600
+ //#region src/GuestFlow.ts
601
+ /**
602
+ * @author Martin Høgh <mh@mapcentia.com>
603
+ * @copyright 2013-2026 MapCentia ApS
604
+ * @license https://opensource.org/license/mit The MIT License
605
+ *
606
+ */
607
+ /**
608
+ * Guest token flow. Issues access/refresh tokens for the database's default
609
+ * user (the sub-user used for anonymous access) without any user credentials.
610
+ * `clientSecret` is only required when the OAuth client is not public.
611
+ */
612
+ var GuestFlow = class {
613
+ constructor(options) {
614
+ this.options = options;
615
+ this.service = new Gc2Service(options);
616
+ }
617
+ async signIn() {
618
+ var _this = this;
619
+ const { access_token, refresh_token } = await _this.service.getGuestToken();
620
+ setTokens({
621
+ accessToken: access_token,
622
+ refreshToken: refresh_token
623
+ });
624
+ setOptions({
625
+ clientId: _this.options.clientId,
626
+ host: _this.options.host,
627
+ redirectUri: "",
628
+ clientSecret: _this.options.clientSecret
629
+ });
630
+ }
631
+ signOut() {
632
+ this.clear();
633
+ }
634
+ clear() {
635
+ clearTokens();
636
+ clearOptions();
637
+ clearNonce();
638
+ }
639
+ };
640
+
584
641
  //#endregion
585
642
  //#region src/http/errors.ts
586
643
  /**
@@ -3046,6 +3103,157 @@
3046
3103
  }
3047
3104
  };
3048
3105
 
3106
+ //#endregion
3107
+ //#region src/ogc/Ogc.ts
3108
+ /** Default CRS of the OGC API: WGS 84 in longitude/latitude order. */
3109
+ const OGC_CRS84 = "http://www.opengis.net/def/crs/OGC/1.3/CRS84";
3110
+ /**
3111
+ * CRS URI for an EPSG code, e.g. `ogcEpsgCrs(25832)`. Note that
3112
+ * `ogcEpsgCrs(4326)` is latitude/longitude order; use `OGC_CRS84` for lon/lat.
3113
+ */
3114
+ function ogcEpsgCrs(epsg) {
3115
+ return `http://www.opengis.net/def/crs/EPSG/0/${epsg}`;
3116
+ }
3117
+ function bboxToString(bbox) {
3118
+ return typeof bbox === "string" ? bbox : bbox.join(",");
3119
+ }
3120
+ function spatialQuery(options) {
3121
+ const query = {};
3122
+ if ((options === null || options === void 0 ? void 0 : options.bbox) !== void 0) query.bbox = bboxToString(options.bbox);
3123
+ if ((options === null || options === void 0 ? void 0 : options.bboxCrs) !== void 0) query["bbox-crs"] = options.bboxCrs;
3124
+ if ((options === null || options === void 0 ? void 0 : options.crs) !== void 0) query.crs = options.crs;
3125
+ if ((options === null || options === void 0 ? void 0 : options.datetime) !== void 0) query.datetime = options.datetime;
3126
+ return query;
3127
+ }
3128
+ function nonEmpty(query) {
3129
+ return Object.keys(query).length > 0 ? query : void 0;
3130
+ }
3131
+ /**
3132
+ * OGC API Features (Part 1 Core, Part 2 CRS) and OGC API Maps (Part 1 Core)
3133
+ * wrapper for `/api/v4/ogc/database/{database}`.
3134
+ *
3135
+ * The endpoints accept Bearer token, HTTP Basic and anonymous requests. A
3136
+ * Bearer token must match the `database` in the path. Anonymous callers read
3137
+ * layers below `Read/write`; a `Read/write` collection answers 401 (Basic
3138
+ * challenge) for anonymous callers and 403 for identities without privilege.
3139
+ * Geofence rules, versioning and workflow are applied server-side.
3140
+ *
3141
+ * Map images cannot be fetched through this client; use `mapUrl` /
3142
+ * `datasetMapUrl` to build image URLs for `<img>` tags or map libraries.
3143
+ *
3144
+ * ```ts
3145
+ * const ogc = new Ogc(createCentiaClient({ baseUrl, auth }));
3146
+ * const page = await ogc.getItems('my_database', 'my_schema.roads', { bbox: [9, 55, 10, 56], limit: 100 });
3147
+ * ```
3148
+ */
3149
+ var Ogc = class {
3150
+ constructor(client) {
3151
+ this.client = client;
3152
+ }
3153
+ basePath(database) {
3154
+ return `api/v4/ogc/database/${encodeURIComponent(database)}`;
3155
+ }
3156
+ collectionPath(database, collectionId) {
3157
+ return `${this.basePath(database)}/collections/${encodeURIComponent(collectionId)}`;
3158
+ }
3159
+ /** The landing page with links to conformance, collections and the OpenAPI document. */
3160
+ async getLandingPage(database) {
3161
+ var _this = this;
3162
+ return _this.client.request({
3163
+ path: _this.basePath(database),
3164
+ method: "GET"
3165
+ });
3166
+ }
3167
+ /** Conformance classes implemented by the server. */
3168
+ async getConformance(database) {
3169
+ var _this2 = this;
3170
+ return _this2.client.request({
3171
+ path: `${_this2.basePath(database)}/conformance`,
3172
+ method: "GET"
3173
+ });
3174
+ }
3175
+ /** The collections (OWS-enabled layers) the caller may read, paged. */
3176
+ async getCollections(database, options) {
3177
+ var _this3 = this;
3178
+ const query = {};
3179
+ if ((options === null || options === void 0 ? void 0 : options.limit) !== void 0) query.limit = String(options.limit);
3180
+ if ((options === null || options === void 0 ? void 0 : options.offset) !== void 0) query.offset = String(options.offset);
3181
+ return _this3.client.request({
3182
+ path: `${_this3.basePath(database)}/collections`,
3183
+ method: "GET",
3184
+ query: nonEmpty(query)
3185
+ });
3186
+ }
3187
+ /**
3188
+ * One collection. Throws a `CentiaApiError` with status 404 (unknown),
3189
+ * 401 (anonymous caller, credentials required) or 403 (no privilege).
3190
+ */
3191
+ async getCollection(database, collectionId) {
3192
+ var _this4 = this;
3193
+ return _this4.client.request({
3194
+ path: _this4.collectionPath(database, collectionId),
3195
+ method: "GET"
3196
+ });
3197
+ }
3198
+ /**
3199
+ * Features of a collection as a GeoJSON FeatureCollection page. The default
3200
+ * page size is 10; follow `links` with `rel: 'next'` or pass `offset`.
3201
+ */
3202
+ async getItems(database, collectionId, options) {
3203
+ var _this5 = this;
3204
+ const query = {};
3205
+ if ((options === null || options === void 0 ? void 0 : options.limit) !== void 0) query.limit = String(options.limit);
3206
+ if ((options === null || options === void 0 ? void 0 : options.offset) !== void 0) query.offset = String(options.offset);
3207
+ Object.assign(query, spatialQuery(options));
3208
+ return _this5.client.request({
3209
+ path: `${_this5.collectionPath(database, collectionId)}/items`,
3210
+ method: "GET",
3211
+ query: nonEmpty(query),
3212
+ accept: "application/geo+json"
3213
+ });
3214
+ }
3215
+ /** One feature by primary key. Throws a 404 `CentiaApiError` when it does not exist. */
3216
+ async getItem(database, collectionId, featureId, options) {
3217
+ var _this6 = this;
3218
+ const query = {};
3219
+ if ((options === null || options === void 0 ? void 0 : options.crs) !== void 0) query.crs = options.crs;
3220
+ if ((options === null || options === void 0 ? void 0 : options.datetime) !== void 0) query.datetime = options.datetime;
3221
+ return _this6.client.request({
3222
+ path: `${_this6.collectionPath(database, collectionId)}/items/${encodeURIComponent(String(featureId))}`,
3223
+ method: "GET",
3224
+ query: nonEmpty(query),
3225
+ accept: "application/geo+json"
3226
+ });
3227
+ }
3228
+ /**
3229
+ * URL of a rendered map of one collection (PNG/JPEG), without fetching it.
3230
+ * Authorization travels in the `Authorization` header, so for protected
3231
+ * collections fetch the image with the header set (or use Basic auth).
3232
+ */
3233
+ mapUrl(database, collectionId, options) {
3234
+ return this.buildUrl(`${this.collectionPath(database, collectionId)}/map`, this.mapQuery(options));
3235
+ }
3236
+ /** URL of a rendered map of several collections of the same schema. */
3237
+ datasetMapUrl(database, collections, options) {
3238
+ const query = _objectSpread2({ collections: collections.join(",") }, this.mapQuery(options));
3239
+ return this.buildUrl(`${this.basePath(database)}/map`, query);
3240
+ }
3241
+ mapQuery(options) {
3242
+ const query = spatialQuery(options);
3243
+ if ((options === null || options === void 0 ? void 0 : options.width) !== void 0) query.width = String(options.width);
3244
+ if ((options === null || options === void 0 ? void 0 : options.height) !== void 0) query.height = String(options.height);
3245
+ if ((options === null || options === void 0 ? void 0 : options.format) !== void 0) query.f = options.format;
3246
+ if ((options === null || options === void 0 ? void 0 : options.transparent) !== void 0) query.transparent = String(options.transparent);
3247
+ if ((options === null || options === void 0 ? void 0 : options.bgcolor) !== void 0) query.bgcolor = options.bgcolor;
3248
+ return query;
3249
+ }
3250
+ buildUrl(path, query) {
3251
+ let url = `${this.client.baseUrl}/${path}`;
3252
+ if (Object.keys(query).length > 0) url += `?${new URLSearchParams(query).toString()}`;
3253
+ return url;
3254
+ }
3255
+ };
3256
+
3049
3257
  //#endregion
3050
3258
  //#region src/keyvalue/Keyvalue.ts
3051
3259
  /**
@@ -3310,10 +3518,13 @@ exports.Claims = Claims;
3310
3518
  exports.CodeFlow = CodeFlow;
3311
3519
  exports.Features = Features;
3312
3520
  exports.Gql = Gql;
3521
+ exports.GuestFlow = GuestFlow;
3313
3522
  exports.Keyvalue = Keyvalue;
3314
3523
  exports.Mapcache = Mapcache;
3315
3524
  exports.Meta = Meta;
3316
3525
  exports.NotLoggedInError = NotLoggedInError;
3526
+ exports.OGC_CRS84 = OGC_CRS84;
3527
+ exports.Ogc = Ogc;
3317
3528
  exports.Ows = Ows;
3318
3529
  exports.PasswordFlow = PasswordFlow;
3319
3530
  exports.Rpc = Rpc;
@@ -3333,4 +3544,5 @@ exports.createCentiaClient = createCentiaClient;
3333
3544
  exports.createSqlBuilder = createSqlBuilder;
3334
3545
  exports.createTokenProvider = createTokenProvider;
3335
3546
  exports.isCentiaApiError = isCentiaApiError;
3547
+ exports.ogcEpsgCrs = ogcEpsgCrs;
3336
3548
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centia-io/sdk",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "Centia-io TypeScript SDK",
5
5
  "author": "Martin Høgh",
6
6
  "license": "MIT",