@red-hat-developer-hub/backstage-plugin-adoption-insights-backend 0.0.2 → 0.0.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @red-hat-developer-hub/backstage-plugin-adoption-insights-backend
2
2
 
3
+ ## 0.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 808a0a4: fix subquery alias in total_users endpoint
8
+
3
9
  ## 0.0.2
4
10
 
5
11
  ### Patch Changes
@@ -85,8 +85,8 @@ class BaseDatabaseAdapter {
85
85
  const { start_date, end_date } = this.filters;
86
86
  const db = this.db;
87
87
  const query = db("events").select(db.raw("CAST(COUNT(*) as INTEGER) as logged_in_users")).from(
88
- db("events").select("user_ref").whereBetween("created_at", [start_date, end_date]).groupBy("user_ref")
89
- ).as("sub");
88
+ db("events").select("user_ref").whereBetween("created_at", [start_date, end_date]).groupBy("user_ref").as("sub")
89
+ );
90
90
  return query.then((result) => {
91
91
  const { licensedUsers } = this.config;
92
92
  result[0] = { ...result[0], licensed_users: licensedUsers };
@@ -1 +1 @@
1
- {"version":3,"file":"BaseAdapter.cjs.js","sources":["../../../src/database/adapters/BaseAdapter.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Knex } from 'knex';\nimport { Filters, EventDatabase, UserConfig } from '../event-database';\nimport { Event } from '../../models/Event';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport {\n DailyUser,\n Grouping,\n ResponseData,\n ResponseWithGrouping,\n} from '../../types/event';\nimport { convertToLocalTimezone } from '../../utils/date';\n\nexport abstract class BaseDatabaseAdapter implements EventDatabase {\n protected db: Knex;\n private readonly logger: LoggerService;\n protected filters?: Filters;\n protected config?: UserConfig;\n\n constructor(db: Knex, logger: LoggerService) {\n this.db = db;\n this.logger = logger;\n }\n\n setFilters(filters: Filters) {\n this.filters = filters;\n return this;\n }\n setConfig(config: UserConfig) {\n this.config = config;\n return this;\n }\n\n async insertFailedEvent(\n event: string,\n errorMessage: string,\n retryAttempts = 0,\n ) {\n const db = this.db;\n try {\n await db('failed_events').insert({\n event_data: event,\n error_message: errorMessage,\n retry_attempts: retryAttempts,\n created_at: new Date().toISOString(),\n });\n\n this.logger.info(`[DB] Failed event logged: ${event}`);\n } catch (error) {\n this.logger.error(`[DB] Error inserting failed event:`, error);\n }\n }\n\n async insertEvents(events: Event[]): Promise<void> {\n try {\n await this.db.transaction(async trx => {\n const evts = events.map(event => event.toJSON());\n await trx('events').insert(evts); // Bulk insert into events table ('events')\n });\n this.logger.info(\n `[DB] Successfully inserted ${events.length} events in bulk`,\n );\n } catch (error) {\n this.logger.error(`[DB] Error inserting batch:`, error);\n throw error; // Re-throw the error for retry handling\n }\n }\n\n protected selectFromEvents(\n queryBuilder: Knex.QueryBuilder,\n columns: (string | Knex.Raw<any>)[],\n dateRange?: [string, string],\n ): Knex.QueryBuilder {\n const query = queryBuilder\n .select(columns)\n .from('events')\n .andWhere('action', 'navigate');\n\n if (dateRange) {\n query.whereBetween('created_at', dateRange);\n }\n\n return query;\n }\n\n async getDailyUsers(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date } = this.filters!;\n const db = this.db;\n\n const groupedEventsQuery = db('events')\n .select(db.raw(this.getDynamicDateGrouping()), 'user_ref')\n .whereBetween('created_at', [start_date, end_date])\n .groupByRaw('date, user_ref');\n\n const firstSeenQuery = db('events')\n .select('user_ref')\n .min('created_at as first_seen')\n .groupBy('user_ref');\n\n const query = db\n .from(db.raw('(?) as ge', [groupedEventsQuery]))\n .leftJoin(\n db.raw('(?) as fs', [firstSeenQuery]),\n 'ge.user_ref',\n 'fs.user_ref',\n )\n .select(\n 'ge.date',\n db.raw('CAST(COUNT(*) as INTEGER) as total_users'),\n db.raw(\n `CAST(SUM(CASE WHEN fs.first_seen >= ${this.getFormatedDate(\n 'ge.date',\n )} THEN 1 ELSE 0 END) as INTEGER) as new_users`,\n ),\n db.raw(\n `CAST(SUM(CASE WHEN fs.first_seen < ${this.getFormatedDate(\n 'ge.date',\n )} THEN 1 ELSE 0 END) as INTEGER) as returning_users`,\n ),\n )\n .groupBy('ge.date')\n .orderBy('ge.date');\n\n return query.then(data => this.getResponseWithGrouping<DailyUser[]>(data));\n }\n\n async getUsers(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(db.raw('CAST(COUNT(*) as INTEGER) as logged_in_users'))\n .from(\n db('events')\n .select('user_ref')\n .whereBetween('created_at', [start_date, end_date])\n .groupBy('user_ref'),\n )\n .as('sub');\n\n return query.then(result => {\n const { licensedUsers } = this.config!;\n result[0] = { ...result[0], licensed_users: licensedUsers } as any;\n return this.getResponseData(result);\n });\n }\n\n async getTopTemplateViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(\n db.raw(`context->>'entityRef' AS entityref`),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n db.raw(this.getLastUsedDate()),\n )\n .where({\n action: 'click',\n subject: 'Create',\n plugin_id: 'scaffolder',\n })\n .whereBetween('created_at', [start_date, end_date])\n .groupByRaw('entityref')\n .orderBy('count', 'desc')\n .limit(Number(limit) || 3);\n\n return query.then(data => this.getResponseData(data, 'last_used'));\n }\n\n async getTopSearches(): Promise<Knex.QueryBuilder> {\n const db = this.db;\n this.ensureFiltersSet();\n const { start_date, end_date, limit } = this.filters!;\n const query = db('events')\n .select(\n db.raw(this.getDynamicDateGrouping()),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n )\n .whereBetween('created_at', [start_date, end_date])\n .andWhere('action', 'search')\n .groupByRaw('date')\n .orderBy('date', 'asc')\n .limit(Number(limit) || 3);\n\n return query.then(data => this.getResponseWithGrouping(data));\n }\n\n async getTopTechDocsViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n db.raw(this.getLastUsedDate()),\n db.raw(`COALESCE(LOWER(attributes->>'kind'), '') AS kind`),\n db.raw(`COALESCE(attributes->>'name', '') AS name`),\n db.raw(`COALESCE(attributes->>'namespace', '') AS namespace`),\n )\n .where({\n action: 'navigate',\n plugin_id: 'techdocs',\n })\n .whereBetween('created_at', [start_date, end_date])\n .groupByRaw(`name, kind, namespace`)\n .orderBy('count', 'desc')\n .limit(Number(limit) || 3);\n\n return query.then(data => this.getResponseData(data, 'last_used'));\n }\n\n async getTopCatalogEntitiesViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit, kind } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(\n 'plugin_id',\n db.raw(`LOWER(attributes->>'kind') AS kind`),\n db.raw(`attributes->>'name' AS name`),\n db.raw(`attributes->>'namespace' AS namespace`),\n db.raw(this.getLastUsedDate()),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n )\n .whereBetween('created_at', [start_date, end_date])\n .andWhere(db.raw(`attributes->>'kind' IS NOT NULL`))\n .andWhere('action', 'navigate')\n .andWhere('plugin_id', 'catalog')\n .groupByRaw('plugin_id, kind, name, namespace')\n .orderBy('count', 'desc')\n .limit(Number(limit) || 3);\n\n if (kind) {\n query.andWhere(db.raw(`LOWER(attributes->>'kind') = ?`, [kind]));\n }\n return query.then(data => this.getResponseData(data, 'last_used'));\n }\n\n async getTopPluginViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit = 3 } = this.filters!;\n const dateRange: [string, string] = [start_date, end_date];\n const db = this.db;\n\n // return grouped plugin counts by date.\n const getTrendDataQuery = (qb: Knex.QueryBuilder) => {\n const trend_data_columns = [\n 'plugin_id',\n db.raw(this.getDynamicDateGrouping()),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n ];\n\n return this.selectFromEvents(qb, trend_data_columns, dateRange).groupBy(\n 'plugin_id',\n 'date',\n );\n };\n\n // return grouped plugin counts\n const getPluginCountsQuery = (qb: Knex.QueryBuilder) => {\n const plugin_counts_columns = [\n 'plugin_id',\n db.raw('CAST(COUNT(*) as INTEGER) AS visit_count'),\n ];\n return this.selectFromEvents(\n qb,\n plugin_counts_columns,\n dateRange,\n ).groupBy('plugin_id');\n };\n\n // return aggregated trends JSON object and first_count, last_count to calculate the trend percentage\n const getAggregatedTrendsQuery = (qb: Knex.QueryBuilder) => {\n return qb\n .select([\n 'plugin_id',\n db.raw(`\n json(${this.getJsonAggregationQuery('date', 'count')}) AS trend,\n COALESCE((SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date LIMIT 1),0) AS first_count,\n COALESCE((SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date DESC LIMIT 1),0) AS last_count\n `),\n ])\n .from('trend_data AS t')\n .groupBy('plugin_id');\n };\n\n // Main query to get top plugins counts, trends for the given date range.\n const query = db\n .with('trend_data', qb => getTrendDataQuery(qb))\n .with('plugin_counts', qb => getPluginCountsQuery(qb))\n .with('aggregated_trends', qb => getAggregatedTrendsQuery(qb))\n .select([\n 'p.plugin_id',\n 'p.visit_count',\n 't.trend',\n db.raw(`\n CASE\n WHEN t.first_count = 0 THEN NULL\n ELSE ROUND(((t.last_count - t.first_count) * 100.0) / NULLIF(t.first_count, 0), 2)\n END AS trend_percentage\n `),\n ])\n .from('plugin_counts AS p')\n .leftJoin('aggregated_trends AS t', 'p.plugin_id', 't.plugin_id')\n .orderBy('p.visit_count', 'desc')\n .limit(limit);\n\n return query.then(data => {\n return this.getResponseWithGrouping(\n this.transformJson(data, 'trend'),\n 'trend',\n );\n });\n }\n\n abstract getDate(): string;\n abstract getLastUsedDate(): string;\n abstract isJsonSupported(): boolean;\n abstract isPartitionSupported(): boolean;\n abstract getDateBetweenQuery(): string;\n abstract getDynamicDateGrouping(onlyText?: boolean): Grouping | string;\n abstract getFormatedDate(column: string): string;\n abstract getJsonAggregationQuery(...args: any[]): string;\n\n // Helper methods\n transformDateRange(dateRange: [string, string]): [string, string] {\n return dateRange;\n }\n\n transformJson(data: any[], jsonField: string): any {\n return data.map((row: any) => ({\n ...row,\n [jsonField]: row[jsonField]\n ? JSON.parse(JSON.stringify(row[jsonField]))\n : null,\n }));\n }\n\n modifyDateInObject<T extends any>(\n obj: T & { [key: string]: string | number },\n datePath: string = 'date',\n ) {\n if (obj[datePath]) {\n return {\n ...obj,\n [datePath]: convertToLocalTimezone(obj[datePath] as string),\n };\n }\n return obj;\n }\n\n getResponseData<T extends any[]>(\n data: T,\n datePath: string = 'date',\n ): ResponseData<T> {\n return {\n data: data.map(d => {\n if (Array.isArray(d[datePath])) {\n return {\n ...d,\n [datePath]: d[datePath].map((dp: any) =>\n this.modifyDateInObject(dp),\n ),\n };\n }\n return this.modifyDateInObject(d, datePath);\n }) as T,\n };\n }\n\n getResponseWithGrouping = <T extends any[]>(\n data: T,\n datePath: string = 'date',\n ): ResponseWithGrouping<T> => {\n const grouping = this.getDynamicDateGrouping(true) as Grouping;\n\n if (grouping === 'hourly') {\n return {\n grouping,\n data: data.map(d => {\n if (Array.isArray(d[datePath])) {\n return {\n ...d,\n [datePath]: d[datePath].map((dp: any) =>\n this.modifyDateInObject(dp),\n ),\n };\n }\n return this.modifyDateInObject(d, datePath);\n }) as T,\n };\n }\n\n return {\n grouping,\n data,\n };\n };\n\n ensureFiltersSet() {\n if (!this.filters) {\n throw new Error(\n 'Filters must be set using setFilters() before calling methods.',\n );\n }\n }\n}\n"],"names":["convertToLocalTimezone"],"mappings":"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"}
1
+ {"version":3,"file":"BaseAdapter.cjs.js","sources":["../../../src/database/adapters/BaseAdapter.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Knex } from 'knex';\nimport { Filters, EventDatabase, UserConfig } from '../event-database';\nimport { Event } from '../../models/Event';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport {\n DailyUser,\n Grouping,\n ResponseData,\n ResponseWithGrouping,\n} from '../../types/event';\nimport { convertToLocalTimezone } from '../../utils/date';\n\nexport abstract class BaseDatabaseAdapter implements EventDatabase {\n protected db: Knex;\n private readonly logger: LoggerService;\n protected filters?: Filters;\n protected config?: UserConfig;\n\n constructor(db: Knex, logger: LoggerService) {\n this.db = db;\n this.logger = logger;\n }\n\n setFilters(filters: Filters) {\n this.filters = filters;\n return this;\n }\n setConfig(config: UserConfig) {\n this.config = config;\n return this;\n }\n\n async insertFailedEvent(\n event: string,\n errorMessage: string,\n retryAttempts = 0,\n ) {\n const db = this.db;\n try {\n await db('failed_events').insert({\n event_data: event,\n error_message: errorMessage,\n retry_attempts: retryAttempts,\n created_at: new Date().toISOString(),\n });\n\n this.logger.info(`[DB] Failed event logged: ${event}`);\n } catch (error) {\n this.logger.error(`[DB] Error inserting failed event:`, error);\n }\n }\n\n async insertEvents(events: Event[]): Promise<void> {\n try {\n await this.db.transaction(async trx => {\n const evts = events.map(event => event.toJSON());\n await trx('events').insert(evts); // Bulk insert into events table ('events')\n });\n this.logger.info(\n `[DB] Successfully inserted ${events.length} events in bulk`,\n );\n } catch (error) {\n this.logger.error(`[DB] Error inserting batch:`, error);\n throw error; // Re-throw the error for retry handling\n }\n }\n\n protected selectFromEvents(\n queryBuilder: Knex.QueryBuilder,\n columns: (string | Knex.Raw<any>)[],\n dateRange?: [string, string],\n ): Knex.QueryBuilder {\n const query = queryBuilder\n .select(columns)\n .from('events')\n .andWhere('action', 'navigate');\n\n if (dateRange) {\n query.whereBetween('created_at', dateRange);\n }\n\n return query;\n }\n\n async getDailyUsers(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date } = this.filters!;\n const db = this.db;\n\n const groupedEventsQuery = db('events')\n .select(db.raw(this.getDynamicDateGrouping()), 'user_ref')\n .whereBetween('created_at', [start_date, end_date])\n .groupByRaw('date, user_ref');\n\n const firstSeenQuery = db('events')\n .select('user_ref')\n .min('created_at as first_seen')\n .groupBy('user_ref');\n\n const query = db\n .from(db.raw('(?) as ge', [groupedEventsQuery]))\n .leftJoin(\n db.raw('(?) as fs', [firstSeenQuery]),\n 'ge.user_ref',\n 'fs.user_ref',\n )\n .select(\n 'ge.date',\n db.raw('CAST(COUNT(*) as INTEGER) as total_users'),\n db.raw(\n `CAST(SUM(CASE WHEN fs.first_seen >= ${this.getFormatedDate(\n 'ge.date',\n )} THEN 1 ELSE 0 END) as INTEGER) as new_users`,\n ),\n db.raw(\n `CAST(SUM(CASE WHEN fs.first_seen < ${this.getFormatedDate(\n 'ge.date',\n )} THEN 1 ELSE 0 END) as INTEGER) as returning_users`,\n ),\n )\n .groupBy('ge.date')\n .orderBy('ge.date');\n\n return query.then(data => this.getResponseWithGrouping<DailyUser[]>(data));\n }\n\n async getUsers(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(db.raw('CAST(COUNT(*) as INTEGER) as logged_in_users'))\n .from(\n db('events')\n .select('user_ref')\n .whereBetween('created_at', [start_date, end_date])\n .groupBy('user_ref')\n .as('sub'),\n );\n\n return query.then(result => {\n const { licensedUsers } = this.config!;\n result[0] = { ...result[0], licensed_users: licensedUsers } as any;\n return this.getResponseData(result);\n });\n }\n\n async getTopTemplateViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(\n db.raw(`context->>'entityRef' AS entityref`),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n db.raw(this.getLastUsedDate()),\n )\n .where({\n action: 'click',\n subject: 'Create',\n plugin_id: 'scaffolder',\n })\n .whereBetween('created_at', [start_date, end_date])\n .groupByRaw('entityref')\n .orderBy('count', 'desc')\n .limit(Number(limit) || 3);\n\n return query.then(data => this.getResponseData(data, 'last_used'));\n }\n\n async getTopSearches(): Promise<Knex.QueryBuilder> {\n const db = this.db;\n this.ensureFiltersSet();\n const { start_date, end_date, limit } = this.filters!;\n const query = db('events')\n .select(\n db.raw(this.getDynamicDateGrouping()),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n )\n .whereBetween('created_at', [start_date, end_date])\n .andWhere('action', 'search')\n .groupByRaw('date')\n .orderBy('date', 'asc')\n .limit(Number(limit) || 3);\n\n return query.then(data => this.getResponseWithGrouping(data));\n }\n\n async getTopTechDocsViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n db.raw(this.getLastUsedDate()),\n db.raw(`COALESCE(LOWER(attributes->>'kind'), '') AS kind`),\n db.raw(`COALESCE(attributes->>'name', '') AS name`),\n db.raw(`COALESCE(attributes->>'namespace', '') AS namespace`),\n )\n .where({\n action: 'navigate',\n plugin_id: 'techdocs',\n })\n .whereBetween('created_at', [start_date, end_date])\n .groupByRaw(`name, kind, namespace`)\n .orderBy('count', 'desc')\n .limit(Number(limit) || 3);\n\n return query.then(data => this.getResponseData(data, 'last_used'));\n }\n\n async getTopCatalogEntitiesViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit, kind } = this.filters!;\n const db = this.db;\n const query = db('events')\n .select(\n 'plugin_id',\n db.raw(`LOWER(attributes->>'kind') AS kind`),\n db.raw(`attributes->>'name' AS name`),\n db.raw(`attributes->>'namespace' AS namespace`),\n db.raw(this.getLastUsedDate()),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n )\n .whereBetween('created_at', [start_date, end_date])\n .andWhere(db.raw(`attributes->>'kind' IS NOT NULL`))\n .andWhere('action', 'navigate')\n .andWhere('plugin_id', 'catalog')\n .groupByRaw('plugin_id, kind, name, namespace')\n .orderBy('count', 'desc')\n .limit(Number(limit) || 3);\n\n if (kind) {\n query.andWhere(db.raw(`LOWER(attributes->>'kind') = ?`, [kind]));\n }\n return query.then(data => this.getResponseData(data, 'last_used'));\n }\n\n async getTopPluginViews(): Promise<Knex.QueryBuilder> {\n this.ensureFiltersSet();\n const { start_date, end_date, limit = 3 } = this.filters!;\n const dateRange: [string, string] = [start_date, end_date];\n const db = this.db;\n\n // return grouped plugin counts by date.\n const getTrendDataQuery = (qb: Knex.QueryBuilder) => {\n const trend_data_columns = [\n 'plugin_id',\n db.raw(this.getDynamicDateGrouping()),\n db.raw('CAST(COUNT(*) as INTEGER) AS count'),\n ];\n\n return this.selectFromEvents(qb, trend_data_columns, dateRange).groupBy(\n 'plugin_id',\n 'date',\n );\n };\n\n // return grouped plugin counts\n const getPluginCountsQuery = (qb: Knex.QueryBuilder) => {\n const plugin_counts_columns = [\n 'plugin_id',\n db.raw('CAST(COUNT(*) as INTEGER) AS visit_count'),\n ];\n return this.selectFromEvents(\n qb,\n plugin_counts_columns,\n dateRange,\n ).groupBy('plugin_id');\n };\n\n // return aggregated trends JSON object and first_count, last_count to calculate the trend percentage\n const getAggregatedTrendsQuery = (qb: Knex.QueryBuilder) => {\n return qb\n .select([\n 'plugin_id',\n db.raw(`\n json(${this.getJsonAggregationQuery('date', 'count')}) AS trend,\n COALESCE((SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date LIMIT 1),0) AS first_count,\n COALESCE((SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date DESC LIMIT 1),0) AS last_count\n `),\n ])\n .from('trend_data AS t')\n .groupBy('plugin_id');\n };\n\n // Main query to get top plugins counts, trends for the given date range.\n const query = db\n .with('trend_data', qb => getTrendDataQuery(qb))\n .with('plugin_counts', qb => getPluginCountsQuery(qb))\n .with('aggregated_trends', qb => getAggregatedTrendsQuery(qb))\n .select([\n 'p.plugin_id',\n 'p.visit_count',\n 't.trend',\n db.raw(`\n CASE\n WHEN t.first_count = 0 THEN NULL\n ELSE ROUND(((t.last_count - t.first_count) * 100.0) / NULLIF(t.first_count, 0), 2)\n END AS trend_percentage\n `),\n ])\n .from('plugin_counts AS p')\n .leftJoin('aggregated_trends AS t', 'p.plugin_id', 't.plugin_id')\n .orderBy('p.visit_count', 'desc')\n .limit(limit);\n\n return query.then(data => {\n return this.getResponseWithGrouping(\n this.transformJson(data, 'trend'),\n 'trend',\n );\n });\n }\n\n abstract getDate(): string;\n abstract getLastUsedDate(): string;\n abstract isJsonSupported(): boolean;\n abstract isPartitionSupported(): boolean;\n abstract getDateBetweenQuery(): string;\n abstract getDynamicDateGrouping(onlyText?: boolean): Grouping | string;\n abstract getFormatedDate(column: string): string;\n abstract getJsonAggregationQuery(...args: any[]): string;\n\n // Helper methods\n transformDateRange(dateRange: [string, string]): [string, string] {\n return dateRange;\n }\n\n transformJson(data: any[], jsonField: string): any {\n return data.map((row: any) => ({\n ...row,\n [jsonField]: row[jsonField]\n ? JSON.parse(JSON.stringify(row[jsonField]))\n : null,\n }));\n }\n\n modifyDateInObject<T extends any>(\n obj: T & { [key: string]: string | number },\n datePath: string = 'date',\n ) {\n if (obj[datePath]) {\n return {\n ...obj,\n [datePath]: convertToLocalTimezone(obj[datePath] as string),\n };\n }\n return obj;\n }\n\n getResponseData<T extends any[]>(\n data: T,\n datePath: string = 'date',\n ): ResponseData<T> {\n return {\n data: data.map(d => {\n if (Array.isArray(d[datePath])) {\n return {\n ...d,\n [datePath]: d[datePath].map((dp: any) =>\n this.modifyDateInObject(dp),\n ),\n };\n }\n return this.modifyDateInObject(d, datePath);\n }) as T,\n };\n }\n\n getResponseWithGrouping = <T extends any[]>(\n data: T,\n datePath: string = 'date',\n ): ResponseWithGrouping<T> => {\n const grouping = this.getDynamicDateGrouping(true) as Grouping;\n\n if (grouping === 'hourly') {\n return {\n grouping,\n data: data.map(d => {\n if (Array.isArray(d[datePath])) {\n return {\n ...d,\n [datePath]: d[datePath].map((dp: any) =>\n this.modifyDateInObject(dp),\n ),\n };\n }\n return this.modifyDateInObject(d, datePath);\n }) as T,\n };\n }\n\n return {\n grouping,\n data,\n };\n };\n\n ensureFiltersSet() {\n if (!this.filters) {\n throw new Error(\n 'Filters must be set using setFilters() before calling methods.',\n );\n }\n }\n}\n"],"names":["convertToLocalTimezone"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@red-hat-developer-hub/backstage-plugin-adoption-insights-backend",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",