@stryke/fs 0.23.3 → 0.24.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/dist/install.cjs CHANGED
@@ -3,20 +3,22 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.packageExists = exports.install = void 0;
6
+ exports.install = install;
7
+ exports.packageExists = void 0;
7
8
  var _installPkg = require("@antfu/install-pkg");
8
9
  var _resolve = require("@stryke/path/resolve");
9
10
  require("tinyexec");
10
- const install = async (t, a) => (0, _installPkg.installPackage)(t, a),
11
- packageExists = async (t, a) => {
12
- const r = await (0, _resolve.resolve)(a?.cwd || process.cwd());
13
- try {
14
- await (0, _resolve.resolve)(t, {
15
- paths: [r]
16
- });
17
- } catch {
18
- await install(t, a);
19
- }
20
- };
21
- exports.packageExists = packageExists;
22
- exports.install = install;
11
+ async function install(t, a) {
12
+ return (0, _installPkg.installPackage)(t, a);
13
+ }
14
+ const packageExists = async (t, a) => {
15
+ const s = await (0, _resolve.resolve)(a?.cwd || process.cwd());
16
+ try {
17
+ await (0, _resolve.resolve)(t, {
18
+ paths: [s]
19
+ });
20
+ } catch {
21
+ await install(t, a);
22
+ }
23
+ };
24
+ exports.packageExists = packageExists;
package/dist/install.d.ts CHANGED
@@ -1,13 +1,20 @@
1
1
  import type { InstallPackageOptions } from "@antfu/install-pkg";
2
+ import { installPackage } from "@antfu/install-pkg";
2
3
  import "tinyexec";
3
4
  /**
4
- * Install a package
5
+ * Install a specific package
5
6
  *
6
7
  * @param name - The name of the package to install
7
8
  * @param options - The options to use when installing the package
8
- * @returns The result of the command or an exception
9
9
  */
10
- export declare const install: (names: string | string[], options?: InstallPackageOptions) => Promise<import("tinyexec").Output>;
10
+ export declare function install(name: string, options?: InstallPackageOptions): Promise<ReturnType<typeof installPackage>>;
11
+ /**
12
+ * Install a list of packages
13
+ *
14
+ * @param names - The list of package names to install
15
+ * @param options - The options to use when installing the package
16
+ */
17
+ export declare function install(names: string[], options?: InstallPackageOptions): Promise<ReturnType<typeof installPackage>>;
11
18
  /**
12
19
  * Check if a package exists and install it if it does not
13
20
  *
package/dist/install.mjs CHANGED
@@ -1 +1 @@
1
- import{installPackage as n}from"@antfu/install-pkg";import{resolve as s}from"@stryke/path/resolve";import"tinyexec";export const install=async(t,a)=>n(t,a),packageExists=async(t,a)=>{const r=await s(a?.cwd||process.cwd());try{await s(t,{paths:[r]})}catch{await install(t,a)}};
1
+ import{installPackage as e}from"@antfu/install-pkg";import{resolve as n}from"@stryke/path/resolve";import"tinyexec";export async function install(t,a){return e(t,a)}export const packageExists=async(t,a)=>{const s=await n(a?.cwd||process.cwd());try{await n(t,{paths:[s]})}catch{await install(t,a)}};
@@ -12,12 +12,14 @@ var _path = require("@stryke/path");
12
12
  var _getParentPath = require("@stryke/path/get-parent-path");
13
13
  var _getWorkspaceRoot = require("@stryke/path/get-workspace-root");
14
14
  var _resolve = require("@stryke/path/resolve");
15
+ var _isString = require("@stryke/type-checks/is-string");
15
16
  var _nodeFs = require("node:fs");
16
17
  var _json = require("./json.cjs");
17
- function getPackageManager(a = (0, _getWorkspaceRoot.getWorkspaceRoot)()) {
18
- const n = (0, _getParentPath.getParentPath)(["package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lock"], a);
19
- if (!n) return "pnpm";
20
- switch ((0, _path.findFileName)(n)) {
18
+ var _semverFns = require("./semver-fns.cjs");
19
+ function getPackageManager(n = (0, _getWorkspaceRoot.getWorkspaceRoot)()) {
20
+ const e = (0, _getParentPath.getParentPath)(["package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lock"], n);
21
+ if (!e) return "pnpm";
22
+ switch ((0, _path.findFileName)(e)) {
21
23
  case "yarn.lock":
22
24
  return "yarn";
23
25
  case "pnpm-lock.yaml":
@@ -28,44 +30,46 @@ function getPackageManager(a = (0, _getWorkspaceRoot.getWorkspaceRoot)()) {
28
30
  return "npm";
29
31
  }
30
32
  }
31
- async function f(a) {
32
- let n;
33
+ async function y(n) {
34
+ let e;
33
35
  for (;;) {
34
- if (!a) return;
35
- const e = (0, _path.findFilePath)(a);
36
- if (e === a) return;
37
- if (a = e, n = (0, _path.joinPaths)(a, "package.json"), await (0, _path.exists)(n)) break;
36
+ if (!n) return;
37
+ const a = (0, _path.findFilePath)(n);
38
+ if (a === n) return;
39
+ if (n = a, e = (0, _path.joinPaths)(n, "package.json"), await (0, _path.exists)(e)) break;
38
40
  }
39
- return n;
41
+ return e;
40
42
  }
41
- async function u(a, n = {}) {
42
- const e = await (0, _resolve.resolvePackage)(a, n);
43
- if (e) return f(e);
43
+ async function v(n, e = {}) {
44
+ const a = await (0, _resolve.resolvePackage)(n, e);
45
+ if (a) return y(a);
44
46
  }
45
- async function getPackageInfo(a, n = {}) {
46
- const e = await u(a, n);
47
- if (!e) return;
48
- const t = await (0, _json.readJsonFile)(e);
47
+ async function getPackageInfo(n, e = {}) {
48
+ const a = await v(n, e);
49
+ if (!a) return;
50
+ const s = await (0, _json.readJsonFile)(a);
49
51
  return {
50
- name: a,
51
- version: t.version,
52
- rootPath: (0, _path.findFilePath)(e),
53
- packageJsonPath: e,
54
- packageJson: t
52
+ name: n,
53
+ version: s.version,
54
+ rootPath: (0, _path.findFilePath)(a),
55
+ packageJsonPath: a,
56
+ packageJson: s
55
57
  };
56
58
  }
57
- async function loadPackageJson(a = (0, _getWorkspaceRoot.getWorkspaceRoot)()) {
58
- const n = (0, _getParentPath.getParentPath)("package.json", a, {
59
+ async function loadPackageJson(n = (0, _getWorkspaceRoot.getWorkspaceRoot)()) {
60
+ const e = (0, _getParentPath.getParentPath)("package.json", n, {
59
61
  skipCwd: !1
60
62
  });
61
- return !n || !(0, _nodeFs.existsSync)(n) ? null : (0, _json.readJsonFile)(n);
63
+ return !e || !(0, _nodeFs.existsSync)(e) ? null : (0, _json.readJsonFile)(e);
62
64
  }
63
- async function isPackageListed(a, n) {
64
- let e = a;
65
- e.includes("@") && (e = !e.startsWith("@") || e.lastIndexOf("@") > 0 ? e.slice(0, e.lastIndexOf("@")) : e);
66
- const t = (await loadPackageJson(n)) ?? {};
67
- return e in (t.dependencies ?? {}) || e in (t.devDependencies ?? {});
65
+ async function isPackageListed(n, e) {
66
+ const a = n.replace(/@.*$/, ""),
67
+ s = (0, _isString.isString)(e) ? e : e?.cwd;
68
+ let o = (0, _isString.isString)(e) ? void 0 : e?.version;
69
+ (!o || !(0, _semverFns.isValidRange)(o)) && (o = n.includes("@") && (0, _semverFns.isValidRange)(n.replace(/^.*@/, "")) ? n.replace(/^.*@/, "") : void 0);
70
+ const t = await loadPackageJson(s);
71
+ return t ? !!((t.dependencies && a in t.dependencies && (!o || (0, _semverFns.satisfiesVersion)(t.dependencies[a], o))) ?? (t.devDependencies && a in t.devDependencies && t.devDependencies[a])) : !1;
68
72
  }
69
- function isPackageExists(a, n = {}) {
70
- return !!(0, _resolve.resolvePackage)(a, n);
73
+ function isPackageExists(n, e = {}) {
74
+ return !!(0, _resolve.resolvePackage)(n, e);
71
75
  }
@@ -1,6 +1,7 @@
1
1
  import type { PackageResolvingOptions } from "@stryke/path/resolve";
2
2
  import type { PackageJson } from "@stryke/types/package-json";
3
3
  import type { PackageManager } from "@stryke/types/package-manager";
4
+ import type { Range } from "semver";
4
5
  /**
5
6
  * Get the package manager used in the project
6
7
  * @param dir - The path to the project
@@ -28,6 +29,16 @@ export declare function getPackageInfo(name: string, options?: PackageResolvingO
28
29
  * @returns The package info
29
30
  */
30
31
  export declare function loadPackageJson(cwd?: any): Promise<PackageJson | null>;
32
+ export interface PackageExistsOptions {
33
+ /**
34
+ * The current working directory
35
+ */
36
+ cwd?: string;
37
+ /**
38
+ * The version range of the package to check
39
+ */
40
+ version?: string | Range;
41
+ }
31
42
  /**
32
43
  * Check if a package is listed in the package.json file
33
44
  *
@@ -36,6 +47,14 @@ export declare function loadPackageJson(cwd?: any): Promise<PackageJson | null>;
36
47
  * @returns An indicator specifying if the package is listed
37
48
  */
38
49
  export declare function isPackageListed(name: string, cwd?: string): Promise<boolean>;
50
+ /**
51
+ * Check if a package is listed in the package.json file
52
+ *
53
+ * @param name - The name of the package
54
+ * @param options - The options to use when checking if the package is listed
55
+ * @returns An indicator specifying if the package is listed
56
+ */
57
+ export declare function isPackageListed(name: string, options?: PackageExistsOptions): Promise<boolean>;
39
58
  /**
40
59
  * Check if a package exists
41
60
  *
@@ -1 +1 @@
1
- import{exists as p,findFileName as g,findFilePath as o,joinPaths as k}from"@stryke/path";import{getParentPath as r}from"@stryke/path/get-parent-path";import{getWorkspaceRoot as s}from"@stryke/path/get-workspace-root";import{resolvePackage as i}from"@stryke/path/resolve";import{existsSync as l}from"node:fs";import{readJsonFile as c}from"./json";export function getPackageManager(a=s()){const n=r(["package-lock.json","yarn.lock","pnpm-lock.yaml","bun.lock"],a);if(!n)return"pnpm";switch(g(n)){case"yarn.lock":return"yarn";case"pnpm-lock.yaml":return"pnpm";case"bun.lock":return"bun";default:return"npm"}}async function f(a){let n;for(;;){if(!a)return;const e=o(a);if(e===a)return;if(a=e,n=k(a,"package.json"),await p(n))break}return n}async function u(a,n={}){const e=await i(a,n);if(e)return f(e)}export async function getPackageInfo(a,n={}){const e=await u(a,n);if(!e)return;const t=await c(e);return{name:a,version:t.version,rootPath:o(e),packageJsonPath:e,packageJson:t}}export async function loadPackageJson(a=s()){const n=r("package.json",a,{skipCwd:!1});return!n||!l(n)?null:c(n)}export async function isPackageListed(a,n){let e=a;e.includes("@")&&(e=!e.startsWith("@")||e.lastIndexOf("@")>0?e.slice(0,e.lastIndexOf("@")):e);const t=await loadPackageJson(n)??{};return e in(t.dependencies??{})||e in(t.devDependencies??{})}export function isPackageExists(a,n={}){return!!i(a,n)}
1
+ import{exists as f,findFileName as m,findFilePath as r,joinPaths as u}from"@stryke/path";import{getParentPath as i}from"@stryke/path/get-parent-path";import{getWorkspaceRoot as c}from"@stryke/path/get-workspace-root";import{resolvePackage as p}from"@stryke/path/resolve";import{isString as g}from"@stryke/type-checks/is-string";import{existsSync as P}from"node:fs";import{readJsonFile as k}from"./json";import{isValidRange as l,satisfiesVersion as d}from"./semver-fns";export function getPackageManager(n=c()){const e=i(["package-lock.json","yarn.lock","pnpm-lock.yaml","bun.lock"],n);if(!e)return"pnpm";switch(m(e)){case"yarn.lock":return"yarn";case"pnpm-lock.yaml":return"pnpm";case"bun.lock":return"bun";default:return"npm"}}async function y(n){let e;for(;;){if(!n)return;const a=r(n);if(a===n)return;if(n=a,e=u(n,"package.json"),await f(e))break}return e}async function v(n,e={}){const a=await p(n,e);if(a)return y(a)}export async function getPackageInfo(n,e={}){const a=await v(n,e);if(!a)return;const s=await k(a);return{name:n,version:s.version,rootPath:r(a),packageJsonPath:a,packageJson:s}}export async function loadPackageJson(n=c()){const e=i("package.json",n,{skipCwd:!1});return!e||!P(e)?null:k(e)}export async function isPackageListed(n,e){const a=n.replace(/@.*$/,""),s=g(e)?e:e?.cwd;let o=g(e)?void 0:e?.version;(!o||!l(o))&&(o=n.includes("@")&&l(n.replace(/^.*@/,""))?n.replace(/^.*@/,""):void 0);const t=await loadPackageJson(s);return t?!!((t.dependencies&&a in t.dependencies&&(!o||d(t.dependencies[a],o)))??(t.devDependencies&&a in t.devDependencies&&t.devDependencies[a])):!1}export function isPackageExists(n,e={}){return!!p(n,e)}
@@ -3,20 +3,38 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.parseVersion = exports.isRelativeVersionKeyword = exports.deriveNewSemverVersion = void 0;
6
+ exports.satisfiesVersion = exports.parseVersion = exports.isValidVersion = exports.isValidSemver = exports.isValidRange = exports.isSemver = exports.isRelativeVersionKeyword = exports.isRange = exports.deriveNewSemverVersion = exports.coerceVersion = void 0;
7
+ var _isObject = require("@stryke/type-checks/is-object");
8
+ var _isString = require("@stryke/type-checks/is-string");
7
9
  var _semver = require("semver");
8
- const parseVersion = e => (0, _semver.parse)(e),
10
+ const parseVersion = (e, r = !0) => (0, _semver.parse)(e, r),
11
+ coerceVersion = (e, r) => (0, _semver.coerce)(e, r),
12
+ isSemver = e => (0, _isObject.isObject)(e) && "version" in e,
13
+ isRange = e => (0, _isObject.isObject)(e) && "range" in e,
14
+ isValidSemver = (e, r = !0) => ((0, _isString.isString)(e) || isSemver(e)) && (0, _semver.valid)(e, r) !== null,
15
+ isValidRange = (e, r = !0) => ((0, _isString.isString)(e) || isRange(e)) && (0, _semver.validRange)(e, r) !== null,
16
+ isValidVersion = (e, r = !0) => isValidSemver(e, r) || isValidRange(e, r),
17
+ satisfiesVersion = (e, r, n = !0) => !e || !r || !isValidSemver(e, n) || !isValidRange(r, n) ? !1 : (0, _semver.satisfies)(e, r, {
18
+ loose: n
19
+ }),
9
20
  isRelativeVersionKeyword = e => _semver.RELEASE_TYPES.includes(e),
10
21
  deriveNewSemverVersion = (e, r, n) => {
11
22
  if (!(0, _semver.valid)(e)) throw new Error(`Invalid semver version "${e}" provided.`);
12
- let o = r;
23
+ let t = r;
13
24
  if (isRelativeVersionKeyword(r)) {
14
- const i = (0, _semver.inc)(e, r, n);
15
- if (!i) throw new Error(`Unable to derive new version from current version "${e}" and version specifier "${r}"`);
16
- o = i;
25
+ const o = (0, _semver.inc)(e, r, n);
26
+ if (!o) throw new Error(`Unable to derive new version from current version "${e}" and version specifier "${r}"`);
27
+ t = o;
17
28
  } else if (!(0, _semver.valid)(r)) throw new Error(`Invalid semver version specifier "${r}" provided. Please provide either a valid semver version or a valid semver version keyword.`);
18
- return o;
29
+ return t;
19
30
  };
20
31
  exports.deriveNewSemverVersion = deriveNewSemverVersion;
21
32
  exports.isRelativeVersionKeyword = isRelativeVersionKeyword;
33
+ exports.satisfiesVersion = satisfiesVersion;
34
+ exports.isValidVersion = isValidVersion;
35
+ exports.isValidRange = isValidRange;
36
+ exports.isValidSemver = isValidSemver;
37
+ exports.isRange = isRange;
38
+ exports.isSemver = isSemver;
39
+ exports.coerceVersion = coerceVersion;
22
40
  exports.parseVersion = parseVersion;
@@ -1,4 +1,86 @@
1
- import type { ReleaseType } from "semver";
2
- export declare const parseVersion: (semver: string) => import("semver").SemVer | null;
1
+ import type { CoerceOptions, Range, ReleaseType, SemVer } from "semver";
2
+ /**
3
+ * Parse a semver string into a SemVer object
4
+ *
5
+ * @param semver - The semver string to parse
6
+ * @param loose - Whether to use loose parsing
7
+ * @returns The parsed SemVer object
8
+ */
9
+ export declare const parseVersion: (semver: string, loose?: boolean) => SemVer | null;
10
+ /**
11
+ * Coerce a version string into a valid SemVer string
12
+ *
13
+ * @param version - The version string or number or {@link SemVer} to coerce
14
+ * @param options - Options to use when coercing the version
15
+ * @returns The coerced SemVer string or null if invalid
16
+ */
17
+ export declare const coerceVersion: (version: string | number | SemVer | null | undefined, options?: CoerceOptions) => SemVer | null;
18
+ /**
19
+ * Type check for {@link SemVer}
20
+ *
21
+ * @param val - The value to check
22
+ * @returns Whether the value is a valid {@link SemVer}
23
+ */
24
+ export declare const isSemver: (val: any) => val is SemVer;
25
+ /**
26
+ * Type check for {@link Range}
27
+ *
28
+ * @param val - The value to check
29
+ * @returns Whether the value is a valid {@link Range}
30
+ */
31
+ export declare const isRange: (val: any) => val is Range;
32
+ /**
33
+ * Check if a {@link SemVer} string is valid
34
+ *
35
+ * @remarks
36
+ * If you're looking for type checking, please use the {@link isSemver} function.
37
+ *
38
+ * @param semver - The semver string to check
39
+ * @param loose - Whether to use loose parsing
40
+ * @returns Whether the semver string is valid
41
+ */
42
+ export declare const isValidSemver: (semver: any, loose?: boolean) => boolean;
43
+ /**
44
+ * Check if a {@link Range} string is valid
45
+ *
46
+ * @remarks
47
+ * If you're looking for type checking, please use the {@link isRange} function.
48
+ *
49
+ * @param range - The range string to check
50
+ * @param loose - Whether to use loose parsing
51
+ * @returns Whether the range string is valid
52
+ */
53
+ export declare const isValidRange: (range: any, loose?: boolean) => boolean;
54
+ /**
55
+ * Check if a {@link SemVer} or {@link Range} string is valid
56
+ *
57
+ * @param version - The semver string to check
58
+ * @param loose - Whether to use loose parsing
59
+ * @returns Whether the semver string is valid
60
+ */
61
+ export declare const isValidVersion: (version: string | SemVer | Range | null | undefined, loose?: boolean) => boolean;
62
+ /**
63
+ * Check if a semver string satisfies a range
64
+ *
65
+ * @param version - The semver string to check
66
+ * @param range - The range to check against
67
+ * @param loose - Whether to use loose parsing
68
+ * @returns Whether the semver string satisfies the range
69
+ */
70
+ export declare const satisfiesVersion: (version: string | SemVer | null | undefined, range: string | Range | null | undefined, loose?: boolean) => boolean;
71
+ /**
72
+ * Check if a string is a valid relative version keyword
73
+ *
74
+ * @param val - The string to check
75
+ * @returns Whether the string is a valid relative version keyword
76
+ */
3
77
  export declare const isRelativeVersionKeyword: (val: string) => val is ReleaseType;
78
+ /**
79
+ * Derive a new semver version from the current version and a version specifier
80
+ *
81
+ * @param currentSemverVersion - The current semver version
82
+ * @param semverSpecifier - The semver specifier to use
83
+ * @param preid - The pre-release identifier to use
84
+ * @returns The derived new semver version
85
+ */
4
86
  export declare const deriveNewSemverVersion: (currentSemverVersion: string, semverSpecifier: string, preid?: string) => string;
@@ -1 +1 @@
1
- import{RELEASE_TYPES as t,inc as a,parse as d,valid as s}from"semver";export const parseVersion=e=>d(e),isRelativeVersionKeyword=e=>t.includes(e),deriveNewSemverVersion=(e,r,n)=>{if(!s(e))throw new Error(`Invalid semver version "${e}" provided.`);let o=r;if(isRelativeVersionKeyword(r)){const i=a(e,r,n);if(!i)throw new Error(`Unable to derive new version from current version "${e}" and version specifier "${r}"`);o=i}else if(!s(r))throw new Error(`Invalid semver version specifier "${r}" provided. Please provide either a valid semver version or a valid semver version keyword.`);return o};
1
+ import{isObject as s}from"@stryke/type-checks/is-object";import{isString as a}from"@stryke/type-checks/is-string";import{RELEASE_TYPES as l,coerce as d,inc as u,parse as p,satisfies as v,valid as i,validRange as c}from"semver";export const parseVersion=(e,r=!0)=>p(e,r),coerceVersion=(e,r)=>d(e,r),isSemver=e=>s(e)&&"version"in e,isRange=e=>s(e)&&"range"in e,isValidSemver=(e,r=!0)=>(a(e)||isSemver(e))&&i(e,r)!==null,isValidRange=(e,r=!0)=>(a(e)||isRange(e))&&c(e,r)!==null,isValidVersion=(e,r=!0)=>isValidSemver(e,r)||isValidRange(e,r),satisfiesVersion=(e,r,n=!0)=>!e||!r||!isValidSemver(e,n)||!isValidRange(r,n)?!1:v(e,r,{loose:n}),isRelativeVersionKeyword=e=>l.includes(e),deriveNewSemverVersion=(e,r,n)=>{if(!i(e))throw new Error(`Invalid semver version "${e}" provided.`);let t=r;if(isRelativeVersionKeyword(r)){const o=u(e,r,n);if(!o)throw new Error(`Unable to derive new version from current version "${e}" and version specifier "${r}"`);t=o}else if(!i(r))throw new Error(`Invalid semver version specifier "${r}" provided. Please provide either a valid semver version or a valid semver version keyword.`);return t};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stryke/fs",
3
- "version": "0.23.3",
3
+ "version": "0.24.0",
4
4
  "type": "module",
5
5
  "description": "A package containing various file system utilities that expand the functionality of NodeJs's built-in `fs` module.",
6
6
  "repository": {
@@ -15,7 +15,7 @@
15
15
  "@antfu/install-pkg": "^1.0.0",
16
16
  "@ltd/j-toml": "^1.38.0",
17
17
  "@stryke/convert": "^0.3.1",
18
- "@stryke/path": "^0.12.3",
18
+ "@stryke/path": "0.12.5",
19
19
  "@zkochan/js-yaml": "^0.0.7",
20
20
  "chalk": "^5.4.1",
21
21
  "defu": "^6.1.4",
@@ -24,8 +24,8 @@
24
24
  "nanotar": "^0.2.0",
25
25
  "semver": "7.7.1",
26
26
  "@stryke/json": "^0.9.3",
27
- "@stryke/type-checks": "^0.3.7",
28
- "@stryke/types": "^0.8.8"
27
+ "@stryke/type-checks": "^0.3.9",
28
+ "@stryke/types": "^0.8.9"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^22.14.0",
@@ -337,5 +337,5 @@
337
337
  "main": "./dist/index.cjs",
338
338
  "module": "./dist/index.mjs",
339
339
  "types": "./dist/index.d.ts",
340
- "gitHead": "bd1c18c69a24e82c1b126b1e5de36008bbac52d9"
340
+ "gitHead": "f8abb224a6b6540e442cc664bbb2cf1273b2be2b"
341
341
  }