Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • jw_sonar
  • jw_sonar_backup
  • main
  • move-to-esm-only
  • open_tool_for_self_hosting
  • v5.0
  • v4.1
  • v4.2
8 results

Target

Select target project
  • dojo_project/projects/shared/nodesharedcode
1 result
Select Git revision
  • jw_sonar
  • jw_sonar_backup
  • main
  • move-to-esm-only
  • open_tool_for_self_hosting
  • v5.0
  • v4.1
  • v4.2
8 results
Show changes
Commits on Source (10)
......@@ -7,7 +7,8 @@ This repo contains some code that can be shared across node projects of Dojo.
These packages are needed :
- `ajv`
- `hjson`
- `json5`
- `tar-stream`
- `winston`
## How to use it
......
import fs from 'node:fs';
import path from 'node:path';
import tar from 'tar-stream';
import stream from 'node:stream';
import { Writable } from 'stream';
import zlib from 'zlib';
class ArchiveHelper {
private async explore(absoluteBasePath: string, rootPath: string, pack: tar.Pack) {
for ( let file of await fs.promises.readdir(rootPath) ) {
if ( file === 'output.tar' ) {
continue;
}
file = path.join(rootPath, file);
const stat = await fs.promises.stat(file);
if ( stat.isDirectory() ) {
await this.explore(absoluteBasePath, file, pack);
continue;
}
const entry = pack.entry({
name: file.replace(absoluteBasePath, ''),
size: stat.size
}, (err) => {
if ( err ) {
throw err;
}
});
const stream = fs.createReadStream(file);
stream.pipe(entry);
}
}
private async compress(folderPath: string, tarDataStream: stream.Writable) {
const pack = tar.pack();
await this.explore(folderPath, folderPath, pack);
pack.pipe(zlib.createGzip()).pipe(tarDataStream);
pack.finalize();
}
public async getBase64(folderPath: string): Promise<string> {
let data: any;
const tarDataStream = new stream.Writable({
write(this: Writable, chunk: Buffer, _encoding: BufferEncoding, next: (error?: Error | null) => void) {
if ( data ) {
data += chunk.toString('hex');
} else {
data = chunk.toString('hex');
}
next();
}
});
await this.compress(folderPath, tarDataStream);
await (new Promise((resolve, reject) => {
tarDataStream.on('close', () => {
resolve(0);
});
}));
return Buffer.from(data, 'hex').toString('base64');
}
}
export default new ArchiveHelper();
\ No newline at end of file
......@@ -5,9 +5,7 @@ import JSON5 from 'json5';
class ExerciceHelper {
validateResultFile(resultsFilePath: string): {
results: ExerciceResultsFile, isValid: boolean, errors: ErrorObject<string, Record<string, any>, unknown>[] | null | undefined
} {
validateResultFile(resultsFilePathOrStr: string, isFile: boolean = true): { results: ExerciceResultsFile | undefined, isValid: boolean, errors: Array<ErrorObject<string, Record<string, any>, unknown> | string> | null | undefined } {
const ajv = new Ajv();
const schema: JTDSchemaType<ExerciceResultsFile> = {
......@@ -34,14 +32,32 @@ class ExerciceHelper {
const validator = ajv.compile(schema);
const results = JSON5.parse(fs.readFileSync(resultsFilePath, 'utf8'));
try {
const results = JSON5.parse(isFile ? fs.readFileSync(resultsFilePathOrStr, 'utf8') : resultsFilePathOrStr);
const isValid = validator(results);
if ( isValid ) {
if ( results.successfulTests === undefined && results.successfulTestsList !== undefined ) {
results.successfulTests = results.successfulTestsList.length;
}
if ( results.failedTests === undefined && results.failedTestsList !== undefined ) {
results.failedTests = results.failedTestsList.length;
}
}
return {
results: isValid ? results as ExerciceResultsFile : results as any,
results: isValid ? results : results as any,
isValid: isValid,
errors : validator.errors
};
} catch ( error ) {
return {
results: undefined,
isValid: false,
errors : [ `JSON5 invalid : ${ JSON.stringify(error) }` ]
};
}
}
}
......
......@@ -42,6 +42,14 @@ class Toolbox {
getTotalSize: this.getTotalSize.bind(this)
};
}
public snakeToCamel(str: string): string {
return str.toLowerCase().replace(/([-_][a-z])/g, (group: string) => group.toUpperCase().replace('-', '').replace('_', ''));
}
public getKeysWithPrefix(obj: object, prefix: string): Array<string> {
return Object.keys(obj).filter(key => key.startsWith(prefix));
}
}
......
......@@ -59,7 +59,7 @@ function registerStringCapitalizeName() {
function registerStringConvertWithEnvVars() {
String.prototype.convertWithEnvVars = function (this: string): string {
return this.replace(/\${?([a-zA-Z0-9_]+)}?/g, (match: string, p1: string) => {
return this.replace(/\${?([a-zA-Z0-9_]+)}?/g, (_match: string, p1: string) => {
return process.env[p1] || '';
});
};
......
Source: recursive-readdir-files
===
Modified for Dojo
===
## Usage
```js
import recursiveReaddirFiles from 'recursive-readdir-files';
const files = await recursiveReaddirFiles(process.cwd(), {
ignored: /\/(node_modules|\.git)/
});
// `files` is an array
console.log(files);
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// [
// {
// dev: 16777233,
// mode: 33188,
// nlink: 1,
// uid: 501,
// gid: 20,
// rdev: 0,
// blksize: 4096,
// ino: 145023089,
// size: 89,
// blocks: 8,
// atimeMs: 1649303678077.934,
// mtimeMs: 1649303676847.1777,
// ctimeMs: 1649303676847.1777,
// birthtimeMs: 1649301118132.6782,
// atime: 2022-04-07T03:54:38.078Z,
// mtime: 2022-04-07T03:54:36.847Z,
// ctime: 2022-04-07T03:54:36.847Z,
// birthtime: 2022-04-07T03:11:58.133Z,
// name: 'watch.ts',
// path: '/Users/xxx/watch.ts',
// ext: 'ts'
// },
// // ...
// ]
```
Or
```js
recursiveReaddirFiles(process.cwd(), {
ignored: /\/(node_modules|\.git)/
}, (filepath, state) => {
console.log(filepath);
// 👉 /Users/xxx/watch.ts
console.log(state.isFile()); // 👉 true
console.log(state.isDirectory()); // 👉 false
console.log(state);
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// {
// dev: 16777233,
// mode: 33188,
// nlink: 1,
// uid: 501,
// gid: 20,
// rdev: 0,
// blksize: 4096,
// ino: 145023089,
// size: 89,
// blocks: 8,
// atimeMs: 1649303678077.934,
// mtimeMs: 1649303676847.1777,
// ctimeMs: 1649303676847.1777,
// birthtimeMs: 1649301118132.6782,
// atime: 2022-04-07T03:54:38.078Z,
// mtime: 2022-04-07T03:54:36.847Z,
// ctime: 2022-04-07T03:54:36.847Z,
// birthtime: 2022-04-07T03:11:58.133Z,
// name: 'watch.ts',
// path: '/Users/xxx/watch.ts',
// ext: 'ts'
// }
})
```
## Options
```ts
export interface RecursiveReaddirFilesOptions {
/**
* Ignore files
* @example `/\/(node_modules|\.git)/`
*/
ignored?: RegExp;
/**
* Specifies a list of `glob` patterns that match files to be included in compilation.
* @example `/(\.json)$/`
*/
include?: RegExp;
/**
* Specifies a list of files to be excluded from compilation.
* @example `/(package\.json)$/`
*/
exclude?: RegExp;
/** Provide filtering methods to filter data. */
filter?: (item: IFileDirStat) => boolean;
/** Do not give the absolute path but the relative one from the root folder */
replacePathByRelativeOne?: boolean;
/** Remove stats that are not necessary for transfert */
liteStats?: boolean;
}
```
## Result
```ts
import fs from 'node:fs';
export interface IFileDirStat extends Partial<fs.Stats> {
/**
* @example `/a/sum.jpg` => `sum.jpg`
*/
name: string;
/**
* @example `/basic/src/utils/sum.ts`
*/
path: string;
/**
* @example `/a/b.jpg` => `jpg`
*/
ext?: string;
}
declare type Callback = (filepath: string, stat: IFileDirStat) => void;
export default function recursiveReaddirFiles(rootPath: string, options?: RecursiveReaddirFilesOptions, callback?: Callback): Promise<IFileDirStat[]>;
export { recursiveReaddirFiles };
export declare const getStat: (filepath: string) => Promise<IFileDirStat>;
/**
* Get ext
* @param {String} filePath `/a/b.jpg` => `jpg`
*/
export declare const getExt: (filePath: string) => string;
```
## License
Licensed under the MIT License.
import fs from 'node:fs';
import path from 'node:path';
export interface RecursiveReaddirFilesOptions {
/**
* Ignore files
* @example `/\/(node_modules|\.git)/`
*/
ignored?: RegExp;
/**
* Specifies a list of `glob` patterns that match files to be included in compilation.
* @example `/(\.json)$/`
*/
include?: RegExp;
/**
* Specifies a list of files to be excluded from compilation.
* @example `/(package\.json)$/`
*/
exclude?: RegExp;
/** Provide filtering methods to filter data. */
filter?: (item: IFileDirStat) => boolean;
/** Do not give the absolute path but the relative one from the root folder */
replacePathByRelativeOne?: boolean;
/** Remove stats that are not necessary for transfert */
liteStats?: boolean;
}
export interface IFileDirStat extends Partial<fs.Stats> {
/**
* @example `/a/sum.jpg` => `sum.jpg`
*/
name: string;
/**
* @example `/basic/src/utils/sum.ts`
*/
path: string;
/**
* @example `/a/b.jpg` => `jpg`
*/
ext?: string;
}
type Callback = (filepath: string, stat: IFileDirStat) => void;
class RecursiveFilesStats {
async explore(rootPath: string, options: RecursiveReaddirFilesOptions = {}, callback?: Callback): Promise<IFileDirStat[]> {
return this.getFiles(`${ path.resolve(rootPath) }/`, rootPath, options, [], callback);
}
private async getFiles(absoluteBasePath: string, rootPath: string, options: RecursiveReaddirFilesOptions = {}, files: IFileDirStat[] = [], callback?: Callback): Promise<IFileDirStat[]> {
const {
ignored, include, exclude, filter
} = options;
const filesData = await fs.promises.readdir(rootPath);
const fileDir: IFileDirStat[] = filesData.map((file) => ({
name: file, path: path.join(rootPath, file)
})).filter((item) => {
if ( include && include.test(item.path) ) {
return true;
}
if ( exclude && exclude.test(item.path) ) {
return false;
}
if ( ignored ) {
return !ignored.test(item.path);
}
return true;
});
if ( callback ) {
fileDir.map(async (item: IFileDirStat) => {
const stat = await this.getStat(item.path, absoluteBasePath, options);
if ( stat.isDirectory!() ) {
await this.getFiles(absoluteBasePath, item.path, options, [], callback);
}
callback(item.path, stat);
});
} else {
await Promise.all(fileDir.map(async (item: IFileDirStat) => {
const stat = await this.getStat(item.path, absoluteBasePath, options);
if ( stat.isDirectory!() ) {
const arr = await this.getFiles(absoluteBasePath, item.path, options, []);
files = files.concat(arr);
} else if ( stat.isFile!() ) {
files.push(stat);
}
}));
}
return files.filter((item) => {
if ( filter && typeof filter === 'function' ) {
return filter(item);
}
return true;
});
}
private async getStat(filepath: string, absoluteRootPath: string, options: RecursiveReaddirFilesOptions): Promise<IFileDirStat> {
const stat = (await fs.promises.stat(filepath)) as IFileDirStat;
stat.ext = '';
if ( stat.isFile!() ) {
stat.ext = this.getExt(filepath);
stat.name = path.basename(filepath);
stat.path = path.resolve(filepath);
}
if ( options.replacePathByRelativeOne && stat.path ) {
stat.path = stat.path.replace(absoluteRootPath, '');
}
if ( options.liteStats ) {
delete stat.dev;
delete stat.nlink;
delete stat.uid;
delete stat.gid;
delete stat.rdev;
delete stat.blksize;
delete stat.ino;
delete stat.blocks;
delete stat.atimeMs;
delete stat.mtimeMs;
delete stat.ctimeMs;
delete stat.birthtimeMs;
delete stat.atime;
//delete stat.mtime;
delete stat.ctime;
//delete stat.birthtime;
//delete stat.mode;
}
return stat;
};
/**
* Get ext
* @param {String} filePath `/a/b.jpg` => `jpg`
*/
private getExt(filePath: string): string {
return path.extname(filePath).replace(/^\./, '').toLowerCase();
}
}
export default new RecursiveFilesStats();