codify-plugin-lib 1.0.182-beta7 → 1.0.182-beta70
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/bin/build.js +189 -0
- package/dist/bin/build.js +0 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/messages/handlers.js +10 -2
- package/dist/plan/plan.js +7 -1
- package/dist/plugin/plugin.d.ts +2 -1
- package/dist/plugin/plugin.js +6 -1
- package/dist/pty/background-pty.d.ts +3 -2
- package/dist/pty/background-pty.js +7 -14
- package/dist/pty/index.d.ts +8 -2
- package/dist/pty/seqeuntial-pty.d.ts +3 -2
- package/dist/pty/seqeuntial-pty.js +47 -12
- package/dist/resource/parsed-resource-settings.d.ts +5 -2
- package/dist/resource/parsed-resource-settings.js +16 -2
- package/dist/resource/resource-controller.js +5 -5
- package/dist/resource/resource-settings.d.ts +13 -3
- package/dist/resource/resource-settings.js +2 -2
- package/dist/test.d.ts +1 -0
- package/dist/test.js +5 -0
- package/dist/utils/file-utils.d.ts +14 -7
- package/dist/utils/file-utils.js +65 -51
- package/dist/utils/functions.js +2 -2
- package/dist/utils/index.d.ts +21 -1
- package/dist/utils/index.js +160 -0
- package/dist/utils/load-resources.d.ts +1 -0
- package/dist/utils/load-resources.js +46 -0
- package/dist/utils/package-json-utils.d.ts +12 -0
- package/dist/utils/package-json-utils.js +34 -0
- package/package.json +5 -4
- package/rollup.config.js +24 -0
- package/src/index.ts +3 -0
- package/src/messages/handlers.test.ts +23 -0
- package/src/messages/handlers.ts +11 -2
- package/src/plan/plan.ts +11 -1
- package/src/plugin/plugin.test.ts +31 -0
- package/src/plugin/plugin.ts +8 -2
- package/src/pty/background-pty.ts +10 -18
- package/src/pty/index.ts +10 -4
- package/src/pty/seqeuntial-pty.ts +62 -16
- package/src/pty/sequential-pty.test.ts +137 -4
- package/src/resource/parsed-resource-settings.test.ts +24 -0
- package/src/resource/parsed-resource-settings.ts +26 -8
- package/src/resource/resource-controller.test.ts +126 -0
- package/src/resource/resource-controller.ts +5 -6
- package/src/resource/resource-settings.test.ts +36 -0
- package/src/resource/resource-settings.ts +17 -5
- package/src/utils/file-utils.test.ts +7 -0
- package/src/utils/file-utils.ts +70 -55
- package/src/utils/functions.ts +3 -3
- package/src/utils/index.ts +197 -1
- package/src/utils/internal-utils.test.ts +1 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JSONSchemaType } from 'ajv';
|
|
2
|
-
import { OS, StringIndexedObject } from 'codify-schemas';
|
|
2
|
+
import { LinuxDistro, OS, StringIndexedObject } from 'codify-schemas';
|
|
3
|
+
import { ZodObject, z } from 'zod';
|
|
3
4
|
|
|
4
5
|
import { StatefulParameterController } from '../stateful-parameter/stateful-parameter-controller.js';
|
|
5
6
|
import {
|
|
@@ -7,12 +8,12 @@ import {
|
|
|
7
8
|
DefaultParameterSetting,
|
|
8
9
|
InputTransformation,
|
|
9
10
|
ParameterSetting,
|
|
11
|
+
ResourceSettings,
|
|
12
|
+
StatefulParameterSetting,
|
|
10
13
|
resolveElementEqualsFn,
|
|
11
14
|
resolveEqualsFn,
|
|
12
15
|
resolveMatcher,
|
|
13
|
-
resolveParameterTransformFn
|
|
14
|
-
ResourceSettings,
|
|
15
|
-
StatefulParameterSetting
|
|
16
|
+
resolveParameterTransformFn
|
|
16
17
|
} from './resource-settings.js';
|
|
17
18
|
|
|
18
19
|
export interface ParsedStatefulParameterSetting extends DefaultParameterSetting {
|
|
@@ -29,7 +30,7 @@ export type ParsedArrayParameterSetting = {
|
|
|
29
30
|
|
|
30
31
|
export type ParsedParameterSetting =
|
|
31
32
|
{
|
|
32
|
-
|
|
33
|
+
isEqual: (desired: unknown, current: unknown) => boolean;
|
|
33
34
|
} & (DefaultParameterSetting
|
|
34
35
|
| ParsedArrayParameterSetting
|
|
35
36
|
| ParsedStatefulParameterSetting)
|
|
@@ -37,10 +38,13 @@ export type ParsedParameterSetting =
|
|
|
37
38
|
export class ParsedResourceSettings<T extends StringIndexedObject> implements ResourceSettings<T> {
|
|
38
39
|
private cache = new Map<string, unknown>();
|
|
39
40
|
id!: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
|
|
40
43
|
schema?: Partial<JSONSchemaType<T | any>>;
|
|
41
44
|
allowMultiple?: {
|
|
45
|
+
identifyingParameters?: string[];
|
|
42
46
|
matcher?: (desired: Partial<T>, current: Partial<T>) => boolean;
|
|
43
|
-
|
|
47
|
+
findAllParameters?: () => Promise<Array<Partial<T>>>
|
|
44
48
|
} | boolean;
|
|
45
49
|
|
|
46
50
|
removeStatefulParametersBeforeDestroy?: boolean | undefined;
|
|
@@ -48,16 +52,30 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
|
|
|
48
52
|
transformation?: InputTransformation;
|
|
49
53
|
|
|
50
54
|
operatingSystems!: Array<OS>;
|
|
55
|
+
linuxDistros?: Array<LinuxDistro>;
|
|
56
|
+
|
|
51
57
|
isSensitive?: boolean;
|
|
52
58
|
|
|
53
59
|
private settings: ResourceSettings<T>;
|
|
54
60
|
|
|
55
61
|
constructor(settings: ResourceSettings<T>) {
|
|
56
62
|
this.settings = settings;
|
|
63
|
+
const { parameterSettings, schema, ...rest } = settings;
|
|
57
64
|
|
|
58
|
-
const { parameterSettings, ...rest } = settings;
|
|
59
65
|
Object.assign(this, rest);
|
|
60
66
|
|
|
67
|
+
if (schema) {
|
|
68
|
+
this.schema = schema instanceof ZodObject
|
|
69
|
+
? z.toJSONSchema(schema.strict(), {
|
|
70
|
+
target: 'draft-7',
|
|
71
|
+
override(ctx) {
|
|
72
|
+
ctx.jsonSchema.title = settings.id;
|
|
73
|
+
ctx.jsonSchema.description = settings.description ?? `${settings.id} resource. Can be used to manage ${settings.id}`;
|
|
74
|
+
}
|
|
75
|
+
}) as JSONSchemaType<T>
|
|
76
|
+
: schema;
|
|
77
|
+
}
|
|
78
|
+
|
|
61
79
|
this.validateSettings();
|
|
62
80
|
}
|
|
63
81
|
|
|
@@ -199,7 +217,7 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
|
|
|
199
217
|
throw new Error(`Resource: ${this.id}. Stateful parameters are not allowed to be identifying parameters for allowMultiple.`)
|
|
200
218
|
}
|
|
201
219
|
|
|
202
|
-
const schema = this.
|
|
220
|
+
const schema = this.schema as JSONSchemaType<any>;
|
|
203
221
|
if (!this.settings.importAndDestroy && (schema?.oneOf
|
|
204
222
|
&& Array.isArray(schema.oneOf)
|
|
205
223
|
&& schema.oneOf.some((s) => s.required)
|
|
@@ -11,6 +11,7 @@ import { tildify, untildify } from '../utils/functions.js';
|
|
|
11
11
|
import { ArrayStatefulParameter, StatefulParameter } from '../stateful-parameter/stateful-parameter.js';
|
|
12
12
|
import { Plan } from '../plan/plan.js';
|
|
13
13
|
import os from 'node:os';
|
|
14
|
+
import { z } from 'zod';
|
|
14
15
|
|
|
15
16
|
describe('Resource tests', () => {
|
|
16
17
|
|
|
@@ -952,4 +953,129 @@ describe('Resource tests', () => {
|
|
|
952
953
|
|
|
953
954
|
process.env = oldProcessEnv;
|
|
954
955
|
})
|
|
956
|
+
|
|
957
|
+
it('Can import and return all of the imported parameters (zod schema)', async () => {
|
|
958
|
+
const schema = z.object({
|
|
959
|
+
path: z
|
|
960
|
+
.string()
|
|
961
|
+
.describe(
|
|
962
|
+
'A list of paths to add to the PATH environment variable'
|
|
963
|
+
),
|
|
964
|
+
paths: z
|
|
965
|
+
.array(z.string())
|
|
966
|
+
.describe(
|
|
967
|
+
'A list of paths to add to the PATH environment variable'
|
|
968
|
+
),
|
|
969
|
+
prepend: z
|
|
970
|
+
.boolean()
|
|
971
|
+
.describe(
|
|
972
|
+
'Whether to prepend the paths to the PATH environment variable'
|
|
973
|
+
),
|
|
974
|
+
declarationsOnly: z
|
|
975
|
+
.boolean()
|
|
976
|
+
.describe(
|
|
977
|
+
'Whether to only declare the paths in the PATH environment variable'
|
|
978
|
+
),
|
|
979
|
+
})
|
|
980
|
+
|
|
981
|
+
const resource = new class extends TestResource {
|
|
982
|
+
getSettings(): ResourceSettings<any> {
|
|
983
|
+
return {
|
|
984
|
+
id: 'path',
|
|
985
|
+
schema,
|
|
986
|
+
operatingSystems: [OS.Darwin],
|
|
987
|
+
parameterSettings: {
|
|
988
|
+
path: { type: 'directory' },
|
|
989
|
+
paths: { canModify: true, type: 'array', itemType: 'directory' },
|
|
990
|
+
prepend: { default: false, setting: true },
|
|
991
|
+
declarationsOnly: { default: false, setting: true },
|
|
992
|
+
},
|
|
993
|
+
importAndDestroy: {
|
|
994
|
+
refreshMapper: (input, context) => {
|
|
995
|
+
if (Object.keys(input).length === 0) {
|
|
996
|
+
return { paths: [], declarationsOnly: true };
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
return input;
|
|
1000
|
+
}
|
|
1001
|
+
},
|
|
1002
|
+
allowMultiple: {
|
|
1003
|
+
matcher: (desired, current) => {
|
|
1004
|
+
if (desired.path) {
|
|
1005
|
+
return desired.path === current.path;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
const currentPaths = new Set(current.paths)
|
|
1009
|
+
return desired.paths?.some((p) => currentPaths.has(p));
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
async refresh(parameters: Partial<TestConfig>): Promise<Partial<TestConfig> | null> {
|
|
1016
|
+
return {
|
|
1017
|
+
paths: [
|
|
1018
|
+
`${os.homedir()}/.pyenv/bin`,
|
|
1019
|
+
`${os.homedir()}/.bun/bin`,
|
|
1020
|
+
`${os.homedir()}/.deno/bin`,
|
|
1021
|
+
`${os.homedir()}/.jenv/bin`,
|
|
1022
|
+
`${os.homedir()}/a/random/path`,
|
|
1023
|
+
`${os.homedir()}/.nvm/.bin/2`,
|
|
1024
|
+
`${os.homedir()}/.nvm/.bin/3`
|
|
1025
|
+
]
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
const oldProcessEnv = structuredClone(process.env);
|
|
1031
|
+
|
|
1032
|
+
process.env['PYENV_ROOT'] = `${os.homedir()}/.pyenv`
|
|
1033
|
+
process.env['BUN_INSTALL'] = `${os.homedir()}/.bun`
|
|
1034
|
+
process.env['DENO_INSTALL'] = `${os.homedir()}/.deno`
|
|
1035
|
+
process.env['JENV'] = `${os.homedir()}/.jenv`
|
|
1036
|
+
process.env['NVM_DIR'] = `${os.homedir()}/.nvm`
|
|
1037
|
+
|
|
1038
|
+
const controller = new ResourceController(resource);
|
|
1039
|
+
const importResult1 = await controller.import({ type: 'path' }, {});
|
|
1040
|
+
expect(importResult1).toMatchObject([
|
|
1041
|
+
{
|
|
1042
|
+
'core': {
|
|
1043
|
+
'type': 'path'
|
|
1044
|
+
},
|
|
1045
|
+
'parameters': {
|
|
1046
|
+
'paths': [
|
|
1047
|
+
'$PYENV_ROOT/bin',
|
|
1048
|
+
'$BUN_INSTALL/bin',
|
|
1049
|
+
'$DENO_INSTALL/bin',
|
|
1050
|
+
'$JENV/bin',
|
|
1051
|
+
'~/a/random/path',
|
|
1052
|
+
'$NVM_DIR/.bin/2',
|
|
1053
|
+
'$NVM_DIR/.bin/3'
|
|
1054
|
+
]
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
])
|
|
1058
|
+
|
|
1059
|
+
const importResult2 = await controller.import({ type: 'path' }, { paths: ['$PYENV_ROOT/bin', '$BUN_INSTALL/bin'] });
|
|
1060
|
+
expect(importResult2).toMatchObject([
|
|
1061
|
+
{
|
|
1062
|
+
'core': {
|
|
1063
|
+
'type': 'path'
|
|
1064
|
+
},
|
|
1065
|
+
'parameters': {
|
|
1066
|
+
'paths': [
|
|
1067
|
+
'$PYENV_ROOT/bin',
|
|
1068
|
+
'$BUN_INSTALL/bin',
|
|
1069
|
+
'$DENO_INSTALL/bin',
|
|
1070
|
+
'$JENV/bin',
|
|
1071
|
+
'~/a/random/path',
|
|
1072
|
+
'$NVM_DIR/.bin/2',
|
|
1073
|
+
'$NVM_DIR/.bin/3'
|
|
1074
|
+
]
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
])
|
|
1078
|
+
|
|
1079
|
+
process.env = oldProcessEnv;
|
|
1080
|
+
})
|
|
955
1081
|
});
|
|
@@ -36,18 +36,17 @@ export class ResourceController<T extends StringIndexedObject> {
|
|
|
36
36
|
|
|
37
37
|
this.typeId = this.settings.id;
|
|
38
38
|
this.dependencies = this.settings.dependencies ?? [];
|
|
39
|
+
this.parsedSettings = new ParsedResourceSettings<T>(this.settings);
|
|
39
40
|
|
|
40
|
-
if (this.
|
|
41
|
+
if (this.parsedSettings.schema) {
|
|
41
42
|
this.ajv = new Ajv({
|
|
42
43
|
allErrors: true,
|
|
43
44
|
strict: true,
|
|
44
45
|
strictRequired: false,
|
|
45
46
|
allowUnionTypes: true
|
|
46
47
|
})
|
|
47
|
-
this.schemaValidator = this.ajv.compile(this.
|
|
48
|
+
this.schemaValidator = this.ajv.compile(this.parsedSettings.schema);
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
this.parsedSettings = new ParsedResourceSettings<T>(this.settings);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
async initialize(): Promise<void> {
|
|
@@ -526,8 +525,8 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
526
525
|
}
|
|
527
526
|
|
|
528
527
|
private getAllParameterKeys(): string[] {
|
|
529
|
-
return this.
|
|
530
|
-
? Object.keys((this.
|
|
528
|
+
return this.parsedSettings.schema
|
|
529
|
+
? Object.keys((this.parsedSettings.schema as any)?.properties)
|
|
531
530
|
: Object.keys(this.parsedSettings.parameterSettings);
|
|
532
531
|
}
|
|
533
532
|
|
|
@@ -13,6 +13,7 @@ import { ArrayParameterSetting, ParameterSetting, ResourceSettings } from './res
|
|
|
13
13
|
import { ResourceController } from './resource-controller.js';
|
|
14
14
|
import os from 'node:os';
|
|
15
15
|
import path from 'node:path';
|
|
16
|
+
import { z } from 'zod';
|
|
16
17
|
|
|
17
18
|
describe('Resource parameter tests', () => {
|
|
18
19
|
it('Generates a resource plan that includes stateful parameters (create)', async () => {
|
|
@@ -1174,4 +1175,39 @@ describe('Resource parameter tests', () => {
|
|
|
1174
1175
|
expect(from2).to.eq('$HOME/abc/def')
|
|
1175
1176
|
|
|
1176
1177
|
})
|
|
1178
|
+
|
|
1179
|
+
it('Can match directories 2', async () => {
|
|
1180
|
+
|
|
1181
|
+
const schema = z.object({
|
|
1182
|
+
propA: z.string(),
|
|
1183
|
+
propB: z.number(),
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
const resource = new class extends TestResource {
|
|
1187
|
+
getSettings(): ResourceSettings<z.infer<typeof schema>> {
|
|
1188
|
+
return {
|
|
1189
|
+
id: 'resourceType',
|
|
1190
|
+
schema,
|
|
1191
|
+
operatingSystems: [OS.Darwin],
|
|
1192
|
+
parameterSettings: {
|
|
1193
|
+
propA: { type: 'directory' }
|
|
1194
|
+
},
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
const controller = new ResourceController(resource);
|
|
1200
|
+
const transformations = controller.parsedSettings.inputTransformations.propA;
|
|
1201
|
+
|
|
1202
|
+
const to = transformations!.to('$HOME/abc/def')
|
|
1203
|
+
expect(to).to.eq(os.homedir() + '/abc/def')
|
|
1204
|
+
|
|
1205
|
+
const from = transformations!.from(os.homedir() + '/abc/def')
|
|
1206
|
+
expect(from).to.eq('~/abc/def')
|
|
1207
|
+
|
|
1208
|
+
const from2 = transformations!.from(os.homedir() + '/abc/def', '$HOME/abc/def')
|
|
1209
|
+
expect(from2).to.eq('$HOME/abc/def')
|
|
1210
|
+
|
|
1211
|
+
})
|
|
1212
|
+
|
|
1177
1213
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { JSONSchemaType } from 'ajv';
|
|
2
|
-
import { OS, StringIndexedObject } from 'codify-schemas';
|
|
2
|
+
import { LinuxDistro, OS, StringIndexedObject } from 'codify-schemas';
|
|
3
3
|
import isObjectsEqual from 'lodash.isequal'
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { ZodObject } from 'zod';
|
|
5
6
|
|
|
6
7
|
import { ArrayStatefulParameter, StatefulParameter } from '../stateful-parameter/stateful-parameter.js';
|
|
7
8
|
import {
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
tildify,
|
|
12
13
|
untildify
|
|
13
14
|
} from '../utils/functions.js';
|
|
15
|
+
import { ParsedResourceSettings } from './parsed-resource-settings.js';
|
|
14
16
|
import { RefreshContext } from './resource.js';
|
|
15
17
|
|
|
16
18
|
export interface InputTransformation {
|
|
@@ -33,10 +35,15 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
33
35
|
*/
|
|
34
36
|
operatingSystems: Array<OS>;
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* List of supported linux distros
|
|
40
|
+
*/
|
|
41
|
+
linuxDistros?: Array<LinuxDistro>;
|
|
42
|
+
|
|
36
43
|
/**
|
|
37
44
|
* Schema to validate user configs with. Must be in the format JSON Schema draft07
|
|
38
45
|
*/
|
|
39
|
-
schema?: Partial<JSONSchemaType<T | any
|
|
46
|
+
schema?: Partial<JSONSchemaType<T | any>> | ZodObject;
|
|
40
47
|
|
|
41
48
|
/**
|
|
42
49
|
* Mark the resource as sensitive. Defaults to false. This prevents the resource from automatically being imported by init and import.
|
|
@@ -44,6 +51,11 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
44
51
|
*/
|
|
45
52
|
isSensitive?: boolean;
|
|
46
53
|
|
|
54
|
+
/**
|
|
55
|
+
* An optional description of the resource. This does not affect the behavior of the resource.
|
|
56
|
+
*/
|
|
57
|
+
description?: string;
|
|
58
|
+
|
|
47
59
|
/**
|
|
48
60
|
* Allow multiple of the same resource to unique. Set truthy if
|
|
49
61
|
* multiples are allowed, for example for applications, there can be multiple copy of the same application installed
|
|
@@ -349,7 +361,7 @@ export interface StatefulParameterSetting extends DefaultParameterSetting {
|
|
|
349
361
|
|
|
350
362
|
const ParameterEqualsDefaults: Partial<Record<ParameterSettingType, (a: unknown, b: unknown) => boolean>> = {
|
|
351
363
|
'boolean': (a: unknown, b: unknown) => Boolean(a) === Boolean(b),
|
|
352
|
-
'directory'
|
|
364
|
+
'directory'(a: unknown, b: unknown) {
|
|
353
365
|
let transformedA = resolvePathWithVariables(untildify(String(a)))
|
|
354
366
|
let transformedB = resolvePathWithVariables(untildify(String(b)))
|
|
355
367
|
|
|
@@ -430,7 +442,7 @@ export function resolveFnFromEqualsFnOrString(
|
|
|
430
442
|
const ParameterTransformationDefaults: Partial<Record<ParameterSettingType, InputTransformation>> = {
|
|
431
443
|
'directory': {
|
|
432
444
|
to: (a: unknown) => resolvePathWithVariables((untildify(String(a)))),
|
|
433
|
-
from
|
|
445
|
+
from(a: unknown, original) {
|
|
434
446
|
if (ParameterEqualsDefaults.directory!(a, original)) {
|
|
435
447
|
return original;
|
|
436
448
|
}
|
|
@@ -489,7 +501,7 @@ export function resolveParameterTransformFn(
|
|
|
489
501
|
}
|
|
490
502
|
|
|
491
503
|
export function resolveMatcher<T extends StringIndexedObject>(
|
|
492
|
-
settings:
|
|
504
|
+
settings: ParsedResourceSettings<T>
|
|
493
505
|
): (desired: Partial<T>, current: Partial<T>) => boolean {
|
|
494
506
|
return typeof settings.allowMultiple === 'boolean' || !settings.allowMultiple?.matcher
|
|
495
507
|
? ((desired: Partial<T>, current: Partial<T>) => {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { describe, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
describe('File utils tests', { timeout: 100_000_000 }, () => {
|
|
4
|
+
it('Can download a file', async () => {
|
|
5
|
+
// await FileUtils.downloadFile('https://download.jetbrains.com/webstorm/WebStorm-2025.3.1-aarch64.dmg?_gl=1*1huoi7o*_gcl_aw*R0NMLjE3NjU3NDAwMTcuQ2p3S0NBaUEzZm5KQmhBZ0Vpd0F5cW1ZNVhLVENlbHJOcTk2YXdjZVlfMS1wdE91MXc0WDk2bFJkVDM3QURhUFNJMUtwNVVSVUhxWTJob0NuZ0FRQXZEX0J3RQ..*_gcl_au*MjA0MDQ0MjE2My4xNzYzNjQzNzMz*FPAU*MjA0MDQ0MjE2My4xNzYzNjQzNzMz*_ga*MTYxMDg4MTkzMi4xNzYzNjQzNzMz*_ga_9J976DJZ68*czE3NjYzNjI5ODAkbzEyJGcxJHQxNzY2MzYzMDQwJGo2MCRsMCRoMA..', path.join(process.cwd(), 'google.html'));
|
|
6
|
+
})
|
|
7
|
+
})
|
package/src/utils/file-utils.ts
CHANGED
|
@@ -25,7 +25,7 @@ export class FileUtils {
|
|
|
25
25
|
console.log(`Finished downloading to ${destination}`);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
static async
|
|
28
|
+
static async addToShellRc(line: string): Promise<void> {
|
|
29
29
|
const lineToInsert = addLeadingSpacer(
|
|
30
30
|
addTrailingSpacer(line)
|
|
31
31
|
);
|
|
@@ -45,7 +45,7 @@ export class FileUtils {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
static async
|
|
48
|
+
static async addAllToShellRc(lines: string[]): Promise<void> {
|
|
49
49
|
const formattedLines = '\n' + lines.join('\n') + '\n';
|
|
50
50
|
const shellRc = Utils.getPrimaryShellRc();
|
|
51
51
|
|
|
@@ -55,7 +55,17 @@ ${lines.join('\n')}`)
|
|
|
55
55
|
await fs.appendFile(shellRc, formattedLines)
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
/**
|
|
59
|
+
* This method adds a directory path to the shell rc file if it doesn't already exist.
|
|
60
|
+
*
|
|
61
|
+
* @param value - The directory path to add.
|
|
62
|
+
* @param prepend - Whether to prepend the path to the existing PATH variable.
|
|
63
|
+
*/
|
|
64
|
+
static async addPathToShellRc(value: string, prepend: boolean): Promise<void> {
|
|
65
|
+
if (await Utils.isDirectoryOnPath(value)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
59
69
|
const shellRc = Utils.getPrimaryShellRc();
|
|
60
70
|
console.log(`Saving path: ${value} to ${shellRc}`);
|
|
61
71
|
|
|
@@ -67,56 +77,6 @@ ${lines.join('\n')}`)
|
|
|
67
77
|
await fs.appendFile(shellRc, `\nexport PATH=${value}:$PATH;`, { encoding: 'utf8' });
|
|
68
78
|
}
|
|
69
79
|
|
|
70
|
-
static async dirExists(path: string): Promise<boolean> {
|
|
71
|
-
let stat;
|
|
72
|
-
try {
|
|
73
|
-
stat = await fs.stat(path);
|
|
74
|
-
return stat.isDirectory();
|
|
75
|
-
} catch {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
static async fileExists(path: string): Promise<boolean> {
|
|
81
|
-
let stat;
|
|
82
|
-
try {
|
|
83
|
-
stat = await fs.stat(path);
|
|
84
|
-
return stat.isFile();
|
|
85
|
-
} catch {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
static async exists(path: string): Promise<boolean> {
|
|
91
|
-
try {
|
|
92
|
-
await fs.stat(path);
|
|
93
|
-
return true;
|
|
94
|
-
} catch {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
static async checkDirExistsOrThrowIfFile(path: string): Promise<boolean> {
|
|
100
|
-
let stat;
|
|
101
|
-
try {
|
|
102
|
-
stat = await fs.stat(path);
|
|
103
|
-
} catch {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (stat.isDirectory()) {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
throw new Error(`Directory ${path} already exists and is a file`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
static async createDirIfNotExists(path: string): Promise<void> {
|
|
115
|
-
if (!fsSync.existsSync(path)) {
|
|
116
|
-
await fs.mkdir(path, { recursive: true });
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
80
|
static async removeFromFile(filePath: string, search: string): Promise<void> {
|
|
121
81
|
const contents = await fs.readFile(filePath, 'utf8');
|
|
122
82
|
const newContents = contents.replaceAll(search, '');
|
|
@@ -124,7 +84,6 @@ ${lines.join('\n')}`)
|
|
|
124
84
|
await fs.writeFile(filePath, newContents, 'utf8');
|
|
125
85
|
}
|
|
126
86
|
|
|
127
|
-
|
|
128
87
|
static async removeLineFromFile(filePath: string, search: RegExp | string): Promise<void> {
|
|
129
88
|
const file = await fs.readFile(filePath, 'utf8')
|
|
130
89
|
const lines = file.split('\n');
|
|
@@ -168,10 +127,16 @@ ${lines.join('\n')}`)
|
|
|
168
127
|
console.log(`Removed line: ${search} from ${filePath}`)
|
|
169
128
|
}
|
|
170
129
|
|
|
171
|
-
static async
|
|
130
|
+
static async removeLineFromShellRc(search: RegExp | string): Promise<void> {
|
|
172
131
|
return FileUtils.removeLineFromFile(Utils.getPrimaryShellRc(), search);
|
|
173
132
|
}
|
|
174
133
|
|
|
134
|
+
static async removeAllLinesFromShellRc(searches: Array<RegExp | string>): Promise<void> {
|
|
135
|
+
for (const search of searches) {
|
|
136
|
+
await FileUtils.removeLineFromFile(Utils.getPrimaryShellRc(), search);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
175
140
|
// Append the string to the end of a file ensuring at least 1 lines of space between.
|
|
176
141
|
// Ex result:
|
|
177
142
|
// something something;
|
|
@@ -190,6 +155,56 @@ ${lines.join('\n')}`)
|
|
|
190
155
|
return lines.join('\n') + '\n'.repeat(numNewLines) + textToInsert
|
|
191
156
|
}
|
|
192
157
|
|
|
158
|
+
static async dirExists(path: string): Promise<boolean> {
|
|
159
|
+
let stat;
|
|
160
|
+
try {
|
|
161
|
+
stat = await fs.stat(path);
|
|
162
|
+
return stat.isDirectory();
|
|
163
|
+
} catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static async fileExists(path: string): Promise<boolean> {
|
|
169
|
+
let stat;
|
|
170
|
+
try {
|
|
171
|
+
stat = await fs.stat(path);
|
|
172
|
+
return stat.isFile();
|
|
173
|
+
} catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
static async exists(path: string): Promise<boolean> {
|
|
179
|
+
try {
|
|
180
|
+
await fs.stat(path);
|
|
181
|
+
return true;
|
|
182
|
+
} catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static async checkDirExistsOrThrowIfFile(path: string): Promise<boolean> {
|
|
188
|
+
let stat;
|
|
189
|
+
try {
|
|
190
|
+
stat = await fs.stat(path);
|
|
191
|
+
} catch {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (stat.isDirectory()) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
throw new Error(`Directory ${path} already exists and is a file`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static async createDirIfNotExists(path: string): Promise<void> {
|
|
203
|
+
if (!fsSync.existsSync(path)) {
|
|
204
|
+
await fs.mkdir(path, { recursive: true });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
193
208
|
// This is overly complicated but it can be used to insert into any
|
|
194
209
|
// position in the future
|
|
195
210
|
private static calculateEndingNewLines(lines: string[]): number {
|
package/src/utils/functions.ts
CHANGED
|
@@ -9,10 +9,11 @@ export function splitUserConfig<T extends StringIndexedObject>(
|
|
|
9
9
|
type: config.type,
|
|
10
10
|
...(config.name ? { name: config.name } : {}),
|
|
11
11
|
...(config.dependsOn ? { dependsOn: config.dependsOn } : {}),
|
|
12
|
+
...(config.os ? { os: config.os } : {}),
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
15
|
-
const { type, name, dependsOn, ...parameters } = config;
|
|
16
|
+
const { type, name, dependsOn, os, ...parameters } = config;
|
|
16
17
|
|
|
17
18
|
return {
|
|
18
19
|
parameters: parameters as T,
|
|
@@ -35,8 +36,7 @@ export function tildify(pathWithTilde: string) {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export function resolvePathWithVariables(pathWithVariables: string) {
|
|
38
|
-
|
|
39
|
-
return pathWithVariables.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b])
|
|
39
|
+
return pathWithVariables.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b]!)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export function addVariablesToPath(pathWithoutVariables: string) {
|