@powerhousedao/analytics-engine-graphql 6.2.3-dev.43 → 6.2.3-dev.44

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/AnalyticsResolvers.ts","../src/AnalyticsModel.ts","../src/schema.ts"],"mappings":";;qBAEa;;;KCMD;EACV;EACA;EACA;EACA;EACA,aAAa;EACb;;KAGG;EACH;EACA;;KAGG,sBAAsB;EACzB,aAAa;;qBAGF;WAIO,QAAQ;EAH1B,cAAc,OAAO;EAErB,YACkB,QAAQ,sBACxB,eAAe,OAAO;EAKX,MAAM,QAAQ,cAAW;;;;;;;;;;;;EAmDzB,mBAAmB,QAAQ,sBAAmB,uDAAA;EA+C9C,iBAAa;EAInB,iBAAiB;;;;qBC1Ib"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/AnalyticsResolvers.ts","../src/AnalyticsModel.ts","../src/schema.ts"],"mappings":";;qBAEa;;;KCMD;EACV;EACA;EACA;EACA;EACA,aAAa;EACb;;KAGG;EACH;EACA;;KAGG,sBAAsB;EACzB,aAAa;;qBAGF;WAIO,QAAQ;EAH1B,cAAc,OAAO;EAErB,YACkB,QAAQ,sBACxB,eAAe,OAAO;EAKX,MAAM,QAAQ,cAAW;;;;;;;;;;;;EAwDzB,mBAAmB,QAAQ,sBAAmB,uDAAA;EAoD9C,iBAAa;EAInB,iBAAiB;;;;qBCpJb"}
package/dist/index.js CHANGED
@@ -82,8 +82,8 @@ var AnalyticsModel = class {
82
82
  async query(filter) {
83
83
  if (!filter) return [];
84
84
  const query = {
85
- start: filter.start ? DateTime.fromISO(filter.start) : null,
86
- end: filter.end ? DateTime.fromISO(filter.end) : null,
85
+ start: filter.start ? DateTime.fromISO(filter.start, { zone: "utc" }) : null,
86
+ end: filter.end ? DateTime.fromISO(filter.end, { zone: "utc" }) : null,
87
87
  granularity: getGranularity(filter.granularity),
88
88
  metrics: filter.metrics,
89
89
  currency: getCurrency(filter.currency),
@@ -107,8 +107,8 @@ var AnalyticsModel = class {
107
107
  async multiCurrencyQuery(filter) {
108
108
  if (!filter) return [];
109
109
  const query = {
110
- start: filter.start ? DateTime.fromISO(filter.start) : null,
111
- end: filter.end ? DateTime.fromISO(filter.end) : null,
110
+ start: filter.start ? DateTime.fromISO(filter.start, { zone: "utc" }) : null,
111
+ end: filter.end ? DateTime.fromISO(filter.end, { zone: "utc" }) : null,
112
112
  granularity: getGranularity(filter.granularity),
113
113
  metrics: filter.metrics,
114
114
  currency: getCurrency(filter.currency),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/AnalyticsResolvers.ts","../src/AnalyticsModel.ts","../src/schema.ts"],"sourcesContent":["import type { AnalyticsModel } from \"./AnalyticsModel.js\";\n\nexport const AnalyticsResolvers: any = {\n Query: {\n analytics: (_: any, __: any, { dataSources: _dataSources }: any) => {\n return {};\n },\n },\n AnalyticsQuery: {\n series: async (_parent: any, { filter }: any, { dataSources }: any) => {\n const queryEngine: AnalyticsModel = dataSources.db.Analytics;\n const results = await queryEngine.query(filter);\n return results.map((s) => ({\n ...s,\n rows: s.rows.map((r: any) => ({\n ...r,\n dimensions: Object.keys(r.dimensions).map((d) => ({\n name: d,\n path: r.dimensions[d][\"path\"],\n icon: r.dimensions[d][\"icon\"],\n label: r.dimensions[d][\"label\"],\n description: r.dimensions[d][\"description\"],\n })),\n })),\n }));\n },\n metrics: (\n _parent: any,\n { filter: _filter }: any,\n { dataSources: _dataSources }: any,\n ) => {\n return Promise.resolve([\n \"Actuals\",\n \"AuditorNetOutflow\",\n \"Budget\",\n \"Contributors\",\n \"Count\",\n \"DailyDaiPriceChange\",\n \"DailyEthPriceChange\",\n \"DailyMkrPriceChange\",\n \"DailyUsdcPriceChange\",\n \"DailyUsdpPriceChange\",\n \"Forecast\",\n \"PaymentsOffChainIncluded\",\n \"PaymentsOnChain\",\n \"ProtocolNetOutflow\",\n ]);\n },\n dimensions: async (\n _: any,\n { filter: _filter }: any,\n { dataSources }: any,\n ) => {\n const queryEngine: AnalyticsModel = dataSources.db.Analytics;\n return await queryEngine.getDimensions();\n },\n currencies: (\n _: any,\n { filter: _filter }: any,\n { dataSources: _dataSources }: any,\n ) => {\n return Promise.resolve([\n \"DAI\",\n \"FTE\",\n \"GUSD\",\n \"MKR\",\n \"USDC\",\n \"USDP\",\n \"USDT\",\n ]);\n },\n multiCurrencySeries: async (\n _: any,\n { filter }: any,\n { dataSources }: any,\n ) => {\n const queryEngine: AnalyticsModel = dataSources.db.Analytics;\n const results = await queryEngine.multiCurrencyQuery(filter);\n\n return results.map((s) => ({\n ...s,\n rows: s.rows.map((r: any) => ({\n ...r,\n dimensions: Object.keys(r.dimensions).map((d) => ({\n name: d,\n path: r.dimensions[d][\"path\"],\n icon: r.dimensions[d][\"icon\"],\n label: r.dimensions[d][\"label\"],\n description: r.dimensions[d][\"description\"],\n })),\n })),\n }));\n },\n },\n};\n","import type { AnalyticsQueryEngine } from \"@powerhousedao/analytics-engine-core\";\nimport {\n AnalyticsGranularity,\n AnalyticsPath,\n type AnalyticsQuery,\n} from \"@powerhousedao/analytics-engine-core\";\nimport { DateTime } from \"luxon\";\n\nexport type queryFilter = {\n start?: string;\n end?: string;\n granularity?: string;\n metrics: string[];\n dimensions: [Record<string, string>];\n currency?: string;\n};\n\ntype CurrencyConversion = {\n metric: string;\n sourceCurrency: string;\n};\n\ntype MultiCurrencyFilter = queryFilter & {\n conversions: CurrencyConversion[];\n};\n\nexport class AnalyticsModel {\n queryLogger: (query: AnalyticsQuery) => void;\n\n constructor(\n public readonly engine: AnalyticsQueryEngine,\n queryLogger?: (query: AnalyticsQuery) => void,\n ) {\n this.queryLogger = queryLogger || (() => {});\n }\n\n public async query(filter: queryFilter) {\n if (!filter) {\n return [];\n }\n\n const query: AnalyticsQuery = {\n start: filter.start ? DateTime.fromISO(filter.start) : null,\n end: filter.end ? DateTime.fromISO(filter.end) : null,\n granularity: getGranularity(filter.granularity),\n metrics: filter.metrics,\n currency: getCurrency(filter.currency),\n select: {},\n lod: {},\n };\n\n if (query.start && !query.start.isValid) {\n query.start = null;\n }\n\n if (query.end && !query.end.isValid) {\n query.end = null;\n }\n\n if (filter.dimensions.length < 1) {\n throw new Error(\"No dimensions provided\");\n } else {\n filter.dimensions.forEach((dimension) => {\n query.select[dimension.name] = [\n AnalyticsPath.fromString(dimension.select),\n ];\n query.lod[dimension.name] = Number(dimension.lod);\n });\n }\n\n this.queryLogger(query);\n\n const results = await this.engine.execute(query);\n\n // convert dates again\n const convertedResults = results.map((r) => ({\n ...r,\n start: r.start.toJSDate(),\n end: r.end.toJSDate(),\n }));\n\n return convertedResults;\n\n // TODO: pull caching interface out into analytics module\n //return measureAnalyticsQueryPerformance('analyticsQuery', 'analyticsQuery', query, false, \"high\");\n }\n\n public async multiCurrencyQuery(filter: MultiCurrencyFilter) {\n if (!filter) {\n return [];\n }\n\n const query: AnalyticsQuery = {\n start: filter.start ? DateTime.fromISO(filter.start) : null,\n end: filter.end ? DateTime.fromISO(filter.end) : null,\n granularity: getGranularity(filter.granularity),\n metrics: filter.metrics,\n currency: getCurrency(filter.currency),\n select: {},\n lod: {},\n };\n\n if (query.start && !query.start.isValid) {\n query.start = null;\n }\n\n if (query.end && !query.end.isValid) {\n query.end = null;\n }\n\n if (filter.dimensions.length < 1) {\n throw new Error(\"No dimensions provided\");\n } else {\n filter.dimensions.forEach((dimension) => {\n query.select[dimension.name] = [\n AnalyticsPath.fromString(dimension.select),\n ];\n query.lod[dimension.name] = Number(dimension.lod);\n });\n }\n\n this.queryLogger(query);\n\n return this.engine.executeMultiCurrency(query, {\n targetCurrency: query.currency,\n conversions: filter.conversions.map((c) => {\n return {\n metric: c.metric,\n currency: getCurrency(c.sourceCurrency),\n };\n }),\n });\n }\n\n public async getDimensions() {\n return await this.engine.getDimensions();\n }\n\n public getCurrencies(): Promise<string[]> {\n // todo: use knex inside of the analytics engine to select distinct currencies\n return Promise.resolve([\"DAI\", \"FTE\", \"MKR\", \"USDC\", \"USDP\", \"USDT\"]);\n }\n}\n\nconst getGranularity = (\n granularity: string | undefined,\n): AnalyticsGranularity => {\n switch (granularity) {\n case \"hourly\": {\n return AnalyticsGranularity.Hourly;\n }\n case \"daily\": {\n return AnalyticsGranularity.Daily;\n }\n case \"weekly\": {\n return AnalyticsGranularity.Weekly;\n }\n case \"monthly\": {\n return AnalyticsGranularity.Monthly;\n }\n case \"quarterly\": {\n return AnalyticsGranularity.Quarterly;\n }\n case \"semiAnnual\": {\n return AnalyticsGranularity.SemiAnnual;\n }\n case \"annual\": {\n return AnalyticsGranularity.Annual;\n }\n case \"total\": {\n return AnalyticsGranularity.Total;\n }\n default: {\n return AnalyticsGranularity.Total;\n }\n }\n};\n\nconst getCurrency = (currency: string | undefined) => {\n return currency ? AnalyticsPath.fromString(currency) : undefined;\n};\n","export const typedefs = `\ntype AnalyticsQuery {\n series(filter: AnalyticsFilter): [AnalyticsPeriod]\n multiCurrencySeries(filter: MultiCurrencyConversions): [AnalyticsPeriod]\n metrics: [String]\n dimensions: [Dimension]\n currencies: [String]\n}\n\ntype AnalyticsPeriod {\n period: String\n start: DateTime\n end: DateTime\n rows: [AnalyticsSeries]\n}\n\ntype AnalyticsSeries {\n dimensions: [AnalyticsSeriesDimension]\n metric: String\n unit: String\n value: Float\n sum: Float\n}\n\ntype AnalyticsSeriesDimension {\n name: String\n path: String\n label: String\n description: String\n icon: String\n}\n\ntype Dimension {\n name: String\n values: [Value]\n}\n\ntype Value {\n path: String\n label: String\n description: String\n icon: String\n}\n\nenum AnalyticsGranularity {\n hourly\n daily\n weekly\n monthly\n quarterly\n semiAnnual\n annual\n total\n}\n\ninput AnalyticsFilterDimension {\n name: String!\n select: String!\n lod: Int!\n}\n\ninput MultiCurrencyConversions {\n start: String\n end: String\n \"Period to group by\"\n granularity: AnalyticsGranularity\n \"List of metrics to filter by, such as 'budget' or 'actuals'\"\n metrics: [String]\n \"List of dimensions to filter by, such as 'budget' or 'project'\"\n dimensions: [AnalyticsFilterDimension]\n currency: String\n conversions: [CurrencyConversion]!\n}\n\ninput CurrencyConversion {\n metric: String!\n sourceCurrency: String!\n}\n\ninput AnalyticsFilter {\n start: String\n end: String\n \"Period to group by\"\n granularity: AnalyticsGranularity\n \"List of metrics to filter by, such as 'budget' or 'actuals'\"\n metrics: [String]\n \"List of dimensions to filter by, such as 'budget' or 'project'\"\n dimensions: [AnalyticsFilterDimension]\n currency: String\n}\n\nextend type Query {\n analytics: AnalyticsQuery\n}\n`;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/AnalyticsResolvers.ts","../src/AnalyticsModel.ts","../src/schema.ts"],"sourcesContent":["import type { AnalyticsModel } from \"./AnalyticsModel.js\";\n\nexport const AnalyticsResolvers: any = {\n Query: {\n analytics: (_: any, __: any, { dataSources: _dataSources }: any) => {\n return {};\n },\n },\n AnalyticsQuery: {\n series: async (_parent: any, { filter }: any, { dataSources }: any) => {\n const queryEngine: AnalyticsModel = dataSources.db.Analytics;\n const results = await queryEngine.query(filter);\n return results.map((s) => ({\n ...s,\n rows: s.rows.map((r: any) => ({\n ...r,\n dimensions: Object.keys(r.dimensions).map((d) => ({\n name: d,\n path: r.dimensions[d][\"path\"],\n icon: r.dimensions[d][\"icon\"],\n label: r.dimensions[d][\"label\"],\n description: r.dimensions[d][\"description\"],\n })),\n })),\n }));\n },\n metrics: (\n _parent: any,\n { filter: _filter }: any,\n { dataSources: _dataSources }: any,\n ) => {\n return Promise.resolve([\n \"Actuals\",\n \"AuditorNetOutflow\",\n \"Budget\",\n \"Contributors\",\n \"Count\",\n \"DailyDaiPriceChange\",\n \"DailyEthPriceChange\",\n \"DailyMkrPriceChange\",\n \"DailyUsdcPriceChange\",\n \"DailyUsdpPriceChange\",\n \"Forecast\",\n \"PaymentsOffChainIncluded\",\n \"PaymentsOnChain\",\n \"ProtocolNetOutflow\",\n ]);\n },\n dimensions: async (\n _: any,\n { filter: _filter }: any,\n { dataSources }: any,\n ) => {\n const queryEngine: AnalyticsModel = dataSources.db.Analytics;\n return await queryEngine.getDimensions();\n },\n currencies: (\n _: any,\n { filter: _filter }: any,\n { dataSources: _dataSources }: any,\n ) => {\n return Promise.resolve([\n \"DAI\",\n \"FTE\",\n \"GUSD\",\n \"MKR\",\n \"USDC\",\n \"USDP\",\n \"USDT\",\n ]);\n },\n multiCurrencySeries: async (\n _: any,\n { filter }: any,\n { dataSources }: any,\n ) => {\n const queryEngine: AnalyticsModel = dataSources.db.Analytics;\n const results = await queryEngine.multiCurrencyQuery(filter);\n\n return results.map((s) => ({\n ...s,\n rows: s.rows.map((r: any) => ({\n ...r,\n dimensions: Object.keys(r.dimensions).map((d) => ({\n name: d,\n path: r.dimensions[d][\"path\"],\n icon: r.dimensions[d][\"icon\"],\n label: r.dimensions[d][\"label\"],\n description: r.dimensions[d][\"description\"],\n })),\n })),\n }));\n },\n },\n};\n","import type { AnalyticsQueryEngine } from \"@powerhousedao/analytics-engine-core\";\nimport {\n AnalyticsGranularity,\n AnalyticsPath,\n type AnalyticsQuery,\n} from \"@powerhousedao/analytics-engine-core\";\nimport { DateTime } from \"luxon\";\n\nexport type queryFilter = {\n start?: string;\n end?: string;\n granularity?: string;\n metrics: string[];\n dimensions: [Record<string, string>];\n currency?: string;\n};\n\ntype CurrencyConversion = {\n metric: string;\n sourceCurrency: string;\n};\n\ntype MultiCurrencyFilter = queryFilter & {\n conversions: CurrencyConversion[];\n};\n\nexport class AnalyticsModel {\n queryLogger: (query: AnalyticsQuery) => void;\n\n constructor(\n public readonly engine: AnalyticsQueryEngine,\n queryLogger?: (query: AnalyticsQuery) => void,\n ) {\n this.queryLogger = queryLogger || (() => {});\n }\n\n public async query(filter: queryFilter) {\n if (!filter) {\n return [];\n }\n\n const query: AnalyticsQuery = {\n // Date-only filter strings must anchor to UTC midnight: period\n // boundaries are computed in UTC, and parsing in the host zone shifts\n // \"2020-01-01\" off the calendar boundary on any non-UTC host.\n start: filter.start\n ? DateTime.fromISO(filter.start, { zone: \"utc\" })\n : null,\n end: filter.end ? DateTime.fromISO(filter.end, { zone: \"utc\" }) : null,\n granularity: getGranularity(filter.granularity),\n metrics: filter.metrics,\n currency: getCurrency(filter.currency),\n select: {},\n lod: {},\n };\n\n if (query.start && !query.start.isValid) {\n query.start = null;\n }\n\n if (query.end && !query.end.isValid) {\n query.end = null;\n }\n\n if (filter.dimensions.length < 1) {\n throw new Error(\"No dimensions provided\");\n } else {\n filter.dimensions.forEach((dimension) => {\n query.select[dimension.name] = [\n AnalyticsPath.fromString(dimension.select),\n ];\n query.lod[dimension.name] = Number(dimension.lod);\n });\n }\n\n this.queryLogger(query);\n\n const results = await this.engine.execute(query);\n\n // convert dates again\n const convertedResults = results.map((r) => ({\n ...r,\n start: r.start.toJSDate(),\n end: r.end.toJSDate(),\n }));\n\n return convertedResults;\n\n // TODO: pull caching interface out into analytics module\n //return measureAnalyticsQueryPerformance('analyticsQuery', 'analyticsQuery', query, false, \"high\");\n }\n\n public async multiCurrencyQuery(filter: MultiCurrencyFilter) {\n if (!filter) {\n return [];\n }\n\n const query: AnalyticsQuery = {\n // Date-only filter strings must anchor to UTC midnight: period\n // boundaries are computed in UTC, and parsing in the host zone shifts\n // \"2020-01-01\" off the calendar boundary on any non-UTC host.\n start: filter.start\n ? DateTime.fromISO(filter.start, { zone: \"utc\" })\n : null,\n end: filter.end ? DateTime.fromISO(filter.end, { zone: \"utc\" }) : null,\n granularity: getGranularity(filter.granularity),\n metrics: filter.metrics,\n currency: getCurrency(filter.currency),\n select: {},\n lod: {},\n };\n\n if (query.start && !query.start.isValid) {\n query.start = null;\n }\n\n if (query.end && !query.end.isValid) {\n query.end = null;\n }\n\n if (filter.dimensions.length < 1) {\n throw new Error(\"No dimensions provided\");\n } else {\n filter.dimensions.forEach((dimension) => {\n query.select[dimension.name] = [\n AnalyticsPath.fromString(dimension.select),\n ];\n query.lod[dimension.name] = Number(dimension.lod);\n });\n }\n\n this.queryLogger(query);\n\n return this.engine.executeMultiCurrency(query, {\n targetCurrency: query.currency,\n conversions: filter.conversions.map((c) => {\n return {\n metric: c.metric,\n currency: getCurrency(c.sourceCurrency),\n };\n }),\n });\n }\n\n public async getDimensions() {\n return await this.engine.getDimensions();\n }\n\n public getCurrencies(): Promise<string[]> {\n // todo: use knex inside of the analytics engine to select distinct currencies\n return Promise.resolve([\"DAI\", \"FTE\", \"MKR\", \"USDC\", \"USDP\", \"USDT\"]);\n }\n}\n\nconst getGranularity = (\n granularity: string | undefined,\n): AnalyticsGranularity => {\n switch (granularity) {\n case \"hourly\": {\n return AnalyticsGranularity.Hourly;\n }\n case \"daily\": {\n return AnalyticsGranularity.Daily;\n }\n case \"weekly\": {\n return AnalyticsGranularity.Weekly;\n }\n case \"monthly\": {\n return AnalyticsGranularity.Monthly;\n }\n case \"quarterly\": {\n return AnalyticsGranularity.Quarterly;\n }\n case \"semiAnnual\": {\n return AnalyticsGranularity.SemiAnnual;\n }\n case \"annual\": {\n return AnalyticsGranularity.Annual;\n }\n case \"total\": {\n return AnalyticsGranularity.Total;\n }\n default: {\n return AnalyticsGranularity.Total;\n }\n }\n};\n\nconst getCurrency = (currency: string | undefined) => {\n return currency ? AnalyticsPath.fromString(currency) : undefined;\n};\n","export const typedefs = `\ntype AnalyticsQuery {\n series(filter: AnalyticsFilter): [AnalyticsPeriod]\n multiCurrencySeries(filter: MultiCurrencyConversions): [AnalyticsPeriod]\n metrics: [String]\n dimensions: [Dimension]\n currencies: [String]\n}\n\ntype AnalyticsPeriod {\n period: String\n start: DateTime\n end: DateTime\n rows: [AnalyticsSeries]\n}\n\ntype AnalyticsSeries {\n dimensions: [AnalyticsSeriesDimension]\n metric: String\n unit: String\n value: Float\n sum: Float\n}\n\ntype AnalyticsSeriesDimension {\n name: String\n path: String\n label: String\n description: String\n icon: String\n}\n\ntype Dimension {\n name: String\n values: [Value]\n}\n\ntype Value {\n path: String\n label: String\n description: String\n icon: String\n}\n\nenum AnalyticsGranularity {\n hourly\n daily\n weekly\n monthly\n quarterly\n semiAnnual\n annual\n total\n}\n\ninput AnalyticsFilterDimension {\n name: String!\n select: String!\n lod: Int!\n}\n\ninput MultiCurrencyConversions {\n start: String\n end: String\n \"Period to group by\"\n granularity: AnalyticsGranularity\n \"List of metrics to filter by, such as 'budget' or 'actuals'\"\n metrics: [String]\n \"List of dimensions to filter by, such as 'budget' or 'project'\"\n dimensions: [AnalyticsFilterDimension]\n currency: String\n conversions: [CurrencyConversion]!\n}\n\ninput CurrencyConversion {\n metric: String!\n sourceCurrency: String!\n}\n\ninput AnalyticsFilter {\n start: String\n end: String\n \"Period to group by\"\n granularity: AnalyticsGranularity\n \"List of metrics to filter by, such as 'budget' or 'actuals'\"\n metrics: [String]\n \"List of dimensions to filter by, such as 'budget' or 'project'\"\n dimensions: [AnalyticsFilterDimension]\n currency: String\n}\n\nextend type Query {\n analytics: AnalyticsQuery\n}\n`;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/analytics-engine-graphql",
3
- "version": "6.2.3-dev.43",
3
+ "version": "6.2.3-dev.44",
4
4
  "license": "AGPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "luxon": "3.7.2",
26
- "@powerhousedao/analytics-engine-core": "6.2.3-dev.43"
26
+ "@powerhousedao/analytics-engine-core": "6.2.3-dev.44"
27
27
  },
28
28
  "devDependencies": {
29
29
  "vitest": "4.1.1",