@flisk/analyze-tracking 0.1.3 → 0.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/README.md +8 -7
- package/bin/cli.js +2 -21
- package/package.json +1 -1
- package/schema.json +80 -50
- package/src/analyze/index.js +7 -12
- package/src/index.js +5 -3
- package/src/repoDetails.js +61 -0
- package/src/yamlGenerator.js +12 -5
package/README.md
CHANGED
|
@@ -11,7 +11,6 @@ npx @flisk/analyze-tracking /path/to/project [options]
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
Optional arguments:
|
|
14
|
-
- `--repository <repository_url>`: URL of the repository where the code is hosted (defaults to git remote origin in project directory)
|
|
15
14
|
- `--output <output_file>`: Name of the output file (default: `tracking-schema.yaml`)
|
|
16
15
|
|
|
17
16
|
|
|
@@ -19,16 +18,18 @@ Optional arguments:
|
|
|
19
18
|
A YAML file with the following structure is generated:
|
|
20
19
|
|
|
21
20
|
```yaml
|
|
22
|
-
version: 1
|
|
21
|
+
version: 1
|
|
22
|
+
source:
|
|
23
|
+
repository: <repository_url>
|
|
24
|
+
commit: <commit_sha>
|
|
25
|
+
timestamp: <commit_timestamp>
|
|
23
26
|
events:
|
|
24
27
|
<event_name>:
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
path: <path_to_file>
|
|
28
|
+
implementations:
|
|
29
|
+
- path: <path_to_file>
|
|
28
30
|
line: <line_number>
|
|
29
31
|
function: <function_name>
|
|
30
|
-
|
|
31
|
-
- <destination_name>
|
|
32
|
+
destination: <platform_name>
|
|
32
33
|
properties:
|
|
33
34
|
<property_name>:
|
|
34
35
|
type: <property_type>
|
package/bin/cli.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const { execSync } = require('child_process');
|
|
5
4
|
const commandLineArgs = require('command-line-args')
|
|
6
5
|
const { run } = require('../src/index');
|
|
7
6
|
|
|
@@ -12,11 +11,6 @@ const optionDefinitions = [
|
|
|
12
11
|
type: String,
|
|
13
12
|
defaultOption: true,
|
|
14
13
|
},
|
|
15
|
-
{
|
|
16
|
-
name: 'repository',
|
|
17
|
-
alias: 'r',
|
|
18
|
-
type: String,
|
|
19
|
-
},
|
|
20
14
|
{
|
|
21
15
|
name: 'output',
|
|
22
16
|
alias: 'o',
|
|
@@ -25,24 +19,11 @@ const optionDefinitions = [
|
|
|
25
19
|
},
|
|
26
20
|
]
|
|
27
21
|
const options = commandLineArgs(optionDefinitions);
|
|
28
|
-
const { targetDir, output
|
|
22
|
+
const { targetDir, output } = options;
|
|
29
23
|
|
|
30
24
|
if (!targetDir) {
|
|
31
25
|
console.error('Please provide the path to the repository.');
|
|
32
26
|
process.exit(1);
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
function getRepositoryUrl() {
|
|
37
|
-
try {
|
|
38
|
-
const repoUrl = execSync('git config --get remote.origin.url', { cwd: targetDir, encoding: 'utf8' });
|
|
39
|
-
return repoUrl.trim();
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.warn('Could not retrieve repository URL. Using default value "unknown".');
|
|
42
|
-
return 'unknown';
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const repositoryUrl = repository || getRepositoryUrl();
|
|
47
|
-
|
|
48
|
-
run(path.resolve(targetDir), repositoryUrl, output);
|
|
29
|
+
run(path.resolve(targetDir), output);
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -1,30 +1,47 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
3
|
"title": "@flisk/analyze-tracking output schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
6
6
|
"version": {
|
|
7
7
|
"type": "number",
|
|
8
8
|
"enum": [
|
|
9
|
-
1
|
|
9
|
+
1
|
|
10
10
|
],
|
|
11
11
|
"description": "Version of the schema"
|
|
12
12
|
},
|
|
13
|
+
"source": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "URL of git repository that was used to generate the schema"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Git commit hash when this schema was generated"
|
|
23
|
+
},
|
|
24
|
+
"timestamp": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Git commit timestamp when this schema was generated"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"required": [
|
|
30
|
+
"timestamp"
|
|
31
|
+
],
|
|
32
|
+
"additionalProperties": false
|
|
33
|
+
},
|
|
13
34
|
"events": {
|
|
14
35
|
"type": "object",
|
|
15
36
|
"patternProperties": {
|
|
16
37
|
"^[a-zA-Z0-9_-]+$": {
|
|
17
38
|
"type": "object",
|
|
18
39
|
"properties": {
|
|
19
|
-
"
|
|
40
|
+
"implementations": {
|
|
20
41
|
"type": "array",
|
|
21
42
|
"items": {
|
|
22
43
|
"type": "object",
|
|
23
44
|
"properties": {
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "string",
|
|
26
|
-
"description": "Repository URL or name"
|
|
27
|
-
},
|
|
28
45
|
"path": {
|
|
29
46
|
"type": "string",
|
|
30
47
|
"description": "Relative path to the file where the event is tracked"
|
|
@@ -36,71 +53,84 @@
|
|
|
36
53
|
"function": {
|
|
37
54
|
"type": "string",
|
|
38
55
|
"description": "Name of the function where the event is tracked"
|
|
56
|
+
},
|
|
57
|
+
"destination": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"enum": [
|
|
60
|
+
"googleanalytics",
|
|
61
|
+
"segment",
|
|
62
|
+
"mixpanel",
|
|
63
|
+
"amplitude",
|
|
64
|
+
"rudderstack",
|
|
65
|
+
"mparticle",
|
|
66
|
+
"posthog",
|
|
67
|
+
"snowplow",
|
|
68
|
+
"unknown"
|
|
69
|
+
],
|
|
70
|
+
"description": "Name of the platform where the event is sent"
|
|
39
71
|
}
|
|
40
72
|
},
|
|
41
73
|
"required": [
|
|
42
|
-
"repository",
|
|
43
74
|
"path",
|
|
44
75
|
"line",
|
|
45
|
-
"function"
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
"destinations": {
|
|
50
|
-
"type": "array",
|
|
51
|
-
"items": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"enum": [
|
|
54
|
-
"googleanalytics",
|
|
55
|
-
"segment",
|
|
56
|
-
"mixpanel",
|
|
57
|
-
"amplitude",
|
|
58
|
-
"rudderstack",
|
|
59
|
-
"mparticle",
|
|
60
|
-
"snowplow",
|
|
61
|
-
"unknown"
|
|
76
|
+
"function",
|
|
77
|
+
"destination"
|
|
62
78
|
],
|
|
63
|
-
"
|
|
79
|
+
"additionalProperties": false
|
|
64
80
|
}
|
|
65
81
|
},
|
|
66
82
|
"properties": {
|
|
67
83
|
"type": "object",
|
|
68
84
|
"patternProperties": {
|
|
69
85
|
"^[a-zA-Z0-9_-]+$": {
|
|
70
|
-
"
|
|
71
|
-
"properties": {
|
|
72
|
-
"type": {
|
|
73
|
-
"type": "string",
|
|
74
|
-
"description": "Data type of the property (e.g., string, number)"
|
|
75
|
-
},
|
|
76
|
-
"required": {
|
|
77
|
-
"type": "boolean",
|
|
78
|
-
"description": "Whether this property is required"
|
|
79
|
-
},
|
|
80
|
-
"description": {
|
|
81
|
-
"type": "string",
|
|
82
|
-
"description": "Description of the property"
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
"required": [
|
|
86
|
-
"type"
|
|
87
|
-
]
|
|
86
|
+
"$ref": "#/definitions/property"
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
},
|
|
92
91
|
"required": [
|
|
93
|
-
"
|
|
94
|
-
"destinations",
|
|
92
|
+
"implementations",
|
|
95
93
|
"properties"
|
|
96
|
-
]
|
|
94
|
+
],
|
|
95
|
+
"additionalProperties": false
|
|
97
96
|
}
|
|
98
|
-
}
|
|
99
|
-
"additionalProperties": false
|
|
97
|
+
}
|
|
100
98
|
}
|
|
101
99
|
},
|
|
102
100
|
"required": [
|
|
103
101
|
"version",
|
|
102
|
+
"source",
|
|
104
103
|
"events"
|
|
105
|
-
]
|
|
104
|
+
],
|
|
105
|
+
"definitions": {
|
|
106
|
+
"property": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"properties": {
|
|
109
|
+
"type": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"description": "Data type of the property (e.g., string, number, any)"
|
|
112
|
+
},
|
|
113
|
+
"required": {
|
|
114
|
+
"type": "boolean",
|
|
115
|
+
"description": "Whether this property is required"
|
|
116
|
+
},
|
|
117
|
+
"description": {
|
|
118
|
+
"type": "string",
|
|
119
|
+
"description": "Description of the property"
|
|
120
|
+
},
|
|
121
|
+
"properties": {
|
|
122
|
+
"type": "object",
|
|
123
|
+
"patternProperties": {
|
|
124
|
+
"^[a-zA-Z0-9_-]+$": {
|
|
125
|
+
"$ref": "#/definitions/property"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"required": [
|
|
131
|
+
"type"
|
|
132
|
+
],
|
|
133
|
+
"additionalProperties": false
|
|
134
|
+
}
|
|
135
|
+
}
|
|
106
136
|
}
|
package/src/analyze/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const { getAllFiles } = require('../fileProcessor');
|
|
|
4
4
|
const ts = require('typescript');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
|
-
function analyzeDirectory(dirPath
|
|
7
|
+
function analyzeDirectory(dirPath) {
|
|
8
8
|
const files = getAllFiles(dirPath);
|
|
9
9
|
const allEvents = {};
|
|
10
10
|
|
|
@@ -23,27 +23,22 @@ function analyzeDirectory(dirPath, repository) {
|
|
|
23
23
|
|
|
24
24
|
if (!allEvents[event.eventName]) {
|
|
25
25
|
allEvents[event.eventName] = {
|
|
26
|
-
|
|
27
|
-
repository: repository,
|
|
26
|
+
implementations: [{
|
|
28
27
|
path: relativeFilePath,
|
|
29
28
|
line: event.line,
|
|
30
|
-
function: event.functionName
|
|
29
|
+
function: event.functionName,
|
|
30
|
+
destination: event.source
|
|
31
31
|
}],
|
|
32
|
-
destinations: [event.source],
|
|
33
32
|
properties: event.properties,
|
|
34
33
|
};
|
|
35
34
|
} else {
|
|
36
|
-
allEvents[event.eventName].
|
|
37
|
-
repository: repository,
|
|
35
|
+
allEvents[event.eventName].implementations.push({
|
|
38
36
|
path: relativeFilePath,
|
|
39
37
|
line: event.line,
|
|
40
|
-
function: event.functionName
|
|
38
|
+
function: event.functionName,
|
|
39
|
+
destination: event.source
|
|
41
40
|
});
|
|
42
41
|
|
|
43
|
-
if (!allEvents[event.eventName].destinations.includes(event.source)) {
|
|
44
|
-
allEvents[event.eventName].destinations.push(event.source);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
42
|
allEvents[event.eventName].properties = {
|
|
48
43
|
...allEvents[event.eventName].properties,
|
|
49
44
|
...event.properties,
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const { analyzeDirectory } = require('./analyze');
|
|
2
|
+
const { getRepoDetails } = require('./repoDetails');
|
|
2
3
|
const { generateYamlSchema } = require('./yamlGenerator');
|
|
3
4
|
|
|
4
|
-
function run(targetDir,
|
|
5
|
-
const events = analyzeDirectory(targetDir
|
|
6
|
-
|
|
5
|
+
function run(targetDir, outputPath) {
|
|
6
|
+
const events = analyzeDirectory(targetDir);
|
|
7
|
+
const repoDetails = getRepoDetails(targetDir);
|
|
8
|
+
generateYamlSchema(events, repoDetails, outputPath);
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
module.exports = { run };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
|
|
3
|
+
function getRepositoryUrl(targetDir) {
|
|
4
|
+
try {
|
|
5
|
+
const repoUrl = execSync('git config --get remote.origin.url', { cwd: targetDir, encoding: 'utf8' });
|
|
6
|
+
return repoUrl.trim();
|
|
7
|
+
} catch (error) {
|
|
8
|
+
console.warn('Could not determine repository URL. Will exclude.');
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getCommitHash(targetDir) {
|
|
14
|
+
try {
|
|
15
|
+
const commitHash = execSync('git rev-parse HEAD', { cwd: targetDir, encoding: 'utf8' });
|
|
16
|
+
return commitHash.trim();
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.warn('Could not determine latest commit hash. Will exclude.');
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getCommitTimestamp(targetDir, commitHash) {
|
|
24
|
+
try {
|
|
25
|
+
const commitTimestamp = execSync(`git --no-pager show -s --format=%ct ${commitHash}`, { cwd: targetDir, encoding: 'utf8' });
|
|
26
|
+
const unixTimeSeconds = commitTimestamp.trim();
|
|
27
|
+
return new Date(unixTimeSeconds * 1000);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn('Could not retrieve commit timestamp. Using current timestamp as default.')
|
|
30
|
+
return new Date();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function pad(n) {
|
|
35
|
+
return n<10 ? '0'+n : n
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function toISODateString(date) {
|
|
39
|
+
return date.getUTCFullYear()+'-'
|
|
40
|
+
+ pad(date.getUTCMonth()+1)+'-'
|
|
41
|
+
+ pad(date.getUTCDate())+'T'
|
|
42
|
+
+ pad(date.getUTCHours())+':'
|
|
43
|
+
+ pad(date.getUTCMinutes())+':'
|
|
44
|
+
+ pad(date.getUTCSeconds())+'Z'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getRepoDetails(targetDir) {
|
|
48
|
+
const repoUrl = getRepositoryUrl(targetDir);
|
|
49
|
+
const commitHash = getCommitHash(targetDir);
|
|
50
|
+
const commitEpochTime = getCommitTimestamp(targetDir, commitHash);
|
|
51
|
+
const commitTimestamp = toISODateString(commitEpochTime);
|
|
52
|
+
|
|
53
|
+
const repoDetails = {};
|
|
54
|
+
if (!!repoUrl) repoDetails.repository = repoUrl;
|
|
55
|
+
if (!!commitHash) repoDetails.commit = commitHash;
|
|
56
|
+
repoDetails.timestamp = commitTimestamp
|
|
57
|
+
|
|
58
|
+
return repoDetails;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { getRepoDetails };
|
package/src/yamlGenerator.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const yaml = require('js-yaml');
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const VERSION = 1
|
|
5
|
+
const SCHEMA_URL = "https://raw.githubusercontent.com/fliskdata/analyze-tracking/main/schema.json";
|
|
6
|
+
|
|
7
|
+
function generateYamlSchema(events, repository, outputPath) {
|
|
5
8
|
const schema = {
|
|
6
|
-
version:
|
|
9
|
+
version: VERSION,
|
|
10
|
+
source: repository,
|
|
7
11
|
events,
|
|
8
12
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
const options = {
|
|
14
|
+
noRefs: true,
|
|
15
|
+
};
|
|
16
|
+
const yamlOutput = yaml.dump(schema, options);
|
|
17
|
+
const yamlFile = `# yaml-language-server: $schema=${SCHEMA_URL}\n${yamlOutput}`;
|
|
18
|
+
fs.writeFileSync(outputPath, yamlFile, 'utf8');
|
|
12
19
|
console.log(`Tracking schema YAML file generated: ${outputPath}`);
|
|
13
20
|
}
|
|
14
21
|
|