@socialgouv/matomo-postgres 2.2.4 → 2.3.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/README.md CHANGED
@@ -44,14 +44,15 @@ yarn add @socialgouv/matomo-postgres
44
44
 
45
45
  ### Optional Environment Variables
46
46
 
47
- | Variable | Default | Description |
48
- | ------------------------------- | -------------------- | ------------------------------------------------------- |
49
- | `DESTINATION_TABLE` | `matomo` | Selects which table to write to (normal or partitioned) |
50
- | `MATOMO_TABLE_NAME` | `matomo` | Name for the standard table |
51
- | `PARTITIONED_MATOMO_TABLE_NAME` | `matomo_partitioned` | Name for the partitioned table |
52
- | `STARTDATE` | Auto-detected | Override start date for initial import (YYYY-MM-DD) |
53
- | `RESULTPERPAGE` | `500` | API pagination size (max results per request) |
54
- | `INITIAL_OFFSET` | `3` | Days to look back on first run |
47
+ | Variable | Default | Description |
48
+ | ------------------------------- | -------------------- | ------------------------------------------------------------------- |
49
+ | `DESTINATION_TABLE` | `matomo` | Selects which table to write to (normal or partitioned) |
50
+ | `MATOMO_TABLE_NAME` | `matomo` | Name for the standard table |
51
+ | `PARTITIONED_MATOMO_TABLE_NAME` | `matomo_partitioned` | Name for the partitioned table |
52
+ | `STARTDATE` | Auto-detected | Override start date for initial import (YYYY-MM-DD) |
53
+ | `FORCE_STARTDATE` | `false` | When `true`, skip database lookup and use STARTDATE unconditionally |
54
+ | `RESULTPERPAGE` | `500` | API pagination size (max results per request) |
55
+ | `INITIAL_OFFSET` | `3` | Days to look back on first run |
55
56
 
56
57
  ## đŸ—‚ī¸ Table Architecture
57
58
 
@@ -90,6 +91,36 @@ Consider using partitioned tables when:
90
91
 
91
92
  Both tables share the same schema structure, ensuring compatibility regardless of your choice.
92
93
 
94
+ ### Forcing Start Date Override
95
+
96
+ When you need to temporarily override the automatic date detection (e.g., to re-import specific data or recover from errors):
97
+
98
+ ```bash
99
+ export FORCE_STARTDATE=true
100
+ export STARTDATE=2024-01-01
101
+ ```
102
+
103
+ This configuration will:
104
+ - Skip checking the database for the last event
105
+ - Use the specified `STARTDATE` unconditionally
106
+ - Useful for one-time re-imports or data recovery scenarios
107
+
108
+ **Important:** Remember to unset `FORCE_STARTDATE` after your one-time import to restore normal automatic detection behavior.
109
+
110
+ **Cronjob Example:**
111
+
112
+ ```bash
113
+ # Temporarily add to your cronjob environment variables:
114
+ FORCE_STARTDATE=true
115
+ STARTDATE=2024-10-15
116
+ MATOMO_URL=https://analytics.example.com/
117
+ MATOMO_SITE=1
118
+ MATOMO_KEY=your_api_token
119
+ PGDATABASE=postgresql://user:pass@host:5432/db
120
+
121
+ # After import completes, remove FORCE_STARTDATE to resume normal operation
122
+ ```
123
+
93
124
  ## đŸ—ī¸ Architecture
94
125
 
95
126
  The tool follows a systematic ETL process:
@@ -0,0 +1,38 @@
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 { readdir, readFile } from 'fs/promises';
11
+ import { join } from 'path';
12
+ describe('Migration Import Validation', () => {
13
+ it('should not have src/ imports in migration files', () => __awaiter(void 0, void 0, void 0, function* () {
14
+ const migrationsDir = join(__dirname, '../migrations');
15
+ const migrationFiles = yield readdir(migrationsDir);
16
+ const tsFiles = migrationFiles.filter((file) => file.endsWith('.ts'));
17
+ const problematicFiles = [];
18
+ for (const file of tsFiles) {
19
+ const filePath = join(migrationsDir, file);
20
+ const content = yield readFile(filePath, 'utf-8');
21
+ // Check for imports from 'src/' paths
22
+ const srcImportRegex = /(?:import\s+[^;]+from\s+['"]src\/|require\s*\(\s*['"]src\/)/g;
23
+ const matches = content.match(srcImportRegex);
24
+ if (matches) {
25
+ problematicFiles.push(`${file}: ${matches.join(', ')}`);
26
+ }
27
+ }
28
+ if (problematicFiles.length > 0) {
29
+ fail(`Migration files contain problematic src/ imports that will fail in production:\n${problematicFiles.join('\n')}\n\nMigration files should use direct constants or relative imports instead.`);
30
+ }
31
+ }));
32
+ it('should have at least one migration file', () => __awaiter(void 0, void 0, void 0, function* () {
33
+ const migrationsDir = join(__dirname, '../migrations');
34
+ const migrationFiles = yield readdir(migrationsDir);
35
+ const tsFiles = migrationFiles.filter((file) => file.endsWith('.ts'));
36
+ expect(tsFiles.length).toBeGreaterThan(0);
37
+ }));
38
+ });
package/dist/config.js CHANGED
@@ -4,6 +4,7 @@ export const MATOMO_SITE = process.env.MATOMO_SITE || 0;
4
4
  export const PGDATABASE = process.env.PGDATABASE || '';
5
5
  export const INITIAL_OFFSET = process.env.INITIAL_OFFSET || '3';
6
6
  export const RESULTPERPAGE = process.env.RESULTPERPAGE || '500';
7
+ export const FORCE_STARTDATE = process.env.FORCE_STARTDATE === 'true';
7
8
  // We will create both a normal and a partitioned table (MATOMO_TABLE_NAME and PARTITIONED_MATOMO_TABLE_NAME)
8
9
  // and use DESTINATION_TABLE to determine which one to write to.
9
10
  export const DESTINATION_TABLE = process.env.DESTINATION_TABLE || 'matomo';
package/dist/index.js CHANGED
@@ -27,15 +27,23 @@ function run(date) {
27
27
  console.log(`📅 Determining reference date for import...`);
28
28
  // priority:
29
29
  // - optional parameter date
30
+ // - STARTDATE (if FORCE_STARTDATE is true)
30
31
  // - last event in the table
31
- // - optional env.STARTDATE
32
+ // - STARTDATE (if FORCE_STARTDATE is false)
32
33
  // - today
33
34
  let referenceDate;
34
35
  if (!referenceDate && date) {
35
36
  referenceDate = new Date(date);
36
37
  console.log(`✅ Using provided date parameter: ${referenceDate.toISOString()}`);
37
38
  }
38
- if (!referenceDate) {
39
+ // Check FORCE_STARTDATE mode first
40
+ const forceStartDate = process.env.FORCE_STARTDATE === 'true';
41
+ if (!referenceDate && forceStartDate && process.env.STARTDATE) {
42
+ referenceDate = new Date(process.env.STARTDATE);
43
+ console.log(`✅ FORCE_STARTDATE enabled - Using STARTDATE environment variable: ${referenceDate.toISOString()}`);
44
+ }
45
+ // Only query database if not forcing STARTDATE
46
+ if (!referenceDate && !forceStartDate) {
39
47
  console.log(`🔍 Looking for last event in database...`);
40
48
  referenceDate = yield findLastEventInMatomo(db);
41
49
  if (referenceDate) {
@@ -45,6 +53,7 @@ function run(date) {
45
53
  console.log(`â„šī¸ No previous events found in database`);
46
54
  }
47
55
  }
56
+ // Fallback to STARTDATE if database had no results
48
57
  if (!referenceDate && process.env.STARTDATE) {
49
58
  referenceDate = new Date(process.env.STARTDATE);
50
59
  console.log(`✅ Using STARTDATE environment variable: ${referenceDate.toISOString()}`);
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { sql } from 'kysely';
11
- import { PARTITIONED_MATOMO_TABLE_NAME } from 'src/config';
11
+ import { PARTITIONED_MATOMO_TABLE_NAME } from '../config.js';
12
12
  export function up(db) {
13
13
  return __awaiter(this, void 0, void 0, function* () {
14
14
  // First, create the partitioned table structure as a partitioned table
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.4",
4
+ "version": "2.3.0",
5
5
  "types": "types/index.d.ts",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/index.js",