@bcgov/plugin-catalog-backend-module-bc-data-catalogue 0.1.0-aps-4079-publish-npmjs-e4e0ded3

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,42 @@
1
+ # plugin-catalog-backend-module-bc-data-catalogue
2
+
3
+ This plugin integrates the BC Data Catalogue with Backstage, allowing you to import datasets, resources, and their metadata as entities in Backstage's software catalogue.
4
+
5
+ ## Installation
6
+
7
+ This package is published to npmjs.com under the scope `@bcgov`.
8
+
9
+ ### Install the Package
10
+
11
+ #### Using Yarn
12
+
13
+ yarn add @bcgov/plugin-catalog-backend-module-bc-data-catalogue
14
+
15
+ ### Usage in Backstage
16
+
17
+ Add the module to your Backstage backend in `packages/backend/src/index.ts`:
18
+
19
+ ```diff
20
+ import { createBackend } from '@backstage/backend-defaults';
21
+
22
+ const backend = createBackend();
23
+ // ... other backend.add() calls ...
24
+
25
+ + backend.add(import('@bcgov/plugin-catalog-backend-module-bc-data-catalogue'));
26
+
27
+ backend.start();
28
+ ```
29
+
30
+ ### Configure backend reading allowlist
31
+
32
+ Add the following configuration to your `app-config.yaml` to allow the backend to access the BC Data Catalogue API:
33
+
34
+ ```
35
+ backend:
36
+ reading:
37
+ allow:
38
+ - host: catalogue.data.gov.bc.ca
39
+ scheme: https
40
+ ```
41
+
42
+ **Note:** Additional hosts may be required depending what resources are being loaded. See https://github.com/bcgov/csit-backstage-poc/blob/main/app-config.yaml for example.
@@ -0,0 +1,500 @@
1
+ 'use strict';
2
+
3
+ var BcDataCatalogueModel = require('./BcDataCatalogueModel.cjs.js');
4
+
5
+ class BcDataCatalogueApisProvider {
6
+ logger;
7
+ env;
8
+ reader;
9
+ connection;
10
+ taskRunner;
11
+ allowedHosts;
12
+ /** [1] */
13
+ constructor(env, reader, taskRunner, allowedHosts, logger) {
14
+ this.env = env;
15
+ this.reader = reader;
16
+ this.taskRunner = taskRunner;
17
+ this.allowedHosts = allowedHosts;
18
+ this.logger = logger;
19
+ }
20
+ /** [2] */
21
+ getProviderName() {
22
+ return `bc-data-catalogue-${this.env}`;
23
+ }
24
+ /** [3] */
25
+ async connect(connection) {
26
+ this.logger.info("<connect");
27
+ this.connection = connection;
28
+ await this.taskRunner.run({
29
+ id: this.getProviderName(),
30
+ fn: async () => {
31
+ await this.run();
32
+ }
33
+ });
34
+ this.logger.info(">connect");
35
+ }
36
+ /** [4] */
37
+ async run() {
38
+ this.logger.info("<run");
39
+ if (!this.connection) {
40
+ throw new Error("Not initialized");
41
+ }
42
+ let page = 0;
43
+ let retries = 0;
44
+ let allEntities = [];
45
+ let allPackages = [];
46
+ do {
47
+ const start = 1e3 * page;
48
+ const url = `https://catalogue.data.gov.bc.ca/api/3/action/package_search?start=${start}&rows=1000`;
49
+ const response = await this.reader.readUrl(url);
50
+ const data = JSON.parse((await response.buffer()).toString());
51
+ if (!data?.success || !Array.isArray(data.result?.results)) {
52
+ this.logger.warn("Invalid or unsuccessful response", { success: data?.success });
53
+ ++retries;
54
+ continue;
55
+ }
56
+ retries = 0;
57
+ const results = data.result.results;
58
+ if (results.length > 0) {
59
+ const packages = this.getBcDataCataloguePackages(results);
60
+ allPackages.push(...packages);
61
+ ++page;
62
+ } else {
63
+ page = -1;
64
+ }
65
+ } while (page > 0 && retries < 3);
66
+ this.logger.info(`Total packages ${allPackages.length}`);
67
+ const allGroups = /* @__PURE__ */ new Map();
68
+ const bcGovGroupId = this.getGroupId("gov.bc.ca");
69
+ allGroups.set(bcGovGroupId, this.createGroupEntity("gov.bc.ca", "Governent of British Columbia", void 0));
70
+ const allOrganizations = /* @__PURE__ */ new Map();
71
+ allPackages.forEach((pkg) => {
72
+ const organization = pkg.organization;
73
+ allOrganizations.set(organization.id, organization);
74
+ });
75
+ const allSystems = /* @__PURE__ */ new Map();
76
+ this.logger.info(`Organizations ${allOrganizations.size}`);
77
+ allOrganizations.forEach((organization) => {
78
+ const systemEntity = {
79
+ apiVersion: "backstage.io/v1alpha1",
80
+ kind: "System",
81
+ spec: {
82
+ owner: bcGovGroupId,
83
+ type: "government"
84
+ },
85
+ metadata: {
86
+ name: this.toSafeName(organization.name),
87
+ title: organization.title,
88
+ description: organization.description,
89
+ annotations: {
90
+ "backstage.io/managed-by-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
91
+ "backstage.io/managed-by-origin-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
92
+ "bcdata.gov.bc.ca/organization-id": organization.id,
93
+ "bcdata.gov.bc.ca/organization-type": organization.type,
94
+ "bcdata.gov.bc.ca/organization-created": organization.created,
95
+ "bcdata.gov.bc.ca/organization-approval-status": organization.approval_status,
96
+ "bcdata.gov.bc.ca/organization-state": organization.state
97
+ }
98
+ }
99
+ };
100
+ allSystems.set(this.getSystemId(organization.name), systemEntity);
101
+ });
102
+ const allUsers = /* @__PURE__ */ new Map();
103
+ allPackages.forEach((pkg) => {
104
+ pkg.contacts?.forEach((contact) => {
105
+ const email = contact.email.toLowerCase();
106
+ let user = allUsers.get(email);
107
+ if (user == void 0) {
108
+ user = {
109
+ apiVersion: "backstage.io/v1alpha1",
110
+ kind: "User",
111
+ spec: {
112
+ profile: {
113
+ email
114
+ },
115
+ memberOf: []
116
+ },
117
+ metadata: {
118
+ name: this.toSafeName(email),
119
+ annotations: {
120
+ "backstage.io/managed-by-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
121
+ "backstage.io/managed-by-origin-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search"
122
+ }
123
+ }
124
+ };
125
+ allUsers.set(this.getUserId(email), user);
126
+ }
127
+ if (user?.spec.profile?.displayName == void 0) {
128
+ user.spec.profile.displayName = contact.name;
129
+ }
130
+ const hostName = this.getEmailHostname(email);
131
+ if (hostName == void 0) {
132
+ this.logger.warn(`Failed to extract hostname from email address ${email}`);
133
+ } else {
134
+ const groupId = this.getGroupId(hostName);
135
+ let group = allGroups.get(groupId);
136
+ if (group == void 0) {
137
+ allGroups.set(groupId, this.createGroupEntity(hostName, hostName, bcGovGroupId));
138
+ }
139
+ if (!user.spec.memberOf?.includes(groupId)) {
140
+ user.spec.memberOf?.push(groupId);
141
+ }
142
+ }
143
+ });
144
+ });
145
+ const allComponents = /* @__PURE__ */ new Map();
146
+ const allApis = /* @__PURE__ */ new Map();
147
+ for (const pkg of allPackages) {
148
+ const safeName = this.toSafeName(pkg.name);
149
+ const systemId = this.getSystemId(pkg.organization.name);
150
+ const entityLinks = [];
151
+ pkg.contacts.forEach((contact) => {
152
+ const email = contact.email.toLowerCase();
153
+ const entityLink = {
154
+ url: `mailto:${email}`,
155
+ title: `Contact: ${contact.name}`,
156
+ icon: "email",
157
+ type: "contact"
158
+ };
159
+ entityLinks.push(entityLink);
160
+ });
161
+ pkg.more_info?.forEach((more_info) => {
162
+ if (more_info.url.length > 0) {
163
+ const entityLink = {
164
+ url: more_info.url,
165
+ title: more_info.description || more_info.url,
166
+ icon: "externalLink",
167
+ type: "more_info"
168
+ };
169
+ entityLinks.push(entityLink);
170
+ }
171
+ });
172
+ const apiResources = [];
173
+ pkg.resources?.forEach((resource) => {
174
+ if (resource.bcdc_type == "webservice" && resource.format != "kml" || resource.format == "arcgis_rest" || resource.format == "openapi-json") {
175
+ apiResources.push(resource);
176
+ } else if (resource.bcdc_type == "geographic") ; else if (resource.url.length > 0) {
177
+ const entityLink = {
178
+ url: resource.url,
179
+ title: resource.name,
180
+ icon: "catalog",
181
+ type: resource.bcdc_type
182
+ };
183
+ entityLinks.push(entityLink);
184
+ } else {
185
+ this.logger.info(`Missing URL ${resource.bcdc_type} ${resource.format} ${pkg.name}`);
186
+ }
187
+ });
188
+ pkg.dates.forEach((date) => {
189
+ ({ type: date.type, date: date.type });
190
+ });
191
+ const tags = [];
192
+ pkg.tags?.forEach((tag) => {
193
+ tags.push(this.toSafeName(tag.display_name));
194
+ });
195
+ const componentEntity = {
196
+ apiVersion: "backstage.io/v1alpha1",
197
+ kind: "Component",
198
+ spec: {
199
+ type: pkg.type,
200
+ lifecycle: "production",
201
+ owner: bcGovGroupId,
202
+ subcomponentOf: void 0,
203
+ providesApis: [],
204
+ consumesApis: void 0,
205
+ dependsOn: void 0,
206
+ dependencyOf: void 0,
207
+ system: systemId
208
+ },
209
+ metadata: {
210
+ name: safeName,
211
+ description: pkg.notes || "No description available",
212
+ annotations: {
213
+ "backstage.io/managed-by-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
214
+ "backstage.io/managed-by-origin-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
215
+ "bcdata.gov.bc.ca/package-author": pkg.author || "Unknown",
216
+ "bcdata.gov.bc.ca/package-author_email": pkg.author_email || "Unknown",
217
+ "bcdata.gov.bc.ca/package-creator_user_id": pkg.creator_user_id,
218
+ "bcdata.gov.bc.ca/package-download_audience": pkg.download_audience,
219
+ "bcdata.gov.bc.ca/package-id": pkg.id,
220
+ "bcdata.gov.bc.ca/package-isopen": `${pkg.isopen}`,
221
+ "bcdata.gov.bc.ca/package-license_id": pkg.license_id,
222
+ "bcdata.gov.bc.ca/package-license_title": pkg.license_title || "Unknown",
223
+ "bcdata.gov.bc.ca/package-license_url": pkg.license_url,
224
+ "bcdata.gov.bc.ca/package-maintainer": pkg.maintainer || "Unknown",
225
+ "bcdata.gov.bc.ca/package-maintainer_email": pkg.maintainer_email || "Unknown",
226
+ "bcdata.gov.bc.ca/package-metadata_created": pkg.metadata_created,
227
+ "bcdata.gov.bc.ca/package-metadata_modified": pkg.metadata_modified,
228
+ "bcdata.gov.bc.ca/package-metadata_visibility": pkg.metadata_visibility,
229
+ "bcdata.gov.bc.ca/package-name": pkg.name,
230
+ "bcdata.gov.bc.ca/package-notes": pkg.notes || "Unknown",
231
+ "bcdata.gov.bc.ca/package-owner_org": pkg.owner_org,
232
+ "bcdata.gov.bc.ca/package-private": `${pkg.private}`,
233
+ "bcdata.gov.bc.ca/package-publish_state": pkg.publish_state,
234
+ "bcdata.gov.bc.ca/package-record_create_date": pkg.record_create_date || "Unknown",
235
+ "bcdata.gov.bc.ca/package-record_last_modified": pkg.record_last_modified,
236
+ "bcdata.gov.bc.ca/package-record_publish_date": pkg.record_publish_date,
237
+ "bcdata.gov.bc.ca/package-resource_status": pkg.resource_status,
238
+ "bcdata.gov.bc.ca/package-security_class": pkg.security_class,
239
+ "bcdata.gov.bc.ca/package-state": pkg.state,
240
+ "bcdata.gov.bc.ca/package-title": pkg.title || "Unknown",
241
+ "bcdata.gov.bc.ca/package-type": pkg.type,
242
+ "bcdata.gov.bc.ca/package-url": pkg.url || "Unknown",
243
+ "bcdata.gov.bc.ca/package-version": pkg.version || "Unknown",
244
+ "bcdata.gov.bc.ca/package-view_audience": pkg.view_audience
245
+ },
246
+ links: entityLinks,
247
+ tags
248
+ }
249
+ };
250
+ allComponents.set(this.getComponentId(safeName), componentEntity);
251
+ for (const apiResource of apiResources) {
252
+ const name = apiResource.name;
253
+ let resourceSafeName = this.toSafeName(name);
254
+ let apiSafeName = resourceSafeName;
255
+ if (apiResource.bcdc_type === "webservice" || apiResource.format === "arcgis_rest") {
256
+ const prefix = apiResource.format === "openapi-json" ? "api" : apiResource.format;
257
+ const formatSafeName = this.toSafeName(prefix);
258
+ let baseName = this.toSafeName(`${formatSafeName}-${safeName}`);
259
+ let candidateName = baseName;
260
+ let candidateApiId = this.getApiId(candidateName);
261
+ if (allApis.has(candidateApiId)) {
262
+ const distinguishingSuffix = this.extractDistinguishingSuffix(name);
263
+ const suffixWithSeparator = `-${distinguishingSuffix}`;
264
+ const maxBaseLength = 63 - suffixWithSeparator.length;
265
+ let truncatedBase = baseName;
266
+ if (baseName.length > maxBaseLength) {
267
+ truncatedBase = baseName.slice(0, maxBaseLength).replace(/[-_.]+$/, "");
268
+ }
269
+ candidateName = this.toSafeName(`${truncatedBase}${suffixWithSeparator}`);
270
+ candidateApiId = this.getApiId(candidateName);
271
+ let counter = 1;
272
+ while (allApis.has(candidateApiId)) {
273
+ const counterSuffix = `-${counter}`;
274
+ const maxBaseWithCounter = 63 - suffixWithSeparator.length - counterSuffix.length;
275
+ let truncatedBaseForCounter = baseName;
276
+ if (baseName.length > maxBaseWithCounter) {
277
+ truncatedBaseForCounter = baseName.slice(0, maxBaseWithCounter).replace(/[-_.]+$/, "");
278
+ }
279
+ candidateName = this.toSafeName(`${truncatedBaseForCounter}${suffixWithSeparator}${counterSuffix}`);
280
+ candidateApiId = this.getApiId(candidateName);
281
+ counter++;
282
+ }
283
+ }
284
+ apiSafeName = candidateName;
285
+ }
286
+ const definition = apiResource.url;
287
+ const url = new URL(definition);
288
+ const host = url.host.toLowerCase();
289
+ if (!this.allowedHosts.includes(host)) {
290
+ this.logger.warn(`API definition host is NOT allowed: "${host}"`);
291
+ }
292
+ const apiEntityLinks = [];
293
+ if (apiResource.url && apiResource.url.length > 0) {
294
+ const apiEntityLink = {
295
+ url: apiResource.url,
296
+ title: apiResource.name,
297
+ icon: "api",
298
+ type: apiResource.bcdc_type
299
+ };
300
+ apiEntityLinks.push(apiEntityLink);
301
+ }
302
+ let definitionContent = apiResource.url;
303
+ if (apiResource.format === "openapi-json") {
304
+ try {
305
+ const response = await this.reader.readUrl(apiResource.url);
306
+ const content = (await response.buffer()).toString();
307
+ definitionContent = content;
308
+ } catch (error) {
309
+ this.logger.warn(`Failed to fetch OpenAPI definition from ${apiResource.url}: ${error}`);
310
+ definitionContent = apiResource.url;
311
+ }
312
+ }
313
+ const apiEntity = {
314
+ apiVersion: "backstage.io/v1alpha1",
315
+ kind: "API",
316
+ spec: {
317
+ type: apiResource.format === "openapi-json" ? "openapi" : apiResource.bcdc_type,
318
+ lifecycle: "production",
319
+ owner: bcGovGroupId,
320
+ definition: definitionContent,
321
+ system: systemId
322
+ },
323
+ metadata: {
324
+ name: apiSafeName,
325
+ description: apiResource.description || "No description available",
326
+ links: apiEntityLinks,
327
+ // tags: [this.toSafeName(apiResource.format)],
328
+ tags: [this.toSafeName(apiResource.format)],
329
+ annotations: {
330
+ "backstage.io/managed-by-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
331
+ "backstage.io/managed-by-origin-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
332
+ "bcdata.gov.bc.ca/resource-bcdc_type": apiResource.bcdc_type,
333
+ "bcdata.gov.bc.ca/resource-cache_last_updated": apiResource.cache_last_updated || "Undefined",
334
+ "bcdata.gov.bc.ca/resource-cache_url": apiResource.cache_url || "Undefined",
335
+ "bcdata.gov.bc.ca/resource-created": apiResource.created,
336
+ "bcdata.gov.bc.ca/resource-datastore_active": `${apiResource.datastore_active}`,
337
+ "bcdata.gov.bc.ca/resource-description": apiResource.description || "Undefined",
338
+ // 'bcdata.gov.bc.ca/resource-details': apiResource.details,
339
+ "bcdata.gov.bc.ca/resource-format": apiResource.format,
340
+ // 'bcdata.gov.bc.ca/resource-geographic_extent': apiResource.geographic_extent,
341
+ "bcdata.gov.bc.ca/resource-hash": apiResource.hash,
342
+ "bcdata.gov.bc.ca/resource-id": apiResource.id,
343
+ // 'bcdata.gov.bc.ca/resource-iso_topic_category': apiResource.iso_topic_category || 'Undefined',
344
+ "bcdata.gov.bc.ca/resource-metadata_modified": apiResource.metadata_modified,
345
+ "bcdata.gov.bc.ca/resource-mimetype": apiResource.mimetype || "Undefined",
346
+ "bcdata.gov.bc.ca/resource-name": apiResource.name,
347
+ "bcdata.gov.bc.ca/resource-package_id": apiResource.package_id,
348
+ "bcdata.gov.bc.ca/resource-position": `${apiResource.position}`,
349
+ // 'bcdata.gov.bc.ca/resource-preview_info': apiResource.preview_info,
350
+ "bcdata.gov.bc.ca/resource-projection_name": apiResource.projection_name || "Undefined",
351
+ "bcdata.gov.bc.ca/resource-resource_access_method": apiResource.resource_access_method,
352
+ "bcdata.gov.bc.ca/resource-resource_storage_location": apiResource.resource_storage_location,
353
+ "bcdata.gov.bc.ca/resource-resource_type": apiResource.resource_type,
354
+ "bcdata.gov.bc.ca/resource-resource_update_cycle": apiResource.resource_update_cycle,
355
+ "bcdata.gov.bc.ca/resource-size": `${apiResource.size}`,
356
+ "bcdata.gov.bc.ca/resource-spatial_datatype": apiResource.spatial_datatype || "Undefined",
357
+ "bcdata.gov.bc.ca/resource-state": apiResource.state,
358
+ "bcdata.gov.bc.ca/resource-url": apiResource.url,
359
+ "bcdata.gov.bc.ca/resource-url_type": apiResource.url_type || "Undefined"
360
+ }
361
+ }
362
+ };
363
+ const apiId = this.getApiId(apiSafeName);
364
+ if (allApis.has(apiId)) {
365
+ const existingApi = allApis.get(apiId);
366
+ this.logger.warn(
367
+ `Duplicate API name detected: "${apiSafeName}" (ID: ${apiId}). Existing API: name="${existingApi.metadata.name}", Format: "${existingApi.metadata.annotations?.["bcdata.gov.bc.ca/resource-format"]}", resource-id="${existingApi.metadata.annotations?.["bcdata.gov.bc.ca/resource-id"]}", package-id="${existingApi.metadata.annotations?.["bcdata.gov.bc.ca/resource-package_id"]}", url="${existingApi.metadata.annotations?.["bcdata.gov.bc.ca/resource-url"]}". New API: name="${apiEntity.metadata.name}", resource-id="${apiResource.id}", package-id="${apiResource.package_id}", url="${apiResource.url}". The new API will overwrite the existing one.`
368
+ );
369
+ }
370
+ allApis.set(apiId, apiEntity);
371
+ componentEntity.spec.providesApis?.push(apiId);
372
+ }
373
+ }
374
+ const userEntities = Array.from(allUsers.values());
375
+ const groupEntities = Array.from(allGroups.values());
376
+ const systemEntities = Array.from(allSystems.values());
377
+ const componentEntities = Array.from(allComponents.values());
378
+ const apiEntities = Array.from(allApis.values());
379
+ allEntities.push(...userEntities);
380
+ allEntities.push(...groupEntities);
381
+ allEntities.push(...systemEntities);
382
+ allEntities.push(...componentEntities);
383
+ allEntities.push(...apiEntities);
384
+ await this.connection.applyMutation({
385
+ type: "full",
386
+ entities: allEntities.map((entity) => ({
387
+ entity,
388
+ locationKey: `bc-data-catalogue:${this.env}`
389
+ }))
390
+ });
391
+ this.logger.info(">run");
392
+ }
393
+ getEmailHostname(email) {
394
+ const match = email.trim().toLowerCase().match(/@([\w.-]+)/);
395
+ return match ? match[1] : void 0;
396
+ }
397
+ getSystemId(name) {
398
+ return `system:default/${this.toSafeName(name)}`;
399
+ }
400
+ getGroupId(hostName) {
401
+ return `group:default/${this.toSafeName(hostName)}`;
402
+ }
403
+ getUserId(email) {
404
+ return `user:default/${email.toLowerCase()}`;
405
+ }
406
+ getComponentId(name) {
407
+ return `component:default/${name.toLowerCase()}`;
408
+ }
409
+ getApiId(name) {
410
+ return `api:default/${name.toLowerCase()}`;
411
+ }
412
+ createGroupEntity(hostName, displayName, parentGroup) {
413
+ const groupEntity = {
414
+ apiVersion: "backstage.io/v1alpha1",
415
+ kind: "Group",
416
+ metadata: {
417
+ name: this.toSafeName(hostName),
418
+ annotations: {
419
+ "backstage.io/managed-by-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search",
420
+ "backstage.io/managed-by-origin-location": "url:https://catalogue.data.gov.bc.ca/api/3/action/package_search"
421
+ }
422
+ },
423
+ spec: {
424
+ type: "government",
425
+ profile: {
426
+ displayName
427
+ },
428
+ parent: parentGroup,
429
+ children: [],
430
+ members: []
431
+ }
432
+ };
433
+ return groupEntity;
434
+ }
435
+ /**
436
+ * Converts BC Data Catalogue (CKAN package_search) results into Backstage Entities
437
+ */
438
+ getBcDataCataloguePackages(results) {
439
+ this.logger.info("<getBcDataCataloguePackages", {
440
+ resultCount: Array.isArray(results) ? results.length : "unknown"
441
+ });
442
+ const rawPackages = results;
443
+ this.logger.info(`rawPackageCount ${rawPackages.length}`);
444
+ const validPackages = [];
445
+ for (const item of rawPackages) {
446
+ const parseResult = BcDataCatalogueModel.BcDataCataloguePackageSchema.safeParse(item);
447
+ if (parseResult.success) {
448
+ const pkg = parseResult.data;
449
+ if (pkg.type === "bcdc_dataset" && pkg.state === "active") {
450
+ validPackages.push(pkg);
451
+ }
452
+ } else {
453
+ this.logger.warn(JSON.stringify(item));
454
+ this.logger.warn("Invalid package skipped", {
455
+ error: parseResult.error.message
456
+ });
457
+ throw new Error(
458
+ `BC Data Catalogue package validation failedSee logs for details. First issue: ${parseResult.error.issues[0]?.message}`
459
+ );
460
+ }
461
+ }
462
+ this.logger.info(`>getBcDataCataloguePackages ${validPackages.length}`);
463
+ return validPackages;
464
+ }
465
+ toSafeName(name) {
466
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(?:^[-_.]+|[-_.]+$)/g, "").slice(0, 63).replace(/[-_.]+$/, "");
467
+ }
468
+ /**
469
+ * Extracts distinguishing information from a resource name to help make API names unique.
470
+ * Tries to extract meaningful parts like years, version numbers, or other identifiers.
471
+ */
472
+ extractDistinguishingSuffix(resourceName) {
473
+ const safeName = this.toSafeName(resourceName);
474
+ const yearMatch = resourceName.match(/\b(19|20)\d{2}\b/);
475
+ if (yearMatch) {
476
+ return yearMatch[0];
477
+ }
478
+ const versionMatch = resourceName.match(/\b(?:v|version)[\s_-]?(\d+)\b/i);
479
+ if (versionMatch) {
480
+ return `v${versionMatch[1]}`;
481
+ }
482
+ const trailingNumberMatch = resourceName.match(/\b(\d{2,})\b/);
483
+ if (trailingNumberMatch) {
484
+ return trailingNumberMatch[0];
485
+ }
486
+ const words = safeName.split("-").filter(
487
+ (w) => w.length > 0 && !["service", "request", "getcapabilities", "wms", "kml", "arcgis", "rest", "online"].includes(w)
488
+ );
489
+ if (words.length >= 2) {
490
+ return words.slice(-2).join("-");
491
+ } else if (words.length === 1) {
492
+ return words[0];
493
+ } else {
494
+ return safeName.split("-").slice(-1)[0].slice(0, 10);
495
+ }
496
+ }
497
+ }
498
+
499
+ exports.BcDataCatalogueApisProvider = BcDataCatalogueApisProvider;
500
+ //# sourceMappingURL=BcDataCatalogueApisProvider.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BcDataCatalogueApisProvider.cjs.js","sources":["../src/BcDataCatalogueApisProvider.ts"],"sourcesContent":["import { \n Entity, \n ApiEntity, \n ComponentEntity, \n GroupEntity, \n SystemEntity, \n UserEntity, \n EntityLink \n} from '@backstage/catalog-model';\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\nimport {\n SchedulerServiceTaskRunner,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { \n BcDataCataloguePackageSchema\n} from './BcDataCatalogueModel';\nimport type { \n BcDataCataloguePackage, \n BcOrganization, \n BcResource, \n} from './BcDataCatalogueModel';\n\n/**\n * Provides entities from the BC Data Catalogue service.\n */\nexport class BcDataCatalogueApisProvider implements EntityProvider {\n private readonly logger: LoggerService;\n private readonly env: string;\n private readonly reader: UrlReaderService;\n private connection?: EntityProviderConnection;\n private taskRunner: SchedulerServiceTaskRunner;\n private allowedHosts: string[];\n\n /** [1] */\n constructor(\n env: string,\n reader: UrlReaderService,\n taskRunner: SchedulerServiceTaskRunner,\n allowedHosts: string[],\n logger: LoggerService\n ) {\n this.env = env;\n this.reader = reader;\n this.taskRunner = taskRunner;\n this.allowedHosts = allowedHosts;\n this.logger = logger;\n }\n\n /** [2] */\n getProviderName(): string {\n return `bc-data-catalogue-${this.env}`;\n }\n\n /** [3] */\n async connect(connection: EntityProviderConnection): Promise<void> {\n this.logger.info('<connect');\n this.connection = connection;\n await this.taskRunner.run({\n id: this.getProviderName(),\n fn: async () => {\n await this.run();\n },\n });\n this.logger.info('>connect');\n }\n\n /** [4] */\n async run(): Promise<void> {\n this.logger.info('<run');\n\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n \n let page = 0;\n let retries = 0;\n\n let allEntities: Entity[] = [];\n\n let allPackages: BcDataCataloguePackage[] = [];\n\n do {\n\n const start = 1000 * page;\n\n const url: string = `https://catalogue.data.gov.bc.ca/api/3/action/package_search?start=${start}&rows=1000`;\n\n const response = await this.reader.readUrl(url);\n\n const data = JSON.parse((await response.buffer()).toString());\n\n if (!data?.success || !Array.isArray(data.result?.results)) {\n this.logger.warn('Invalid or unsuccessful response', { success: data?.success });\n ++retries;\n continue;\n }\n\n // Reset the retries on success\n retries = 0;\n\n const results = data.result.results as unknown[];\n\n if (results.length > 0) {\n\n const packages: BcDataCataloguePackage[] = this.getBcDataCataloguePackages(results);\n\n allPackages.push(...packages);\n ++page;\n } else {\n page = -1;\n }\n } while (page > 0 && retries < 3);\n\n this.logger.info(`Total packages ${allPackages.length}`)\n\n const allGroups = new Map<string, GroupEntity> ;\n\n const bcGovGroupId = this.getGroupId('gov.bc.ca');\n\n allGroups.set(bcGovGroupId, this.createGroupEntity('gov.bc.ca', 'Governent of British Columbia', undefined));\n\n const allOrganizations = new Map<string, BcOrganization>;\n allPackages.forEach(pkg => {\n \n const organization = pkg.organization;\n\n allOrganizations.set(organization.id, organization);\n });\n\n const allSystems = new Map<string, SystemEntity> ;\n this.logger.info(`Organizations ${allOrganizations.size}`);\n allOrganizations.forEach(organization => { \n\n const systemEntity: SystemEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'System',\n spec: {\n owner: bcGovGroupId,\n type: 'government',\n },\n metadata: {\n name: this.toSafeName(organization.name),\n title: organization.title,\n description: organization.description,\n annotations: {\n 'backstage.io/managed-by-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n 'backstage.io/managed-by-origin-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n\n 'bcdata.gov.bc.ca/organization-id': organization.id,\n 'bcdata.gov.bc.ca/organization-type': organization.type,\n 'bcdata.gov.bc.ca/organization-created': organization.created,\n 'bcdata.gov.bc.ca/organization-approval-status': organization.approval_status,\n 'bcdata.gov.bc.ca/organization-state': organization.state,\n },\n }\n };\n\n allSystems.set(this.getSystemId(organization.name), systemEntity)\n });\n\n const allUsers = new Map<string, UserEntity>;\n allPackages.forEach(pkg => {\n \n pkg.contacts?.forEach(contact => {\n\n const email = contact.email.toLowerCase();\n\n let user: UserEntity | undefined = allUsers.get(email);\n\n if (user == undefined) {\n\n user = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'User',\n spec: {\n profile: {\n email: email\n },\n memberOf: []\n },\n metadata: {\n name: this.toSafeName(email),\n annotations: {\n 'backstage.io/managed-by-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n 'backstage.io/managed-by-origin-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n },\n }\n };\n\n allUsers.set(this.getUserId(email), user);\n }\n\n if (user?.spec.profile?.displayName == undefined) {\n \n user!.spec.profile!.displayName = contact.name\n }\n\n const hostName = this.getEmailHostname(email);\n\n if (hostName == undefined) {\n\n this.logger.warn(`Failed to extract hostname from email address ${email}`);\n } else {\n\n const groupId = this.getGroupId(hostName);\n \n let group = allGroups.get(groupId);\n \n if (group == undefined) {\n\n allGroups.set(groupId, this.createGroupEntity(hostName, hostName, bcGovGroupId));\n }\n\n if (!user.spec.memberOf?.includes(groupId)) {\n\n user.spec.memberOf?.push(groupId);\n }\n }\n });\n });\n \n const allComponents = new Map<string, ComponentEntity>;\n const allApis = new Map<string, ApiEntity>;\n\n for (const pkg of allPackages) {\n\n const safeName = this.toSafeName(pkg.name);\n\n const systemId = this.getSystemId(pkg.organization.name);\n\n const entityLinks: EntityLink[] = [];\n\n pkg.contacts.forEach(contact => {\n\n const email = contact.email.toLowerCase();\n\n const entityLink: EntityLink = {\n url: `mailto:${email}`,\n title: `Contact: ${contact.name}`,\n icon: 'email',\n type: 'contact',\n };\n\n entityLinks.push(entityLink);\n });\n\n pkg.more_info?.forEach(more_info => {\n\n if (more_info.url.length > 0) {\n\n const entityLink: EntityLink = {\n url: more_info.url,\n title: more_info.description || more_info.url,\n icon: 'externalLink',\n type: 'more_info',\n };\n\n entityLinks.push(entityLink);\n }\n });\n\n const apiResources: BcResource[] = [];\n\n pkg.resources?.forEach (resource => {\n\n if (resource.bcdc_type == 'webservice' && resource.format != 'kml'\n || resource.format == 'arcgis_rest' \n || resource.format == 'openapi-json' \n ) {\n\n // this.logger.info(`Found ${resource.bcdc_type} ${resource.format} ${resource.name}`);\n apiResources.push(resource);\n } else if (resource.bcdc_type == 'geographic') {\n\n // TODO What to do with Geographic resources? No URL.\n\n } else if (resource.url.length > 0) {\n\n const entityLink: EntityLink = {\n url: resource.url,\n title: resource.name,\n icon: 'catalog',\n type: resource.bcdc_type,\n };\n\n entityLinks.push(entityLink);\n } else {\n\n this.logger.info(`Missing URL ${resource.bcdc_type} ${resource.format} ${pkg.name}`);\n }\n });\n\n const labels: Record<string, string>[] = [];\n\n pkg.dates.forEach(date => {\n\n const label: Record<string, string> = { type: date.type, date: date.type };\n\n labels.push(label);\n });\n\n const tags: string[] = [];\n\n pkg.tags?.forEach(tag => {\n\n tags.push(this.toSafeName(tag.display_name));\n });\n\n const componentEntity: ComponentEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Component',\n spec: {\n type: pkg.type,\n lifecycle: 'production',\n owner: bcGovGroupId,\n subcomponentOf: undefined,\n providesApis: [],\n consumesApis: undefined,\n dependsOn: undefined,\n dependencyOf: undefined,\n system: systemId\n },\n metadata: {\n name: safeName,\n description: pkg.notes || 'No description available',\n annotations: {\n 'backstage.io/managed-by-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n 'backstage.io/managed-by-origin-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n\n 'bcdata.gov.bc.ca/package-author': pkg.author || 'Unknown',\n 'bcdata.gov.bc.ca/package-author_email': pkg.author_email || 'Unknown',\n 'bcdata.gov.bc.ca/package-creator_user_id': pkg.creator_user_id,\n 'bcdata.gov.bc.ca/package-download_audience': pkg.download_audience,\n 'bcdata.gov.bc.ca/package-id': pkg.id,\n 'bcdata.gov.bc.ca/package-isopen': `${pkg.isopen}`,\n 'bcdata.gov.bc.ca/package-license_id': pkg.license_id,\n 'bcdata.gov.bc.ca/package-license_title': pkg.license_title || 'Unknown',\n 'bcdata.gov.bc.ca/package-license_url': pkg.license_url,\n 'bcdata.gov.bc.ca/package-maintainer': pkg.maintainer || 'Unknown',\n 'bcdata.gov.bc.ca/package-maintainer_email': pkg.maintainer_email || 'Unknown',\n 'bcdata.gov.bc.ca/package-metadata_created': pkg.metadata_created,\n 'bcdata.gov.bc.ca/package-metadata_modified': pkg.metadata_modified,\n 'bcdata.gov.bc.ca/package-metadata_visibility': pkg.metadata_visibility,\n 'bcdata.gov.bc.ca/package-name': pkg.name,\n 'bcdata.gov.bc.ca/package-notes': pkg.notes || 'Unknown',\n 'bcdata.gov.bc.ca/package-owner_org': pkg.owner_org,\n 'bcdata.gov.bc.ca/package-private': `${pkg.private}`,\n 'bcdata.gov.bc.ca/package-publish_state': pkg.publish_state,\n 'bcdata.gov.bc.ca/package-record_create_date': pkg.record_create_date || 'Unknown',\n 'bcdata.gov.bc.ca/package-record_last_modified': pkg.record_last_modified,\n 'bcdata.gov.bc.ca/package-record_publish_date': pkg.record_publish_date,\n 'bcdata.gov.bc.ca/package-resource_status': pkg.resource_status,\n 'bcdata.gov.bc.ca/package-security_class': pkg.security_class,\n 'bcdata.gov.bc.ca/package-state': pkg.state,\n 'bcdata.gov.bc.ca/package-title': pkg.title || 'Unknown',\n 'bcdata.gov.bc.ca/package-type': pkg.type,\n 'bcdata.gov.bc.ca/package-url': pkg.url || 'Unknown',\n 'bcdata.gov.bc.ca/package-version': pkg.version || 'Unknown',\n 'bcdata.gov.bc.ca/package-view_audience': pkg.view_audience,\n },\n links: entityLinks,\n tags: tags,\n },\n };\n\n allComponents.set(this.getComponentId(safeName), componentEntity);\n\n for (const apiResource of apiResources) {\n\n const name = apiResource.name;\n let resourceSafeName = this.toSafeName(name);\n let apiSafeName = resourceSafeName;\n\n // For all webservice resources, prefix with format to ensure uniqueness\n if (apiResource.bcdc_type === 'webservice' || apiResource.format === 'arcgis_rest') {\n // Use 'api' prefix for openapi-json, otherwise use the format as prefix\n const prefix = apiResource.format === 'openapi-json' ? 'api' : apiResource.format;\n const formatSafeName = this.toSafeName(prefix);\n // Start with package name as base (most informative)\n let baseName = this.toSafeName(`${formatSafeName}-${safeName}`);\n \n // Check if this would create a duplicate\n let candidateName = baseName;\n let candidateApiId = this.getApiId(candidateName);\n \n if (allApis.has(candidateApiId)) {\n // Append distinguishing information from resource name to ensure uniqueness\n const distinguishingSuffix = this.extractDistinguishingSuffix(name);\n \n // Calculate space needed: suffix + separator dash (max 63 chars total)\n const suffixWithSeparator = `-${distinguishingSuffix}`;\n const maxBaseLength = 63 - suffixWithSeparator.length;\n \n // Truncate baseName if needed to ensure suffix fits\n let truncatedBase = baseName;\n if (baseName.length > maxBaseLength) {\n truncatedBase = baseName.slice(0, maxBaseLength).replace(/[-_.]+$/, '');\n }\n \n candidateName = this.toSafeName(`${truncatedBase}${suffixWithSeparator}`);\n candidateApiId = this.getApiId(candidateName);\n \n // If still a duplicate, append a counter to ensure uniqueness\n let counter = 1;\n while (allApis.has(candidateApiId)) {\n // Reserve space for counter: suffix + counter + 2 dashes\n const counterSuffix = `-${counter}`;\n const maxBaseWithCounter = 63 - suffixWithSeparator.length - counterSuffix.length;\n let truncatedBaseForCounter = baseName;\n if (baseName.length > maxBaseWithCounter) {\n truncatedBaseForCounter = baseName.slice(0, maxBaseWithCounter).replace(/[-_.]+$/, '');\n }\n candidateName = this.toSafeName(`${truncatedBaseForCounter}${suffixWithSeparator}${counterSuffix}`);\n candidateApiId = this.getApiId(candidateName);\n counter++;\n }\n }\n \n apiSafeName = candidateName;\n }\n\n const definition = apiResource.url;\n const url = new URL(definition);\n const host = url.host.toLowerCase();\n \n if (!this.allowedHosts.includes(host)) {\n\n this.logger.warn(`API definition host is NOT allowed: \"${host}\"`);\n }\n\n const apiEntityLinks: EntityLink[] = [];\n\n if (apiResource.url && apiResource.url.length > 0) {\n const apiEntityLink: EntityLink = {\n url: apiResource.url,\n title: apiResource.name,\n icon: 'api',\n type: apiResource.bcdc_type,\n };\n\n apiEntityLinks.push(apiEntityLink);\n }\n\n // For openapi-json resources, fetch the content and embed it directly\n let definitionContent: string = apiResource.url;\n if (apiResource.format === 'openapi-json') {\n try {\n const response = await this.reader.readUrl(apiResource.url);\n const content = (await response.buffer()).toString();\n definitionContent = content;\n // this.logger.info(`Fetched OpenAPI definition for ${apiResource.name}`);\n } catch (error) {\n this.logger.warn(`Failed to fetch OpenAPI definition from ${apiResource.url}: ${error}`);\n // Fall back to URL if fetch fails\n definitionContent = apiResource.url;\n }\n }\n\n const apiEntity: ApiEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'API',\n spec: {\n type: apiResource.format === 'openapi-json' ? 'openapi' : apiResource.bcdc_type,\n lifecycle: 'production',\n owner: bcGovGroupId,\n definition: definitionContent,\n system: systemId\n },\n metadata: {\n name: apiSafeName,\n description: apiResource.description || 'No description available',\n links: apiEntityLinks,\n // tags: [this.toSafeName(apiResource.format)],\n tags: [this.toSafeName(apiResource.format)],\n annotations: {\n 'backstage.io/managed-by-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n 'backstage.io/managed-by-origin-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n\n 'bcdata.gov.bc.ca/resource-bcdc_type': apiResource.bcdc_type,\n 'bcdata.gov.bc.ca/resource-cache_last_updated': apiResource.cache_last_updated || 'Undefined',\n 'bcdata.gov.bc.ca/resource-cache_url': apiResource.cache_url || 'Undefined',\n 'bcdata.gov.bc.ca/resource-created': apiResource.created,\n 'bcdata.gov.bc.ca/resource-datastore_active': `${apiResource.datastore_active}`,\n 'bcdata.gov.bc.ca/resource-description': apiResource.description || 'Undefined',\n // 'bcdata.gov.bc.ca/resource-details': apiResource.details,\n 'bcdata.gov.bc.ca/resource-format': apiResource.format,\n // 'bcdata.gov.bc.ca/resource-geographic_extent': apiResource.geographic_extent,\n 'bcdata.gov.bc.ca/resource-hash': apiResource.hash,\n 'bcdata.gov.bc.ca/resource-id': apiResource.id,\n // 'bcdata.gov.bc.ca/resource-iso_topic_category': apiResource.iso_topic_category || 'Undefined',\n 'bcdata.gov.bc.ca/resource-metadata_modified': apiResource.metadata_modified,\n 'bcdata.gov.bc.ca/resource-mimetype': apiResource.mimetype || 'Undefined',\n 'bcdata.gov.bc.ca/resource-name': apiResource.name,\n 'bcdata.gov.bc.ca/resource-package_id': apiResource.package_id,\n 'bcdata.gov.bc.ca/resource-position': `${apiResource.position}`,\n // 'bcdata.gov.bc.ca/resource-preview_info': apiResource.preview_info,\n 'bcdata.gov.bc.ca/resource-projection_name': apiResource.projection_name || 'Undefined',\n 'bcdata.gov.bc.ca/resource-resource_access_method': apiResource.resource_access_method,\n 'bcdata.gov.bc.ca/resource-resource_storage_location': apiResource.resource_storage_location,\n 'bcdata.gov.bc.ca/resource-resource_type': apiResource.resource_type,\n 'bcdata.gov.bc.ca/resource-resource_update_cycle': apiResource.resource_update_cycle,\n 'bcdata.gov.bc.ca/resource-size': `${apiResource.size}`,\n 'bcdata.gov.bc.ca/resource-spatial_datatype': apiResource.spatial_datatype || 'Undefined',\n 'bcdata.gov.bc.ca/resource-state': apiResource.state,\n 'bcdata.gov.bc.ca/resource-url': apiResource.url,\n 'bcdata.gov.bc.ca/resource-url_type': apiResource.url_type || 'Undefined',\n }\n }\n };\n\n const apiId = this.getApiId(apiSafeName);\n\n // Check for duplicate API names\n if (allApis.has(apiId)) {\n const existingApi = allApis.get(apiId)!;\n this.logger.warn(\n `Duplicate API name detected: \"${apiSafeName}\" (ID: ${apiId}). ` +\n `Existing API: name=\"${existingApi.metadata.name}\", ` +\n `Format: \"${existingApi.metadata.annotations?.['bcdata.gov.bc.ca/resource-format']}\", ` +\n `resource-id=\"${existingApi.metadata.annotations?.['bcdata.gov.bc.ca/resource-id']}\", ` +\n `package-id=\"${existingApi.metadata.annotations?.['bcdata.gov.bc.ca/resource-package_id']}\", ` +\n `url=\"${existingApi.metadata.annotations?.['bcdata.gov.bc.ca/resource-url']}\". ` +\n `New API: name=\"${apiEntity.metadata.name}\", ` +\n `resource-id=\"${apiResource.id}\", ` +\n `package-id=\"${apiResource.package_id}\", ` +\n `url=\"${apiResource.url}\". ` +\n `The new API will overwrite the existing one.`\n );\n }\n \n allApis.set(apiId, apiEntity);\n\n componentEntity.spec.providesApis?.push(apiId);\n }\n }\n\n const userEntities: UserEntity[] = Array.from(allUsers.values());\n const groupEntities: GroupEntity[] = Array.from(allGroups.values());\n const systemEntities: SystemEntity[] = Array.from(allSystems.values());\n const componentEntities: ComponentEntity[] = Array.from(allComponents.values());\n const apiEntities: ApiEntity[] = Array.from(allApis.values());\n\n allEntities.push(...userEntities);\n allEntities.push(...groupEntities);\n allEntities.push(...systemEntities);\n allEntities.push(...componentEntities);\n allEntities.push(...apiEntities);\n\n await this.connection.applyMutation({\n type: 'full',\n entities: allEntities.map(entity => ({\n entity,\n locationKey: `bc-data-catalogue:${this.env}`,\n })),\n });\n\n this.logger.info('>run');\n }\n\n private getEmailHostname(email: string): string | undefined {\n const match = email.trim().toLowerCase().match(/@([\\w.-]+)/);\n return match ? match[1] : undefined;\n }\n\n private getSystemId(name: string) {\n\n return `system:default/${this.toSafeName(name)}`;\n }\n\n private getGroupId(hostName: string) {\n\n return `group:default/${this.toSafeName(hostName)}`;\n }\n\n private getUserId(email: string) {\n\n return `user:default/${email.toLowerCase()}`;\n }\n\n private getComponentId(name: string) {\n\n return `component:default/${name.toLowerCase()}`;\n }\n\n private getApiId(name: string) {\n\n return `api:default/${name.toLowerCase()}`;\n }\n\n private createGroupEntity(hostName: string, displayName: string, parentGroup?: string): GroupEntity {\n\n const groupEntity: GroupEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Group',\n metadata: {\n name: this.toSafeName(hostName),\n annotations: {\n 'backstage.io/managed-by-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n 'backstage.io/managed-by-origin-location': 'url:https://catalogue.data.gov.bc.ca/api/3/action/package_search',\n },\n },\n spec: {\n type: 'government',\n profile: {\n displayName: displayName\n },\n parent: parentGroup,\n children: [],\n members: []\n }\n };\n\n return groupEntity;\n }\n\n /**\n * Converts BC Data Catalogue (CKAN package_search) results into Backstage Entities\n */\n private getBcDataCataloguePackages(results: any): BcDataCataloguePackage[] {\n this.logger.info('<getBcDataCataloguePackages', {\n resultCount: Array.isArray(results) ? results.length : 'unknown',\n });\n\n const rawPackages = results as unknown[];\n this.logger.info(`rawPackageCount ${rawPackages.length}`);\n\n // Parse and validate each package with Zod\n const validPackages: BcDataCataloguePackage[] = [];\n\n for (const item of rawPackages) {\n const parseResult = BcDataCataloguePackageSchema.safeParse(item);\n\n if (parseResult.success) {\n const pkg = parseResult.data;\n\n // Extra runtime filter: only active BC Data Catalogue datasets\n if (pkg.type === 'bcdc_dataset' && pkg.state === 'active') {\n validPackages.push(pkg);\n }\n } else {\n this.logger.warn(JSON.stringify(item));\n this.logger.warn('Invalid package skipped', {\n error: parseResult.error.message,\n });\n \n throw new Error(\n `BC Data Catalogue package validation failed` +\n `See logs for details. First issue: ${parseResult.error.issues[0]?.message}`\n );\n }\n }\n\n this.logger.info(`>getBcDataCataloguePackages ${validPackages.length}`);\n return validPackages;\n }\n\n private toSafeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-') // collapse any non-alnum to single '-'\n .replace(/(?:^[-_.]+|[-_.]+$)/g, '') // trim leading/trailing -_. \n .slice(0, 63) // max 63 chars\n .replace(/[-_.]+$/, ''); // ensure it doesn't end with -_. if truncated\n }\n\n /**\n * Extracts distinguishing information from a resource name to help make API names unique.\n * Tries to extract meaningful parts like years, version numbers, or other identifiers.\n */\n private extractDistinguishingSuffix(resourceName: string): string {\n const safeName = this.toSafeName(resourceName);\n \n // Try to extract year (4-digit number, likely 1900-2100)\n const yearMatch = resourceName.match(/\\b(19|20)\\d{2}\\b/);\n if (yearMatch) {\n return yearMatch[0];\n }\n \n // Try to extract version-like patterns (v1, v2, version-1, etc.)\n const versionMatch = resourceName.match(/\\b(?:v|version)[\\s_-]?(\\d+)\\b/i);\n if (versionMatch) {\n return `v${versionMatch[1]}`;\n }\n \n // Try to extract any trailing numbers that might be identifiers\n const trailingNumberMatch = resourceName.match(/\\b(\\d{2,})\\b/);\n if (trailingNumberMatch) {\n return trailingNumberMatch[0];\n }\n \n // If no clear distinguishing pattern, use a shortened version of the resource name\n // Take the last meaningful words (avoiding common suffixes like \"service\", \"request\", etc.)\n const words = safeName.split('-').filter(w => \n w.length > 0 && \n !['service', 'request', 'getcapabilities', 'wms', 'kml', 'arcgis', 'rest', 'online'].includes(w)\n );\n \n // Use last 2-3 meaningful words if available, otherwise last 5 chars\n if (words.length >= 2) {\n return words.slice(-2).join('-');\n } else if (words.length === 1) {\n return words[0];\n } else {\n // Fallback: use last part of safe name (up to 10 chars)\n return safeName.split('-').slice(-1)[0].slice(0, 10);\n }\n }\n\n}"],"names":["BcDataCataloguePackageSchema"],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ 'use strict';
2
+
3
+ var zod = require('zod');
4
+
5
+ const BcMoreInfoSchema = zod.z.object({
6
+ url: zod.z.string(),
7
+ description: zod.z.string().nullable().optional()
8
+ });
9
+ const BcTagSchema = zod.z.object({
10
+ display_name: zod.z.string(),
11
+ id: zod.z.string(),
12
+ name: zod.z.string(),
13
+ state: zod.z.string(),
14
+ vocabulary_id: zod.z.string().nullable()
15
+ });
16
+ const BcGroupSchema = zod.z.object({
17
+ description: zod.z.string(),
18
+ display_name: zod.z.string(),
19
+ id: zod.z.string(),
20
+ image_display_url: zod.z.string(),
21
+ name: zod.z.string(),
22
+ title: zod.z.string()
23
+ });
24
+ const BcContactSchema = zod.z.object({
25
+ displayed: zod.z.array(zod.z.string()).optional(),
26
+ email: zod.z.string(),
27
+ name: zod.z.string(),
28
+ org: zod.z.string(),
29
+ role: zod.z.string()
30
+ });
31
+ const BcOrganizationSchema = zod.z.object({
32
+ id: zod.z.string(),
33
+ name: zod.z.string(),
34
+ title: zod.z.string(),
35
+ type: zod.z.string(),
36
+ description: zod.z.string(),
37
+ image_url: zod.z.string(),
38
+ created: zod.z.string(),
39
+ // ISO date string
40
+ is_organization: zod.z.literal(true),
41
+ approval_status: zod.z.string(),
42
+ state: zod.z.string()
43
+ });
44
+ const BcGeographicExtentSchema = zod.z.object({
45
+ east_bound_longitude: zod.z.string(),
46
+ north_bound_latitude: zod.z.string(),
47
+ south_bound_latitude: zod.z.string(),
48
+ west_bound_longitude: zod.z.string()
49
+ });
50
+ const BcResourceDetailsSchema = zod.z.object({
51
+ column_comments: zod.z.string().optional(),
52
+ column_name: zod.z.string(),
53
+ data_precision: zod.z.number().or(zod.z.string()),
54
+ data_type: zod.z.string(),
55
+ short_name: zod.z.string().optional()
56
+ });
57
+ const BcResourcePreviewInfoSchema = zod.z.object({
58
+ layer_name: zod.z.string().optional(),
59
+ name: zod.z.string().optional(),
60
+ preview_latitude: zod.z.string().optional(),
61
+ preview_longitude: zod.z.string().optional(),
62
+ preview_zoom_level: zod.z.string().optional(),
63
+ link_to_imap: zod.z.string().optional(),
64
+ preview_map_service_url: zod.z.string().optional()
65
+ });
66
+ const BcResourceSchema = zod.z.object({
67
+ bcdc_type: zod.z.string(),
68
+ cache_last_updated: zod.z.string().nullable(),
69
+ cache_url: zod.z.string().nullable(),
70
+ created: zod.z.string(),
71
+ datastore_active: zod.z.string().or(zod.z.boolean()),
72
+ description: zod.z.string().optional(),
73
+ details: zod.z.array(BcResourceDetailsSchema).optional(),
74
+ format: zod.z.string(),
75
+ geographic_extent: zod.z.array(BcGeographicExtentSchema).optional(),
76
+ hash: zod.z.string(),
77
+ id: zod.z.string(),
78
+ iso_topic_category: zod.z.array(zod.z.string()).optional(),
79
+ metadata_modified: zod.z.string(),
80
+ mimetype: zod.z.string().nullable(),
81
+ name: zod.z.string(),
82
+ package_id: zod.z.string(),
83
+ position: zod.z.number(),
84
+ preview_info: zod.z.array(BcResourcePreviewInfoSchema).optional(),
85
+ projection_name: zod.z.string().optional(),
86
+ resource_access_method: zod.z.string(),
87
+ resource_storage_location: zod.z.string(),
88
+ resource_type: zod.z.string(),
89
+ resource_update_cycle: zod.z.string(),
90
+ size: zod.z.number().nullable(),
91
+ spatial_datatype: zod.z.string().optional(),
92
+ state: zod.z.string(),
93
+ url: zod.z.string(),
94
+ url_type: zod.z.string().nullable()
95
+ });
96
+ const BcDataCataloguePackageSchema = zod.z.object({
97
+ author: zod.z.string().nullable(),
98
+ author_email: zod.z.string().email().nullable(),
99
+ creator_user_id: zod.z.string(),
100
+ download_audience: zod.z.string(),
101
+ id: zod.z.string(),
102
+ isopen: zod.z.boolean(),
103
+ license_id: zod.z.string(),
104
+ license_title: zod.z.string().nullable(),
105
+ license_url: zod.z.string().url(),
106
+ maintainer: zod.z.string().nullable(),
107
+ maintainer_email: zod.z.string().email().nullable(),
108
+ metadata_created: zod.z.string(),
109
+ metadata_modified: zod.z.string(),
110
+ metadata_visibility: zod.z.string(),
111
+ name: zod.z.string(),
112
+ notes: zod.z.string().nullable(),
113
+ num_resources: zod.z.number(),
114
+ num_tags: zod.z.number(),
115
+ organization: BcOrganizationSchema,
116
+ owner_org: zod.z.string(),
117
+ private: zod.z.boolean().nullable(),
118
+ publish_state: zod.z.string(),
119
+ record_create_date: zod.z.string().optional(),
120
+ record_last_modified: zod.z.string(),
121
+ record_publish_date: zod.z.string(),
122
+ resource_status: zod.z.string(),
123
+ security_class: zod.z.string(),
124
+ state: zod.z.string(),
125
+ title: zod.z.string().nullable(),
126
+ type: zod.z.string(),
127
+ url: zod.z.string().nullable(),
128
+ version: zod.z.string().nullable(),
129
+ view_audience: zod.z.string(),
130
+ // Arrays
131
+ contacts: zod.z.array(BcContactSchema),
132
+ dates: zod.z.array(zod.z.object({
133
+ date: zod.z.string(),
134
+ type: zod.z.string()
135
+ })),
136
+ groups: zod.z.array(BcGroupSchema),
137
+ more_info: zod.z.array(BcMoreInfoSchema).nullable().optional(),
138
+ resources: zod.z.array(BcResourceSchema).nullable(),
139
+ tags: zod.z.array(BcTagSchema).nullable(),
140
+ // These are usually empty arrays of relationship IDs
141
+ relationships_as_subject: zod.z.array(zod.z.string()),
142
+ relationships_as_object: zod.z.array(zod.z.string())
143
+ });
144
+
145
+ exports.BcDataCataloguePackageSchema = BcDataCataloguePackageSchema;
146
+ //# sourceMappingURL=BcDataCatalogueModel.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BcDataCatalogueModel.cjs.js","sources":["../src/BcDataCatalogueModel.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Child schemas (defined in order of dependency)\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst BcMoreInfoSchema = z.object({\n url: z.string(),\n description: z.string().nullable().optional(),\n});\n\nconst BcTagSchema = z.object({\n display_name: z.string(),\n id: z.string(),\n name: z.string(),\n state: z.string(),\n vocabulary_id: z.string().nullable(),\n});\n\nconst BcGroupSchema = z.object({\n description: z.string(),\n display_name: z.string(),\n id: z.string(),\n image_display_url: z.string(),\n name: z.string(),\n title: z.string(),\n});\n\nconst BcContactSchema = z.object({\n displayed: z.array(z.string()).optional(),\n email: z.string(),\n name: z.string(),\n org: z.string(),\n role: z.string(),\n});\n\nconst BcOrganizationSchema = z.object({\n id: z.string(),\n name: z.string(),\n title: z.string(),\n type: z.string(), \n description: z.string(),\n image_url: z.string(),\n created: z.string(), // ISO date string\n is_organization: z.literal(true),\n approval_status: z.string(),\n state: z.string(),\n});\n\nconst BcGeographicExtentSchema = z.object({\n east_bound_longitude: z.string(),\n north_bound_latitude: z.string(),\n south_bound_latitude: z.string(),\n west_bound_longitude: z.string(),\n});\n\nconst BcResourceDetailsSchema = z.object({\n column_comments: z.string().optional(),\n column_name: z.string(),\n data_precision: z.number().or(z.string()),\n data_type: z.string(),\n short_name: z.string().optional(),\n});\n\nconst BcResourcePreviewInfoSchema = z.object({\n layer_name: z.string().optional(),\n name: z.string().optional(),\n preview_latitude: z.string().optional(),\n preview_longitude: z.string().optional(),\n preview_zoom_level: z.string().optional(),\n link_to_imap: z.string().optional(),\n preview_map_service_url: z.string().optional(),\n});\n\nconst BcResourceSchema = z.object({\n bcdc_type: z.string(),\n cache_last_updated: z.string().nullable(),\n cache_url: z.string().nullable(),\n created: z.string(),\n datastore_active: z.string().or(z.boolean()),\n description: z.string().optional(),\n details: z.array(BcResourceDetailsSchema).optional(),\n format: z.string(),\n geographic_extent: z.array(BcGeographicExtentSchema).optional(),\n hash: z.string(),\n id: z.string(),\n iso_topic_category: z.array(z.string()).optional(),\n metadata_modified: z.string(),\n mimetype: z.string().nullable(),\n name: z.string(),\n package_id: z.string(),\n position: z.number(),\n preview_info: z.array(BcResourcePreviewInfoSchema).optional(),\n projection_name: z.string().optional(),\n resource_access_method: z.string(),\n resource_storage_location: z.string(),\n resource_type: z.string(),\n resource_update_cycle: z.string(),\n size: z.number().nullable(),\n spatial_datatype: z.string().optional(),\n state: z.string(),\n url: z.string(),\n url_type: z.string().nullable(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Main schema\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const BcDataCataloguePackageSchema = z.object({\n author: z.string().nullable(),\n author_email: z.string().email().nullable(),\n creator_user_id: z.string(),\n download_audience: z.string(),\n id: z.string(),\n isopen: z.boolean(),\n license_id: z.string(),\n license_title: z.string().nullable(),\n license_url: z.string().url(),\n maintainer: z.string().nullable(),\n maintainer_email: z.string().email().nullable(),\n metadata_created: z.string(),\n metadata_modified: z.string(),\n metadata_visibility: z.string(),\n name: z.string(),\n notes: z.string().nullable(),\n num_resources: z.number(),\n num_tags: z.number(),\n organization: BcOrganizationSchema,\n owner_org: z.string(),\n private: z.boolean().nullable(),\n publish_state: z.string(),\n record_create_date: z.string().optional(),\n record_last_modified: z.string(),\n record_publish_date: z.string(),\n resource_status: z.string(),\n security_class: z.string(),\n state: z.string(),\n title: z.string().nullable(),\n type: z.string(),\n url: z.string().nullable(),\n version: z.string().nullable(),\n view_audience: z.string(),\n\n // Arrays\n contacts: z.array(BcContactSchema),\n dates: z.array(z.object({\n date: z.string(),\n type: z.string(),\n })),\n groups: z.array(BcGroupSchema),\n more_info: z.array(BcMoreInfoSchema).nullable().optional(),\n resources: z.array(BcResourceSchema).nullable(),\n tags: z.array(BcTagSchema).nullable(),\n\n // These are usually empty arrays of relationship IDs\n relationships_as_subject: z.array(z.string()),\n relationships_as_object: z.array(z.string()),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inferred types (exactly match your original interfaces)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type BcDataCataloguePackage = z.infer<typeof BcDataCataloguePackageSchema>;\nexport type BcOrganization = z.infer<typeof BcOrganizationSchema>;\nexport type BcContact = z.infer<typeof BcContactSchema>;\nexport type BcGroup = z.infer<typeof BcGroupSchema>;\nexport type BcTag = z.infer<typeof BcTagSchema>;\nexport type BcResource = z.infer<typeof BcResourceSchema>;\nexport type BcMoreInfo = z.infer<typeof BcMoreInfoSchema>;"],"names":["z"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var module$1 = require('./module.cjs.js');
6
+
7
+
8
+
9
+ exports.default = module$1.catalogModuleBcDataCatalogueApis;
10
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,5 @@
1
+ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
+
3
+ declare const catalogModuleBcDataCatalogueApis: _backstage_backend_plugin_api.BackendFeature;
4
+
5
+ export { catalogModuleBcDataCatalogueApis as default };
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var alpha = require('@backstage/plugin-catalog-node/alpha');
5
+ var BcDataCatalogueApisProvider = require('./BcDataCatalogueApisProvider.cjs.js');
6
+
7
+ const catalogModuleBcDataCatalogueApis = backendPluginApi.createBackendModule({
8
+ pluginId: "catalog",
9
+ moduleId: "bc-data-catalogue",
10
+ register(reg) {
11
+ reg.registerInit({
12
+ deps: {
13
+ catalog: alpha.catalogProcessingExtensionPoint,
14
+ // For adding the provider
15
+ reader: backendPluginApi.coreServices.urlReader,
16
+ // Injects UrlReaderService
17
+ scheduler: backendPluginApi.coreServices.scheduler,
18
+ // For creating task runners
19
+ config: backendPluginApi.coreServices.rootConfig,
20
+ // Optional: For env-specific config
21
+ logger: backendPluginApi.coreServices.logger
22
+ },
23
+ async init({ catalog, reader, scheduler, config, logger }) {
24
+ logger.info("BcDataCatalogue provider module is starting...");
25
+ const env = config.getString("backend.baseUrl").includes("dev") ? "dev" : "prod";
26
+ const allowedHosts = config.getConfigArray("backend.reading.allow").map((entry) => entry.getString("host")).map((h) => h.toLowerCase());
27
+ const taskRunner = scheduler.createScheduledTaskRunner({
28
+ frequency: { minutes: 1 },
29
+ timeout: { seconds: 45 }
30
+ });
31
+ const provider = new BcDataCatalogueApisProvider.BcDataCatalogueApisProvider(
32
+ env,
33
+ reader,
34
+ taskRunner,
35
+ allowedHosts,
36
+ logger
37
+ );
38
+ catalog.addEntityProvider(provider);
39
+ logger.info("BcDataCatalogue provider registered and scheduled");
40
+ }
41
+ });
42
+ }
43
+ });
44
+
45
+ exports.catalogModuleBcDataCatalogueApis = catalogModuleBcDataCatalogueApis;
46
+ //# sourceMappingURL=module.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.cjs.js","sources":["../src/module.ts"],"sourcesContent":["import {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\nimport { BcDataCatalogueApisProvider } from './BcDataCatalogueApisProvider';\n\nexport const catalogModuleBcDataCatalogueApis = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'bc-data-catalogue',\n register(reg) {\n reg.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint, // For adding the provider\n reader: coreServices.urlReader, // Injects UrlReaderService\n scheduler: coreServices.scheduler, // For creating task runners\n config: coreServices.rootConfig, // Optional: For env-specific config\n logger: coreServices.logger,\n },\n async init({ catalog, reader, scheduler, config, logger }) {\n \n logger.info('BcDataCatalogue provider module is starting...');\n\n const env = config.getString('backend.baseUrl').includes('dev') ? 'dev' : 'prod';\n\n const allowedHosts = config.getConfigArray('backend.reading.allow').map(entry => entry.getString('host')).map(h => h.toLowerCase());\n\n // Create a task runner with your schedule\n const taskRunner = scheduler.createScheduledTaskRunner({\n frequency: { minutes: 1 },\n timeout: { seconds: 45 },\n });\n \n // Instantiate with your constructor deps\n const provider = new BcDataCatalogueApisProvider(\n env, \n reader, \n taskRunner, \n allowedHosts, \n logger,\n );\n\n // Register the provider\n catalog.addEntityProvider(provider);\n\n logger.info('BcDataCatalogue provider registered and scheduled');\n },\n });\n },\n});\n"],"names":["createBackendModule","catalogProcessingExtensionPoint","coreServices","BcDataCatalogueApisProvider"],"mappings":";;;;;;AAOO,MAAM,mCAAmCA,oCAAA,CAAoB;AAAA,EAClE,QAAA,EAAU,SAAA;AAAA,EACV,QAAA,EAAU,mBAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,OAAA,EAASC,qCAAA;AAAA;AAAA,QACT,QAAQC,6BAAA,CAAa,SAAA;AAAA;AAAA,QACrB,WAAWA,6BAAA,CAAa,SAAA;AAAA;AAAA,QACxB,QAAQA,6BAAA,CAAa,UAAA;AAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa;AAAA,OACvB;AAAA,MACA,MAAM,KAAK,EAAE,OAAA,EAAS,QAAQ,SAAA,EAAW,MAAA,EAAQ,QAAO,EAAG;AAEzD,QAAA,MAAA,CAAO,KAAK,gDAAgD,CAAA;AAE5D,QAAA,MAAM,GAAA,GAAM,OAAO,SAAA,CAAU,iBAAiB,EAAE,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,MAAA;AAE1E,QAAA,MAAM,eAAe,MAAA,CAAO,cAAA,CAAe,uBAAuB,CAAA,CAAE,IAAI,CAAA,KAAA,KAAS,KAAA,CAAM,SAAA,CAAU,MAAM,CAAC,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,aAAa,CAAA;AAGlI,QAAA,MAAM,UAAA,GAAa,UAAU,yBAAA,CAA0B;AAAA,UACrD,SAAA,EAAW,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,UACxB,OAAA,EAAS,EAAE,OAAA,EAAS,EAAA;AAAG,SACxB,CAAA;AAGD,QAAA,MAAM,WAAW,IAAIC,uDAAA;AAAA,UACnB,GAAA;AAAA,UACA,MAAA;AAAA,UACA,UAAA;AAAA,UACA,YAAA;AAAA,UACA;AAAA,SACF;AAGA,QAAA,OAAA,CAAQ,kBAAkB,QAAQ,CAAA;AAElC,QAAA,MAAA,CAAO,KAAK,mDAAmD,CAAA;AAAA,MACjE;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@bcgov/plugin-catalog-backend-module-bc-data-catalogue",
3
+ "version": "0.1.0-aps-4079-publish-npmjs-e4e0ded3",
4
+ "license": "Apache-2.0",
5
+ "description": "The bc-data-catalogue backend module for the catalog plugin.",
6
+ "main": "./dist/index.cjs.js",
7
+ "types": "./dist/index.d.ts",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "backstage": {
12
+ "role": "backend-plugin-module",
13
+ "pluginId": "catalog",
14
+ "pluginPackage": "true",
15
+ "features": {
16
+ ".": "@backstage/BackendFeature"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "start": "backstage-cli package start",
21
+ "build": "backstage-cli package build",
22
+ "lint": "backstage-cli package lint",
23
+ "test": "backstage-cli package test",
24
+ "clean": "backstage-cli package clean",
25
+ "prepack": "backstage-cli package prepack",
26
+ "postpack": "backstage-cli package postpack"
27
+ },
28
+ "dependencies": {
29
+ "@backstage/backend-plugin-api": "^1.4.1"
30
+ },
31
+ "devDependencies": {
32
+ "@backstage/backend-test-utils": "^1.7.0",
33
+ "@backstage/cli": "^0.33.0"
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/bcgov/csit-backstage-poc",
41
+ "directory": "plugins/catalog-backend-module-bc-data-catalogue"
42
+ },
43
+ "typesVersions": {
44
+ "*": {
45
+ "package.json": [
46
+ "package.json"
47
+ ]
48
+ }
49
+ }
50
+ }