tally-http-json 0.0.0-stage → 1.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KeshavSoft
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to do so, subject to the
10
+ following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,77 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # tally-extract
2
+
3
+ Fast, typed Tally XML & JSON client for Node.js, driven directly by structure specifications.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/tally-extract.svg)](https://www.npmjs.com/package/tally-extract)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ---
9
+
10
+ ## Features
11
+
12
+ - **Dual Return Flavor:** Query raw TDL XML responses or automatically parsed JSON objects.
13
+ - **Autocomplete Tree:** Fully typed dot-notation interface with IntelliSense for all endpoints (e.g. `tally.company.fetch()`, `tally.masters.units.all()`).
14
+ - **Direct Route Calls:** Invoke endpoints flexibly with path strings using `call()` or `asJson()`.
15
+ - **Zero Schema Dependencies:** Pure ES Module client with built-in TypeScript declarations.
16
+
17
+ ---
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install tally-extract
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Usage
28
+
29
+ Ensure your local Tally instance is running with ODBC / HTTP server enabled (default port `9000`).
30
+
31
+ ### 1. Autocomplete Dot-Notation
32
+
33
+ ```javascript
34
+ import tally from "tally-extract";
35
+
36
+ // 1. Fetch raw XML string
37
+ const xml = await tally.company.fetch("Company Name");
38
+ console.log(xml);
39
+
40
+ // 2. Fetch parsed JSON object directly
41
+ const json = await tally.company.fetch.asJson("Company Name");
42
+ console.log(json);
43
+
44
+ // Master routes
45
+ const units = await tally.masters.units.all.asJson("Company Name");
46
+ const stockItems = await tally.masters.stockItems.withBatches.asJson("Company Name");
47
+ ```
48
+
49
+ ### 2. Direct Route Invocation
50
+
51
+ ```javascript
52
+ import { call, asJson, getJson } from "tally-extract";
53
+
54
+ // Raw XML
55
+ const rawXml = await call("tally.company.fetch", "Company Name");
56
+
57
+ // Parsed JSON
58
+ const data = await asJson("tally.masters.units.all", "Company Name");
59
+ ```
60
+
61
+ ---
62
+
63
+ ## TypeScript Support
64
+
65
+ Full TypeScript IntelliSense definitions are bundled out of the box:
66
+
67
+ ```typescript
68
+ import tally, { call, asJson } from "tally-extract";
69
+ ```
70
+
71
+ All routes, parameter hints, and method signatures are auto-completed in VS Code and modern IDEs.
72
+
73
+ ---
74
+
75
+ ## License
76
+
77
+ [MIT](LICENSE) © [KeshavSoft](https://github.com/keshavsoft)
package/package.json CHANGED
@@ -1,6 +1,39 @@
1
- {
2
- "name": "tally-http-json",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "tally-http-json",
3
+ "version": "1.2.2",
4
+ "description": "Tally HTTP JSON client for TallyPrime",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js",
9
+ "./package.json": "./package.json"
10
+ },
11
+ "files": [
12
+ "src",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/keshavsoft/tally-http-json.git"
19
+ },
20
+ "homepage": "https://github.com/keshavsoft/tally-http-json#readme",
21
+ "bugs": {
22
+ "url": "https://github.com/keshavsoft/tally-http-json/issues"
23
+ },
24
+ "keywords": [
25
+ "tally",
26
+ "tally-prime",
27
+ "http",
28
+ "json",
29
+ "accounting"
30
+ ],
31
+ "license": "MIT",
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "devDependencies": {},
36
+ "dependencies": {
37
+ "tally-spec": "^1.5.1"
38
+ }
39
+ }
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default, noCompany } from "./v2/index.js";
@@ -0,0 +1,16 @@
1
+ import transport from "../transport.js";
2
+ import reportTemplate from "./template.js";
3
+
4
+ const report = async ({
5
+ reportId = "Stock Summary",
6
+ company = "mani9",
7
+ explode = true,
8
+ url = "http://localhost:9000"
9
+ } = {}) => {
10
+ const inXml = reportTemplate({ reportId, company, explode });
11
+ console.log("inXml : ", inXml);
12
+
13
+ return transport({ inXml, url });
14
+ };
15
+
16
+ export default report;
@@ -0,0 +1,23 @@
1
+ const stockSummaryTemplate = ({ company = "mani9", reportId = "Stock Summary", explode = true } = {}) => `
2
+ <ENVELOPE>
3
+ <HEADER>
4
+ <VERSION>1</VERSION>
5
+ <TALLYREQUEST>Export</TALLYREQUEST>
6
+ <TYPE>Data</TYPE>
7
+ <ID>${reportId}</ID>
8
+ </HEADER>
9
+ <BODY>
10
+ <DESC>
11
+ <STATICVARIABLES>
12
+ <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
13
+ <SVCURRENTCOMPANY>${company}</SVCURRENTCOMPANY>
14
+ <ITEM>Viaadi Hooks</ITEM>
15
+ ${explode ? "<EXPLODEFLAG>Yes</EXPLODEFLAG>" : ""}
16
+ </STATICVARIABLES>
17
+ </DESC>
18
+ </BODY>
19
+ </ENVELOPE>
20
+ `;
21
+
22
+ export default stockSummaryTemplate;
23
+ export { stockSummaryTemplate };
@@ -0,0 +1,69 @@
1
+ import tallySpec from "tally-spec";
2
+ import send from "./send/index.js";
3
+ import sendPeriod from "./send/period.js";
4
+ import byId from "./byId/index.js";
5
+
6
+ /**
7
+ * Story: Clean Tally XML Client (v12)
8
+ *
9
+ * Directly imports tally-spec for TDL definitions.
10
+ * Exposes:
11
+ * 1. companyFilter(inPath, inCompany): Fetches masters/company from Tally given a path and company name.
12
+ * 2. companyAndPeriodFilter(inPath, inCompany, inFromDate, inToDate): Fetches period vouchers from Tally.
13
+ * 3. reports(): Fetches reports (e.g. Stock Summary) from Tally.
14
+ */
15
+ const companyFilter = async (inPath, inCompany) => {
16
+ const localPath = inPath;
17
+ const localCompany = inCompany;
18
+
19
+ const endpoint = localPath.split(".").reduce((acc, key) => acc?.[key], tallySpec.source);
20
+
21
+ if (!endpoint?.tdl) {
22
+ throw new Error(`Master endpoint not found in structure: ${localPath}`);
23
+ }
24
+
25
+ return await send({
26
+ inTdlMessage: endpoint.tdl,
27
+ inCompany: localCompany
28
+ });
29
+ };
30
+
31
+ const companyAndPeriodFilter = async (inPath, inCompany, inFromDate, inToDate) => {
32
+ const localPath = inPath;
33
+ const localCompany = inCompany;
34
+ const localFromDate = inFromDate;
35
+ const localToDate = inToDate;
36
+
37
+ const endpoint = localPath.split(".").reduce((acc, key) => acc?.[key], tallySpec.source);
38
+
39
+ if (!endpoint?.tdl) {
40
+ throw new Error(`Master endpoint not found in structure: ${localPath}`);
41
+ }
42
+
43
+ return await sendPeriod({
44
+ inTdlMessage: endpoint.tdl,
45
+ inCompany: localCompany,
46
+ inFromDate: localFromDate,
47
+ inToDate: localToDate
48
+ });
49
+ };
50
+
51
+ const reports = async (inPath, inCompany) => {
52
+ const localPath = inPath;
53
+ const localCompany = inCompany;
54
+
55
+ const endpoint = localPath.split(".").reduce((acc, key) => acc?.[key], tallySpec.source);
56
+ // console.log("endpoint : ", endpoint);
57
+
58
+ if (!endpoint?.reportId) {
59
+ throw new Error(`Master endpoint not found in structure: ${localPath}`);
60
+ };
61
+
62
+ return await byId({
63
+ reportId: endpoint.reportId,
64
+ company: localCompany
65
+ });
66
+ };
67
+
68
+ export default companyFilter;
69
+ export { companyFilter, companyAndPeriodFilter, reports };
@@ -0,0 +1,31 @@
1
+ import transport from "../transport.js";
2
+ import { variableTemplate } from "./templates.js";
3
+
4
+ /**
5
+ * Story: Sending XML Payload to Tally
6
+ *
7
+ * 1. Wraps the TDL message into the Tally XML envelope.
8
+ * 2. Injects SVCURRENTCOMPANY if a company name is supplied.
9
+ * 3. Delegates HTTP dispatch to transport.
10
+ * 4. Returns the raw XML response text.
11
+ */
12
+ const startFunc = async ({ inTdlMessage, inCompany }) => {
13
+ const localTdlMessage = inTdlMessage;
14
+ const localCompany = inCompany;
15
+
16
+ let localXml = variableTemplate.replace("{{TDLMESSAGE}}", () => localTdlMessage);
17
+
18
+ if (localCompany) {
19
+ const companyTag = `<SVCURRENTCOMPANY>${localCompany}</SVCURRENTCOMPANY>`;
20
+ localXml = localXml.replace("{{STATICVARIABLES}}", companyTag);
21
+ } else {
22
+ localXml = localXml.replace("{{STATICVARIABLES}}", "");
23
+ }
24
+ console.log("localXml : ", localXml);
25
+
26
+ return await transport({
27
+ inXml: localXml
28
+ });
29
+ };
30
+
31
+ export default startFunc;
@@ -0,0 +1,36 @@
1
+ import transport from "../transport.js";
2
+ import { variableTemplate } from "./templates.js";
3
+
4
+ /**
5
+ * Story: Sending XML Payload to Tally with Period
6
+ *
7
+ * 1. Wraps the TDL message into the Tally XML envelope.
8
+ * 2. Injects SVCURRENTCOMPANY and date range into static variables.
9
+ * 3. Delegates HTTP dispatch to transport.
10
+ * 4. Returns the raw XML response text.
11
+ */
12
+ const startFunc = async ({ inTdlMessage, inCompany, inFromDate, inToDate }) => {
13
+ const localTdlMessage = inTdlMessage?.replaceAll("$$$$", "$$");
14
+ const localCompany = inCompany;
15
+ const localFromDate = inFromDate;
16
+ const localToDate = inToDate;
17
+
18
+ let localXml = variableTemplate.replace("{{TDLMESSAGE}}", () => localTdlMessage);
19
+
20
+ if (localCompany) {
21
+ const companyTag = `<SVCURRENTCOMPANY>${localCompany}</SVCURRENTCOMPANY>`;
22
+ const fromDateTag = `<SVFROMDATE TYPE="Date">${localFromDate}</SVFROMDATE>`;
23
+ const toDateTag = `<SVTODATE TYPE="Date">${localToDate}</SVTODATE>`;
24
+ localXml = localXml.replace("{{STATICVARIABLES}}", companyTag + fromDateTag + toDateTag);
25
+ } else {
26
+ const fromDateTag = `<SVFROMDATE TYPE="Date">${localFromDate}</SVFROMDATE>`;
27
+ const toDateTag = `<SVTODATE TYPE="Date">${localToDate}</SVTODATE>`;
28
+ localXml = localXml.replace("{{STATICVARIABLES}}", fromDateTag + toDateTag);
29
+ }
30
+
31
+ return await transport({
32
+ inXml: localXml
33
+ });
34
+ };
35
+
36
+ export default startFunc;
@@ -0,0 +1,90 @@
1
+ const companyTemplate = `<ENVELOPE>
2
+ <HEADER>
3
+ <VERSION>1</VERSION>
4
+ <TALLYREQUEST>Export</TALLYREQUEST>
5
+ <TYPE>Collection</TYPE>
6
+ <ID>ks</ID>
7
+ </HEADER>
8
+ <BODY>
9
+ <DESC>
10
+ <STATICVARIABLES>
11
+ <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
12
+ </STATICVARIABLES>
13
+ <TDL>
14
+ <TDLMESSAGE>
15
+ <COLLECTION NAME="ks">
16
+ {{TDLMESSAGE}}
17
+ </COLLECTION>
18
+ </TDLMESSAGE>
19
+ </TDL>
20
+ </DESC>
21
+ </BODY>
22
+ </ENVELOPE>`;
23
+
24
+ const variableTemplate = `<ENVELOPE>
25
+ <HEADER>
26
+ <VERSION>1</VERSION>
27
+ <TALLYREQUEST>Export</TALLYREQUEST>
28
+ <TYPE>Collection</TYPE>
29
+ <ID>ks</ID>
30
+ </HEADER>
31
+ <BODY>
32
+ <DESC>
33
+ <STATICVARIABLES>
34
+ <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
35
+ {{STATICVARIABLES}}
36
+ </STATICVARIABLES>
37
+ <TDL>
38
+ <TDLMESSAGE>
39
+ <COLLECTION NAME="ks">
40
+ {{TDLMESSAGE}}
41
+ </COLLECTION>
42
+ </TDLMESSAGE>
43
+ </TDL>
44
+ </DESC>
45
+ </BODY>
46
+ </ENVELOPE>`;
47
+
48
+ const K2 = `<ENVELOPE>
49
+ <HEADER>
50
+ <VERSION>1</VERSION>
51
+ <TALLYREQUEST>Export</TALLYREQUEST>
52
+ <TYPE>Collection</TYPE>
53
+ <ID>ks</ID>
54
+ </HEADER>
55
+
56
+ <BODY>
57
+ <DESC>
58
+ <STATICVARIABLES>
59
+ <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
60
+
61
+ <SVFROMDATE TYPE="Date">20260401</SVFROMDATE>
62
+ <SVTODATE TYPE="Date">20260401</SVTODATE>
63
+ </STATICVARIABLES>
64
+
65
+ <TDL>
66
+ <TDLMESSAGE>
67
+
68
+ <COLLECTION NAME="ks">
69
+ <TYPE>Vouchers:VoucherType</TYPE>
70
+ <CHILDOF>$$VchTypeSales</CHILDOF>
71
+ <BELONGSTO>Yes</BELONGSTO>
72
+
73
+ <FETCH>
74
+ Date,
75
+ VoucherNumber,
76
+ VoucherTypeName,
77
+ PartyLedgerName,
78
+ Amount,
79
+ AllInventoryEntries,
80
+ AllLedgerEntries
81
+ </FETCH>
82
+ </COLLECTION>
83
+
84
+ </TDLMESSAGE>
85
+ </TDL>
86
+ </DESC>
87
+ </BODY>
88
+ </ENVELOPE>`;
89
+
90
+ export { companyTemplate, variableTemplate, K2 };
@@ -0,0 +1 @@
1
+ export { default, reportTemplate } from "../../send/templates/reports/stockSummary.js";
@@ -0,0 +1,16 @@
1
+ const startFunc = async ({ inXml }) => {
2
+ const localXml = inXml;
3
+ const localUrl = "http://localhost:9000";
4
+
5
+ const response = await fetch(localUrl, {
6
+ method: "POST",
7
+ headers: {
8
+ "Content-Type": "text/xml"
9
+ },
10
+ body: localXml
11
+ });
12
+
13
+ return await response.text();
14
+ };
15
+
16
+ export default startFunc;
@@ -0,0 +1,8 @@
1
+ import noCompanyFromInternal from "./noCompany/index.js";
2
+
3
+ const noCompany = async (headerId = "") => {
4
+ return await noCompanyFromInternal({ inHeaderId: headerId });
5
+ };
6
+
7
+ export default noCompany;
8
+ export { noCompany };
@@ -0,0 +1,9 @@
1
+ {
2
+ "static_variables": [
3
+ {
4
+ "name": "svExportFormat",
5
+ "value": "jsonex"
6
+ }
7
+ ],
8
+ "fetch_list": []
9
+ }
@@ -0,0 +1,18 @@
1
+ import transport from "../transport.js";
2
+ import body from "./body.json" with { type: "json" };
3
+
4
+ const startFunc = async ({
5
+ inHeaderId,
6
+ inUrl = "http://localhost:9000"
7
+ } = {}) => {
8
+ const localHeaderId = inHeaderId;
9
+ const localUrl = inUrl;
10
+
11
+ return transport({
12
+ inHeaderId: localHeaderId,
13
+ inUrl: localUrl,
14
+ inBodyAsJson: JSON.stringify(body)
15
+ });
16
+ };
17
+
18
+ export default startFunc;
@@ -0,0 +1,21 @@
1
+ const startFunc = async ({ inBodyAsJson, inHeaderId, inUrl = "http://localhost:9000" }) => {
2
+ const localBodyAsJson = inBodyAsJson;
3
+ const localHeaderId = inHeaderId;
4
+ const localUrl = inUrl;
5
+
6
+ const response = await fetch(localUrl, {
7
+ method: "POST",
8
+ headers: {
9
+ "Content-Type": "application/json",
10
+ "version": "1",
11
+ "tallyrequest": "Export",
12
+ "type": "Collection",
13
+ "id": localHeaderId
14
+ },
15
+ body: localBodyAsJson
16
+ });
17
+
18
+ return await response.json();
19
+ };
20
+
21
+ export default startFunc;