@runium/cli 0.0.3 → 0.0.4

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 (106) hide show
  1. package/{lib/commands → commands}/index.js +0 -0
  2. package/{lib/constants → constants}/index.js +0 -0
  3. package/{lib/macros → macros}/index.js +0 -0
  4. package/package.json +6 -31
  5. package/{lib/services → services}/index.js +0 -0
  6. package/{lib/utils → utils}/index.js +0 -0
  7. package/{lib/validation → validation}/index.js +0 -0
  8. package/.eslintrc.json +0 -31
  9. package/.prettierrc.json +0 -10
  10. package/README.md +0 -3
  11. package/build.js +0 -125
  12. package/lib/package.json +0 -22
  13. package/src/app.ts +0 -190
  14. package/src/commands/index.ts +0 -2
  15. package/src/commands/plugin/plugin-add.ts +0 -48
  16. package/src/commands/plugin/plugin-command.ts +0 -36
  17. package/src/commands/plugin/plugin-disable.ts +0 -46
  18. package/src/commands/plugin/plugin-enable.ts +0 -50
  19. package/src/commands/plugin/plugin-list.ts +0 -61
  20. package/src/commands/plugin/plugin-remove.ts +0 -42
  21. package/src/commands/plugin/plugin.ts +0 -36
  22. package/src/commands/project/project-add.ts +0 -64
  23. package/src/commands/project/project-command.ts +0 -43
  24. package/src/commands/project/project-list.ts +0 -32
  25. package/src/commands/project/project-remove.ts +0 -41
  26. package/src/commands/project/project-start.ts +0 -158
  27. package/src/commands/project/project-state-command.ts +0 -53
  28. package/src/commands/project/project-status.ts +0 -116
  29. package/src/commands/project/project-stop.ts +0 -59
  30. package/src/commands/project/project-validate.ts +0 -56
  31. package/src/commands/project/project.ts +0 -40
  32. package/src/commands/runium-command.ts +0 -52
  33. package/src/constants/error-code.ts +0 -28
  34. package/src/constants/index.ts +0 -1
  35. package/src/global.d.ts +0 -6
  36. package/src/index.ts +0 -24
  37. package/src/macros/conditional.ts +0 -31
  38. package/src/macros/date.ts +0 -15
  39. package/src/macros/empty.ts +0 -6
  40. package/src/macros/env.ts +0 -8
  41. package/src/macros/index.ts +0 -17
  42. package/src/macros/path.ts +0 -24
  43. package/src/services/command.ts +0 -171
  44. package/src/services/config.ts +0 -119
  45. package/src/services/file.ts +0 -272
  46. package/src/services/index.ts +0 -9
  47. package/src/services/output.ts +0 -205
  48. package/src/services/plugin-context.ts +0 -140
  49. package/src/services/plugin.ts +0 -248
  50. package/src/services/profile.ts +0 -199
  51. package/src/services/project.ts +0 -142
  52. package/src/services/shutdown.ts +0 -147
  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/get-version.ts +0 -13
  57. package/src/utils/index.ts +0 -4
  58. package/src/validation/create-validator.ts +0 -27
  59. package/src/validation/get-config-schema.ts +0 -59
  60. package/src/validation/get-error-messages.ts +0 -35
  61. package/src/validation/get-plugin-schema.ts +0 -137
  62. package/src/validation/index.ts +0 -4
  63. package/tsconfig.json +0 -38
  64. /package/{lib/app.js → app.js} +0 -0
  65. /package/{lib/commands → commands}/plugin/plugin-add.js +0 -0
  66. /package/{lib/commands → commands}/plugin/plugin-command.js +0 -0
  67. /package/{lib/commands → commands}/plugin/plugin-disable.js +0 -0
  68. /package/{lib/commands → commands}/plugin/plugin-enable.js +0 -0
  69. /package/{lib/commands → commands}/plugin/plugin-list.js +0 -0
  70. /package/{lib/commands → commands}/plugin/plugin-remove.js +0 -0
  71. /package/{lib/commands → commands}/plugin/plugin.js +0 -0
  72. /package/{lib/commands → commands}/project/project-add.js +0 -0
  73. /package/{lib/commands → commands}/project/project-command.js +0 -0
  74. /package/{lib/commands → commands}/project/project-list.js +0 -0
  75. /package/{lib/commands → commands}/project/project-remove.js +0 -0
  76. /package/{lib/commands → commands}/project/project-start.js +0 -0
  77. /package/{lib/commands → commands}/project/project-state-command.js +0 -0
  78. /package/{lib/commands → commands}/project/project-status.js +0 -0
  79. /package/{lib/commands → commands}/project/project-stop.js +0 -0
  80. /package/{lib/commands → commands}/project/project-validate.js +0 -0
  81. /package/{lib/commands → commands}/project/project.js +0 -0
  82. /package/{lib/commands → commands}/runium-command.js +0 -0
  83. /package/{lib/constants → constants}/error-code.js +0 -0
  84. /package/{lib/index.js → index.js} +0 -0
  85. /package/{lib/macros → macros}/conditional.js +0 -0
  86. /package/{lib/macros → macros}/date.js +0 -0
  87. /package/{lib/macros → macros}/empty.js +0 -0
  88. /package/{lib/macros → macros}/env.js +0 -0
  89. /package/{lib/macros → macros}/path.js +0 -0
  90. /package/{lib/services → services}/command.js +0 -0
  91. /package/{lib/services → services}/config.js +0 -0
  92. /package/{lib/services → services}/file.js +0 -0
  93. /package/{lib/services → services}/output.js +0 -0
  94. /package/{lib/services → services}/plugin-context.js +0 -0
  95. /package/{lib/services → services}/plugin.js +0 -0
  96. /package/{lib/services → services}/profile.js +0 -0
  97. /package/{lib/services → services}/project.js +0 -0
  98. /package/{lib/services → services}/shutdown.js +0 -0
  99. /package/{lib/utils → utils}/convert-path-to-valid-file-name.js +0 -0
  100. /package/{lib/utils → utils}/debounce.js +0 -0
  101. /package/{lib/utils → utils}/format-timestamp.js +0 -0
  102. /package/{lib/utils → utils}/get-version.js +0 -0
  103. /package/{lib/validation → validation}/create-validator.js +0 -0
  104. /package/{lib/validation → validation}/get-config-schema.js +0 -0
  105. /package/{lib/validation → validation}/get-error-messages.js +0 -0
  106. /package/{lib/validation → validation}/get-plugin-schema.js +0 -0
@@ -1,147 +0,0 @@
1
- import { Inject, Service } from 'typedi';
2
- import { OutputService, PluginService } from '@services';
3
-
4
- type ShutdownBlocker = (reason?: string) => 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(
16
- @Inject() private outputService: OutputService,
17
- @Inject() private pluginService: PluginService
18
- ) {}
19
- /**
20
- * Initialize shutdown handlers
21
- */
22
- async init(): Promise<void> {
23
- SIGNALS.forEach(signal => {
24
- process.on(signal, () => {
25
- this.shutdown(signal).catch(error => {
26
- this.outputService.error('Error during shutdown: %s', error.message);
27
- this.outputService.debug('Error details:', error);
28
- process.exit(1);
29
- });
30
- });
31
- });
32
-
33
- process.on('uncaughtException', error => {
34
- this.outputService.error('Uncaught exception: %s', error.message);
35
- this.outputService.debug('Error details:', error);
36
- this.shutdown('uncaughtException').catch(() => {
37
- process.exit(1);
38
- });
39
- });
40
-
41
- process.on('unhandledRejection', (reason, promise) => {
42
- this.outputService.error(
43
- 'Unhandled rejection at:',
44
- promise,
45
- 'reason:',
46
- reason
47
- );
48
- this.outputService.debug('Error details:', { reason, promise });
49
- this.shutdown('unhandledRejection').catch(() => {
50
- process.exit(1);
51
- });
52
- });
53
-
54
- process.on('beforeExit', () => {
55
- if (!this.isShuttingDown) {
56
- this.shutdown('exit').catch(() => {
57
- process.exit(1);
58
- });
59
- }
60
- });
61
- }
62
-
63
- /**
64
- * Add a shutdown blocker function
65
- * @param blocker
66
- */
67
- addBlocker(blocker: ShutdownBlocker): void {
68
- this.blockers.add(blocker);
69
- }
70
-
71
- /**
72
- * Remove a shutdown blocker
73
- * @param blocker
74
- */
75
- removeBlocker(blocker: ShutdownBlocker): boolean {
76
- return this.blockers.delete(blocker);
77
- }
78
-
79
- /**
80
- * Execute graceful shutdown
81
- * @param reason
82
- */
83
- async shutdown(reason?: string): Promise<void> {
84
- if (this.isShuttingDown || !reason) {
85
- return;
86
- }
87
-
88
- // add plugin beforeExit hooks as shutdown blockers
89
- const plugins = this.pluginService.getAllPlugins();
90
- for (const plugin of plugins) {
91
- const hook = plugin.hooks?.app?.beforeExit;
92
- if (hook) {
93
- this.addBlocker(hook.bind(plugin, reason));
94
- }
95
- }
96
-
97
- this.isShuttingDown = true;
98
-
99
- const exitProcess = (code: number): void => {
100
- setTimeout(() => {
101
- process.exit(code);
102
- }, EXIT_DELAY);
103
- };
104
-
105
- if (this.blockers.size === 0) {
106
- exitProcess(0);
107
- return;
108
- }
109
-
110
- try {
111
- await this.executeBlockersWithTimeout(reason);
112
- exitProcess(0);
113
- } catch (error) {
114
- exitProcess(1);
115
- }
116
- }
117
-
118
- /**
119
- * Execute all blockers with timeout
120
- * @param reason
121
- */
122
- private async executeBlockersWithTimeout(reason: string): Promise<void> {
123
- const blockerPromises = Array.from(this.blockers).map(blocker =>
124
- this.executeBlocker(blocker, reason)
125
- );
126
-
127
- const timeoutPromise = new Promise<never>((_, reject) => {
128
- setTimeout(() => {
129
- reject(new Error(`Shutdown timeout after ${TIMEOUT}ms`));
130
- }, TIMEOUT);
131
- });
132
-
133
- await Promise.race([Promise.allSettled(blockerPromises), timeoutPromise]);
134
- }
135
-
136
- /**
137
- * Execute a single blocker with error handling
138
- * @param blocker
139
- * @param reason
140
- */
141
- private async executeBlocker(
142
- blocker: ShutdownBlocker,
143
- reason: string
144
- ): Promise<void> {
145
- await blocker(reason);
146
- }
147
- }
@@ -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,13 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
-
4
- let version: string | null = null;
5
-
6
- export function getVersion(): string {
7
- if (!version) {
8
- const packageJsonPath = resolve(import.meta.dirname, '..', 'package.json');
9
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
10
- version = packageJson.version;
11
- }
12
- return version as string;
13
- }
@@ -1,4 +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';
4
- export { getVersion } from './get-version.js';
@@ -1,27 +0,0 @@
1
- import Ajv, { ValidateFunction } from 'ajv/dist/2020.js';
2
-
3
- const classes = { Function: Function };
4
-
5
- export type Validator<T = unknown> = ValidateFunction<T>;
6
-
7
- /**
8
- * Create validator
9
- * @param schema
10
- */
11
- export function createValidator<T = unknown>(schema: object): Validator<T> {
12
- const ajv = new Ajv({
13
- allowUnionTypes: true,
14
- allErrors: true,
15
- verbose: true,
16
- });
17
-
18
- ajv.addKeyword({
19
- keyword: 'instanceof',
20
- schemaType: 'string',
21
- validate: (schema: string, data: unknown) => {
22
- return data instanceof classes[schema as keyof typeof classes];
23
- },
24
- });
25
-
26
- return ajv.compile<T>(schema);
27
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Get config schema
3
- */
4
- export function getConfigSchema(): object {
5
- return {
6
- $schema: 'https://json-schema.org/draft/2020-12/schema',
7
- $id: 'https://runium.dev/schemas/config.json',
8
- title: 'Runium Config',
9
- type: 'object',
10
- properties: {
11
- env: {
12
- type: 'object',
13
- properties: {
14
- path: {
15
- type: 'array',
16
- items: {
17
- type: 'string',
18
- },
19
- },
20
- },
21
- additionalProperties: false,
22
- },
23
- output: {
24
- type: 'object',
25
- properties: {
26
- debug: {
27
- type: 'boolean',
28
- },
29
- },
30
- additionalProperties: false,
31
- },
32
- profile: {
33
- type: 'object',
34
- properties: {
35
- path: {
36
- type: 'string',
37
- },
38
- },
39
- additionalProperties: false,
40
- },
41
- plugins: {
42
- type: 'object',
43
- additionalProperties: {
44
- type: 'object',
45
- properties: {
46
- disabled: {
47
- type: 'boolean',
48
- },
49
- options: {
50
- type: 'object',
51
- },
52
- },
53
- additionalProperties: false,
54
- },
55
- },
56
- },
57
- additionalProperties: false,
58
- };
59
- }
@@ -1,35 +0,0 @@
1
- import { ErrorObject } from 'ajv';
2
- import { AggregateAjvError, Options } from '@segment/ajv-human-errors';
3
- import { AjvError } from '@segment/ajv-human-errors/dist/cjs/aggregate-ajv-error';
4
-
5
- interface GetErrorMessagesOptions extends Options {
6
- filter?: (error: AjvError) => boolean;
7
- }
8
-
9
- /**
10
- * Get error messages
11
- * @param errors
12
- * @param options
13
- */
14
- export function getErrorMessages(
15
- errors: ErrorObject[],
16
- options: GetErrorMessagesOptions = {
17
- filter: () => true,
18
- }
19
- ): string[] {
20
- const humanErrors = new AggregateAjvError(errors, {
21
- fieldLabels: 'jsonPath',
22
- includeData: true,
23
- includeOriginalError: true,
24
- });
25
-
26
- const filter = options?.filter ?? (_ => true);
27
- const messages = [];
28
- for (const error of humanErrors) {
29
- if (filter(error)) {
30
- messages.push(error.message);
31
- }
32
- }
33
-
34
- return messages;
35
- }
@@ -1,137 +0,0 @@
1
- import { ID_REGEX } from '@runium/core';
2
-
3
- /**
4
- * Get plugin schema with function validation
5
- */
6
- export function getPluginSchema(): object {
7
- return {
8
- $schema: 'https://json-schema.org/draft/2020-12/schema',
9
- $id: 'https://runium.dev/schemas/plugin.json',
10
- title: 'Runium Plugin',
11
- type: 'object',
12
- properties: {
13
- name: {
14
- type: 'string',
15
- minLength: 2,
16
- pattern: ID_REGEX.source,
17
- },
18
- options: {
19
- type: 'object',
20
- description: 'Plugin configuration options',
21
- },
22
- project: {
23
- type: 'object',
24
- description: 'Project-level plugin definitions',
25
- properties: {
26
- macros: {
27
- type: 'object',
28
- description: 'Macro definitions for config file expansion',
29
- additionalProperties: {
30
- instanceof: 'Function',
31
- },
32
- },
33
- tasks: {
34
- type: 'object',
35
- description: 'Task constructor definitions',
36
- additionalProperties: {
37
- instanceof: 'Function',
38
- },
39
- },
40
- actions: {
41
- type: 'object',
42
- description: 'Action function definitions',
43
- additionalProperties: {
44
- instanceof: 'Function',
45
- },
46
- },
47
- triggers: {
48
- type: 'object',
49
- description: 'Trigger constructor definitions',
50
- additionalProperties: {
51
- instanceof: 'Function',
52
- },
53
- },
54
- validationSchema: {
55
- type: 'object',
56
- description: 'JSON Schema extension for project config validation',
57
- additionalProperties: true,
58
- },
59
- },
60
- additionalProperties: false,
61
- },
62
- app: {
63
- type: 'object',
64
- description: 'Application-level plugin definitions',
65
- properties: {
66
- commands: {
67
- type: 'array',
68
- description: 'Command constructor definitions',
69
- items: {
70
- instanceof: 'Function',
71
- },
72
- },
73
- },
74
- additionalProperties: false,
75
- },
76
- hooks: {
77
- type: 'object',
78
- description: 'Lifecycle hooks for app and project events',
79
- properties: {
80
- app: {
81
- type: 'object',
82
- description: 'Application lifecycle hooks',
83
- properties: {
84
- afterInit: {
85
- instanceof: 'Function',
86
- description: 'Hook called after app initialization',
87
- },
88
- beforeExit: {
89
- instanceof: 'Function',
90
- description: 'Hook called before app exit',
91
- },
92
- beforeCommandRun: {
93
- instanceof: 'Function',
94
- description: 'Hook called before command execution',
95
- },
96
- afterCommandRun: {
97
- instanceof: 'Function',
98
- description: 'Hook called after command execution',
99
- },
100
- },
101
- additionalProperties: false,
102
- },
103
- project: {
104
- type: 'object',
105
- description: 'Project lifecycle hooks',
106
- properties: {
107
- beforeConfigRead: {
108
- instanceof: 'Function',
109
- description: 'Hook called before reading config file',
110
- },
111
- afterConfigRead: {
112
- instanceof: 'Function',
113
- description: 'Hook called after reading config file content',
114
- },
115
- afterConfigMacrosApply: {
116
- instanceof: 'Function',
117
- description: 'Hook called after applying macros to config',
118
- },
119
- afterConfigParse: {
120
- instanceof: 'Function',
121
- description: 'Hook called after parsing config',
122
- },
123
- beforeStart: {
124
- instanceof: 'Function',
125
- description: 'Hook called before project starts',
126
- },
127
- },
128
- additionalProperties: false,
129
- },
130
- },
131
- additionalProperties: false,
132
- },
133
- },
134
- required: ['name'],
135
- additionalProperties: false,
136
- };
137
- }
@@ -1,4 +0,0 @@
1
- export { createValidator } from './create-validator.js';
2
- export { getConfigSchema } from './get-config-schema.js';
3
- export { getErrorMessages } from './get-error-messages.js';
4
- export { getPluginSchema } from './get-plugin-schema.js';
package/tsconfig.json DELETED
@@ -1,38 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "baseUrl": ".",
4
- "target": "esnext",
5
- "outDir": "./lib",
6
- "rootDir": "src",
7
- "strict": true,
8
- "esModuleInterop": true,
9
- "skipLibCheck": true,
10
- "module": "esnext",
11
- "moduleResolution": "bundler",
12
- "forceConsistentCasingInFileNames": true,
13
- "declaration": false,
14
- "sourceMap": false,
15
- "strictNullChecks": true,
16
- "removeComments": true,
17
- "emitDecoratorMetadata": true,
18
- "experimentalDecorators": true,
19
- "allowSyntheticDefaultImports": true,
20
- "paths": {
21
- "@commands/*": ["src/commands/*"],
22
- "@commands": ["src/commands/index.js"],
23
- "@constants/*": ["src/constants/*"],
24
- "@constants": ["src/constants/index.js"],
25
- "@macros/*": ["src/macros/*"],
26
- "@macros": ["src/macros/index.js"],
27
- "@services/*": ["src/services/*"],
28
- "@services": ["src/services/index.js"],
29
- "@utils/*": ["src/utils/*"],
30
- "@utils": ["src/utils/index.js"],
31
- "@validation/*": ["src/validation/*"],
32
- "@validation": ["src/validation/index.js"]
33
- },
34
- "types": ["node", "@runium/types-core"]
35
- },
36
- "include": ["src/**/*"],
37
- "exclude": ["lib/**/*"]
38
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes