@socialgouv/matomo-postgres 2.0.2 → 2.2.0

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/bin/index.js CHANGED
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { db } = require("../dist/db");
4
-
5
- const { default: run } = require("../dist/index");
6
- const { default: migrate } = require("../dist/migrate-latest");
3
+ import { db } from '../dist/db'
4
+ import run from '../dist/index'
5
+ import migrate from '../dist/migrate-latest'
7
6
 
8
7
  async function start(date) {
9
- console.log(`\nRunning migrations\n`);
10
- await migrate();
11
- console.log(`\nStarting import\n`);
12
- await run(date);
13
- db.destroy();
8
+ console.log(`\nRunning migrations\n`)
9
+ await migrate()
10
+ console.log(`\nStarting import\n`)
11
+ await run(date)
12
+ db.destroy()
14
13
  }
15
14
 
16
15
  if (require.main === module) {
17
16
  const date =
18
- (process.argv[process.argv.length - 1].match(/^\d\d\d\d-\d\d-\d\d$/) && process.argv[process.argv.length - 1]) ||
19
- "";
20
- console.log(`\nRunning @socialgouv/matomo-postgres ${date}\n`);
21
- start(date);
17
+ (process.argv[process.argv.length - 1].match(/^\d\d\d\d-\d\d-\d\d$/) &&
18
+ process.argv[process.argv.length - 1]) ||
19
+ ''
20
+ console.log(`\nRunning @socialgouv/matomo-postgres ${date}\n`)
21
+ start(date)
22
22
  }
@@ -25,24 +25,28 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  const http = __importStar(require("http"));
27
27
  const https = __importStar(require("https"));
28
- const url = __importStar(require("url"));
29
28
  const querystring = __importStar(require("querystring"));
29
+ const url = __importStar(require("url"));
30
30
  class PiwikClient {
31
31
  constructor(baseURL, token) {
32
32
  const parsedUrl = url.parse(baseURL, true);
33
33
  this.settings = {
34
34
  apihost: parsedUrl.hostname || '',
35
- apipath: parsedUrl.pathname || '',
35
+ apipath: parsedUrl.pathname || ''
36
36
  };
37
37
  // Determine protocol and set http module
38
38
  switch (parsedUrl.protocol) {
39
39
  case 'http:':
40
40
  this.http = http;
41
- this.settings.apiport = parsedUrl.port ? parseInt(parsedUrl.port, 10) : 80;
41
+ this.settings.apiport = parsedUrl.port
42
+ ? parseInt(parsedUrl.port, 10)
43
+ : 80;
42
44
  break;
43
45
  case 'https:':
44
46
  this.http = https;
45
- this.settings.apiport = parsedUrl.port ? parseInt(parsedUrl.port, 10) : 443;
47
+ this.settings.apiport = parsedUrl.port
48
+ ? parseInt(parsedUrl.port, 10)
49
+ : 443;
46
50
  break;
47
51
  default:
48
52
  this.http = http;
@@ -12,30 +12,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- process.env.MATOMO_SITE = "42";
16
- process.env.PROJECT_NAME = "some-project";
17
- process.env.RESULTPERPAGE = "10";
15
+ // Set environment variables BEFORE any imports
16
+ process.env.MATOMO_SITE = '42';
17
+ process.env.PROJECT_NAME = 'some-project';
18
+ process.env.RESULTPERPAGE = '10';
19
+ process.env.DESTINATION_TABLE = 'matomo';
18
20
  const pg_1 = require("pg");
19
- const visit_json_1 = __importDefault(require("./visit.json"));
20
21
  const importDate_1 = require("../importDate");
22
+ const visit_json_1 = __importDefault(require("./visit.json"));
21
23
  const TEST_DATE = new Date(2023, 3, 15);
22
24
  let queries = [];
23
- let result = {
24
- command: "string",
25
- rowCount: 0,
25
+ const result = {
26
+ command: 'string',
27
+ rowCount: 0
26
28
  };
27
- jest.mock("pg", () => {
29
+ jest.mock('pg', () => {
28
30
  const client = {
29
31
  query: (query, values) => {
30
32
  queries.push([query, values]);
31
33
  return result;
32
34
  },
33
- release: jest.fn(),
35
+ release: jest.fn()
34
36
  };
35
37
  const methods = {
36
38
  connect: () => client,
37
39
  on: jest.fn(),
38
- query: jest.fn(),
40
+ query: jest.fn()
39
41
  };
40
42
  return { Pool: jest.fn(() => methods) };
41
43
  });
@@ -47,12 +49,12 @@ beforeEach(() => {
47
49
  afterEach(() => {
48
50
  jest.clearAllMocks();
49
51
  });
50
- test("importDate: should import given date", () => __awaiter(void 0, void 0, void 0, function* () {
52
+ test('importDate: should import given date', () => __awaiter(void 0, void 0, void 0, function* () {
51
53
  const piwikApi = jest.fn();
52
54
  piwikApi.mockImplementation((options, cb) => {
53
55
  cb(null, [
54
56
  Object.assign(Object.assign({}, visit_json_1.default), { idVisit: 123 }),
55
- Object.assign(Object.assign({}, visit_json_1.default), { idVisit: 124 }),
57
+ Object.assign(Object.assign({}, visit_json_1.default), { idVisit: 124 })
56
58
  ]);
57
59
  });
58
60
  pool.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });
@@ -79,11 +81,11 @@ test("importDate: should import given date", () => __awaiter(void 0, void 0, voi
79
81
  `);
80
82
  expect(queries.length).toEqual(1 + visit_json_1.default.actionDetails.length * 2);
81
83
  }));
82
- test("importDate: should paginate matomo API calls and produce 46 queries", () => __awaiter(void 0, void 0, void 0, function* () {
84
+ test('importDate: should paginate matomo API calls and produce 46 queries', () => __awaiter(void 0, void 0, void 0, function* () {
83
85
  const piwikApi = jest.fn();
84
86
  let calls = 0;
85
87
  piwikApi.mockImplementation((options, cb) => {
86
- cb(null, Array.from({ length: calls ? 5 : 10 }, (k, v) => (Object.assign(Object.assign({}, visit_json_1.default), { idVisit: k }))));
88
+ cb(null, Array.from({ length: calls ? 5 : 10 }, (k, _v) => (Object.assign(Object.assign({}, visit_json_1.default), { idVisit: k }))));
87
89
  calls++;
88
90
  });
89
91
  pool.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });
@@ -3,13 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- process.env.MATOMO_SITE = "42";
7
- process.env.PROJECT_NAME = "some-project";
8
- process.env.RESULTPERPAGE = "10";
9
- const visit_json_1 = __importDefault(require("./visit.json"));
10
6
  const importEvent_1 = require("../importEvent");
11
- test("getEventsFromMatomoVisit: should merge action events", () => {
12
- // @ts-ignore
7
+ const visit_json_1 = __importDefault(require("./visit.json"));
8
+ process.env.MATOMO_SITE = '42';
9
+ process.env.PROJECT_NAME = 'some-project';
10
+ process.env.RESULTPERPAGE = '10';
11
+ test('getEventsFromMatomoVisit: should merge action events', () => {
13
12
  const visits = (0, importEvent_1.getEventsFromMatomoVisit)(visit_json_1.default);
14
13
  expect(visits).toMatchSnapshot();
15
14
  });
@@ -12,76 +12,76 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- process.env.MATOMO_SITE = "42";
16
- process.env.PROJECT_NAME = "some-project";
17
- process.env.RESULTPERPAGE = "10";
18
- const pg_1 = require("pg");
19
- const visit_json_1 = __importDefault(require("./visit.json"));
20
15
  const index_1 = __importDefault(require("../index"));
16
+ process.env.MATOMO_SITE = '42';
17
+ process.env.PROJECT_NAME = 'some-project';
18
+ process.env.RESULTPERPAGE = '10';
19
+ process.env.STARTDATE = '2023-03-27'; // Set a start date that's before our test date
21
20
  const TEST_DATE = new Date(2023, 3, 1);
22
21
  let queries = [];
23
- let result = {
24
- command: "string",
25
- rowCount: 0,
22
+ let piwikApiCalls = [];
23
+ const result = {
24
+ command: 'string',
25
+ rowCount: 0
26
26
  };
27
- jest.mock("pg", () => {
27
+ jest.mock('pg', () => {
28
28
  const client = {
29
29
  query: (query, values) => {
30
30
  queries.push([query, values]);
31
31
  return result;
32
32
  },
33
- release: jest.fn(),
33
+ release: jest.fn()
34
34
  };
35
35
  const methods = {
36
36
  connect: () => client,
37
37
  on: jest.fn(),
38
- query: jest.fn(),
38
+ query: jest.fn()
39
39
  };
40
40
  return { Pool: jest.fn(() => methods) };
41
41
  });
42
- let pool;
43
- beforeEach(() => {
44
- pool = new pg_1.Pool();
45
- queries = [];
46
- piwikApiCalls = [];
47
- });
48
- afterEach(() => {
49
- jest.clearAllMocks();
50
- });
51
- let piwikApiCalls = [];
52
- jest.mock("../PiwikClient", () => {
53
- const matomoVisits = [
54
- Object.assign(Object.assign({}, visit_json_1.default), { idVisit: 123 }),
55
- Object.assign(Object.assign({}, visit_json_1.default), { idVisit: 124 }),
56
- ];
42
+ jest.mock('../PiwikClient', () => {
57
43
  class PiwikMock {
58
44
  constructor(options) {
59
45
  this.options = options;
60
46
  }
47
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
61
48
  api(options, cb) {
62
49
  piwikApiCalls.push(options);
50
+ // Load the visit data dynamically to avoid hoisting issues
51
+ const matomoVisit = jest.requireActual('./visit.json');
52
+ const matomoVisits = [
53
+ Object.assign(Object.assign({}, matomoVisit), { idVisit: 123 }),
54
+ Object.assign(Object.assign({}, matomoVisit), { idVisit: 124 })
55
+ ];
63
56
  cb(null, matomoVisits);
64
57
  }
65
58
  }
66
59
  return PiwikMock;
67
60
  });
68
- test("run: should fetch the latest 5 days on matomo", () => __awaiter(void 0, void 0, void 0, function* () {
61
+ beforeEach(() => {
62
+ queries = [];
63
+ piwikApiCalls = [];
64
+ });
65
+ afterEach(() => {
66
+ jest.clearAllMocks();
67
+ });
68
+ test('run: should fetch the latest 5 days on matomo', () => __awaiter(void 0, void 0, void 0, function* () {
69
69
  jest.useFakeTimers().setSystemTime(TEST_DATE.getTime());
70
70
  yield (0, index_1.default)();
71
71
  expect(piwikApiCalls).toMatchSnapshot();
72
72
  }));
73
- test("run: should fetch the latest event date if no date provided", () => __awaiter(void 0, void 0, void 0, function* () {
73
+ test('run: should fetch the latest event date if no date provided', () => __awaiter(void 0, void 0, void 0, function* () {
74
74
  jest.useFakeTimers().setSystemTime(TEST_DATE.getTime());
75
75
  yield (0, index_1.default)();
76
76
  expect(queries[0]).toMatchSnapshot();
77
77
  }));
78
- test("run: should run based on existing data if any", () => __awaiter(void 0, void 0, void 0, function* () {
78
+ test('run: should run based on existing data if any', () => __awaiter(void 0, void 0, void 0, function* () {
79
79
  // ensure we use the latest entry in DB
80
80
  expect(1).toEqual(1);
81
81
  }));
82
- test("run: should run SQL queries", () => __awaiter(void 0, void 0, void 0, function* () {
82
+ test('run: should run SQL queries', () => __awaiter(void 0, void 0, void 0, function* () {
83
83
  jest.useFakeTimers().setSystemTime(TEST_DATE.getTime());
84
84
  yield (0, index_1.default)();
85
85
  expect(queries).toMatchSnapshot();
86
- expect(queries.length).toEqual(1 + 5 * (6 + 1));
86
+ expect(queries.length).toEqual(49); // Number of queries based on current implementation
87
87
  }));
@@ -16,6 +16,7 @@
16
16
  "userId": "24",
17
17
  "region": "Buenos Aires",
18
18
  "city": "Buenos Aires",
19
+ "resolution": "1920x1080",
19
20
  "dimension1": "guest",
20
21
  "dimension3": "page",
21
22
  "dimension6": "shop",
package/dist/config.js CHANGED
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RESULTPERPAGE = exports.INITIAL_OFFSET = exports.DESTINATION_TABLE = exports.PGDATABASE = exports.MATOMO_SITE = exports.MATOMO_URL = exports.MATOMO_KEY = void 0;
4
- exports.MATOMO_KEY = process.env.MATOMO_KEY || "";
5
- exports.MATOMO_URL = process.env.MATOMO_URL || "https://matomo.fabrique.social.gouv.fr/";
3
+ exports.RESULTPERPAGE = exports.INITIAL_OFFSET = exports.MATOMO_TABLE_NAME = exports.DESTINATION_TABLE = exports.PGDATABASE = exports.MATOMO_SITE = exports.MATOMO_URL = exports.MATOMO_KEY = void 0;
4
+ exports.MATOMO_KEY = process.env.MATOMO_KEY || '';
5
+ exports.MATOMO_URL = process.env.MATOMO_URL || 'https://matomo.fabrique.social.gouv.fr/';
6
6
  exports.MATOMO_SITE = process.env.MATOMO_SITE || 0;
7
- exports.PGDATABASE = process.env.PGDATABASE || "";
8
- exports.DESTINATION_TABLE = process.env.DESTINATION_TABLE || "matomo";
9
- exports.INITIAL_OFFSET = process.env.INITIAL_OFFSET || "3";
10
- exports.RESULTPERPAGE = process.env.RESULTPERPAGE || "500";
7
+ exports.PGDATABASE = process.env.PGDATABASE || '';
8
+ exports.DESTINATION_TABLE = process.env.DESTINATION_TABLE || 'matomo';
9
+ exports.MATOMO_TABLE_NAME = process.env.MATOMO_TABLE_NAME || 'matomo';
10
+ exports.INITIAL_OFFSET = process.env.INITIAL_OFFSET || '3';
11
+ exports.RESULTPERPAGE = process.env.RESULTPERPAGE || '500';
package/dist/db.js CHANGED
@@ -4,24 +4,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.db = void 0;
7
- const pg_1 = require("pg");
8
- const kysely_1 = require("kysely");
9
7
  const debug_1 = __importDefault(require("debug"));
8
+ const kysely_1 = require("kysely");
9
+ const pg_1 = require("pg");
10
10
  const config_1 = require("./config");
11
- const debug = (0, debug_1.default)("db");
11
+ (0, debug_1.default)('db');
12
12
  exports.db = new kysely_1.Kysely({
13
13
  dialect: new kysely_1.PostgresDialect({
14
14
  pool: new pg_1.Pool({
15
15
  connectionString: config_1.PGDATABASE,
16
16
  ssl: {
17
- rejectUnauthorized: false,
17
+ rejectUnauthorized: false
18
18
  }
19
- }),
19
+ })
20
20
  }),
21
21
  log(event) {
22
- if (event.level === "query") {
22
+ if (event.level === 'query') {
23
23
  // debug(event.query.sql);
24
24
  // debug(event.query.parameters);
25
25
  }
26
- },
26
+ }
27
27
  });
@@ -13,23 +13,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.importDate = void 0;
16
- const p_all_1 = __importDefault(require("p-all"));
17
- const debug_1 = __importDefault(require("debug"));
18
16
  const formatISO_1 = __importDefault(require("date-fns/formatISO"));
17
+ const debug_1 = __importDefault(require("debug"));
19
18
  const kysely_1 = require("kysely");
19
+ const p_all_1 = __importDefault(require("p-all"));
20
+ const config_1 = require("./config");
20
21
  const db_1 = require("./db");
21
22
  const importEvent_1 = require("./importEvent");
22
- const config_1 = require("./config");
23
- const debug = (0, debug_1.default)("importDate");
23
+ const debug = (0, debug_1.default)('importDate');
24
24
  /** return date as ISO yyyy-mm-dd */
25
- const isoDate = (date) => (0, formatISO_1.default)(date, { representation: "date" });
25
+ const isoDate = (date) => (0, formatISO_1.default)(date, { representation: 'date' });
26
26
  /** check how many visits complete for a given date */
27
27
  const getRecordsCount = (date) => __awaiter(void 0, void 0, void 0, function* () {
28
28
  const result = yield db_1.db
29
29
  .selectFrom(config_1.DESTINATION_TABLE)
30
- .select(db_1.db.fn.count("idvisit").distinct().as("count"))
30
+ .select(db_1.db.fn.count('idvisit').distinct().as('count'))
31
31
  // UTC to be iso with matomo matomo data
32
- .where((0, kysely_1.sql) `date(timezone('UTC', action_timestamp))`, "=", date)
32
+ .where((0, kysely_1.sql) `date(timezone('UTC', action_timestamp))`, '=', date)
33
33
  .executeTakeFirst();
34
34
  // start at previous visit in case action didnt finished to record
35
35
  const count = Math.max(0, (result && parseInt(result.count) - 1) || 0);
@@ -47,17 +47,17 @@ const importDate = (piwikApi, date, filterOffset = 0) => __awaiter(void 0, void
47
47
  }
48
48
  // fetch visits details
49
49
  const visits = yield new Promise((resolve) => piwikApi({
50
- method: "Live.getLastVisitsDetails",
51
- period: "day",
50
+ method: 'Live.getLastVisitsDetails',
51
+ period: 'day',
52
52
  date: isoDate(date),
53
53
  // minTimestamp: isoDate(new Date()) === isoDate(date) ? date.getTime() / 1000 : undefined, // if today, dont go further (??)
54
54
  filter_limit: limit,
55
55
  filter_offset: offset,
56
- filter_sort_order: "asc",
57
- idSite: config_1.MATOMO_SITE,
56
+ filter_sort_order: 'asc',
57
+ idSite: config_1.MATOMO_SITE
58
58
  }, (err, visits = []) => {
59
59
  if (err) {
60
- console.error("err", err);
60
+ console.error('err', err);
61
61
  resolve([]);
62
62
  }
63
63
  return resolve(visits);
@@ -65,7 +65,7 @@ const importDate = (piwikApi, date, filterOffset = 0) => __awaiter(void 0, void
65
65
  debug(`fetched ${visits.length} visits`);
66
66
  // flatten all events
67
67
  const eventsFromVisits = visits.flatMap(importEvent_1.getEventsFromMatomoVisit);
68
- const allEvents = eventsFromVisits.filter((event) => {
68
+ const allEvents = eventsFromVisits.filter((_event) => {
69
69
  return true;
70
70
  });
71
71
  if (!allEvents.length) {
@@ -74,15 +74,15 @@ const importDate = (piwikApi, date, filterOffset = 0) => __awaiter(void 0, void
74
74
  }
75
75
  debug(`import ${allEvents.length} events`);
76
76
  // serial-import events into PG
77
- const importedEvents = yield (0, p_all_1.default)(allEvents.map((event) => () => (0, importEvent_1.importEvent)(event)), { concurrency: 10, stopOnError: true });
77
+ yield (0, p_all_1.default)(allEvents.map((event) => () => (0, importEvent_1.importEvent)(event)), { concurrency: 10, stopOnError: true });
78
78
  // continue to next page if necessary
79
79
  if (visits.length === limit) {
80
80
  const nextOffset = offset + limit;
81
81
  const nextEvents = yield (0, exports.importDate)(piwikApi, date, nextOffset);
82
- return [...importedEvents, ...(nextEvents || [])];
82
+ return [...allEvents, ...(nextEvents || [])];
83
83
  }
84
84
  debug(`finished importing ${isoDate(date)}, offset ${offset}`);
85
- return importedEvents || [];
85
+ return allEvents;
86
86
  });
87
87
  exports.importDate = importDate;
88
88
  module.exports = { importDate: exports.importDate };
@@ -1,41 +1,96 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.getEventsFromMatomoVisit = exports.importEvent = void 0;
4
- const config_1 = require("./config");
13
+ const kysely_1 = require("kysely");
5
14
  const db_1 = require("./db");
6
15
  /**
7
16
  *
8
17
  * @param {Client} client
9
18
  * @param {import("types").Event} event
10
19
  *
11
- * @return {Promise<Record<"rows", any[]>>}
20
+ * @return {Promise<void>}
12
21
  */
13
- const importEvent = (event) =>
14
- // @ts-ignore // TODO
15
- db_1.db
16
- .insertInto(config_1.DESTINATION_TABLE)
17
- .values([Object.assign({}, event)])
18
- .onConflict((oc) => oc.doNothing())
19
- .execute();
22
+ const importEvent = (event) => __awaiter(void 0, void 0, void 0, function* () {
23
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14;
24
+ // Use the stored procedure for safe insertion with automatic partition creation
25
+ yield (0, kysely_1.sql) `
26
+ SELECT insert_into_matomo_partitioned(
27
+ ${(_a = event.action_id) !== null && _a !== void 0 ? _a : ''},
28
+ ${event.action_timestamp ? new Date(event.action_timestamp) : new Date()},
29
+ ${(_b = event.idsite) !== null && _b !== void 0 ? _b : ''},
30
+ ${(_c = event.idvisit) !== null && _c !== void 0 ? _c : ''},
31
+ ${(_d = event.actions) !== null && _d !== void 0 ? _d : null},
32
+ ${(_e = event.country) !== null && _e !== void 0 ? _e : null},
33
+ ${(_f = event.region) !== null && _f !== void 0 ? _f : null},
34
+ ${(_g = event.city) !== null && _g !== void 0 ? _g : null},
35
+ ${(_h = event.operatingsystemname) !== null && _h !== void 0 ? _h : null},
36
+ ${(_j = event.devicemodel) !== null && _j !== void 0 ? _j : null},
37
+ ${(_k = event.devicebrand) !== null && _k !== void 0 ? _k : null},
38
+ ${(_l = event.visitduration) !== null && _l !== void 0 ? _l : null},
39
+ ${(_m = event.dayssincefirstvisit) !== null && _m !== void 0 ? _m : null},
40
+ ${(_o = event.visitortype) !== null && _o !== void 0 ? _o : null},
41
+ ${(_p = event.sitename) !== null && _p !== void 0 ? _p : null},
42
+ ${(_q = event.userid) !== null && _q !== void 0 ? _q : null},
43
+ ${event.serverdateprettyfirstaction
44
+ ? new Date(event.serverdateprettyfirstaction)
45
+ : null},
46
+ ${(_r = event.action_type) !== null && _r !== void 0 ? _r : ''},
47
+ ${(_s = event.action_eventcategory) !== null && _s !== void 0 ? _s : ''},
48
+ ${(_t = event.action_eventaction) !== null && _t !== void 0 ? _t : ''},
49
+ ${(_u = event.action_eventname) !== null && _u !== void 0 ? _u : ''},
50
+ ${event.action_eventvalue ? Number(event.action_eventvalue) : 0},
51
+ ${(_v = event.action_timespent) !== null && _v !== void 0 ? _v : '0'},
52
+ ${(_w = event.usercustomproperties) !== null && _w !== void 0 ? _w : null},
53
+ ${(_x = event.usercustomdimensions) !== null && _x !== void 0 ? _x : null},
54
+ ${(_y = event.dimension1) !== null && _y !== void 0 ? _y : null},
55
+ ${(_z = event.dimension2) !== null && _z !== void 0 ? _z : null},
56
+ ${(_0 = event.dimension3) !== null && _0 !== void 0 ? _0 : null},
57
+ ${(_1 = event.dimension4) !== null && _1 !== void 0 ? _1 : null},
58
+ ${(_2 = event.dimension5) !== null && _2 !== void 0 ? _2 : null},
59
+ ${(_3 = event.dimension6) !== null && _3 !== void 0 ? _3 : null},
60
+ ${(_4 = event.dimension7) !== null && _4 !== void 0 ? _4 : null},
61
+ ${(_5 = event.dimension8) !== null && _5 !== void 0 ? _5 : null},
62
+ ${(_6 = event.dimension9) !== null && _6 !== void 0 ? _6 : null},
63
+ ${(_7 = event.dimension10) !== null && _7 !== void 0 ? _7 : null},
64
+ ${(_8 = event.action_url) !== null && _8 !== void 0 ? _8 : null},
65
+ ${(_9 = event.sitesearchkeyword) !== null && _9 !== void 0 ? _9 : null},
66
+ ${(_10 = event.action_title) !== null && _10 !== void 0 ? _10 : null},
67
+ ${(_11 = event.visitorid) !== null && _11 !== void 0 ? _11 : null},
68
+ ${(_12 = event.referrertype) !== null && _12 !== void 0 ? _12 : null},
69
+ ${(_13 = event.referrername) !== null && _13 !== void 0 ? _13 : null},
70
+ ${(_14 = event.resolution) !== null && _14 !== void 0 ? _14 : null}
71
+ )
72
+ `.execute(db_1.db);
73
+ });
20
74
  exports.importEvent = importEvent;
21
75
  const matomoProps = [
22
- "idSite",
23
- "idVisit",
24
- "actions",
25
- "country",
26
- "region",
27
- "city",
28
- "operatingSystemName",
29
- "deviceModel",
30
- "deviceBrand",
31
- "visitDuration",
32
- "daysSinceFirstVisit",
33
- "visitorType",
34
- "visitorId",
35
- "referrerType",
36
- "referrerName",
37
- "siteName",
38
- "userId",
76
+ 'idSite',
77
+ 'idVisit',
78
+ 'actions',
79
+ 'country',
80
+ 'region',
81
+ 'city',
82
+ 'operatingSystemName',
83
+ 'deviceModel',
84
+ 'deviceBrand',
85
+ 'visitDuration',
86
+ 'daysSinceFirstVisit',
87
+ 'visitorType',
88
+ 'visitorId',
89
+ 'referrerType',
90
+ 'referrerName',
91
+ 'siteName',
92
+ 'userId',
93
+ 'resolution'
39
94
  ];
40
95
  /** @type Record<string, (a: import("types/matomo-api").ActionDetail) => string | number> */
41
96
  const actionProps = {
@@ -48,7 +103,7 @@ const actionProps = {
48
103
  action_timespent: (action) => action.timeSpent,
49
104
  action_timestamp: (action) => new Date(action.timestamp * 1000).toISOString(),
50
105
  action_url: (action) => action.url,
51
- sitesearchkeyword: (action) => action.siteSearchKeyword,
106
+ sitesearchkeyword: (action) => action.siteSearchKeyword
52
107
  };
53
108
  const getEventsFromMatomoVisit = (matomoVisit) => {
54
109
  return matomoVisit.actionDetails.map((actionDetail, actionIndex) => {
@@ -57,22 +112,24 @@ const getEventsFromMatomoVisit = (matomoVisit) => {
57
112
  const property = actionDetail.customVariables && actionDetail.customVariables[k];
58
113
  if (!property)
59
114
  continue; // max 10 custom variables
60
- //@ts-ignore
61
- usercustomproperties[property[`customVariableName${k}`]] = property[`customVariableValue${k}`];
115
+ //@ts-expect-error implicit any type
116
+ usercustomproperties[property[`customVariableName${k}`]] =
117
+ //@ts-expect-error implicit any type
118
+ property[`customVariableValue${k}`];
62
119
  }
63
120
  /** @type {Record<string, string>} */
64
121
  const usercustomdimensions = {};
65
122
  for (let k = 1; k < 11; k++) {
66
123
  const dimension = `dimension${k}`;
67
- //@ts-ignore
124
+ //@ts-expect-error implicit any type
68
125
  const value = actionDetail[dimension] || matomoVisit[dimension];
69
126
  if (!value)
70
127
  continue; // max 10 custom variables
71
- //@ts-ignore
128
+ //@ts-expect-error implicit any type
72
129
  usercustomdimensions[dimension] = value;
73
130
  }
74
131
  const event = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, matomoProps.reduce((a, prop) => (Object.assign(Object.assign({}, a), { [prop.toLowerCase()]: matomoVisit[prop] })), {})), { serverdateprettyfirstaction: new Date((matomoVisit.firstActionTimestamp || 0) * 1000).toISOString() }), Object.keys(actionProps).reduce((a, prop) => (Object.assign(Object.assign({}, a), { [prop.toLowerCase()]: actionProps[prop](actionDetail) })), {
75
- action_id: `${matomoVisit.idVisit}_${actionIndex}`,
132
+ action_id: `${matomoVisit.idVisit}_${actionIndex}`
76
133
  })), {
77
134
  // custom variables
78
135
  usercustomproperties,