@diia-inhouse/genproto 3.3.1 → 4.0.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/package.json CHANGED
@@ -1,25 +1,33 @@
1
1
  {
2
2
  "name": "@diia-inhouse/genproto",
3
- "version": "3.3.1",
3
+ "version": "4.0.0",
4
+ "type": "module",
4
5
  "description": "JS codegen from proto with imports from @diia-inhouse/types",
5
6
  "bin": {
6
7
  "genproto": "./dist/genproto.js"
7
8
  },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/types/genproto.d.ts",
12
+ "default": "./dist/genproto.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
8
16
  "repository": "https://github.com/diia-open-source/be-genproto",
9
17
  "scripts": {
10
18
  "prebuild": "rimraf dist",
11
19
  "build": "tsc",
12
20
  "build:watch": "tsc --watch",
13
21
  "semantic-release": "semantic-release",
14
- "lint": "eslint . && prettier --check .",
15
- "lint-fix": "eslint --fix . && prettier --write .",
22
+ "lint": "oxlint && oxfmt --check .",
23
+ "lint-fix": "oxlint --fix && oxfmt .",
16
24
  "lint:lockfile": "lockfile-lint --path package-lock.json --allowed-hosts registry.npmjs.org --validate-https",
17
25
  "prepare": "npm run build",
18
26
  "test": "tsc --project tests/tsconfig.json && vitest run",
19
27
  "find-circulars": "madge --circular --extensions ts ./"
20
28
  },
21
29
  "engines": {
22
- "node": ">=20"
30
+ "node": ">=24"
23
31
  },
24
32
  "author": "Diia",
25
33
  "license": "SEE LICENSE IN LICENSE.md",
@@ -28,28 +36,29 @@
28
36
  "src"
29
37
  ],
30
38
  "dependencies": {
31
- "glob": "11.1.0",
39
+ "glob": "13.0.6",
32
40
  "lodash": "4.18.1",
33
- "lookpath": "1.2.2",
34
- "yargs": "17.7.2"
41
+ "lookpath": "1.2.3",
42
+ "yargs": "18.0.0"
35
43
  },
36
44
  "peerDependencies": {
37
45
  "ts-proto": ">=2.7.0"
38
46
  },
39
47
  "devDependencies": {
40
- "@diia-inhouse/configs": "6.1.1",
41
- "@diia-inhouse/eslint-config": "8.8.2",
48
+ "@diia-inhouse/configs": "7.0.0",
49
+ "@diia-inhouse/oxc-config": "1.9.3",
42
50
  "@types/lodash": "4.17.24",
43
- "@types/node": "20.17.1",
44
- "@types/yargs": "17.0.33",
45
- "@vitest/coverage-v8": "4.1.2",
46
- "eslint": "9.33.0",
47
- "lockfile-lint": "4.14.0",
48
- "madge": "7.0.0",
49
- "prettier": "3.3.3",
50
- "rimraf": "6.0.1",
51
- "semantic-release": "24.0.0",
52
- "vitest": "4.1.2"
51
+ "@types/node": "25.6.2",
52
+ "@types/yargs": "17.0.35",
53
+ "@vitest/coverage-v8": "4.1.5",
54
+ "lockfile-lint": "5.0.0",
55
+ "madge": "8.0.0",
56
+ "oxfmt": "0.48.0",
57
+ "oxlint": "1.63.0",
58
+ "oxlint-tsgolint": "0.22.1",
59
+ "rimraf": "6.1.3",
60
+ "semantic-release": "25.0.3",
61
+ "vitest": "4.1.5"
53
62
  },
54
63
  "release": {
55
64
  "extends": "@diia-inhouse/configs/dist/semantic-release/package"
@@ -57,7 +66,6 @@
57
66
  "commitlint": {
58
67
  "extends": "@diia-inhouse/configs/dist/commitlint"
59
68
  },
60
- "prettier": "@diia-inhouse/eslint-config/prettier",
61
69
  "madge": {
62
70
  "tsConfig": "./tsconfig.json"
63
71
  }
@@ -3,7 +3,7 @@ import path from 'node:path'
3
3
 
4
4
  import { glob } from 'glob'
5
5
 
6
- import Logger from '../logger'
6
+ import Logger from '../logger.js'
7
7
 
8
8
  export enum Platform {
9
9
  ts = 'ts',
@@ -25,7 +25,7 @@ export abstract class CommandBuilder {
25
25
  const protoFiles = await glob(`${this.rootDir}/**/*.proto`, { ignore: '**/node_modules/**' })
26
26
 
27
27
  if (protoFiles.length > 0) {
28
- iPath += ' ' + protoFiles.join(' ')
28
+ iPath += ` ${protoFiles.join(' ')}`
29
29
  }
30
30
 
31
31
  return iPath.trim()
@@ -61,7 +61,6 @@ export abstract class CommandBuilder {
61
61
  return acc
62
62
  }
63
63
 
64
- // eslint-disable-next-line security/detect-non-literal-fs-filename
65
64
  const contents = fs.readFileSync(value) // nosemgrep: eslint.detect-non-literal-fs-filename
66
65
  if (!contents.includes('package ua.gov.diia')) {
67
66
  return acc
@@ -1,4 +1,4 @@
1
- import { CommandBuilder } from './index'
1
+ import { CommandBuilder } from './index.js'
2
2
 
3
3
  export default class JavaCommandBuilder extends CommandBuilder {
4
4
  async protocCommand(): Promise<string[]> {
@@ -1,4 +1,3 @@
1
- /* eslint-disable security/detect-non-literal-fs-filename */
2
1
  import { once } from 'node:events'
3
2
  import { WriteStream, createWriteStream, existsSync } from 'node:fs'
4
3
  import fsPromises from 'node:fs/promises'
@@ -6,16 +5,16 @@ import path from 'node:path'
6
5
  import { finished } from 'node:stream/promises'
7
6
 
8
7
  import { glob } from 'glob'
9
- import { snakeCase } from 'lodash'
8
+ import snakeCase from 'lodash/snakeCase.js'
10
9
 
11
- import Logger from '../logger'
12
- import { CommandBuilder } from './index'
13
-
14
- // import "designSystem/molecules/attentionIconMessageMlc.proto";
15
- const importRegex = /import "(?<path>[^"]+)";/
16
- const slashPrefix = /^\/+/
10
+ import Logger from '../logger.js'
11
+ import { CommandBuilder } from './index.js'
17
12
 
18
13
  export default class PythonCommandBuilder extends CommandBuilder {
14
+ // import "designSystem/molecules/attentionIconMessageMlc.proto";
15
+ static readonly importRegex = /import "(?<path>[^"]+)";/
16
+ static readonly slashPrefix = /^\/+/
17
+
19
18
  private cardinalDependencies: Record<string, string> = {
20
19
  'node_modules/@diia-inhouse/types/dist/proto': 'types_proto',
21
20
  'node_modules/@diia-inhouse/design-system/dist/proto': 'design_system_proto',
@@ -33,8 +32,8 @@ export default class PythonCommandBuilder extends CommandBuilder {
33
32
  '--proto_path=node_modules/protobufjs/google',
34
33
  '--proto_path=/usr/local/include',
35
34
  ...Object.keys(this.cardinalDependencies)
36
- .filter((path) => existsSync(path)) // nosemgrep: eslint.detect-non-literal-fs-filename
37
- .map((path) => `--proto_path=${path}`),
35
+ .filter((depPath) => existsSync(depPath)) // nosemgrep: eslint.detect-non-literal-fs-filename
36
+ .map((depPath) => `--proto_path=${depPath}`),
38
37
  ]
39
38
 
40
39
  for (const protoPath of this.protoPaths) {
@@ -71,7 +70,7 @@ export default class PythonCommandBuilder extends CommandBuilder {
71
70
  const files = await glob(dep + protoPattern)
72
71
 
73
72
  for (const file of files) {
74
- const res = file.replace(dep, '').replace(slashPrefix, '')
73
+ const res = file.replace(dep, '').replace(PythonCommandBuilder.slashPrefix, '')
75
74
 
76
75
  mapping[res] = this.cardinalDependencies[dep]
77
76
 
@@ -79,7 +78,7 @@ export default class PythonCommandBuilder extends CommandBuilder {
79
78
  }
80
79
  }
81
80
 
82
- const localProtos = await glob('proto' + protoPattern)
81
+ const localProtos = await glob(`proto${protoPattern}`)
83
82
 
84
83
  const rulesTasks = []
85
84
  for (const localProto of localProtos) {
@@ -90,7 +89,7 @@ export default class PythonCommandBuilder extends CommandBuilder {
90
89
 
91
90
  replaceRules = [...new Map(rules.flat().map((rule) => [rule.regex.source, rule])).values()]
92
91
 
93
- const generatedFiles = await glob(this.outputDir + '/**/*.py')
92
+ const generatedFiles = await glob(`${this.outputDir}/**/*.py`)
94
93
 
95
94
  const tasks: Promise<void>[] = []
96
95
  for (const generatedFile of generatedFiles) {
@@ -119,7 +118,7 @@ async function touchFilesInTree(dirPath: string, fileName: string, logger: Logge
119
118
  await handle.utimes(new Date(), new Date()) // nosemgrep: eslint.detect-non-literal-fs-filename
120
119
  await handle.close()
121
120
  } catch (err) {
122
- logger.log(`Could not touch file in ${dirPath}: ${err instanceof Error ? err.message : err}`)
121
+ logger.log(`Could not touch file in ${dirPath}: ${err instanceof Error ? err.message : String(err)}`)
123
122
  }
124
123
 
125
124
  for (const entry of entries) {
@@ -149,7 +148,6 @@ async function replaceRulesTask(
149
148
  const protoFilenameSnakeImportAlies = doubleInnerUnderscores(protoFilenameSnake)
150
149
 
151
150
  if (protoDirname === 'proto') {
152
- // eslint-disable-next-line security/detect-non-literal-regexp
153
151
  const rootImportRegex = new RegExp( // nosemgrep: eslint.detect-non-literal-regexp
154
152
  `^${escapeRegex(`import ${protoFilenameSnake}_pb2 as ${protoFilenameSnakeImportAlies}__pb2`)}`,
155
153
  )
@@ -161,7 +159,7 @@ async function replaceRulesTask(
161
159
  }
162
160
 
163
161
  for await (const line of handle.readLines()) {
164
- const result = importRegex.exec(line)
162
+ const result = PythonCommandBuilder.importRegex.exec(line)
165
163
  const importPath = result?.groups?.path
166
164
 
167
165
  if (importPath === undefined) {
@@ -175,13 +173,12 @@ async function replaceRulesTask(
175
173
  const depname = mapping[importPath]
176
174
 
177
175
  if (depname === undefined) {
178
- logger.log(`Looking for ${importPath} in mapper, received ${depname}. Skipping the mapper.`)
176
+ logger.log(`Looking for ${importPath} in mapper, received undefined. Skipping the mapper.`)
179
177
  continue
180
178
  }
181
179
 
182
180
  logger.log(`I'm looking for ${fileName} (${fileName}) to map as "import ${fileName}_pb2"`)
183
181
 
184
- // eslint-disable-next-line security/detect-non-literal-regexp
185
182
  const flatImportRegex = new RegExp(`^${escapeRegex(`import ${fileName}_pb2`)}`) // nosemgrep: eslint.detect-non-literal-regexp
186
183
 
187
184
  replaceRules.push({
@@ -192,7 +189,7 @@ async function replaceRulesTask(
192
189
  const depname = mapping[importPath]
193
190
 
194
191
  if (depname === undefined) {
195
- logger.log(`Looking for ${importPath} in mapper, received ${depname}. Skipping the mapper.`)
192
+ logger.log(`Looking for ${importPath} in mapper, received undefined. Skipping the mapper.`)
196
193
  continue
197
194
  }
198
195
 
@@ -200,7 +197,6 @@ async function replaceRulesTask(
200
197
 
201
198
  logger.log(`I'm looking for ${fileName} (${fileName}) to map as "from ${importName} import ${fileName}_pb2"`)
202
199
 
203
- // eslint-disable-next-line security/detect-non-literal-regexp
204
200
  const nestedImportRegex = new RegExp(`^${escapeRegex(`from ${importName} import ${fileName}_pb2`)}`) // nosemgrep: eslint.detect-non-literal-regexp
205
201
 
206
202
  replaceRules.push({
@@ -225,7 +221,7 @@ async function fileMapper(generatedFile: string, replaceRules: { regex: RegExp;
225
221
  try {
226
222
  handle = await fsPromises.open(generatedFile) // nosemgrep: eslint.detect-non-literal-fs-filename
227
223
 
228
- wstream = createWriteStream(generatedFile + '.new') // nosemgrep: eslint.detect-non-literal-fs-filename
224
+ wstream = createWriteStream(`${generatedFile}.new`) // nosemgrep: eslint.detect-non-literal-fs-filename
229
225
 
230
226
  for await (const line of handle.readLines()) {
231
227
  let mutableLine = line
@@ -233,7 +229,7 @@ async function fileMapper(generatedFile: string, replaceRules: { regex: RegExp;
233
229
  mutableLine = mutableLine.replace(rule.regex, rule.to)
234
230
  }
235
231
 
236
- const writeOk = wstream.write(mutableLine + '\n')
232
+ const writeOk = wstream.write(`${mutableLine}\n`)
237
233
 
238
234
  if (!writeOk) {
239
235
  await once(wstream, 'drain')
@@ -251,22 +247,22 @@ async function fileMapper(generatedFile: string, replaceRules: { regex: RegExp;
251
247
  await finished(wstream)
252
248
 
253
249
  // nosemgrep: eslint.detect-non-literal-fs-filename
254
- if (!isOk && existsSync(generatedFile + '.new')) {
255
- await fsPromises.unlink(generatedFile + '.new') // nosemgrep: eslint.detect-non-literal-fs-filename
250
+ if (!isOk && existsSync(`${generatedFile}.new`)) {
251
+ await fsPromises.unlink(`${generatedFile}.new`) // nosemgrep: eslint.detect-non-literal-fs-filename
256
252
  }
257
253
  }
258
254
  }
259
255
 
260
256
  try {
261
- await fsPromises.rename(generatedFile + '.new', generatedFile) // nosemgrep: eslint.detect-non-literal-fs-filename
257
+ await fsPromises.rename(`${generatedFile}.new`, generatedFile) // nosemgrep: eslint.detect-non-literal-fs-filename
262
258
  logger.log('Update successful!')
263
259
  } catch (err) {
264
260
  // nosemgrep: eslint.detect-non-literal-fs-filename
265
- if (existsSync(generatedFile + '.new')) {
266
- await fsPromises.unlink(generatedFile + '.new') // nosemgrep: eslint.detect-non-literal-fs-filename
261
+ if (existsSync(`${generatedFile}.new`)) {
262
+ await fsPromises.unlink(`${generatedFile}.new`) // nosemgrep: eslint.detect-non-literal-fs-filename
267
263
  }
268
264
 
269
- logger.log(`Final swap failed: ${err}`)
265
+ logger.log(`Final swap failed: ${err instanceof Error ? err.message : String(err)}`)
270
266
  throw err
271
267
  }
272
268
  }
@@ -4,58 +4,58 @@ import path from 'node:path'
4
4
 
5
5
  import { glob } from 'glob'
6
6
 
7
- import Logger from '../logger'
8
- import { CommandBuilder, Platform } from './index'
9
-
10
- const reservedWords = new Set([
11
- 'break',
12
- 'case',
13
- 'catch',
14
- 'class',
15
- 'const',
16
- 'continue',
17
- 'debugger',
18
- 'default',
19
- 'delete',
20
- 'do',
21
- 'else',
22
- 'enum',
23
- 'export',
24
- 'extends',
25
- 'false',
26
- 'finally',
27
- 'for',
28
- 'function',
29
- 'if',
30
- 'import',
31
- 'in',
32
- 'instanceof',
33
- 'new',
34
- 'null',
35
- 'return',
36
- 'super',
37
- 'switch',
38
- 'this',
39
- 'throw',
40
- 'true',
41
- 'try',
42
- 'typeof',
43
- 'var',
44
- 'void',
45
- 'while',
46
- 'with',
47
- 'yield',
48
- 'let',
49
- 'static',
50
- 'implements',
51
- 'interface',
52
- 'package',
53
- 'private',
54
- 'protected',
55
- 'public',
56
- ])
7
+ import Logger from '../logger.js'
8
+ import { CommandBuilder, Platform } from './index.js'
57
9
 
58
10
  export default class TsCommandBuilder extends CommandBuilder {
11
+ private static readonly reservedWords = new Set([
12
+ 'break',
13
+ 'case',
14
+ 'catch',
15
+ 'class',
16
+ 'const',
17
+ 'continue',
18
+ 'debugger',
19
+ 'default',
20
+ 'delete',
21
+ 'do',
22
+ 'else',
23
+ 'enum',
24
+ 'export',
25
+ 'extends',
26
+ 'false',
27
+ 'finally',
28
+ 'for',
29
+ 'function',
30
+ 'if',
31
+ 'import',
32
+ 'in',
33
+ 'instanceof',
34
+ 'new',
35
+ 'null',
36
+ 'return',
37
+ 'super',
38
+ 'switch',
39
+ 'this',
40
+ 'throw',
41
+ 'true',
42
+ 'try',
43
+ 'typeof',
44
+ 'var',
45
+ 'void',
46
+ 'while',
47
+ 'with',
48
+ 'yield',
49
+ 'let',
50
+ 'static',
51
+ 'implements',
52
+ 'interface',
53
+ 'package',
54
+ 'private',
55
+ 'protected',
56
+ 'public',
57
+ ])
58
+
59
59
  // By default ts plugin should be linked to .bin dir but in case if it doesn't
60
60
  // try to look it up in "standard" locations
61
61
  private tsPluginLocations = [
@@ -80,7 +80,6 @@ export default class TsCommandBuilder extends CommandBuilder {
80
80
 
81
81
  for (const location of this.tsPluginLocations) {
82
82
  try {
83
- // eslint-disable-next-line security/detect-non-literal-fs-filename
84
83
  await fs.realpath(location) // nosemgrep: eslint.detect-non-literal-fs-filename
85
84
  } catch {
86
85
  continue
@@ -115,7 +114,7 @@ export default class TsCommandBuilder extends CommandBuilder {
115
114
  switch (projectPlatform) {
116
115
  case Platform.java: {
117
116
  typesProtoPath = `./${this.javaModule ?? '.'}/build/extracted-protos/main/`
118
- typesSubPaths = [`${this.javaModule ?? '.'}`, 'build', 'extracted-protos', 'main']
117
+ typesSubPaths = [this.javaModule ?? '.', 'build', 'extracted-protos', 'main']
119
118
  dependenciesPattern = `${this.javaModule ?? '.'}/build/extracted-protos/main/**/*.proto`
120
119
  execSync(`./gradlew ${this.javaModule ?? ''}:extractProto`, { stdio: 'pipe' })
121
120
  break
@@ -187,7 +186,6 @@ export default class TsCommandBuilder extends CommandBuilder {
187
186
  const files = await glob(path.join(this.outputDir, '**/*.ts'))
188
187
 
189
188
  for (const file of files) {
190
- // eslint-disable-next-line security/detect-non-literal-fs-filename
191
189
  const content = await fs.readFile(file, 'utf8') // nosemgrep: eslint.detect-non-literal-fs-filename
192
190
 
193
191
  if (!content.includes('export namespace ')) {
@@ -197,7 +195,6 @@ export default class TsCommandBuilder extends CommandBuilder {
197
195
  const result = this.stripReservedWordTypeAliases(content)
198
196
 
199
197
  if (result !== content) {
200
- // eslint-disable-next-line security/detect-non-literal-fs-filename
201
198
  await fs.writeFile(file, result) // nosemgrep: eslint.detect-non-literal-fs-filename
202
199
  }
203
200
  }
@@ -235,7 +232,7 @@ export default class TsCommandBuilder extends CommandBuilder {
235
232
  if (insideNamespace) {
236
233
  const match = line.match(/^\s*export type (\w+) = typeof /)
237
234
 
238
- if (match && reservedWords.has(match[1])) {
235
+ if (match && TsCommandBuilder.reservedWords.has(match[1])) {
239
236
  continue
240
237
  }
241
238
 
package/src/genproto.ts CHANGED
@@ -5,13 +5,14 @@ import path from 'node:path'
5
5
 
6
6
  import { lookpath } from 'lookpath'
7
7
  import yargs from 'yargs'
8
+ import { hideBin } from 'yargs/helpers'
8
9
 
9
- import { CommandBuilder, Platform } from './command'
10
- import JavaCommandBuilder from './command/javaCommandBuilder'
11
- import PythonCommandBuilder from './command/pythonCommandBuilder'
12
- import TsCommandBuilder from './command/tsCommandBuilder'
13
- import Logger from './logger'
14
- import Utils from './utils'
10
+ import { CommandBuilder, Platform } from './command/index.js'
11
+ import JavaCommandBuilder from './command/javaCommandBuilder.js'
12
+ import PythonCommandBuilder from './command/pythonCommandBuilder.js'
13
+ import TsCommandBuilder from './command/tsCommandBuilder.js'
14
+ import Logger from './logger.js'
15
+ import Utils from './utils/index.js'
15
16
 
16
17
  async function main(): Promise<void> {
17
18
  const protocExists = await lookpath('protoc')
@@ -20,7 +21,7 @@ async function main(): Promise<void> {
20
21
  throw new Error("Couldn't find protoc in PATH")
21
22
  }
22
23
 
23
- const options = await yargs
24
+ const options = await yargs(hideBin(process.argv))
24
25
  .usage('$0 --rootDir dirname --outputDir dirname')
25
26
  .option('v', { type: 'boolean', default: false })
26
27
  .option('platform', { type: 'string', default: Platform.ts })
@@ -51,12 +52,11 @@ async function main(): Promise<void> {
51
52
 
52
53
  logger.log(`Creating directory ${outputAbsoluteDir}...`)
53
54
 
54
- // eslint-disable-next-line security/detect-non-literal-fs-filename
55
55
  await fs.promises.mkdir(outputDir, { recursive: true }) // nosemgrep: eslint.detect-non-literal-fs-filename
56
56
 
57
57
  let commandBuilder: CommandBuilder
58
58
 
59
- switch (platform) {
59
+ switch (platform as Platform) {
60
60
  case Platform.java: {
61
61
  commandBuilder = new JavaCommandBuilder(logger, generateClient, rootDir, outputDir, protoPaths)
62
62
  break
@@ -91,7 +91,7 @@ async function main(): Promise<void> {
91
91
  logger.log(`Generating index.ts for directory: ${indexDir}`)
92
92
  await Utils.generateIndexForDirectory(indexDir, rootDir)
93
93
  } catch (err) {
94
- logger.log(`Error processing directory ${dir}: ${err}`)
94
+ logger.log(`Error processing directory ${dir}: ${err instanceof Error ? err.message : String(err)}`)
95
95
  }
96
96
  }
97
97
  }
package/src/logger.ts CHANGED
@@ -6,7 +6,7 @@ export default class Logger {
6
6
  }
7
7
 
8
8
  log(...message: string[]): void {
9
- // eslint-disable-next-line no-console
9
+ // oxlint-disable-next-line eslint/no-console
10
10
  console.log(...message)
11
11
  }
12
12
 
@@ -15,7 +15,7 @@ export default class Logger {
15
15
  return
16
16
  }
17
17
 
18
- // eslint-disable-next-line no-console
18
+ // oxlint-disable-next-line eslint/no-console
19
19
  console.log(...message)
20
20
  }
21
21
  }
@@ -3,25 +3,28 @@ import syncFs, { promises as fs } from 'node:fs'
3
3
  import path from 'node:path'
4
4
  import { createInterface } from 'node:readline'
5
5
 
6
+ interface ExportedNames {
7
+ valueNames: string[]
8
+ typeNames: string[]
9
+ }
10
+
6
11
  /**
7
12
  * Extract exported symbol names from a ts-proto generated TypeScript file.
8
13
  * Returns arrays of value exports and type-only exports separately.
9
14
  * Names that exist as both value and type (e.g. interface + const with same name)
10
15
  * are only included in valueNames to avoid duplicate identifier errors.
11
16
  */
12
- function extractExportedNames(content: string): { valueNames: string[]; typeNames: string[] } {
17
+ function extractExportedNames(content: string): ExportedNames {
13
18
  const valueSet = new Set<string>()
14
19
  const typeSet = new Set<string>()
15
20
 
16
- // eslint-disable-next-line regexp/no-unused-capturing-group
17
- const exportRegex = /^export\s+(?:(const|let|var|function|enum|class)\s+(\w+)|(interface|type)\s+(\w+))/gm
18
- let match
19
- // eslint-disable-next-line no-cond-assign
20
- while ((match = exportRegex.exec(content)) !== null) {
21
- if (match[2]) {
22
- valueSet.add(match[2])
23
- } else if (match[4]) {
24
- typeSet.add(match[4])
21
+ const exportRegex = /^export\s+(?:(?:const|let|var|function|enum|class)\s+(\w+)|(?:interface|type)\s+(\w+))/gm
22
+
23
+ for (const match of content.matchAll(exportRegex)) {
24
+ if (match[1]) {
25
+ valueSet.add(match[1])
26
+ } else if (match[2]) {
27
+ typeSet.add(match[2])
25
28
  }
26
29
  }
27
30
 
@@ -36,7 +39,6 @@ export default {
36
39
  const exportedNames = new Set<string>()
37
40
 
38
41
  const recursivePaths = async (realpath: string): Promise<string[]> => {
39
- // eslint-disable-next-line security/detect-non-literal-fs-filename
40
42
  const items = await fs.readdir(realpath, { withFileTypes: true }) // nosemgrep: eslint.detect-non-literal-fs-filename
41
43
  let paths: string[] = []
42
44
 
@@ -54,7 +56,6 @@ export default {
54
56
  }
55
57
 
56
58
  for (const recPaths of await recursivePaths(dir)) {
57
- // eslint-disable-next-line security/detect-non-literal-fs-filename
58
59
  const stream = syncFs.createReadStream(recPaths) // nosemgrep: eslint.detect-non-literal-fs-filename
59
60
  const rl = createInterface({
60
61
  input: stream,
@@ -69,10 +70,8 @@ export default {
69
70
  const protoFile = matchArr[1]
70
71
 
71
72
  const protofilepath = path.resolve(protoRoot, protoFile)
72
- // prettier-ignore
73
- // eslint-disable-next-line security/detect-non-literal-fs-filename
74
- if (syncFs.existsSync(protofilepath)) { // nosemgrep: eslint.detect-non-literal-fs-filename
75
- // eslint-disable-next-line security/detect-non-literal-fs-filename
73
+ const exists = syncFs.existsSync(protofilepath) // nosemgrep: eslint.detect-non-literal-fs-filename
74
+ if (exists) {
76
75
  const contents = syncFs.readFileSync(protofilepath) // nosemgrep: eslint.detect-non-literal-fs-filename
77
76
 
78
77
  ownPackage = contents.includes('package ua.gov.diia')
@@ -94,7 +93,6 @@ export default {
94
93
 
95
94
  if (ownPackage) {
96
95
  // Read file and extract exported names to avoid re-export conflicts (TS2308)
97
- // eslint-disable-next-line security/detect-non-literal-fs-filename
98
96
  const content = await fs.readFile(recPaths, 'utf8') // nosemgrep: eslint.detect-non-literal-fs-filename
99
97
  const { valueNames, typeNames } = extractExportedNames(content)
100
98
 
@@ -118,7 +116,6 @@ export default {
118
116
  exportLines.push(parts.join('\n'))
119
117
  }
120
118
  } else {
121
- // eslint-disable-next-line unicorn/prefer-string-replace-all
122
119
  const namespace = fileNameWithPrefix.replace(/[/\\]/g, '_').replace(/[^\w$]/g, '_')
123
120
 
124
121
  exportLines.push(`export * as ${namespace} from '${importPath}';`)
@@ -128,8 +125,7 @@ export default {
128
125
  if (exportLines.length > 0) {
129
126
  const indexFilePath = path.join(dir, 'index.ts')
130
127
 
131
- // eslint-disable-next-line security/detect-non-literal-fs-filename
132
- await fs.writeFile(indexFilePath, exportLines.join('\n\n') + '\n') // nosemgrep: eslint.detect-non-literal-fs-filename
128
+ await fs.writeFile(indexFilePath, `${exportLines.join('\n\n')}\n`) // nosemgrep: eslint.detect-non-literal-fs-filename
133
129
  }
134
130
  },
135
131
  }