@runium/cli 0.0.1 → 0.0.2

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.
Files changed (89) hide show
  1. package/{lib/commands → commands}/index.js +0 -0
  2. package/{lib/commands → commands}/project/project-start.js +1 -1
  3. package/{lib/constants → constants}/index.js +0 -0
  4. package/{lib/macros → macros}/index.js +0 -0
  5. package/package.json +7 -30
  6. package/{lib/services → services}/index.js +0 -0
  7. package/services/plugin-context.js +1 -0
  8. package/services/shutdown.js +1 -0
  9. package/{lib/utils → utils}/index.js +0 -0
  10. package/.eslintrc.json +0 -31
  11. package/.prettierrc.json +0 -10
  12. package/README.md +0 -3
  13. package/build.js +0 -104
  14. package/lib/package.json +0 -21
  15. package/lib/services/plugin-context.js +0 -1
  16. package/lib/services/shutdown.js +0 -1
  17. package/src/app.ts +0 -175
  18. package/src/commands/index.ts +0 -2
  19. package/src/commands/plugin/plugin-add.ts +0 -48
  20. package/src/commands/plugin/plugin-command.ts +0 -36
  21. package/src/commands/plugin/plugin-disable.ts +0 -46
  22. package/src/commands/plugin/plugin-enable.ts +0 -50
  23. package/src/commands/plugin/plugin-list.ts +0 -61
  24. package/src/commands/plugin/plugin-remove.ts +0 -42
  25. package/src/commands/plugin/plugin.ts +0 -41
  26. package/src/commands/project/project-add.ts +0 -46
  27. package/src/commands/project/project-command.ts +0 -36
  28. package/src/commands/project/project-list.ts +0 -32
  29. package/src/commands/project/project-remove.ts +0 -41
  30. package/src/commands/project/project-start.ts +0 -152
  31. package/src/commands/project/project-state-command.ts +0 -68
  32. package/src/commands/project/project-status.ts +0 -103
  33. package/src/commands/project/project-stop.ts +0 -55
  34. package/src/commands/project/project-validate.ts +0 -43
  35. package/src/commands/project/project.ts +0 -45
  36. package/src/commands/runium-command.ts +0 -50
  37. package/src/constants/error-code.ts +0 -15
  38. package/src/constants/index.ts +0 -1
  39. package/src/index.ts +0 -21
  40. package/src/macros/conditional.ts +0 -31
  41. package/src/macros/empty.ts +0 -6
  42. package/src/macros/env.ts +0 -8
  43. package/src/macros/index.ts +0 -12
  44. package/src/macros/path.ts +0 -9
  45. package/src/services/config.ts +0 -76
  46. package/src/services/index.ts +0 -7
  47. package/src/services/output.ts +0 -201
  48. package/src/services/plugin-context.ts +0 -81
  49. package/src/services/plugin.ts +0 -144
  50. package/src/services/profile.ts +0 -211
  51. package/src/services/project.ts +0 -114
  52. package/src/services/shutdown.ts +0 -130
  53. package/src/utils/convert-path-to-valid-file-name.ts +0 -39
  54. package/src/utils/debounce.ts +0 -23
  55. package/src/utils/format-timestamp.ts +0 -17
  56. package/src/utils/index.ts +0 -3
  57. package/tsconfig.json +0 -40
  58. /package/{lib/app.js → app.js} +0 -0
  59. /package/{lib/commands → commands}/plugin/plugin-add.js +0 -0
  60. /package/{lib/commands → commands}/plugin/plugin-command.js +0 -0
  61. /package/{lib/commands → commands}/plugin/plugin-disable.js +0 -0
  62. /package/{lib/commands → commands}/plugin/plugin-enable.js +0 -0
  63. /package/{lib/commands → commands}/plugin/plugin-list.js +0 -0
  64. /package/{lib/commands → commands}/plugin/plugin-remove.js +0 -0
  65. /package/{lib/commands → commands}/plugin/plugin.js +0 -0
  66. /package/{lib/commands → commands}/project/project-add.js +0 -0
  67. /package/{lib/commands → commands}/project/project-command.js +0 -0
  68. /package/{lib/commands → commands}/project/project-list.js +0 -0
  69. /package/{lib/commands → commands}/project/project-remove.js +0 -0
  70. /package/{lib/commands → commands}/project/project-state-command.js +0 -0
  71. /package/{lib/commands → commands}/project/project-status.js +0 -0
  72. /package/{lib/commands → commands}/project/project-stop.js +0 -0
  73. /package/{lib/commands → commands}/project/project-validate.js +0 -0
  74. /package/{lib/commands → commands}/project/project.js +0 -0
  75. /package/{lib/commands → commands}/runium-command.js +0 -0
  76. /package/{lib/constants → constants}/error-code.js +0 -0
  77. /package/{lib/index.js → index.js} +0 -0
  78. /package/{lib/macros → macros}/conditional.js +0 -0
  79. /package/{lib/macros → macros}/empty.js +0 -0
  80. /package/{lib/macros → macros}/env.js +0 -0
  81. /package/{lib/macros → macros}/path.js +0 -0
  82. /package/{lib/services → services}/config.js +0 -0
  83. /package/{lib/services → services}/output.js +0 -0
  84. /package/{lib/services → services}/plugin.js +0 -0
  85. /package/{lib/services → services}/profile.js +0 -0
  86. /package/{lib/services → services}/project.js +0 -0
  87. /package/{lib/utils → utils}/convert-path-to-valid-file-name.js +0 -0
  88. /package/{lib/utils → utils}/debounce.js +0 -0
  89. /package/{lib/utils → utils}/format-timestamp.js +0 -0
@@ -1,144 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
- import { Service } from 'typedi';
4
- import {
5
- isRuniumError,
6
- Macro,
7
- ProjectSchemaExtension,
8
- RuniumError,
9
- RuniumTaskConstructor,
10
- RuniumTriggerConstructor,
11
- RuniumTriggerOptions,
12
- } from '@runium/core';
13
- import { ErrorCode } from '@constants';
14
-
15
- type PluginOptions = Record<string, unknown>;
16
-
17
- type PluginModule = { default: (options?: PluginOptions) => Plugin };
18
-
19
- export interface PluginProjectDefinition {
20
- macros?: Record<string, Macro>;
21
- tasks?: Record<string, RuniumTaskConstructor>;
22
- actions?: Record<string, (payload: unknown) => void>;
23
- triggers?: Record<string, RuniumTriggerConstructor<RuniumTriggerOptions>>;
24
- validationSchema?: ProjectSchemaExtension;
25
- }
26
-
27
- export interface PluginOptionsDefinition {
28
- value?: PluginOptions;
29
- validate?(options: PluginOptions): boolean;
30
- }
31
-
32
- export interface PluginAppDefinition {
33
- commands?: Record<string, unknown>;
34
- }
35
-
36
- export interface Plugin {
37
- name: string;
38
- project?: PluginProjectDefinition;
39
- options?: PluginOptionsDefinition;
40
- app?: PluginAppDefinition;
41
- }
42
-
43
- @Service()
44
- export class PluginService {
45
- private plugins: Map<string, Plugin> = new Map();
46
-
47
- /**
48
- * Get all plugins
49
- */
50
- getAllPlugins(): Plugin[] {
51
- return Array.from(this.plugins.values());
52
- }
53
-
54
- /**
55
- * Get plugin by name
56
- * @param name
57
- */
58
- getPluginByName(name: string): Plugin | undefined {
59
- return this.plugins.get(name);
60
- }
61
-
62
- /**
63
- * Load plugin
64
- * @param path
65
- */
66
- async loadPlugin(path: string): Promise<string> {
67
- if (!path || !existsSync(path)) {
68
- throw new RuniumError(
69
- `Plugin file "${path}" does not exist`,
70
- ErrorCode.PLUGIN_FILE_NOT_FOUND,
71
- { path }
72
- );
73
- }
74
-
75
- try {
76
- const pluginModule = (await import(path)) as PluginModule;
77
- const { default: getPlugin } = pluginModule;
78
- if (!getPlugin || typeof getPlugin !== 'function') {
79
- throw new RuniumError(
80
- 'Plugin module must have a default function',
81
- ErrorCode.PLUGIN_INCORRECT_MODULE,
82
- { path }
83
- );
84
- }
85
- const plugin = getPlugin();
86
-
87
- this.validate(plugin);
88
-
89
- this.plugins.set(plugin.name, plugin);
90
-
91
- return plugin.name;
92
- } catch (error) {
93
- if (isRuniumError(error)) {
94
- throw error;
95
- }
96
- throw new RuniumError(
97
- `Failed to load plugin "${path}"`,
98
- ErrorCode.PLUGIN_INCORRECT_PLUGIN,
99
- { path, original: error }
100
- );
101
- }
102
- }
103
-
104
- /**
105
- * Unload plugin
106
- * @param name
107
- */
108
- async unloadPlugin(name: string): Promise<boolean> {
109
- return this.plugins.delete(name);
110
- }
111
-
112
- /**
113
- * Resolve path
114
- * @param path
115
- * @param isFile
116
- */
117
- resolvePath(path: string, isFile: boolean = false): string {
118
- try {
119
- const resolvedPath = isFile ? resolve(path) : import.meta.resolve(path);
120
- return resolvedPath.replace('file://', '');
121
- } catch (error) {
122
- throw new RuniumError(
123
- `Failed to resolve plugin path "${path}"`,
124
- ErrorCode.PLUGIN_PATH_RESOLVE_ERROR,
125
- { path, original: error }
126
- );
127
- }
128
- }
129
-
130
- /**
131
- * Validate plugin
132
- * @param plugin
133
- */
134
- private validate(plugin: Plugin): void {
135
- // TODO add plugin validation
136
- if (!plugin || !plugin?.name) {
137
- throw new RuniumError(
138
- 'Incorrect plugin format',
139
- ErrorCode.PLUGIN_INCORRECT_PLUGIN,
140
- { name: plugin.name }
141
- );
142
- }
143
- }
144
- }
@@ -1,211 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { mkdir } from 'node:fs/promises';
3
- import { dirname, join } from 'node:path';
4
- import { Inject, Service } from 'typedi';
5
- import {
6
- JSONObject,
7
- readJsonFile,
8
- RuniumError,
9
- writeJsonFile,
10
- } from '@runium/core';
11
- import { ConfigService } from '@services';
12
- import { ErrorCode } from '@constants';
13
-
14
- export interface ProfilePlugin {
15
- name: string;
16
- path: string;
17
- file?: boolean;
18
- disabled?: boolean;
19
- options?: Record<string, unknown>;
20
- }
21
-
22
- export interface ProfileProject {
23
- name: string;
24
- path: string;
25
- }
26
-
27
- const PLUGINS_FILE_NAME = 'plugins.json';
28
- const PROJECTS_FILE_NAME = 'projects.json';
29
-
30
- @Service()
31
- export class ProfileService {
32
- private path: string = process.cwd();
33
-
34
- private plugins: ProfilePlugin[] = [];
35
-
36
- private projects: ProfileProject[] = [];
37
-
38
- constructor(@Inject() private configService: ConfigService) {}
39
-
40
- /**
41
- * Initialize the profile service
42
- */
43
- async init(): Promise<void> {
44
- this.path = this.configService.get('profile').path;
45
- if (!existsSync(this.path)) {
46
- await mkdir(this.path, { recursive: true });
47
- }
48
-
49
- await this.readPlugins();
50
- await this.readProjects();
51
- }
52
-
53
- /**
54
- * Get plugins
55
- */
56
- getPlugins(): ProfilePlugin[] {
57
- return this.plugins;
58
- }
59
-
60
- /**
61
- * Get plugin by name
62
- * @param name
63
- */
64
- getPluginByName(name: string): ProfilePlugin | undefined {
65
- return this.plugins.find(p => p.name === name);
66
- }
67
-
68
- /**
69
- * Add plugin
70
- * @param plugin
71
- */
72
- async addPlugin(plugin: ProfilePlugin): Promise<void> {
73
- this.plugins = this.plugins
74
- .filter(p => p.name !== plugin.name)
75
- .concat(plugin);
76
- await this.writePlugins();
77
- }
78
-
79
- /**
80
- * Update plugin
81
- * @param name
82
- */
83
- async removePlugin(name: string): Promise<void> {
84
- this.plugins = this.plugins.filter(plugin => plugin.name !== name);
85
- await this.writePlugins();
86
- }
87
-
88
- /**
89
- * Update plugin
90
- * @param name
91
- * @param data
92
- */
93
- async updatePlugin(
94
- name: string,
95
- data: Partial<Omit<ProfilePlugin, 'name'>>
96
- ): Promise<void> {
97
- const index = this.plugins.findIndex(plugin => plugin.name === name);
98
- if (index !== -1) {
99
- this.plugins[index] = {
100
- ...this.plugins[index],
101
- ...data,
102
- };
103
- await this.writePlugins();
104
- }
105
- }
106
-
107
- /**
108
- * Get projects
109
- */
110
- getProjects(): ProfileProject[] {
111
- return this.projects;
112
- }
113
-
114
- /**
115
- * Get project by name
116
- * @param name
117
- */
118
- getProjectByName(name: string): ProfileProject | undefined {
119
- return this.projects.find(p => p.name === name);
120
- }
121
-
122
- /**
123
- * Add project
124
- * @param project
125
- */
126
- async addProject(project: ProfileProject): Promise<void> {
127
- this.projects = this.projects
128
- .filter(p => p.name !== project.name)
129
- .concat(project);
130
- await this.writeProjects();
131
- }
132
-
133
- /**
134
- * Remove project
135
- * @param name
136
- */
137
- async removeProject(name: string): Promise<void> {
138
- this.projects = this.projects.filter(p => p.name !== name);
139
- await this.writeProjects();
140
- }
141
-
142
- /**
143
- * Read JSON file
144
- * @param pathParts
145
- */
146
- async readJsonFile(...pathParts: string[]): Promise<JSONObject> {
147
- return readJsonFile(this.getPath(...pathParts));
148
- }
149
-
150
- /**
151
- * Write JSON file
152
- * @param data
153
- * @param parts
154
- */
155
- async writeJsonFile(data: unknown, ...parts: string[]): Promise<void> {
156
- const path = this.getPath(...parts);
157
- try {
158
- const dirName = dirname(path);
159
- if (!existsSync(dirName)) {
160
- await mkdir(dirName, { recursive: true });
161
- }
162
- await writeJsonFile(path, data);
163
- } catch (error) {
164
- throw new RuniumError(
165
- `Failed to write JSON file`,
166
- ErrorCode.PROFILE_JSON_WRITE_ERROR,
167
- { path, data, original: error }
168
- );
169
- }
170
- }
171
- /**
172
- * Read JSON file
173
- * @param parts
174
- */
175
- private getPath(...parts: string[]): string {
176
- return join(this.path, ...parts);
177
- }
178
-
179
- /**
180
- * Read plugins from file
181
- */
182
- private async readPlugins(): Promise<void> {
183
- this.plugins =
184
- ((await readJsonFile(this.getPath(PLUGINS_FILE_NAME)).catch(
185
- () => []
186
- )) as ProfilePlugin[]) || this.plugins;
187
- }
188
-
189
- /**
190
- * Write plugins to file
191
- */
192
- private async writePlugins(): Promise<void> {
193
- await writeJsonFile(this.getPath(PLUGINS_FILE_NAME), this.plugins);
194
- }
195
- /**
196
- * Read projects from file
197
- */
198
- private async readProjects(): Promise<void> {
199
- this.projects =
200
- ((await readJsonFile(this.getPath(PROJECTS_FILE_NAME)).catch(
201
- () => []
202
- )) as ProfileProject[]) || this.projects;
203
- }
204
-
205
- /**
206
- * Write projects to file
207
- */
208
- private async writeProjects(): Promise<void> {
209
- await writeJsonFile(this.getPath(PROJECTS_FILE_NAME), this.projects);
210
- }
211
- }
@@ -1,114 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { readFile } from 'node:fs/promises';
3
- import { resolve } from 'node:path';
4
- import { Inject, Service } from 'typedi';
5
- import { applyMacros, Project, ProjectConfig, RuniumError } from '@runium/core';
6
- import { ErrorCode } from '@constants';
7
- import { macros } from '@macros';
8
- import { PluginProjectDefinition, PluginService } from '@services';
9
-
10
- @Service()
11
- export class ProjectService {
12
- constructor(@Inject() private pluginService: PluginService) {}
13
-
14
- /**
15
- * Init project
16
- * @param path
17
- */
18
- async initProject(path: string): Promise<Project> {
19
- const content = await this.readFile(path);
20
- const projectContent = this.applyMacros(content);
21
- const projectData = this.parseProjectContent(projectContent, path);
22
-
23
- const project = new Project(projectData);
24
- return this.extendProjectWithPlugins(project);
25
- }
26
-
27
- /**
28
- * Resolve path
29
- * @param path
30
- */
31
- resolvePath(path: string): string {
32
- return resolve(path);
33
- }
34
-
35
- /**
36
- * Read project file
37
- * @param path
38
- */
39
- private async readFile(path: string): Promise<string> {
40
- if (!existsSync(path)) {
41
- throw new RuniumError(
42
- `Project file "${path}" does not exist`,
43
- ErrorCode.PROJECT_FILE_NOT_FOUND,
44
- { path }
45
- );
46
- }
47
- try {
48
- return readFile(path, { encoding: 'utf-8' });
49
- } catch (error) {
50
- throw new RuniumError(
51
- `Failed to read project file "${path}"`,
52
- ErrorCode.PROJECT_FILE_CAN_NOT_READ,
53
- { path, original: error }
54
- );
55
- }
56
- }
57
-
58
- /**
59
- * Apply macros to text
60
- * @param text
61
- */
62
- private applyMacros(text: string): string {
63
- const plugins = this.pluginService.getAllPlugins();
64
- const pluginMacros = plugins.reduce(
65
- (acc, plugin) => ({ ...acc, ...(plugin.project?.macros || {}) }),
66
- {}
67
- );
68
- return applyMacros(text, { ...pluginMacros, ...macros });
69
- }
70
-
71
- /**
72
- * Parse project content
73
- * @param content
74
- * @param path
75
- */
76
- private parseProjectContent(content: string, path: string): ProjectConfig {
77
- try {
78
- return JSON.parse(content);
79
- } catch (error) {
80
- throw new RuniumError(
81
- `Failed to parse project "${path}"`,
82
- ErrorCode.PROJECT_JSON_PARSE_ERROR,
83
- { path, original: error }
84
- );
85
- }
86
- }
87
-
88
- /**
89
- * Extends the project with plugins
90
- * @param project
91
- */
92
- private extendProjectWithPlugins(project: Project): Project {
93
- const plugins = this.pluginService.getAllPlugins();
94
-
95
- plugins.forEach(plugin => {
96
- const { tasks, actions, triggers, validationSchema } = (plugin.project ||
97
- {}) as PluginProjectDefinition;
98
- Object.entries(actions || {}).forEach(([type, processor]) => {
99
- project.registerAction(type, processor);
100
- });
101
- Object.entries(tasks || {}).forEach(([type, processor]) => {
102
- project.registerTask(type, processor);
103
- });
104
- Object.entries(triggers || {}).forEach(([type, processor]) => {
105
- project.registerTrigger(type, processor);
106
- });
107
- if (validationSchema) {
108
- project.extendValidationSchema(validationSchema);
109
- }
110
- });
111
-
112
- return project;
113
- }
114
- }
@@ -1,130 +0,0 @@
1
- import { Inject, Service } from 'typedi';
2
- import { OutputService } from '@services';
3
-
4
- type ShutdownBlocker = () => Promise<void> | void;
5
-
6
- const TIMEOUT = 30000;
7
- const EXIT_DELAY = 250;
8
- const SIGNALS: NodeJS.Signals[] = ['SIGHUP', 'SIGINT', 'SIGTERM', 'SIGQUIT'];
9
-
10
- @Service()
11
- export class ShutdownService {
12
- private blockers: Set<ShutdownBlocker> = new Set();
13
- private isShuttingDown = false;
14
-
15
- constructor(@Inject() private outputService: OutputService) {}
16
- /**
17
- * Initialize shutdown handlers
18
- */
19
- async init(): Promise<void> {
20
- SIGNALS.forEach(signal => {
21
- process.on(signal, () => {
22
- this.shutdown(signal).catch(error => {
23
- this.outputService.error('Error during shutdown: %s', error.message);
24
- this.outputService.debug('Error details:', error);
25
- process.exit(1);
26
- });
27
- });
28
- });
29
-
30
- process.on('uncaughtException', error => {
31
- this.outputService.error('Uncaught exception: %s', error.message);
32
- this.outputService.debug('Error details:', error);
33
- this.shutdown('uncaughtException').catch(() => {
34
- process.exit(1);
35
- });
36
- });
37
-
38
- process.on('unhandledRejection', (reason, promise) => {
39
- this.outputService.error(
40
- 'Unhandled rejection at:',
41
- promise,
42
- 'reason:',
43
- reason
44
- );
45
- this.outputService.debug('Error details:', { reason, promise });
46
- this.shutdown('unhandledRejection').catch(() => {
47
- process.exit(1);
48
- });
49
- });
50
-
51
- process.on('beforeExit', () => {
52
- if (!this.isShuttingDown) {
53
- this.shutdown('exit').catch(() => {
54
- process.exit(1);
55
- });
56
- }
57
- });
58
- }
59
-
60
- /**
61
- * Add a shutdown blocker function
62
- * @param blocker
63
- */
64
- addBlocker(blocker: ShutdownBlocker): void {
65
- this.blockers.add(blocker);
66
- }
67
-
68
- /**
69
- * Remove a shutdown blocker
70
- * @param blocker
71
- */
72
- removeBlocker(blocker: ShutdownBlocker): boolean {
73
- return this.blockers.delete(blocker);
74
- }
75
-
76
- /**
77
- * Execute graceful shutdown
78
- * @param reason
79
- */
80
- async shutdown(reason?: string): Promise<void> {
81
- if (this.isShuttingDown || !reason) {
82
- return;
83
- }
84
-
85
- this.isShuttingDown = true;
86
-
87
- const exitProcess = (code: number): void => {
88
- setTimeout(() => {
89
- process.exit(code);
90
- }, EXIT_DELAY);
91
- };
92
-
93
- if (this.blockers.size === 0) {
94
- exitProcess(0);
95
- return;
96
- }
97
-
98
- try {
99
- await this.executeBlockersWithTimeout();
100
- exitProcess(0);
101
- } catch (error) {
102
- exitProcess(1);
103
- }
104
- }
105
-
106
- /**
107
- * Execute all blockers with timeout
108
- */
109
- private async executeBlockersWithTimeout(): Promise<void> {
110
- const blockerPromises = Array.from(this.blockers).map(blocker =>
111
- this.executeBlocker(blocker)
112
- );
113
-
114
- const timeoutPromise = new Promise<never>((_, reject) => {
115
- setTimeout(() => {
116
- reject(new Error(`Shutdown timeout after ${TIMEOUT}ms`));
117
- }, TIMEOUT);
118
- });
119
-
120
- await Promise.race([Promise.allSettled(blockerPromises), timeoutPromise]);
121
- }
122
-
123
- /**
124
- * Execute a single blocker with error handling
125
- * @param blocker
126
- */
127
- private async executeBlocker(blocker: ShutdownBlocker): Promise<void> {
128
- await blocker();
129
- }
130
- }
@@ -1,39 +0,0 @@
1
- const MAX_FILENAME_LENGTH = 200;
2
-
3
- /**
4
- * Converts a file path to a valid filename by replacing invalid characters
5
- * @param filePath
6
- * @param replacement
7
- */
8
- export function convertPathToValidFileName(
9
- filePath: string,
10
- replacement: string = '_'
11
- ): string {
12
- let filename = filePath.trim();
13
-
14
- // replace path separators (both forward and backward slashes)
15
- filename = filename.replace(/^\/+/, '');
16
- filename = filename.replace(/[/\\]/g, replacement);
17
-
18
- // replace invalid filename characters
19
- // Windows: < > : " | ? * and control characters (0-31)
20
- // also replacing common problematic characters
21
- // eslint-disable-next-line no-control-regex
22
- filename = filename.replace(/[<>:"|?*\x00-\x1F]/g, replacement);
23
-
24
- // remove leading/trailing dots and spaces (problematic on Windows)
25
- filename = filename.replace(/^[.\s]+|[.\s]+$/g, '');
26
-
27
- // replace multiple consecutive replacement characters with a single one
28
- const replacementRegex = new RegExp(
29
- `${replacement.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}+`,
30
- 'g'
31
- );
32
- filename = filename.replace(replacementRegex, replacement);
33
-
34
- if (filename.length > MAX_FILENAME_LENGTH) {
35
- filename = filename.substring(0, MAX_FILENAME_LENGTH);
36
- }
37
-
38
- return filename;
39
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * Create a debounced function
3
- *
4
- * @param func
5
- * @param wait
6
- */
7
- export function debounce<T extends (...args: unknown[]) => unknown>(
8
- func: T,
9
- wait: number
10
- ): (...args: Parameters<T>) => void {
11
- let timeoutId: NodeJS.Timeout | null = null;
12
-
13
- return function debounced(...args: Parameters<T>): void {
14
- if (timeoutId !== null) {
15
- clearTimeout(timeoutId);
16
- }
17
-
18
- timeoutId = setTimeout(() => {
19
- func(...args);
20
- timeoutId = null;
21
- }, wait);
22
- };
23
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Format a timestamp to 'yyyy-mm-dd hh:mm:ss' format
3
- * @param timestamp
4
- */
5
- export function formatTimestamp(timestamp: number | Date): string {
6
- const date = typeof timestamp === 'number' ? new Date(timestamp) : timestamp;
7
-
8
- const year = date.getFullYear();
9
- const month = String(date.getMonth() + 1).padStart(2, '0');
10
- const day = String(date.getDate()).padStart(2, '0');
11
- const hours = String(date.getHours()).padStart(2, '0');
12
- const minutes = String(date.getMinutes()).padStart(2, '0');
13
- const seconds = String(date.getSeconds()).padStart(2, '0');
14
- const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
15
-
16
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`;
17
- }
@@ -1,3 +0,0 @@
1
- export { convertPathToValidFileName } from './convert-path-to-valid-file-name.js';
2
- export { debounce } from './debounce.js';
3
- export { formatTimestamp } from './format-timestamp.js';