tally-simple 1.1.1 → 1.8.2
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/CHANGELOG.md +8 -8
- package/LICENSE +21 -21
- package/README.md +176 -70
- package/bin/tally-simple.js +170 -175
- package/docs/.nojekyll +1 -0
- package/docs/architecture.html +73 -0
- package/docs/architecture.md +82 -43
- package/docs/execution-pipeline.html +71 -0
- package/docs/execution-pipeline.md +158 -0
- package/docs/index.html +294 -0
- package/docs/queries.html +107 -0
- package/docs/queries.md +122 -0
- package/docs/route-engine.html +57 -0
- package/docs/route-engine.md +141 -0
- package/docs/style.css +137 -0
- package/docs/usage.html +82 -0
- package/docs/usage.md +117 -73
- package/package.json +61 -47
- package/src/index.js +2 -8
- package/src/v5/external-api/api.js +21 -0
- package/src/v5/external-api/api.json +6 -0
- package/src/v5/index.js +1 -0
- package/src/v5/internal-working/execution/buildXmlBody.js +41 -0
- package/src/v5/internal-working/execution/getTdl.js +12 -0
- package/src/v5/internal-working/execution/index.js +30 -0
- package/src/v5/internal-working/execution/postHttp.js +26 -0
- package/src/v5/internal-working/execution/validateCompany.js +11 -0
- package/src/v5/internal-working/route/attachPath.js +25 -0
- package/src/v5/internal-working/route/createLeafHandler.js +17 -0
- package/src/v5/internal-working/route/index.js +24 -0
- package/src/{v1 → v5}/source.json +38 -40
- package/src/v6/external-api/api.js +21 -0
- package/src/v6/external-api/api.json +6 -0
- package/src/v6/index.js +1 -0
- package/src/v6/internal-working/execution/buildXmlBody.js +41 -0
- package/src/v6/internal-working/execution/getTdl.js +12 -0
- package/src/v6/internal-working/execution/index.js +30 -0
- package/src/v6/internal-working/execution/postHttp.js +26 -0
- package/src/v6/internal-working/execution/validateCompany.js +11 -0
- package/src/v6/internal-working/route/attachPath.js +25 -0
- package/src/v6/internal-working/route/createLeafHandler.js +17 -0
- package/src/v6/internal-working/route/index.js +24 -0
- package/src/v6/source.json +38 -0
- package/src/v7/api.json +6 -0
- package/src/v7/index.js +14 -0
- package/src/v7/internal-working/execution/buildXmlBody.js +41 -0
- package/src/v7/internal-working/execution/getTdl.js +12 -0
- package/src/v7/internal-working/execution/index.js +30 -0
- package/src/v7/internal-working/execution/postHttp.js +26 -0
- package/src/v7/internal-working/execution/validateCompany.js +11 -0
- package/src/v7/internal-working/route/attachPath.js +25 -0
- package/src/v7/internal-working/route/createLeafHandler.js +17 -0
- package/src/v7/internal-working/route/index.js +24 -0
- package/src/v7/source.json +38 -0
- package/src/v8/engine/index.js +18 -0
- package/src/v8/engine/parseXml.js +11 -0
- package/src/v8/index.js +21 -0
- package/docs/api.md +0 -19
- package/docs/cli.md +0 -32
- package/docs/development.md +0 -66
- package/src/index.d.ts +0 -36
- package/src/v1/external-api/api.js +0 -67
- package/src/v1/external-api/api.json +0 -5
- package/src/v1/external-api/index.js +0 -1
- package/src/v1/index.js +0 -1
- package/src/v1/traverse.js +0 -103
- package/src/v1/traverseObject/index.js +0 -39
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>System Architecture — Tally Simple</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div class="container">
|
|
11
|
+
<nav class="doc-nav">
|
|
12
|
+
<a href="index.html">← Documentation Hub</a>
|
|
13
|
+
<a href="architecture.md">View Markdown</a>
|
|
14
|
+
</nav>
|
|
15
|
+
|
|
16
|
+
<h1>System Architecture</h1>
|
|
17
|
+
<p>Tally Simple is designed with strict boundaries separating the public contract from the internal execution engines.</p>
|
|
18
|
+
|
|
19
|
+
<h2>Architectural Overview</h2>
|
|
20
|
+
<pre><code>┌─────────────────────────────────────────────────────────────┐
|
|
21
|
+
│ 1. Declarative Specifications │
|
|
22
|
+
│ │
|
|
23
|
+
│ src/v7/api.json src/v7/source.json │
|
|
24
|
+
│ (Public Route Allowlist) (TDL Definition Tree) │
|
|
25
|
+
└──────────────────────────────┬──────────────────────────────┘
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
29
|
+
│ 2. Public Composition Root │
|
|
30
|
+
│ │
|
|
31
|
+
│ src/v7/index.js │
|
|
32
|
+
│ (Injects Specifications into Route & Execution Engines) │
|
|
33
|
+
└──────────────────────────────┬──────────────────────────────┘
|
|
34
|
+
│
|
|
35
|
+
▼
|
|
36
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
37
|
+
│ 3. Internal Working Engines │
|
|
38
|
+
│ │
|
|
39
|
+
│ internal-working/route/ internal-working/execution│
|
|
40
|
+
│ (Object Tree Assembly) (4-Step Request Pipeline) │
|
|
41
|
+
└─────────────────────────────────────────────────────────────┘</code></pre>
|
|
42
|
+
|
|
43
|
+
<h2>The Three Layers</h2>
|
|
44
|
+
|
|
45
|
+
<h3>1. The Declarative Specifications (<code>src/v7/</code>)</h3>
|
|
46
|
+
<ul>
|
|
47
|
+
<li><strong><code>api.json</code> (The Allowlist)</strong>: An explicit array of dot-separated string paths that declare the public API boundary (e.g., <code>["tally.masters.units.fetch", "tally.masters.stockItems.withBatches", ...]</code>).</li>
|
|
48
|
+
<li><strong><code>source.json</code> (The Tree of Truth)</strong>: A pure domain tree containing the TDL collection queries (<code><TYPE>Unit</TYPE>...</code>) and actions. It is completely decoupled from transport and contains no connection settings or HTTP logic.</li>
|
|
49
|
+
</ul>
|
|
50
|
+
|
|
51
|
+
<h3>2. The Public Composition Root (<code>src/v7/index.js</code>)</h3>
|
|
52
|
+
<ul>
|
|
53
|
+
<li>Acts as the single entry point for the active version.</li>
|
|
54
|
+
<li>Imports <code>source.json</code> and <code>api.json</code> and injects them directly into the internal route builder via dependency injection.</li>
|
|
55
|
+
<li>Exports a single, ready-to-use default client object.</li>
|
|
56
|
+
</ul>
|
|
57
|
+
|
|
58
|
+
<h3>3. The Internal Working Engines (<code>src/v7/internal-working/</code>)</h3>
|
|
59
|
+
<ul>
|
|
60
|
+
<li><strong><code>route/</code></strong>: Dynamically builds the nested, callable JavaScript object tree based on <code>api.json</code> without hardcoding methods.</li>
|
|
61
|
+
<li><strong><code>execution/</code></strong>: Executes the runtime query: validates the company argument, retrieves the TDL query from <code>source.json</code>, constructs the XML request envelope, and dispatches the HTTP POST request to Tally.</li>
|
|
62
|
+
</ul>
|
|
63
|
+
|
|
64
|
+
<h2>Architectural Principles</h2>
|
|
65
|
+
<ol>
|
|
66
|
+
<li><strong>Single Source of Truth for Domain Only:</strong> <code>source.json</code> is the authority on <em>what queries exist and what TDL they request</em>, not a dumping ground for server URLs or HTTP headers.</li>
|
|
67
|
+
<li><strong>Strictly One Export per File:</strong> Every module in the codebase adheres to a single default export (<code>export default startFunc;</code>).</li>
|
|
68
|
+
<li><strong>Explicit Parameter Unwrapping:</strong> Every function accepts a single object with <code>in</code>-prefixed keys and unwraps them immediately to <code>local</code>-prefixed variables.</li>
|
|
69
|
+
<li><strong>Zero Runtime Dependencies:</strong> Built entirely on standard Node.js built-ins.</li>
|
|
70
|
+
</ol>
|
|
71
|
+
</div>
|
|
72
|
+
</body>
|
|
73
|
+
</html>
|
package/docs/architecture.md
CHANGED
|
@@ -1,43 +1,82 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
# System Architecture
|
|
2
|
+
|
|
3
|
+
[**View this document as HTML**](./architecture.html) · [**Documentation Hub**](./index.html)
|
|
4
|
+
|
|
5
|
+
Tally Simple is designed with strict boundaries separating the public contract from the internal execution engines.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Architectural Overview
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ 1. Declarative Specifications │
|
|
14
|
+
│ │
|
|
15
|
+
│ src/v7/api.json src/v7/source.json │
|
|
16
|
+
│ (Public Route Allowlist) (TDL Definition Tree) │
|
|
17
|
+
└──────────────────────────────┬──────────────────────────────┘
|
|
18
|
+
│
|
|
19
|
+
▼
|
|
20
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
21
|
+
│ 2. Public Composition Root │
|
|
22
|
+
│ │
|
|
23
|
+
│ src/v7/index.js │
|
|
24
|
+
│ (Injects Specifications into Route & Execution Engines) │
|
|
25
|
+
└──────────────────────────────┬──────────────────────────────┘
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
29
|
+
│ 3. Internal Working Engines │
|
|
30
|
+
│ │
|
|
31
|
+
│ internal-working/route/ internal-working/execution│
|
|
32
|
+
│ (Object Tree Assembly) (4-Step Request Pipeline) │
|
|
33
|
+
└─────────────────────────────────────────────────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The Three Layers
|
|
39
|
+
|
|
40
|
+
### 1. The Declarative Specifications (`src/v7/`)
|
|
41
|
+
- **`api.json` (The Allowlist)**: An explicit array of dot-separated string paths that declare the public API boundary (e.g., `["tally.masters.units.fetch", "tally.masters.stockItems.withBatches", ...]`).
|
|
42
|
+
- **`source.json` (The Tree of Truth)**: A pure domain tree containing the TDL collection queries (`<TYPE>Unit</TYPE>...`) and actions. It is completely decoupled from transport and contains **no** connection settings or HTTP logic.
|
|
43
|
+
|
|
44
|
+
### 2. The Public Composition Root (`src/v7/index.js`)
|
|
45
|
+
- Acts as the single entry point for the active version.
|
|
46
|
+
- Imports `source.json` and `api.json` and injects them directly into the internal route builder:
|
|
47
|
+
```javascript
|
|
48
|
+
const tally = createRoute({
|
|
49
|
+
inApiPaths: apiPaths,
|
|
50
|
+
inSource: source,
|
|
51
|
+
inExecutor: execute
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
- Exports a single, ready-to-use default client object.
|
|
55
|
+
|
|
56
|
+
### 3. The Internal Working Engines (`src/v7/internal-working/`)
|
|
57
|
+
- **`route/`**: Dynamically builds the nested, callable JavaScript object tree based on `api.json` without hardcoding methods.
|
|
58
|
+
- **`execution/`**: Executes the runtime query: validates the company argument, retrieves the TDL query from `source.json`, constructs the XML request envelope, and dispatches the HTTP POST request to Tally.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Architectural Principles
|
|
63
|
+
|
|
64
|
+
1. **Single Source of Truth for Domain Only:**
|
|
65
|
+
`source.json` is the sole authority on *what queries exist and what TDL they request*, not a dumping ground for server URLs or HTTP headers.
|
|
66
|
+
|
|
67
|
+
2. **Strictly One Export per File:**
|
|
68
|
+
Every module in the codebase adheres to a single default export (`export default startFunc;`).
|
|
69
|
+
|
|
70
|
+
3. **Explicit Parameter Unwrapping:**
|
|
71
|
+
Every function accepts a single object with `in`-prefixed keys and unwraps them immediately to `local`-prefixed variables:
|
|
72
|
+
```javascript
|
|
73
|
+
const startFunc = ({ inRoutePath, inCompany, inSource }) => {
|
|
74
|
+
const localRoutePath = inRoutePath;
|
|
75
|
+
const localCompany = inCompany;
|
|
76
|
+
const localSource = inSource;
|
|
77
|
+
// ...
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
4. **Zero Runtime Dependencies:**
|
|
82
|
+
Built entirely on standard Node.js built-ins. No intermediate proxy frameworks, no third-party HTTP libraries.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Execution Pipeline — Tally Simple</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div class="container">
|
|
11
|
+
<nav class="doc-nav">
|
|
12
|
+
<a href="index.html">← Documentation Hub</a>
|
|
13
|
+
<a href="execution-pipeline.md">View Markdown</a>
|
|
14
|
+
</nav>
|
|
15
|
+
|
|
16
|
+
<h1>Execution Pipeline</h1>
|
|
17
|
+
<p>When a consumer invokes an endpoint like <code>tally.masters.units.fetch("Mani9")</code>, the execution engine handles the request through a clean, 4-step pipeline.</p>
|
|
18
|
+
|
|
19
|
+
<h2>The Pipeline Flow</h2>
|
|
20
|
+
<pre><code>Invocation: tally.masters.units.fetch("Mani9")
|
|
21
|
+
│
|
|
22
|
+
▼
|
|
23
|
+
Step 1: validateCompany({ inCompany })
|
|
24
|
+
│ Ensures company is a non-empty string; returns trimmed name
|
|
25
|
+
▼
|
|
26
|
+
Step 2: getTdl({ inSource, inRoutePath })
|
|
27
|
+
│ Direct O(1) path lookup of TDL collection query from source.json
|
|
28
|
+
▼
|
|
29
|
+
Step 3: buildXmlBody({ inCompany, inTdl })
|
|
30
|
+
│ XML-escapes company name and injects into XML envelope template
|
|
31
|
+
▼
|
|
32
|
+
Step 4: postHttp({ inXmlBody })
|
|
33
|
+
│ Sends HTTP POST to Tally (http://localhost:9000) and returns XML text
|
|
34
|
+
▼
|
|
35
|
+
Caller receives raw XML string</code></pre>
|
|
36
|
+
|
|
37
|
+
<h2>The Four Narrative Steps</h2>
|
|
38
|
+
|
|
39
|
+
<h3>Step 1: Validate Company Name (<code>validateCompany.js</code>)</h3>
|
|
40
|
+
<p>Verifies that the supplied company name is a non-empty string. Throws early if invalid.</p>
|
|
41
|
+
|
|
42
|
+
<h3>Step 2: Direct TDL Lookup (<code>getTdl.js</code>)</h3>
|
|
43
|
+
<p>Instead of crawling or traversing the JSON structure, the endpoint is retrieved in a single line using path reduction.</p>
|
|
44
|
+
|
|
45
|
+
<h3>Step 3: XML Body Construction (<code>buildXmlBody.js</code>)</h3>
|
|
46
|
+
<p>Safely escapes XML special characters in the company name and substitutes <code>{company}</code> and <code>{collectionBody}</code> into the envelope template.</p>
|
|
47
|
+
|
|
48
|
+
<h3>Step 4: HTTP Transport (<code>postHttp.js</code>)</h3>
|
|
49
|
+
<p>Performs a standard <code>POST</code> request to <code>http://localhost:9000</code> with <code>Content-Type: text/xml</code>.</p>
|
|
50
|
+
|
|
51
|
+
<h2>The Coordinator (<code>index.js</code>)</h2>
|
|
52
|
+
<p>The main entry point reads like a 4-line story:</p>
|
|
53
|
+
<pre><code>const companyName = validateCompany({ inCompany: localCompany });
|
|
54
|
+
const tdl = getTdl({ inSource: localSource, inRoutePath: localRoutePath });
|
|
55
|
+
const xmlBody = buildXmlBody({ inCompany: companyName, inTdl: tdl });
|
|
56
|
+
|
|
57
|
+
return await postHttp({ inXmlBody: xmlBody });</code></pre>
|
|
58
|
+
|
|
59
|
+
<h2>Architectural Highlights</h2>
|
|
60
|
+
<ul>
|
|
61
|
+
<li><strong>Direct Resolution:</strong> No recursion, no skipping keys, no runtime guessing.</li>
|
|
62
|
+
<li><strong>Single Responsibility:</strong> Each file does exactly one job.</li>
|
|
63
|
+
<li><strong>Strict Single Export:</strong> Every file exports <code>export default startFunc;</code>.</li>
|
|
64
|
+
</ul>
|
|
65
|
+
|
|
66
|
+
<footer>
|
|
67
|
+
<p>© KeshavSoft. Distributed under the MIT License.</p>
|
|
68
|
+
</footer>
|
|
69
|
+
</div>
|
|
70
|
+
</body>
|
|
71
|
+
</html>
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Execution Pipeline
|
|
2
|
+
|
|
3
|
+
[**View this document as HTML**](./execution-pipeline.html) · [**Documentation Hub**](./index.html)
|
|
4
|
+
|
|
5
|
+
When a consumer invokes an endpoint like `tally.masters.units.fetch("Mani9")`, the execution engine handles the request through a clean, 4-step pipeline.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Pipeline Flow
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Invocation: tally.masters.units.fetch("Mani9")
|
|
13
|
+
│
|
|
14
|
+
▼
|
|
15
|
+
Step 1: validateCompany({ inCompany })
|
|
16
|
+
│ Ensures company is a non-empty string; returns trimmed name
|
|
17
|
+
▼
|
|
18
|
+
Step 2: getTdl({ inSource, inRoutePath })
|
|
19
|
+
│ Direct O(1) path lookup of TDL collection query from source.json
|
|
20
|
+
▼
|
|
21
|
+
Step 3: buildXmlBody({ inCompany, inTdl })
|
|
22
|
+
│ XML-escapes company name and injects into XML envelope template
|
|
23
|
+
▼
|
|
24
|
+
Step 4: postHttp({ inXmlBody })
|
|
25
|
+
│ Sends HTTP POST to Tally (http://localhost:9000) and returns XML text
|
|
26
|
+
▼
|
|
27
|
+
Caller receives raw XML string
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## The Four Narrative Steps
|
|
33
|
+
|
|
34
|
+
Each step is encapsulated in its own focused module under `internal-working/execution/`:
|
|
35
|
+
|
|
36
|
+
### Step 1: Validate Company Name (`validateCompany.js`)
|
|
37
|
+
|
|
38
|
+
Verifies that the supplied company name is a non-empty string. Throws early if invalid:
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
const startFunc = ({ inCompany }) => {
|
|
42
|
+
const localCompany = inCompany;
|
|
43
|
+
|
|
44
|
+
if (typeof localCompany !== "string" || !localCompany.trim()) {
|
|
45
|
+
throw new TypeError("Company name is required.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return localCompany.trim();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default startFunc;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### Step 2: Direct TDL Lookup (`getTdl.js`)
|
|
57
|
+
|
|
58
|
+
Instead of crawling or traversing the JSON structure, the endpoint is retrieved in a single line using path reduction:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const startFunc = ({ inSource, inRoutePath }) => {
|
|
62
|
+
const localSource = inSource;
|
|
63
|
+
const localRoutePath = inRoutePath;
|
|
64
|
+
|
|
65
|
+
const endpoint = localRoutePath
|
|
66
|
+
.split(".")
|
|
67
|
+
.reduce((current, key) => current?.[key], localSource);
|
|
68
|
+
|
|
69
|
+
return endpoint?.tdl;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default startFunc;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Step 3: XML Body Construction (`buildXmlBody.js`)
|
|
78
|
+
|
|
79
|
+
Safely escapes XML special characters (`&`, `<`, `>`, `"`, `'`) in the company name and substitutes `{company}` and `{collectionBody}` into the envelope template:
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
const startFunc = ({ inCompany, inTdl }) => {
|
|
83
|
+
const localCompany = inCompany;
|
|
84
|
+
const localTdl = inTdl;
|
|
85
|
+
|
|
86
|
+
return xmlEnvelopeTemplate
|
|
87
|
+
.replace("{company}", escapeXml(localCompany))
|
|
88
|
+
.replace("{collectionBody}", localTdl?.collection ?? "");
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default startFunc;
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### Step 4: HTTP Transport (`postHttp.js`)
|
|
97
|
+
|
|
98
|
+
Performs a standard `POST` request to `http://localhost:9000` with `Content-Type: text/xml`:
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const url = "http://localhost:9000";
|
|
102
|
+
const headers = { "Content-Type": "text/xml" };
|
|
103
|
+
|
|
104
|
+
const startFunc = async ({ inXmlBody }) => {
|
|
105
|
+
const localXmlBody = inXmlBody;
|
|
106
|
+
|
|
107
|
+
const response = await fetch(url, {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: headers,
|
|
110
|
+
body: localXmlBody
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const responseText = await response.text();
|
|
114
|
+
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error(`Tally request failed with HTTP ${response.status}: ${responseText}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return responseText;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export default startFunc;
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### The Coordinator (`index.js`)
|
|
128
|
+
|
|
129
|
+
The main entry point reads like a 4-line story:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import validateCompany from "./validateCompany.js";
|
|
133
|
+
import getTdl from "./getTdl.js";
|
|
134
|
+
import buildXmlBody from "./buildXmlBody.js";
|
|
135
|
+
import postHttp from "./postHttp.js";
|
|
136
|
+
|
|
137
|
+
const startFunc = async ({ inRoutePath, inCompany, inSource }) => {
|
|
138
|
+
const localRoutePath = inRoutePath;
|
|
139
|
+
const localCompany = inCompany;
|
|
140
|
+
const localSource = inSource;
|
|
141
|
+
|
|
142
|
+
const companyName = validateCompany({ inCompany: localCompany });
|
|
143
|
+
const tdl = getTdl({ inSource: localSource, inRoutePath: localRoutePath });
|
|
144
|
+
const xmlBody = buildXmlBody({ inCompany: companyName, inTdl: tdl });
|
|
145
|
+
|
|
146
|
+
return await postHttp({ inXmlBody: xmlBody });
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export default startFunc;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Architectural Highlights
|
|
155
|
+
|
|
156
|
+
- **Direct Resolution:** No recursion, no skipping keys, no runtime guessing.
|
|
157
|
+
- **Single Responsibility:** Each file does exactly one job.
|
|
158
|
+
- **Strict Single Export:** Every file exports `export default startFunc;`.
|