@cloudcare/guance-front-tools 1.0.13 → 1.0.16

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.
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs'
4
+ import path from 'path'
5
+ import { pathToFileURL } from 'url'
6
+ import Ajv from 'ajv'
7
+ import { convertDashboard } from './convert-grafana-dashboard-core.js'
8
+
9
+ if (isDirectExecution()) {
10
+ main()
11
+ }
12
+
13
+ function isDirectExecution() {
14
+ if (!process.argv[1]) return false
15
+ return import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href
16
+ }
17
+
18
+ export function main() {
19
+ const { inputPath, outputPath, validateOutput, schemaId, guancePromqlCompatible, keepGrafanaMeta } = parseArgs(process.argv.slice(2))
20
+ const grafanaDashboard = readJson(inputPath)
21
+ const guanceDashboard = convertDashboard(grafanaDashboard, { guancePromqlCompatible, keepGrafanaMeta })
22
+
23
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true })
24
+ fs.writeFileSync(outputPath, `${JSON.stringify(guanceDashboard, null, 2)}\n`, 'utf8')
25
+ console.log(`Converted ${inputPath} -> ${outputPath}`)
26
+
27
+ if (validateOutput) {
28
+ validateDashboardFile(outputPath, schemaId)
29
+ }
30
+ }
31
+
32
+ function parseArgs(args) {
33
+ let inputPath = ''
34
+ let outputPath = ''
35
+ let validateOutput = false
36
+ let schemaId = 'dashboard-schema.json'
37
+ let guancePromqlCompatible = false
38
+ let keepGrafanaMeta = false
39
+
40
+ for (let index = 0; index < args.length; index++) {
41
+ const value = args[index]
42
+ if ((value === '-i' || value === '--input') && args[index + 1]) {
43
+ inputPath = path.resolve(args[++index])
44
+ continue
45
+ }
46
+ if ((value === '-o' || value === '--output') && args[index + 1]) {
47
+ outputPath = path.resolve(args[++index])
48
+ continue
49
+ }
50
+ if (value === '--validate') {
51
+ validateOutput = true
52
+ continue
53
+ }
54
+ if (value === '--schema' && args[index + 1]) {
55
+ schemaId = args[++index]
56
+ continue
57
+ }
58
+ if (value === '--guance-promql-compatible') {
59
+ guancePromqlCompatible = true
60
+ continue
61
+ }
62
+ if (value === '--keep-grafana-meta') {
63
+ keepGrafanaMeta = true
64
+ continue
65
+ }
66
+ if (value === '-h' || value === '--help') {
67
+ printHelp()
68
+ process.exit(0)
69
+ }
70
+ }
71
+
72
+ if (!inputPath) {
73
+ printHelp()
74
+ process.exit(1)
75
+ }
76
+
77
+ if (!outputPath) {
78
+ const parsed = path.parse(inputPath)
79
+ outputPath = path.join(parsed.dir, `${parsed.name}.guance.json`)
80
+ }
81
+
82
+ return { inputPath, outputPath, validateOutput, schemaId, guancePromqlCompatible, keepGrafanaMeta }
83
+ }
84
+
85
+ function printHelp() {
86
+ console.error(
87
+ 'Usage: node convert-grafana-dashboard.mjs --input <grafana.json> [--output <guance.json>] [--validate] [--schema <schema-id>] [--guance-promql-compatible] [--keep-grafana-meta]'
88
+ )
89
+ }
90
+
91
+ export function validateDashboardFile(filePath, schemaId) {
92
+ const projectRoot = findProjectRoot()
93
+ const schemasDirectory = path.join(projectRoot, 'schemas')
94
+ const ajv = new Ajv({ allErrors: true })
95
+
96
+ forEachFile(schemasDirectory, (schemaPath) => {
97
+ if (!schemaPath.endsWith('.json')) return
98
+ ajv.addSchema(readJson(schemaPath))
99
+ })
100
+
101
+ const valid = ajv.validate(schemaId, readJson(filePath))
102
+ if (valid) {
103
+ console.log(`Validated ${filePath} against ${schemaId}`)
104
+ return
105
+ }
106
+
107
+ console.error(`Validation failed for ${filePath} against ${schemaId}:`)
108
+ for (const error of ajv.errors || []) {
109
+ const instancePath = error.instancePath || '/'
110
+ console.error(`- ${instancePath} ${error.message}`)
111
+ }
112
+ process.exit(1)
113
+ }
114
+
115
+ function findProjectRoot() {
116
+ let currentDirectory = process.cwd()
117
+
118
+ while (true) {
119
+ if (fs.existsSync(path.join(currentDirectory, 'schemas', 'dashboard-schema.json'))) {
120
+ return currentDirectory
121
+ }
122
+
123
+ const parentDirectory = path.dirname(currentDirectory)
124
+ if (parentDirectory === currentDirectory) {
125
+ throw new Error('Could not locate project root containing schemas/dashboard-schema.json')
126
+ }
127
+ currentDirectory = parentDirectory
128
+ }
129
+ }
130
+
131
+ function readJson(filePath) {
132
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'))
133
+ }
134
+
135
+ function forEachFile(directoryPath, visitor) {
136
+ const entries = fs.readdirSync(directoryPath, { withFileTypes: true })
137
+ for (const entry of entries) {
138
+ const entryPath = path.join(directoryPath, entry.name)
139
+ if (entry.isDirectory()) {
140
+ forEachFile(entryPath, visitor)
141
+ continue
142
+ }
143
+ visitor(entryPath)
144
+ }
145
+ }
146
+
147
+ export { convertDashboard }
@@ -1,7 +1,7 @@
1
1
  // This script is the shared conversion source for the published API and CLI.
2
2
  // Keep it thin and delegate to the maintained converter implementation.
3
3
  // @ts-ignore
4
- import { convertDashboard } from '../../skills/grafana-to-guance-dashboard/scripts/convert-grafana-dashboard.mjs';
4
+ import { convertDashboard } from './convert-grafana-dashboard-core.js';
5
5
  export function covert(grafanaData) {
6
6
  return convertDashboard(grafanaData);
7
7
  }
@@ -9,7 +9,7 @@ import type {
9
9
  // This script is the shared conversion source for the published API and CLI.
10
10
  // Keep it thin and delegate to the maintained converter implementation.
11
11
  // @ts-ignore
12
- import { convertDashboard } from '../../skills/grafana-to-guance-dashboard/scripts/convert-grafana-dashboard.mjs'
12
+ import { convertDashboard } from './convert-grafana-dashboard-core.js'
13
13
 
14
14
  export function covert(grafanaData: GrafanaDashboardType): GuanceDashboardType {
15
15
  return convertDashboard(grafanaData) as GuanceDashboardType
@@ -11,7 +11,9 @@ import fs from 'fs';
11
11
  import path from 'path';
12
12
  import yargs from 'yargs';
13
13
  // @ts-ignore
14
- import { convertDashboard, validateDashboardFile, } from '../../skills/grafana-to-guance-dashboard/scripts/convert-grafana-dashboard.mjs';
14
+ import { convertDashboard } from './convert-grafana-dashboard-core.js';
15
+ // @ts-ignore
16
+ import { validateDashboardFile } from './convert-grafana-dashboard.js';
15
17
  export function run(args) {
16
18
  return __awaiter(this, void 0, void 0, function* () {
17
19
  const { argv } = yargs(args)
@@ -2,10 +2,9 @@ import fs from 'fs'
2
2
  import path from 'path'
3
3
  import yargs from 'yargs'
4
4
  // @ts-ignore
5
- import {
6
- convertDashboard,
7
- validateDashboardFile,
8
- } from '../../skills/grafana-to-guance-dashboard/scripts/convert-grafana-dashboard.mjs'
5
+ import { convertDashboard } from './convert-grafana-dashboard-core.js'
6
+ // @ts-ignore
7
+ import { validateDashboardFile } from './convert-grafana-dashboard.js'
9
8
 
10
9
  export async function run(args: string[]) {
11
10
  const { argv } = yargs(args)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcare/guance-front-tools",
3
- "version": "1.0.13",
3
+ "version": "1.0.16",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -16,10 +16,11 @@
16
16
  "types": "lib/cjs/src/index.d.ts",
17
17
  "module": "lib/esm/src/index.js",
18
18
  "scripts": {
19
- "build": "npm run clean && npm run generate && npm run build:cjs && npm run build:esm && npm run build:script",
19
+ "build": "npm run clean && npm run generate && npm run build:cjs && npm run build:esm && npm run build:script && npm run sync:converter",
20
20
  "build:cjs": "tsc -p tsconfig.cjs.json",
21
21
  "build:esm": "tsc -p tsconfig.esm.json",
22
22
  "build:script": "tsc -p tsconfig.script.json",
23
+ "sync:converter": "node scripts/sync-converter.mjs",
23
24
  "clean": "rm -rf ./lib/generated && rm -rf ./lib/esm && rm -rf ./lib/cjs",
24
25
  "generate": "node scripts/generate.mjs",
25
26
  "test": "node --test test/*.test.mjs",
@@ -0,0 +1,57 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import ts from 'typescript'
4
+
5
+ const projectRoot = process.cwd()
6
+ const syncPairs = [
7
+ {
8
+ sourcePath: path.join(projectRoot, 'lib', 'scripts', 'convert-grafana-dashboard.js'),
9
+ targets: [
10
+ path.join(projectRoot, 'lib', 'esm', 'scripts', 'convert-grafana-dashboard.js'),
11
+ path.join(projectRoot, 'lib', 'cjs', 'scripts', 'convert-grafana-dashboard.js'),
12
+ path.join(projectRoot, 'skills', 'grafana-to-guance-dashboard', 'scripts', 'convert-grafana-dashboard.mjs'),
13
+ ],
14
+ },
15
+ {
16
+ sourcePath: path.join(projectRoot, 'lib', 'scripts', 'convert-grafana-dashboard-core.js'),
17
+ targets: [
18
+ path.join(projectRoot, 'lib', 'esm', 'scripts', 'convert-grafana-dashboard-core.js'),
19
+ path.join(projectRoot, 'lib', 'cjs', 'scripts', 'convert-grafana-dashboard-core.js'),
20
+ path.join(projectRoot, 'skills', 'grafana-to-guance-dashboard', 'scripts', 'convert-grafana-dashboard-core.js'),
21
+ ],
22
+ },
23
+ ]
24
+ const staleTargets = [
25
+ path.join(projectRoot, 'lib', 'scripts', 'convert-grafana-dashboard.mjs'),
26
+ path.join(projectRoot, 'lib', 'esm', 'scripts', 'convert-grafana-dashboard.mjs'),
27
+ path.join(projectRoot, 'lib', 'cjs', 'scripts', 'convert-grafana-dashboard.mjs'),
28
+ ]
29
+
30
+ function transpileForTarget(sourcePath, targetPath) {
31
+ const source = fs.readFileSync(sourcePath, 'utf8')
32
+ const isCommonJsTarget = targetPath.includes(`${path.sep}lib${path.sep}cjs${path.sep}`)
33
+ const fileName = targetPath.endsWith('.mjs') ? targetPath.replace(/\.mjs$/, '.mts') : targetPath
34
+ const { outputText } = ts.transpileModule(source, {
35
+ fileName,
36
+ compilerOptions: {
37
+ target: ts.ScriptTarget.ES2018,
38
+ module: isCommonJsTarget ? ts.ModuleKind.CommonJS : ts.ModuleKind.ES2020,
39
+ allowJs: true,
40
+ },
41
+ })
42
+ return outputText
43
+ }
44
+
45
+ for (const { sourcePath, targets } of syncPairs) {
46
+ for (const target of targets) {
47
+ fs.mkdirSync(path.dirname(target), { recursive: true })
48
+ fs.writeFileSync(target, transpileForTarget(sourcePath, target), 'utf8')
49
+ console.log(`Synced ${path.relative(projectRoot, sourcePath)} -> ${path.relative(projectRoot, target)}`)
50
+ }
51
+ }
52
+
53
+ for (const target of staleTargets) {
54
+ if (!fs.existsSync(target)) continue
55
+ fs.rmSync(target, { force: true })
56
+ console.log(`Removed stale ${path.relative(projectRoot, target)}`)
57
+ }