@wexample/js-pseudocode 0.1.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.
Files changed (40) hide show
  1. package/.iml +7 -0
  2. package/.wex/config.yml +3 -0
  3. package/.wex/python/app_manager/.python-version +1 -0
  4. package/.wex/python/app_manager/__main__.py +34 -0
  5. package/.wex/python/app_manager/app_workdir.py +7 -0
  6. package/.wex/python/app_manager/pyproject.toml +13 -0
  7. package/.wex/python/app_manager/requirements.txt +223 -0
  8. package/README.md +140 -0
  9. package/package.json +20 -0
  10. package/src/index.ts +1 -0
  11. package/src/lib/Config/ClassConfig.ts +77 -0
  12. package/src/lib/Config/ClassMethodConfig.ts +56 -0
  13. package/src/lib/Config/ClassPropertyConfig.ts +27 -0
  14. package/src/lib/Config/ConstantConfig.ts +34 -0
  15. package/src/lib/Config/DocCommentConfig.ts +54 -0
  16. package/src/lib/Config/FunctionConfig.ts +56 -0
  17. package/src/lib/Config/FunctionParameterConfig.ts +41 -0
  18. package/src/lib/Config/FunctionReturnConfig.ts +20 -0
  19. package/src/lib/Generator/CodeGenerator.ts +36 -0
  20. package/tests/class_basic_calculator.test.js +48 -0
  21. package/tests/class_basic_calculator.test.ts +26 -0
  22. package/tests/constant_using_const.test.js +33 -0
  23. package/tests/constant_using_const.test.ts +26 -0
  24. package/tests/function_basic.test.js +39 -0
  25. package/tests/function_basic.test.ts +26 -0
  26. package/tests/function_complex.test.js +40 -0
  27. package/tests/function_complex.test.ts +26 -0
  28. package/tests/resources/item/class/basic_calculator.js.txt +19 -0
  29. package/tests/resources/item/class/basic_calculator.yml +23 -0
  30. package/tests/resources/item/constant/constant_using_const.js.txt +4 -0
  31. package/tests/resources/item/constant/constant_using_const.yml +16 -0
  32. package/tests/resources/item/constant/constant_using_define.ts +0 -0
  33. package/tests/resources/item/constant/constant_using_define.yml +16 -0
  34. package/tests/resources/item/function/basic_function.js.txt +10 -0
  35. package/tests/resources/item/function/basic_function.yml +14 -0
  36. package/tests/resources/item/function/complex_function.js.txt +11 -0
  37. package/tests/resources/item/function/complex_function.yml +19 -0
  38. package/tests/utils/testHelpers.ts +9 -0
  39. package/tsconfig.json +13 -0
  40. package/version.txt +1 -0
@@ -0,0 +1,54 @@
1
+ import type { FunctionParameterConfig } from './FunctionParameterConfig.ts';
2
+ import type { FunctionReturnConfig } from './FunctionReturnConfig.ts';
3
+
4
+ export class DocCommentConfig {
5
+ description: string | null;
6
+ parameters: FunctionParameterConfig[];
7
+ return: FunctionReturnConfig | null;
8
+
9
+ constructor({
10
+ description = null,
11
+ parameters = [],
12
+ returnConfig = null,
13
+ }: {
14
+ description?: string | null;
15
+ parameters?: FunctionParameterConfig[];
16
+ returnConfig?: FunctionReturnConfig | null;
17
+ }) {
18
+ this.description = description ?? null;
19
+ this.parameters = parameters;
20
+ this.return = returnConfig ?? null;
21
+ }
22
+
23
+ static buildJSDoc({
24
+ description,
25
+ parameters,
26
+ returnConfig,
27
+ }: {
28
+ description?: string | null;
29
+ parameters: FunctionParameterConfig[];
30
+ returnConfig: FunctionReturnConfig | null;
31
+ }): string {
32
+ const lines: string[] = ['/**'];
33
+ if (description) {
34
+ for (const line of description.split('\n')) {
35
+ lines.push(` * ${line}`);
36
+ }
37
+ }
38
+ const paramLines: string[] = [];
39
+ for (const p of parameters) {
40
+ const desc = p.description ? ` - ${p.description}` : '';
41
+ paramLines.push(` * @param ${p.name}${desc}`);
42
+ }
43
+ const retDesc = returnConfig && returnConfig.description ? ` ${returnConfig.description}` : '';
44
+ if (paramLines.length || returnConfig) {
45
+ if (description) {
46
+ lines.push(' *');
47
+ }
48
+ for (const l of paramLines) lines.push(l);
49
+ if (returnConfig) lines.push(` * @returns${retDesc ? ':' + retDesc : ''}`);
50
+ }
51
+ lines.push(' */');
52
+ return lines.join('\n');
53
+ }
54
+ }
@@ -0,0 +1,56 @@
1
+ import { DocCommentConfig } from './DocCommentConfig.ts';
2
+ import { FunctionParameterConfig } from './FunctionParameterConfig.ts';
3
+ import { FunctionReturnConfig } from './FunctionReturnConfig.ts';
4
+
5
+ export class FunctionConfig {
6
+ type = 'function' as const;
7
+ name: string;
8
+ description: string | null;
9
+ parameters: FunctionParameterConfig[];
10
+ return: FunctionReturnConfig | null;
11
+
12
+ constructor({
13
+ name,
14
+ description,
15
+ parameters,
16
+ returnConfig,
17
+ }: {
18
+ name: string;
19
+ description?: string | null;
20
+ parameters?: FunctionParameterConfig[];
21
+ returnConfig?: FunctionReturnConfig | null;
22
+ }) {
23
+ this.name = name;
24
+ this.description = description || null;
25
+ this.parameters = parameters || [];
26
+ this.return = returnConfig || null;
27
+ }
28
+
29
+ static fromConfig(data: any): FunctionConfig {
30
+ const params = Array.isArray(data.parameters)
31
+ ? data.parameters.map((p: any) => FunctionParameterConfig.fromConfig(p))
32
+ : [];
33
+ const ret = FunctionReturnConfig.fromConfig(data.return);
34
+ return new FunctionConfig({
35
+ name: data.name,
36
+ description: data.description,
37
+ parameters: params,
38
+ returnConfig: ret,
39
+ });
40
+ }
41
+
42
+ toCode(): string {
43
+ const paramsSrc = this.parameters.map((p) => p.toCode()).join(', ');
44
+ const jsdoc = DocCommentConfig.buildJSDoc({
45
+ description: this.description,
46
+ parameters: this.parameters,
47
+ returnConfig: this.return,
48
+ });
49
+ const lines: string[] = [];
50
+ if (jsdoc) lines.push(jsdoc);
51
+ lines.push(`function ${this.name}(${paramsSrc}) {`);
52
+ lines.push(` // TODO: Implement function body`);
53
+ lines.push(`}`);
54
+ return lines.join('\n');
55
+ }
56
+ }
@@ -0,0 +1,41 @@
1
+ export class FunctionParameterConfig {
2
+ name: string;
3
+ type: string | null;
4
+ description: string | null;
5
+ optional: boolean;
6
+ defaultValue: unknown;
7
+
8
+ constructor({
9
+ name,
10
+ type,
11
+ description,
12
+ optional = false,
13
+ defaultValue = undefined,
14
+ }: {
15
+ name: string;
16
+ type?: string | null;
17
+ description?: string | null;
18
+ optional?: boolean;
19
+ defaultValue?: unknown;
20
+ }) {
21
+ this.name = name;
22
+ this.type = type || null;
23
+ this.description = description || null;
24
+ this.optional = !!optional;
25
+ this.defaultValue = defaultValue;
26
+ }
27
+
28
+ static fromConfig(data: any): FunctionParameterConfig {
29
+ return new FunctionParameterConfig({
30
+ name: data.name,
31
+ type: data.type,
32
+ description: data.description,
33
+ optional: data.optional,
34
+ defaultValue: data.default,
35
+ });
36
+ }
37
+
38
+ toCode(): string {
39
+ return this.name;
40
+ }
41
+ }
@@ -0,0 +1,20 @@
1
+ export class FunctionReturnConfig {
2
+ type: string | null;
3
+ description: string | null;
4
+
5
+ constructor({ type, description }: { type?: string | null; description?: string | null }) {
6
+ this.type = type || null;
7
+ this.description = description || null;
8
+ }
9
+
10
+ static fromConfig(data: any): FunctionReturnConfig | null {
11
+ if (!data) return null;
12
+ if (typeof data !== 'object') {
13
+ throw new Error('Invalid YAML for return: expected mapping with key "type"');
14
+ }
15
+ if (!('type' in data) || !data.type) {
16
+ throw new Error('Invalid YAML for return: missing non-empty "type"');
17
+ }
18
+ return new FunctionReturnConfig({ type: data.type, description: data.description });
19
+ }
20
+ }
@@ -0,0 +1,36 @@
1
+ import yaml from 'js-yaml';
2
+ import { ClassConfig } from '../Config/ClassConfig.ts';
3
+ import { ConstantConfig } from '../Config/ConstantConfig.ts';
4
+ import { FunctionConfig } from '../Config/FunctionConfig.ts';
5
+
6
+ export class CodeGenerator {
7
+ generate(yamlText: string): string {
8
+ const data = yaml.load(yamlText) as any;
9
+ if (!data || !Array.isArray(data.items)) {
10
+ throw new Error('Invalid YAML: expected root with items[]');
11
+ }
12
+ const parts: string[] = [];
13
+ for (const item of data.items) {
14
+ switch (item.type) {
15
+ case 'constant': {
16
+ const cfg = ConstantConfig.fromConfig(item);
17
+ parts.push(cfg.toCode());
18
+ break;
19
+ }
20
+ case 'function': {
21
+ const cfg = FunctionConfig.fromConfig(item);
22
+ parts.push(cfg.toCode());
23
+ break;
24
+ }
25
+ case 'class': {
26
+ const cfg = ClassConfig.fromConfig(item);
27
+ parts.push(cfg.toCode());
28
+ break;
29
+ }
30
+ default:
31
+ throw new Error(`Unsupported item type: ${item.type}`);
32
+ }
33
+ }
34
+ return parts.join('\n');
35
+ }
36
+ }
@@ -0,0 +1,48 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.js';
4
+
5
+ const pyFixtureDir =
6
+ '/home/weeger/Desktop/WIP/WEB/WEXAMPLE/PIP/pip/pseudocode/tests/resources/item/class';
7
+
8
+ function normalizeEol(s) {
9
+ return s.replace(/\r\n/g, '\n');
10
+ }
11
+
12
+ const expectedJs = normalizeEol(`/**
13
+ * A class that performs basic arithmetic operations.
14
+ */
15
+ class Calculator {
16
+ constructor() {
17
+ // Stores the result of the last operation performed.
18
+ this.lastResult = 0;
19
+ }
20
+ /**
21
+ * Calculate the sum of two ints.
22
+ *
23
+ * @param a - The first operand.
24
+ * @param b - The second operand.
25
+ * @returns: The sum of the two numbers.
26
+ */
27
+ add(a, b) {
28
+ // TODO: Implement method body
29
+ }
30
+ }`);
31
+
32
+ function assertEqual(a, b, msg) {
33
+ if (a !== b) {
34
+ console.error('Assertion failed:', msg || 'values differ');
35
+ console.error('Expected:\n' + b);
36
+ console.error('Actual:\n' + a);
37
+ process.exit(1);
38
+ }
39
+ }
40
+
41
+ const yml = readFileSync(join(pyFixtureDir, 'basic_calculator.yml'), 'utf-8');
42
+ const code = new CodeGenerator().generate(yml);
43
+ assertEqual(
44
+ normalizeEol(code.trim()),
45
+ expectedJs,
46
+ 'YAML -> JS class generation matches expected JS'
47
+ );
48
+ console.log('OK');
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.ts';
4
+ import { normalizeEol, readExpected } from './utils/testHelpers.ts';
5
+
6
+ const resDir = join(process.cwd(), 'tests', 'resources', 'item', 'class');
7
+
8
+ const expectedJs = readExpected(join(resDir, 'basic_calculator.js.txt'));
9
+
10
+ function assertEqual(a: string, b: string, msg?: string) {
11
+ if (a !== b) {
12
+ console.error('Assertion failed:', msg || 'values differ');
13
+ console.error('Expected:\n' + b);
14
+ console.error('Actual:\n' + a);
15
+ process.exit(1);
16
+ }
17
+ }
18
+
19
+ const yml = readFileSync(join(resDir, 'basic_calculator.yml'), 'utf-8');
20
+ const code = new CodeGenerator().generate(yml);
21
+ assertEqual(
22
+ normalizeEol(code.trim()),
23
+ expectedJs,
24
+ 'YAML -> JS class generation matches expected JS'
25
+ );
26
+ console.log('OK');
@@ -0,0 +1,33 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.js';
4
+
5
+ const phpFixtureDir =
6
+ '/home/weeger/Desktop/WIP/WEB/WEXAMPLE/COMPOSER/packages/wexample/php-pseudocode/tests/resources/item/constant';
7
+
8
+ function normalizeEol(s) {
9
+ return s.replace(/\r\n/g, '\n');
10
+ }
11
+
12
+ const expectedJs = normalizeEol(`// Maximum number of retries for API calls
13
+ const MAX_RETRIES = 3;
14
+ // Base URL for the API
15
+ const API_BASE_URL = "https://api.example.com";`);
16
+
17
+ function assertEqual(a, b, msg) {
18
+ if (a !== b) {
19
+ console.error('Assertion failed:', msg || 'values differ');
20
+ console.error('Expected:\n' + b);
21
+ console.error('Actual:\n' + a);
22
+ process.exit(1);
23
+ }
24
+ }
25
+
26
+ const yml = readFileSync(join(phpFixtureDir, 'constant_using_const.yml'), 'utf-8');
27
+ const code = new CodeGenerator().generate(yml);
28
+ assertEqual(
29
+ normalizeEol(code.trim()),
30
+ expectedJs,
31
+ 'YAML -> JS constants generation matches expected JS'
32
+ );
33
+ console.log('OK');
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.ts';
4
+ import { normalizeEol, readExpected } from './utils/testHelpers.ts';
5
+
6
+ const resDir = join(process.cwd(), 'tests', 'resources', 'item', 'constant');
7
+
8
+ const expectedJs = readExpected(join(resDir, 'constant_using_const.js.txt'));
9
+
10
+ function assertEqual(a: string, b: string, msg?: string) {
11
+ if (a !== b) {
12
+ console.error('Assertion failed:', msg || 'values differ');
13
+ console.error('Expected:\n' + b);
14
+ console.error('Actual:\n' + a);
15
+ process.exit(1);
16
+ }
17
+ }
18
+
19
+ const yml = readFileSync(join(resDir, 'constant_using_const.yml'), 'utf-8');
20
+ const code = new CodeGenerator().generate(yml);
21
+ assertEqual(
22
+ normalizeEol(code.trim()),
23
+ expectedJs,
24
+ 'YAML -> JS constants generation matches expected JS'
25
+ );
26
+ console.log('OK');
@@ -0,0 +1,39 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.js';
4
+
5
+ const pyFixtureDir =
6
+ '/home/weeger/Desktop/WIP/WEB/WEXAMPLE/PIP/pip/pseudocode/tests/resources/item/function';
7
+
8
+ function normalizeEol(s) {
9
+ return s.replace(/\r\n/g, '\n');
10
+ }
11
+
12
+ const expectedJs = normalizeEol(`/**
13
+ * Calculate the sum of two ints.
14
+ *
15
+ * @param a - The first operand.
16
+ * @param b - The second operand.
17
+ * @returns: The sum of the two numbers.
18
+ */
19
+ function add(a, b) {
20
+ // TODO: Implement function body
21
+ }`);
22
+
23
+ function assertEqual(a, b, msg) {
24
+ if (a !== b) {
25
+ console.error('Assertion failed:', msg || 'values differ');
26
+ console.error('Expected:\n' + b);
27
+ console.error('Actual:\n' + a);
28
+ process.exit(1);
29
+ }
30
+ }
31
+
32
+ const yml = readFileSync(join(pyFixtureDir, 'basic_function.yml'), 'utf-8');
33
+ const code = new CodeGenerator().generate(yml);
34
+ assertEqual(
35
+ normalizeEol(code.trim()),
36
+ expectedJs,
37
+ 'YAML -> JS function generation matches expected JS'
38
+ );
39
+ console.log('OK');
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.ts';
4
+ import { normalizeEol, readExpected } from './utils/testHelpers.ts';
5
+
6
+ const resDir = join(process.cwd(), 'tests', 'resources', 'item', 'function');
7
+
8
+ const expectedJs = readExpected(join(resDir, 'basic_function.js.txt'));
9
+
10
+ function assertEqual(a: string, b: string, msg?: string) {
11
+ if (a !== b) {
12
+ console.error('Assertion failed:', msg || 'values differ');
13
+ console.error('Expected:\n' + b);
14
+ console.error('Actual:\n' + a);
15
+ process.exit(1);
16
+ }
17
+ }
18
+
19
+ const yml = readFileSync(join(resDir, 'basic_function.yml'), 'utf-8');
20
+ const code = new CodeGenerator().generate(yml);
21
+ assertEqual(
22
+ normalizeEol(code.trim()),
23
+ expectedJs,
24
+ 'YAML -> JS function generation matches expected JS'
25
+ );
26
+ console.log('OK');
@@ -0,0 +1,40 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.js';
4
+
5
+ const pyFixtureDir =
6
+ '/home/weeger/Desktop/WIP/WEB/WEXAMPLE/PIP/pip/pseudocode/tests/resources/item/function';
7
+
8
+ function normalizeEol(s) {
9
+ return s.replace(/\r\n/g, '\n');
10
+ }
11
+
12
+ const expectedJs = normalizeEol(`/**
13
+ * Process an array of data with optional configuration.
14
+ *
15
+ * @param data - The data to process
16
+ * @param config - Optional configuration parameters
17
+ * @param callback - Optional callback for custom processing
18
+ * @returns
19
+ */
20
+ function processData(data, config, callback) {
21
+ // TODO: Implement function body
22
+ }`);
23
+
24
+ function assertEqual(a, b, msg) {
25
+ if (a !== b) {
26
+ console.error('Assertion failed:', msg || 'values differ');
27
+ console.error('Expected:\n' + b);
28
+ console.error('Actual:\n' + a);
29
+ process.exit(1);
30
+ }
31
+ }
32
+
33
+ const yml = readFileSync(join(pyFixtureDir, 'complex_function.yml'), 'utf-8');
34
+ const code = new CodeGenerator().generate(yml);
35
+ assertEqual(
36
+ normalizeEol(code.trim()),
37
+ expectedJs,
38
+ 'YAML -> JS complex function generation matches expected JS'
39
+ );
40
+ console.log('OK');
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CodeGenerator } from '../src/index.ts';
4
+ import { normalizeEol, readExpected } from './utils/testHelpers.ts';
5
+
6
+ const resDir = join(process.cwd(), 'tests', 'resources', 'item', 'function');
7
+
8
+ const expectedJs = readExpected(join(resDir, 'complex_function.js.txt'));
9
+
10
+ function assertEqual(a: string, b: string, msg?: string) {
11
+ if (a !== b) {
12
+ console.error('Assertion failed:', msg || 'values differ');
13
+ console.error('Expected:\n' + b);
14
+ console.error('Actual:\n' + a);
15
+ process.exit(1);
16
+ }
17
+ }
18
+
19
+ const yml = readFileSync(join(resDir, 'complex_function.yml'), 'utf-8');
20
+ const code = new CodeGenerator().generate(yml);
21
+ assertEqual(
22
+ normalizeEol(code.trim()),
23
+ expectedJs,
24
+ 'YAML -> JS complex function generation matches expected JS'
25
+ );
26
+ console.log('OK');
@@ -0,0 +1,19 @@
1
+ /**
2
+ * A class that performs basic arithmetic operations.
3
+ */
4
+ class Calculator {
5
+ constructor() {
6
+ // Stores the result of the last operation performed.
7
+ this.lastResult = 0;
8
+ }
9
+ /**
10
+ * Calculate the sum of two ints.
11
+ *
12
+ * @param a - The first operand.
13
+ * @param b - The second operand.
14
+ * @returns: The sum of the two numbers.
15
+ */
16
+ add(a, b) {
17
+ // TODO: Implement method body
18
+ }
19
+ }
@@ -0,0 +1,23 @@
1
+ items:
2
+ - name: Calculator
3
+ type: class
4
+ description: "A class that performs basic arithmetic operations."
5
+ properties:
6
+ - name: lastResult
7
+ type: int
8
+ description: "Stores the result of the last operation performed."
9
+ default: 0
10
+ methods:
11
+ - type: method
12
+ name: add
13
+ description: "Calculate the sum of two ints."
14
+ parameters:
15
+ - type: int
16
+ name: a
17
+ description: 'The first operand.'
18
+ - type: int
19
+ name: b
20
+ description: "The second operand."
21
+ return:
22
+ type: int
23
+ description: "The sum of the two numbers."
@@ -0,0 +1,4 @@
1
+ // Maximum number of retries for API calls
2
+ const MAX_RETRIES = 3;
3
+ // Base URL for the API
4
+ const API_BASE_URL = "https://api.example.com";
@@ -0,0 +1,16 @@
1
+ generator:
2
+ php:
3
+ constantDeclaration: "const"
4
+
5
+ items:
6
+ - type: constant
7
+ name: MAX_RETRIES
8
+ value: 3
9
+ description: "Maximum number of retries for API calls"
10
+ - type: constant
11
+ name: API_BASE_URL
12
+ value: "https://api.example.com"
13
+ description: "Base URL for the API"
14
+ generator:
15
+ php:
16
+ constantDeclaration: "define"
@@ -0,0 +1,16 @@
1
+ generator:
2
+ php:
3
+ constantDeclaration: "define"
4
+
5
+ items:
6
+ - type: constant
7
+ name: PI
8
+ value: 3.14159
9
+ description: "Mathematical constant for circle calculations."
10
+ - type: constant
11
+ name: DEFAULT_GREETING
12
+ value: "Hello, World!"
13
+ description: "Default greeting message."
14
+ generator:
15
+ php:
16
+ constantDeclaration: "const"
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Calculate the sum of two ints.
3
+ *
4
+ * @param a - The first operand.
5
+ * @param b - The second operand.
6
+ * @returns: The sum of the two numbers.
7
+ */
8
+ function add(a, b) {
9
+ // TODO: Implement function body
10
+ }
@@ -0,0 +1,14 @@
1
+ items:
2
+ - type: function
3
+ name: add
4
+ description: "Calculate the sum of two ints."
5
+ parameters:
6
+ - name: a
7
+ type: int
8
+ description: "The first operand."
9
+ - name: b
10
+ type: int
11
+ description: "The second operand."
12
+ return:
13
+ type: int
14
+ description: "The sum of the two numbers."
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Process an array of data with optional configuration.
3
+ *
4
+ * @param data - The data to process
5
+ * @param config - Optional configuration parameters
6
+ * @param callback - Optional callback for custom processing
7
+ * @returns
8
+ */
9
+ function processData(data, config, callback) {
10
+ // TODO: Implement function body
11
+ }
@@ -0,0 +1,19 @@
1
+ items:
2
+ - type: function
3
+ name: processData
4
+ description: "Process an array of data with optional configuration."
5
+ parameters:
6
+ - name: data
7
+ type: array
8
+ description: "The data to process"
9
+ - name: config
10
+ type: array
11
+ description: "Optional configuration parameters"
12
+ default: []
13
+ - name: callback
14
+ type: callable
15
+ description: "Optional callback for custom processing"
16
+ optional: true
17
+ default: null
18
+ return:
19
+ type: array
@@ -0,0 +1,9 @@
1
+ import { readFileSync } from 'node:fs';
2
+
3
+ export function normalizeEol(s: string): string {
4
+ return s.replace(/\r\n/g, '\n');
5
+ }
6
+
7
+ export function readExpected(filePath: string): string {
8
+ return normalizeEol(readFileSync(filePath, 'utf-8')).trim();
9
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "noEmit": true,
10
+ "allowImportingTsExtensions": true
11
+ },
12
+ "include": ["src", "tests"]
13
+ }
package/version.txt ADDED
@@ -0,0 +1 @@
1
+ 0.1.0