@socialgouv/matomo-postgres 2.2.0 → 2.2.2

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,4 +1,3 @@
1
- "use strict";
2
1
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
2
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
3
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,11 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
8
  });
10
9
  };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.down = exports.up = void 0;
13
- const kysely_1 = require("kysely");
10
+ import { sql } from 'kysely';
14
11
  const MATOMO_TABLE_NAME = process.env.MATOMO_TABLE_NAME || 'matomo';
15
- function up(db) {
12
+ export function up(db) {
16
13
  return __awaiter(this, void 0, void 0, function* () {
17
14
  yield db.schema
18
15
  .createTable(MATOMO_TABLE_NAME)
@@ -39,7 +36,7 @@ function up(db) {
39
36
  .addColumn('action_eventname', 'text')
40
37
  .addColumn('action_eventvalue', 'numeric')
41
38
  .addColumn('action_timespent', 'text')
42
- .addColumn('action_timestamp', 'timestamptz', (col) => col.defaultTo((0, kysely_1.sql) `now()`))
39
+ .addColumn('action_timestamp', 'timestamptz', (col) => col.defaultTo(sql `now()`))
43
40
  .addColumn('usercustomproperties', 'json')
44
41
  .addColumn('usercustomdimensions', 'json')
45
42
  .addColumn('dimension1', 'text')
@@ -61,10 +58,8 @@ function up(db) {
61
58
  .execute();
62
59
  });
63
60
  }
64
- exports.up = up;
65
- function down(db) {
61
+ export function down(db) {
66
62
  return __awaiter(this, void 0, void 0, function* () {
67
63
  yield db.schema.dropTable(MATOMO_TABLE_NAME).execute();
68
64
  });
69
65
  }
70
- exports.down = down;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
2
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
3
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,9 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
8
  });
10
9
  };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.down = exports.up = void 0;
13
- const kysely_1 = require("kysely");
10
+ import { sql } from 'kysely';
14
11
  const MATOMO_TABLE_NAME = process.env.MATOMO_TABLE_NAME || 'matomo';
15
12
  const indexes = [
16
13
  {
@@ -74,7 +71,7 @@ const indexes = [
74
71
  columns: ['visitorid']
75
72
  }
76
73
  ];
77
- function up(db) {
74
+ export function up(db) {
78
75
  return __awaiter(this, void 0, void 0, function* () {
79
76
  indexes.forEach((index) => __awaiter(this, void 0, void 0, function* () {
80
77
  yield db.schema
@@ -89,12 +86,11 @@ function up(db) {
89
86
  .createIndex('actions_day')
90
87
  .ifNotExists()
91
88
  .on(MATOMO_TABLE_NAME)
92
- .expression((0, kysely_1.sql) `date(timezone('UTC', action_timestamp))`)
89
+ .expression(sql `date(timezone('UTC', action_timestamp))`)
93
90
  .execute();
94
91
  });
95
92
  }
96
- exports.up = up;
97
- function down(db) {
93
+ export function down(db) {
98
94
  return __awaiter(this, void 0, void 0, function* () {
99
95
  indexes.forEach((index) => __awaiter(this, void 0, void 0, function* () {
100
96
  yield db.schema.dropIndex(index.name).execute();
@@ -102,4 +98,3 @@ function down(db) {
102
98
  db.schema.dropIndex('actions_day').execute();
103
99
  });
104
100
  }
105
- exports.down = down;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
2
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
3
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,19 +7,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
8
  });
10
9
  };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.down = exports.up = void 0;
10
+ import { sql } from 'kysely';
13
11
  const MATOMO_TABLE_NAME = process.env.MATOMO_TABLE_NAME || 'matomo';
14
- function up(db) {
12
+ export function up(db) {
15
13
  return __awaiter(this, void 0, void 0, function* () {
16
- yield db.schema
17
- .alterTable(MATOMO_TABLE_NAME)
18
- .addColumn('resolution', 'text')
19
- .execute();
14
+ // Check if the column already exists before trying to add it
15
+ const columnExists = yield sql `
16
+ SELECT EXISTS (
17
+ SELECT 1
18
+ FROM information_schema.columns
19
+ WHERE table_name = ${MATOMO_TABLE_NAME}
20
+ AND column_name = 'resolution'
21
+ ) as exists
22
+ `.execute(db);
23
+ if (!columnExists.rows[0].exists) {
24
+ yield db.schema
25
+ .alterTable(MATOMO_TABLE_NAME)
26
+ .addColumn('resolution', 'text')
27
+ .execute();
28
+ }
20
29
  });
21
30
  }
22
- exports.up = up;
23
- function down(db) {
31
+ export function down(db) {
24
32
  return __awaiter(this, void 0, void 0, function* () {
25
33
  yield db.schema
26
34
  .alterTable(MATOMO_TABLE_NAME)
@@ -28,4 +36,3 @@ function down(db) {
28
36
  .execute();
29
37
  });
30
38
  }
31
- exports.down = down;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
2
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
3
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,15 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
8
  });
10
9
  };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.down = exports.up = void 0;
13
- const kysely_1 = require("kysely");
14
- const PARTITIONED_MATOMO_TABLE_NAME = process.env.PARTITIONED_MATOMO_TABLE_NAME || 'matomo_partitioned';
15
- function up(db) {
10
+ import { sql } from 'kysely';
11
+ import { PARTITIONED_MATOMO_TABLE_NAME } from '../config';
12
+ export function up(db) {
16
13
  return __awaiter(this, void 0, void 0, function* () {
17
14
  // First, create the partitioned table structure as a partitioned table
18
- yield (0, kysely_1.sql) `
19
- CREATE TABLE ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}`)} (
15
+ yield sql `
16
+ CREATE TABLE ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}`)} (
20
17
  action_id text NOT NULL,
21
18
  idsite text,
22
19
  idvisit text,
@@ -62,13 +59,13 @@ function up(db) {
62
59
  ) PARTITION BY RANGE (action_timestamp);
63
60
  `.execute(db);
64
61
  // Add unique constraint that includes partition key
65
- yield (0, kysely_1.sql) `
66
- ALTER TABLE ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}`)}
67
- ADD CONSTRAINT ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_action_id_timestamp_unique`)}
62
+ yield sql `
63
+ ALTER TABLE ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}`)}
64
+ ADD CONSTRAINT ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_action_id_timestamp_unique`)}
68
65
  UNIQUE (action_id, action_timestamp)
69
66
  `.execute(db);
70
67
  // Create function for automatic weekly partition creation
71
- yield (0, kysely_1.sql) `
68
+ yield sql `
72
69
  CREATE OR REPLACE FUNCTION create_weekly_partition_if_not_exists(table_name text, partition_date timestamptz)
73
70
  RETURNS void AS $$
74
71
  DECLARE
@@ -102,23 +99,23 @@ function up(db) {
102
99
  $$ LANGUAGE plpgsql;
103
100
  `.execute(db);
104
101
  // Create trigger function that automatically creates partitions on insert
105
- yield (0, kysely_1.sql) `
106
- CREATE OR REPLACE FUNCTION ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_partition_trigger`)}()
102
+ yield sql `
103
+ CREATE OR REPLACE FUNCTION ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_partition_trigger`)}()
107
104
  RETURNS trigger AS $$
108
105
  BEGIN
109
- PERFORM create_weekly_partition_if_not_exists('${kysely_1.sql.raw(PARTITIONED_MATOMO_TABLE_NAME)}', NEW.action_timestamp);
106
+ PERFORM create_weekly_partition_if_not_exists('${sql.raw(PARTITIONED_MATOMO_TABLE_NAME)}', NEW.action_timestamp);
110
107
  RETURN NEW;
111
108
  END;
112
109
  $$ LANGUAGE plpgsql;
113
110
  `.execute(db);
114
111
  // Create trigger that fires before insert
115
- yield (0, kysely_1.sql) `
116
- CREATE TRIGGER ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_auto_partition`)}
117
- BEFORE INSERT ON ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}`)}
118
- FOR EACH ROW EXECUTE FUNCTION ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_partition_trigger`)}();
112
+ yield sql `
113
+ CREATE TRIGGER ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_auto_partition`)}
114
+ BEFORE INSERT ON ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}`)}
115
+ FOR EACH ROW EXECUTE FUNCTION ${sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_partition_trigger`)}();
119
116
  `.execute(db);
120
117
  // Create stored procedure for safe insertion with automatic partition creation
121
- yield (0, kysely_1.sql) `
118
+ yield sql `
122
119
  CREATE OR REPLACE FUNCTION insert_into_matomo_partitioned(
123
120
  p_action_id text,
124
121
  p_action_timestamp timestamptz,
@@ -165,14 +162,14 @@ function up(db) {
165
162
  )
166
163
  RETURNS void
167
164
  LANGUAGE plpgsql
168
- SECURITY DEFINER
165
+ SECURITY INVOKER
169
166
  AS $$
170
167
  BEGIN
171
168
  -- Ensure partition exists for the given timestamp
172
- PERFORM create_weekly_partition_if_not_exists('${kysely_1.sql.raw(PARTITIONED_MATOMO_TABLE_NAME)}', p_action_timestamp);
169
+ PERFORM create_weekly_partition_if_not_exists('${sql.raw(PARTITIONED_MATOMO_TABLE_NAME)}', p_action_timestamp);
173
170
 
174
171
  -- Insert the data with conflict handling
175
- INSERT INTO ${kysely_1.sql.id(PARTITIONED_MATOMO_TABLE_NAME)} (
172
+ INSERT INTO ${sql.id(PARTITIONED_MATOMO_TABLE_NAME)} (
176
173
  action_id,
177
174
  action_timestamp,
178
175
  idsite,
@@ -343,20 +340,20 @@ function up(db) {
343
340
  yield db.schema
344
341
  .createIndex(`actions_day_${PARTITIONED_MATOMO_TABLE_NAME}`)
345
342
  .on(PARTITIONED_MATOMO_TABLE_NAME)
346
- .expression((0, kysely_1.sql) `date(timezone('UTC', action_timestamp))`)
343
+ .expression(sql `date(timezone('UTC', action_timestamp))`)
347
344
  .execute();
348
345
  });
349
346
  }
350
- exports.up = up;
351
- function down(db) {
347
+ export function down(db) {
352
348
  return __awaiter(this, void 0, void 0, function* () {
353
349
  // Drop trigger and function
354
- yield (0, kysely_1.sql) `DROP TRIGGER IF EXISTS ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_auto_partition`)} ON ${kysely_1.sql.id(PARTITIONED_MATOMO_TABLE_NAME)}`.execute(db);
355
- yield (0, kysely_1.sql) `DROP FUNCTION IF EXISTS ${kysely_1.sql.id(`${PARTITIONED_MATOMO_TABLE_NAME}_partition_trigger`)}()`.execute(db);
356
- yield (0, kysely_1.sql) `DROP FUNCTION IF EXISTS create_weekly_partition_if_not_exists(text, timestamptz)`.execute(db);
357
- yield (0, kysely_1.sql) `DROP FUNCTION IF EXISTS insert_into_matomo_partitioned`.execute(db);
350
+ const trigger_name = `${PARTITIONED_MATOMO_TABLE_NAME}_auto_partition`;
351
+ yield sql `DROP TRIGGER IF EXISTS ${sql.id(trigger_name)} ON ${sql.id(PARTITIONED_MATOMO_TABLE_NAME)}`.execute(db);
352
+ const function_name = `${PARTITIONED_MATOMO_TABLE_NAME}_partition_trigger`;
353
+ yield sql `DROP FUNCTION IF EXISTS ${sql.id(function_name)}()`.execute(db);
354
+ yield sql `DROP FUNCTION IF EXISTS create_weekly_partition_if_not_exists(text, timestamptz)`.execute(db);
355
+ yield sql `DROP FUNCTION IF EXISTS insert_into_matomo_partitioned`.execute(db);
358
356
  // Drop the partitioned table (this will also drop all partitions)
359
357
  yield db.schema.dropTable(PARTITIONED_MATOMO_TABLE_NAME).ifExists().execute();
360
358
  });
361
359
  }
362
- exports.down = down;
@@ -0,0 +1,29 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { sql } from 'kysely';
11
+ const PARTITIONED_MATOMO_TABLE_NAME = process.env.PARTITIONED_MATOMO_TABLE_NAME || 'matomo_partitioned';
12
+ export function up(db) {
13
+ return __awaiter(this, void 0, void 0, function* () {
14
+ // Create conditional index for convention collective analysis
15
+ yield sql `
16
+ CREATE INDEX IF NOT EXISTS idx_convention_analysis_matomo_partitioned
17
+ ON ${sql.id(PARTITIONED_MATOMO_TABLE_NAME)} (action_type, action_url, action_timestamp)
18
+ WHERE action_url LIKE 'https://code.travail.gouv.fr/convention-collective/%'
19
+ `.execute(db);
20
+ });
21
+ }
22
+ export function down(db) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ // Drop the conditional index
25
+ yield sql `
26
+ DROP INDEX IF EXISTS idx_convention_analysis_matomo_partitioned
27
+ `.execute(db);
28
+ });
29
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@socialgouv/matomo-postgres",
3
3
  "description": "Extract visitor events from Matomo API and push to Postgres",
4
- "version": "2.2.0",
4
+ "version": "2.2.2",
5
5
  "types": "types/index.d.ts",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/index.js",
@@ -9,6 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
+ "type": "module",
12
13
  "bin": {
13
14
  "matomo-postgres": "./bin/index.js"
14
15
  },
@@ -41,7 +42,7 @@
41
42
  "@eslint/js": "^9.31.0",
42
43
  "@types/debug": "^4.1.7",
43
44
  "@types/jest": "^29.4.0",
44
- "@types/node": "^18.14.4",
45
+ "@types/node": "^22.0.0",
45
46
  "@types/pg": "^8.6.6",
46
47
  "@typescript-eslint/eslint-plugin": "^8.37.0",
47
48
  "@typescript-eslint/parser": "^8.37.0",
@@ -50,11 +51,10 @@
50
51
  "eslint-plugin-prettier": "^5.5.1",
51
52
  "eslint-plugin-simple-import-sort": "^12.1.1",
52
53
  "globals": "^16.3.0",
53
- "jest": "^29.4.3",
54
- "knip": "^5.61.3",
54
+ "jest": "^29.7.0",
55
55
  "prettier": "^3.6.2",
56
- "ts-jest": "^29.0.5",
56
+ "ts-jest": "^29.4.1",
57
57
  "ts-node": "^10.9.1",
58
- "typescript": "^4.9.5"
58
+ "typescript": "^5.0.0"
59
59
  }
60
60
  }