-
Couldn't load subscription status.
- Fork 0
[WIP] @37bytes/setup-dynamic-environment #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
18a827e
9aa7aec
66c9f58
f6057dc
7bae551
176fd10
e6171a5
50c990b
0c9bc45
4224f78
bcfc469
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| node_modules | ||
| build |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .git | ||
| .idea | ||
| src | ||
|
|
||
| tsconfig.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Setup Dynamic Environment Plugin | ||
|
|
||
| This plugin provides a command-line utility to recursively replace placeholder strings in JavaScript files within a specified directory with dynamic environment values. | ||
|
|
||
| ## Installation | ||
|
|
||
| ``` | ||
| npm install dynamic-environment-replacer | ||
| ``` | ||
|
|
||
| # Usage | ||
| "scripts" section in package.json | ||
| ``` | ||
| "build": " your_build_script && dynamic-environment-replacer --TARGET_DIRECTORY=<target_directory> --ENVIRONMENT_CONFIG=<environment_config>" | ||
| ``` | ||
| ### TARGET_DIRECTORY: | ||
| The target directory containing JavaScript files where replacements will be made. | ||
|
|
||
| ### ENVIRONMENT_CONFIG: | ||
| The path to the environment configuration file in dotenv format. | ||
|
|
||
| ### Example | ||
|
|
||
| ``` | ||
| "build": "rimraf build && npm run prebuild && setup-dynamic-environment TARGET_DIRECTORY=build ENVIRONMENT_CONFIG=.env.production", | ||
| ``` | ||
|
|
||
| # Dynamic Replacement | ||
|
|
||
| The plugin will replace the placeholder string ```"__PLACE_FOR_DYNAMIC_ENVIRONMENT__"``` with the serialized representation of the environment variables defined in the specified ENVIRONMENT_CONFIG file. |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Пакет же называется |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Setup Dynamic Environment Plugin | ||
|
|
||
| Этот плагин предоставляет утилиту командной строки для рекурсивной замены строк-шаблонов в файлах JavaScript в указанном каталоге на объект динамического окружения. | ||
|
|
||
| ## Установка | ||
|
|
||
| ``` | ||
| npm install dynamic-environment-replacer | ||
| ``` | ||
| ## Использование | ||
| секция "scripts" в package.json | ||
| ``` | ||
| "build": " your_build_script && dynamic-environment-replacer --TARGET_DIRECTORY=<target_directory> --ENVIRONMENT_CONFIG=<environment_config>" | ||
| ``` | ||
| ### TARGET_DIRECTORY: | ||
| Целевой каталог, содержащий файлы JavaScript, в которые будут произведены замены. | ||
|
|
||
| ### ENVIRONMENT_CONFIG: | ||
| Путь к файлу конфигурации окружения в формате dotenv. | ||
|
|
||
| ## Пример | ||
|
|
||
| ``` | ||
| "build": "rimraf build && npm run prebuild && setup-dynamic-environment TARGET_DIRECTORY=build ENVIRONMENT_CONFIG=.env.production", | ||
| ``` | ||
|
|
||
| ## Динамическая замена | ||
|
|
||
| Плагин заменяет шаблонную строку ```"__PLACE_FOR_DYNAMIC_ENVIRONMENT__"``` с сериализованным представлением переменных окружения, определенных в указанном файле ENVIRONMENT_CONFIG. |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Предлагаю перейти на |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { describe, test, expect } from '@jest/globals'; | ||
| import extractLaunchArguments from '../src/utils/extractLaunchArguments'; | ||
|
|
||
| describe('extractLaunchArguments', () => { | ||
| test('should extract launch arguments correctly', () => { | ||
| const originalArgv = process.argv; | ||
| process.argv = ['node', 'script.js', 'TARGET_DIRECTORY=dir', 'ENVIRONMENT_CONFIG=env']; | ||
|
|
||
| const result = extractLaunchArguments(); | ||
| expect(result).toEqual({ TARGET_DIRECTORY: 'dir', ENVIRONMENT_CONFIG: 'env' }); | ||
| process.argv = originalArgv; | ||
| }); | ||
|
|
||
| test('should throw an error for missing required arguments', () => { | ||
| const originalArgv = process.argv; | ||
| process.argv = ['node', 'script.js']; | ||
| expect(() => extractLaunchArguments()).toThrowError('Some required arguments missed!'); | ||
|
|
||
| process.argv = originalArgv; | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { beforeEach, describe, test, expect, jest, afterEach } from '@jest/globals'; | ||
| import replaceInDirectory from '../src/utils/replaceInDirectory'; | ||
| import replaceInFile from '../src/utils/replaceInFile'; | ||
| import mock from 'mock-fs'; | ||
| import path from 'path'; | ||
|
|
||
| jest.mock('../src/utils/replaceInFile'); | ||
|
|
||
| describe('replaceInDirectory', () => { | ||
| beforeEach(() => { | ||
| mock({ | ||
| '/testDirectory': { | ||
| 'file1.js': 'content1', | ||
| 'file2.js': 'content2', | ||
| subdir: { | ||
| 'file3.js': 'content3', | ||
| 'file4.txt': 'textfile' | ||
| } | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| mock.restore(); | ||
| }); | ||
|
|
||
| test('should recursively replace strings in JS files', () => { | ||
| const dynamicEnvironment = { key: 'value' }; | ||
|
|
||
| jest.spyOn(global.console, 'log'); | ||
|
|
||
| replaceInDirectory('/testDirectory', dynamicEnvironment); | ||
|
|
||
| const normalizedPaths = [ | ||
| path.normalize('/testDirectory/file1.js'), | ||
| path.normalize('/testDirectory/file2.js'), | ||
| path.normalize('/testDirectory/subdir/file3.js') | ||
| ]; | ||
|
|
||
| expect(global.console.log).toHaveBeenCalledWith('calling replaceInFile...', normalizedPaths[0]); | ||
| expect(global.console.log).toHaveBeenCalledWith('calling replaceInFile...', normalizedPaths[1]); | ||
| expect(global.console.log).toHaveBeenCalledWith('calling replaceInFile...', normalizedPaths[2]); | ||
| expect(global.console.log).toHaveBeenCalledTimes(3); | ||
|
|
||
| expect(replaceInFile).toHaveBeenCalledTimes(3); | ||
|
|
||
| expect(replaceInFile).toHaveBeenCalledWith(normalizedPaths[0], dynamicEnvironment); | ||
| expect(replaceInFile).toHaveBeenCalledWith(normalizedPaths[1], dynamicEnvironment); | ||
| expect(replaceInFile).toHaveBeenCalledWith(normalizedPaths[2], dynamicEnvironment); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { describe, expect, test } from '@jest/globals'; | ||
| import replaceInFile from '../src/utils/replaceInFile'; | ||
| import path from 'path'; | ||
|
|
||
| const fs = require('fs'); | ||
|
|
||
| const testFilePath = path.join(process.cwd(), '__tests__/testFile.txt'); | ||
| const dynamicEnvironment = { key: 'value' }; | ||
| const placeholder = '"__PLACE_FOR_DYNAMIC_ENVIRONMENT__"'; | ||
|
|
||
| describe('replaceInFile', () => { | ||
| test('should replace placeholder in the file content', () => { | ||
| const originalContent = `This is a test file with ${placeholder} inside.`; | ||
|
|
||
| fs.writeFileSync(testFilePath, originalContent, 'utf8'); | ||
| replaceInFile(testFilePath, dynamicEnvironment); | ||
| fs.readFile(testFilePath, 'utf8', (error, data) => { | ||
| const expectedContent = originalContent.replace(placeholder, JSON.stringify(dynamicEnvironment)); | ||
| expect(data).toBe(expectedContent); | ||
| fs.unlink(testFilePath); | ||
| }); | ||
| }); | ||
| test('should not replace anything if placeholder is absent', () => { | ||
| const originalContent = `This is a test file without placeholder inside.`; | ||
|
|
||
| fs.writeFileSync(testFilePath, originalContent, 'utf8'); | ||
| replaceInFile(testFilePath, dynamicEnvironment); | ||
| fs.readFile(testFilePath, 'utf8', (error, data) => { | ||
| const expectedContent = originalContent.replace(placeholder, JSON.stringify(dynamicEnvironment)); | ||
| expect(data).toBe(expectedContent); | ||
| fs.unlink(testFilePath); | ||
| }); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| /** @type {import('ts-jest').JestConfigWithTsJest} */ | ||
| module.exports = { | ||
| preset: 'ts-jest', | ||
| testEnvironment: 'node' | ||
| }; |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Добавь, пожалуйста, description |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| { | ||
| "name": "@37bytes/setup-dynamic-environment", | ||
| "version": "0.0.2", | ||
| "author": "37bytes", | ||
| "license": "MIT", | ||
| "main": "build/index.js", | ||
| "scripts": { | ||
| "build": "rimraf build && tsc --project ./tsconfig.json", | ||
| "build&watch": "rimraf build && tsc --project ./tsconfig.json --watch", | ||
| "npm-packlist": "npm run build && npx -y npm-packlist@6.0.1" | ||
| }, | ||
| "bin": { | ||
| "setup-dynamic-environment": "./build/index.js" | ||
| }, | ||
| "engines": { | ||
| "node": ">=16" | ||
| }, | ||
| "dependencies": { | ||
| "dotenv": "16.3.1", | ||
| "rimraf": "~3.0.2" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "~16.11.57", | ||
| "@types/rimraf": "~3.0.2", | ||
| "mock-fs": "5.2.0", | ||
| "typescript": "~4.8.3" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| enum ProcessArgument { | ||
| TARGET_DIRECTORY = 'TARGET_DIRECTORY', | ||
| ENVIRONMENT_CONFIG = 'ENVIRONMENT_CONFIG' | ||
| } | ||
|
|
||
| export const requiredArguments = [ProcessArgument.TARGET_DIRECTORY, ProcessArgument.ENVIRONMENT_CONFIG] as const; | ||
| export const optionalArguments = [] as const; | ||
| export const allowedArguments = [...requiredArguments, ...optionalArguments]; | ||
|
|
||
| export type ExtractedArguments = Record<(typeof requiredArguments)[number], string> & | ||
| Record<(typeof optionalArguments)[number], unknown>; | ||
|
|
||
| export default ProcessArgument; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #!/usr/bin/env node | ||
| import fs from 'fs'; | ||
| import { parse } from 'dotenv'; | ||
| import path from 'path'; | ||
| import extractLaunchArguments from './utils/extractLaunchArguments'; | ||
| import replaceInDirectory from './utils/replaceInDirectory'; | ||
|
|
||
| const { name: packageName, version: packageVersion } = require('../package.json'); | ||
| console.log(`${packageName}@${packageVersion} called!`); | ||
|
|
||
| const { TARGET_DIRECTORY, ENVIRONMENT_CONFIG } = extractLaunchArguments(); | ||
| console.log('launch arguments processed!', { TARGET_DIRECTORY, ENVIRONMENT_CONFIG }); | ||
|
|
||
| const dynamicEnvironment = parse(fs.readFileSync(path.resolve(process.cwd(), ENVIRONMENT_CONFIG))); | ||
|
|
||
| const initialPath = path.resolve(process.cwd(), TARGET_DIRECTORY); | ||
| console.log('calling replaceInDirectory...', initialPath); | ||
| // Запуск функции для директории из параметров | ||
| replaceInDirectory(initialPath, dynamicEnvironment); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { allowedArguments, ExtractedArguments, requiredArguments } from '../constants/ProcessArgument'; | ||
|
|
||
| const extractLaunchArguments = (): ExtractedArguments => { | ||
| const scriptArguments = process.argv.reduce((result, argument) => { | ||
| if (!allowedArguments.some((argumentName) => argument.startsWith(argumentName))) { | ||
| return result; | ||
| } | ||
|
|
||
| const [name, value] = argument.split('='); | ||
| if (typeof value === 'string' && value !== '') { | ||
| result[name] = value; | ||
| } | ||
|
|
||
| return result; | ||
| }, {}) as ExtractedArguments; | ||
|
|
||
| const missedArguments = requiredArguments.filter((argument) => !scriptArguments[argument]); | ||
| if (missedArguments.length) { | ||
| throw new Error(`Some required arguments missed! ${missedArguments.join(', ')}`); | ||
| } | ||
|
|
||
| return scriptArguments; | ||
| }; | ||
|
|
||
| export default extractLaunchArguments; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import fs from 'fs'; | ||
| import path from 'path'; | ||
| import replaceInFile from './replaceInFile'; | ||
|
|
||
| function replaceInDirectory(directory: string, dynamicEnvironment: object) { | ||
| fs.readdirSync(directory).forEach((file) => { | ||
| const fullPath = path.join(directory, file); | ||
|
|
||
| if (fs.statSync(fullPath).isDirectory()) { | ||
| // Если это директория, рекурсивно обходить ее | ||
| replaceInDirectory(fullPath, dynamicEnvironment); | ||
| } else if (path.extname(file) === '.js') { | ||
| // Если это JS-файл, заменить в нем строки | ||
| console.log('calling replaceInFile...', fullPath); | ||
| replaceInFile(fullPath, dynamicEnvironment); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| export default replaceInDirectory; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| const fs = require('fs'); | ||
|
|
||
| // Функция для замены строк в файлах | ||
| function replaceInFile(filePath: string, dynamicEnvironment: object) { | ||
| fs.readFile(filePath, 'utf8', function (err, data) { | ||
| if (err) { | ||
| return console.log(err); | ||
| } | ||
|
|
||
| const result = data.replace(/"__PLACE_FOR_DYNAMIC_ENVIRONMENT__"/g, JSON.stringify(dynamicEnvironment)); | ||
|
|
||
| fs.writeFile(filePath, result, 'utf8', function (err) { | ||
| if (err) { | ||
| console.log(err); | ||
| } | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| export default replaceInFile; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "extends": "../../tsconfig.node.json", | ||
| "compilerOptions": { | ||
| "outDir": "./build", | ||
| "rootDir": "./src" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Перепроверь README, пожалуйста, пакет же называется
@37bytes/setup-dynamic-environment