ifct2017 2.0.14 → 2.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 (111) hide show
  1. package/LICENSE +661 -21
  2. package/README.md +1019 -71
  3. package/abbreviations/index.csv +78 -0
  4. package/abbreviations/index.d.ts +39 -0
  5. package/abbreviations/index.js +103 -0
  6. package/abbreviations/index.txt +12 -0
  7. package/about/build.ts +31 -0
  8. package/about/index.d.ts +47 -0
  9. package/about/index.js +110 -0
  10. package/about/index.txt +174 -0
  11. package/build.ts +115 -0
  12. package/carbohydrates/index.csv +8 -0
  13. package/carbohydrates/index.d.ts +42 -0
  14. package/carbohydrates/index.js +112 -0
  15. package/carbohydrates/index.txt +14 -0
  16. package/codes/index.csv +2904 -0
  17. package/codes/index.d.ts +36 -0
  18. package/codes/index.js +102 -0
  19. package/codes/index.txt +12 -0
  20. package/columndescriptions/build.ts +22 -0
  21. package/columndescriptions/index.csv +215 -0
  22. package/columndescriptions/index.d.ts +44 -0
  23. package/columndescriptions/index.js +119 -0
  24. package/columns/build.ts +23 -0
  25. package/columns/index.csv +215 -0
  26. package/columns/index.d.ts +39 -0
  27. package/columns/index.js +111 -0
  28. package/columns/index.txt +71 -0
  29. package/compositingcentres/index.csv +7 -0
  30. package/compositingcentres/index.d.ts +35 -0
  31. package/compositingcentres/index.js +103 -0
  32. package/compositingcentres/index.txt +13 -0
  33. package/compositions/build.ts +212 -0
  34. package/compositions/index.csv +543 -0
  35. package/compositions/index.d.ts +254 -0
  36. package/compositions/index.js +204 -0
  37. package/compositionstats/build.ts +103 -0
  38. package/compositionstats/index.csv +4 -0
  39. package/compositionstats/index.d.ts +31 -0
  40. package/compositionstats/index.js +97 -0
  41. package/contents/index.csv +21 -0
  42. package/contents/index.d.ts +39 -0
  43. package/contents/index.js +102 -0
  44. package/contents/index.txt +13 -0
  45. package/deno.lock +67 -0
  46. package/descriptions/index.csv +543 -0
  47. package/descriptions/index.d.ts +45 -0
  48. package/descriptions/index.js +124 -0
  49. package/descriptions/index.txt +15 -0
  50. package/energies/index.csv +6 -0
  51. package/energies/index.d.ts +34 -0
  52. package/energies/index.js +101 -0
  53. package/energies/index.txt +13 -0
  54. package/frequencydistribution/index.csv +10 -0
  55. package/frequencydistribution/index.d.ts +36 -0
  56. package/frequencydistribution/index.js +90 -0
  57. package/frequencydistribution/index.txt +14 -0
  58. package/groups/index.csv +21 -0
  59. package/groups/index.d.ts +46 -0
  60. package/groups/index.js +118 -0
  61. package/groups/index.txt +14 -0
  62. package/hierarchy/asset.csv +215 -0
  63. package/hierarchy/asset.txt +70 -0
  64. package/hierarchy/build.ts +73 -0
  65. package/hierarchy/index.csv +215 -0
  66. package/hierarchy/index.d.ts +39 -0
  67. package/hierarchy/index.js +100 -0
  68. package/hierarchy/index.txt +14 -0
  69. package/index.d.ts +24 -28
  70. package/index.js +28 -39
  71. package/index.test.ts +717 -0
  72. package/intakes/build.ts +28 -0
  73. package/intakes/index.csv +42 -0
  74. package/intakes/index.d.ts +66 -0
  75. package/intakes/index.js +113 -0
  76. package/intakes/index.txt +20 -0
  77. package/jonesfactors/index.csv +15 -0
  78. package/jonesfactors/index.d.ts +35 -0
  79. package/jonesfactors/index.js +105 -0
  80. package/jonesfactors/index.txt +12 -0
  81. package/languages/index.csv +22 -0
  82. package/languages/index.d.ts +39 -0
  83. package/languages/index.js +103 -0
  84. package/languages/index.txt +12 -0
  85. package/methods/build.ts +101 -0
  86. package/methods/index.csv +37 -0
  87. package/methods/index.d.ts +39 -0
  88. package/methods/index.js +196 -0
  89. package/methods/index.txt +13 -0
  90. package/package.json +15 -63
  91. package/regions/index.csv +7 -0
  92. package/regions/index.d.ts +36 -0
  93. package/regions/index.js +100 -0
  94. package/regions/index.txt +12 -0
  95. package/representations/build.ts +133 -0
  96. package/representations/index.csv +215 -0
  97. package/representations/index.d.ts +36 -0
  98. package/representations/index.js +91 -0
  99. package/retentionfactors/groups.csv +21 -0
  100. package/retentionfactors/index.csv +215 -0
  101. package/samplingunits/index.csv +36 -0
  102. package/samplingunits/index.d.ts +39 -0
  103. package/samplingunits/index.js +110 -0
  104. package/samplingunits/index.txt +14 -0
  105. package/yieldfactors/index.csv +543 -0
  106. package/yieldfactors/index.d.ts +57 -0
  107. package/yieldfactors/index.js +158 -0
  108. package/yieldfactors/index.txt +294 -0
  109. package/corpus.js +0 -6
  110. package/corpus.min.js +0 -1
  111. package/pictures.d.ts +0 -41
@@ -0,0 +1,101 @@
1
+ // Copyright (C) 2025-26 Subhajit Sahu
2
+ // SPDX-License-Identifier: AGPL-3.0-or-later
3
+ // See LICENSE for full terms
4
+ import * as path from "@std/path";
5
+ import * as csv from "@std/csv";
6
+ import lunr from "lunr"; // @deno-types="npm:@types/lunr@2.3.7"
7
+ import * as columns from "../columns/index.ts";
8
+
9
+
10
+ const OVERRIDE = new Map([
11
+ ['crypxb', 'Carotenoids'],
12
+ ['cartg', 'Carotenoids'],
13
+ ['carta', 'Carotenoids'],
14
+ ['cartb', 'Carotenoids'],
15
+ ['cholc', 'Stigmasterol, β-Sitosterol, Campesterol, Ergosterol, 5-alpha-Cholestenol'],
16
+ ['phytac', 'Phyates'],
17
+ ['vitb', null],
18
+ ['vitd', 'Vitamin D2 & D3'],
19
+ ['vitk', 'Vitamin K1 & K2'],
20
+ ['olsac', 'Oligosaccharides (Raffinose, Stachyose, Verbascose and Ajugose)'],
21
+ ['phystr', 'Stigmasterol, β-Sitosterol, Campesterol, Ergosterol, 5-alpha-Cholestenol'],
22
+ ['mnrleq', null],
23
+ ['mnrlet', null],
24
+ ['mnrlpet', null],
25
+ ['mnrlnet', null],
26
+ ['mnrltx', null],
27
+ ['vit', null],
28
+ ]);
29
+
30
+
31
+ function bestMatch(idx: lunr.Index, txt: string) {
32
+ const a = []; txt = txt.replace(/\W/g, ' ');
33
+ const ms = idx.search(txt); let max = 0;
34
+ for (const m of ms)
35
+ max = Math.max(max, Object.keys(m.matchData.metadata).length);
36
+ for (const m of ms)
37
+ if (Object.keys(m.matchData.metadata).length===max) a.push(m);
38
+ return a;
39
+ }
40
+
41
+
42
+ function createIndex(arr: Record<string, string | number>[]) {
43
+ return lunr(function(this: lunr.Builder) {
44
+ this.ref('index');
45
+ this.field('analyte');
46
+ this.pipeline.remove(lunr.stopWordFilter);
47
+ for (let i=0, I=arr.length; i<I; i++)
48
+ this.add({index: i, analyte: (arr[i].analyte as string).replace(/\W+/g, ' ')});
49
+ });
50
+ }
51
+
52
+
53
+ async function createMap(idx: lunr.Index, mapping: Map<string, number>) {
54
+ const a = new Map();
55
+ let index = -1;
56
+ for (const c of (await columns.loadColumns()).values()) {
57
+ if (OVERRIDE.has(c.code)) {
58
+ const analyte = OVERRIDE.get(c.code);
59
+ index = analyte!=null? mapping.get(analyte) as number : -1;
60
+ }
61
+ else {
62
+ let tags = `${c.code} ${c.code} ${c.code} ${c.name} ${c.name} ${c.tags}`;
63
+ tags = tags.replace(/\W+/g, ' ').toLowerCase().trim();
64
+ const ms = idx.search(tags);
65
+ // if (c.code==='as') console.log(c, tags, ms);
66
+ index = ms.length>0? ms[0].ref : -1;
67
+ }
68
+ a.set(c.code, index);
69
+ // if (index>=0) console.log(c.code, '->', array[index].analyte, tags);
70
+ // if (c.code==='facis') console.log(ms);
71
+ }
72
+ return a;
73
+ }
74
+
75
+
76
+ async function writeCorpus(outfile: string) {
77
+ await columns.loadColumns();
78
+ const array: Record<string, string | number>[] = [], mapping = new Map();
79
+ const data = await Deno.readTextFile(path.join(import.meta.dirname || '', 'index.csv'));
80
+ const records = csv.parse(data, {skipFirstRow: true, comment: '#'}) as Record<string, string | number>[];
81
+ for (const r of records) {
82
+ mapping.set(r.analyte, array.length);
83
+ array.push(r);
84
+ }
85
+ let a = '';
86
+ const index = createIndex(array);
87
+ const map = await createMap(index, mapping);
88
+ for (let i=0, I=array.length; i<I; i++)
89
+ a += `const I${i} = ${JSON.stringify(array[i]).replace(/\"(\w+)\":/g, '$1:')};\n`;
90
+ a += `const CORPUS = new Map([\n`;
91
+ for (const [k, v] of map)
92
+ a += ` ["${k}", ${v>=0? 'I'+v:'null'}],\n`;
93
+ a += `]);\n`;
94
+ a += `module.exports = CORPUS;\n`;
95
+ await Deno.writeTextFile(outfile, a);
96
+ }
97
+
98
+
99
+ export async function build(corpus='corpus.js') {
100
+ if (corpus) await writeCorpus(corpus);
101
+ }
@@ -0,0 +1,37 @@
1
+ analyte,method,reference
2
+ Moisture,Gravimetric using vacuum / Hot air oven,AOAC 934.01
3
+ Protein,Titrimetry by combustion / Kjeldahl / Mixed catalyst,AOAC 2001.11; Jones (1941)
4
+ Ash,Gravimetric using Muffle furnace,AOAC 942.05
5
+ Total fat,Gravimetry; Ether extraction using Soxhlet apparatus,AOAC 963.15
6
+ "Total, soluble and insoluble dietary fiber",Enzymatic-gravimetric,AOAC 991.43
7
+ Available carbohydrate,Calculation by difference; Trienzyme extraction and spectrophotometry,Greenfield & Southgate (2003); AOAC 991.43; AOAC 985.29
8
+ Energy,Atwater conversion factors,Merrill & Watt (1973); FAO / INFOODS Guidelines (2012)
9
+ Thiamin,Fluorometry,AOAC 942.23; Ramasastri (1975)
10
+ Riboflavin,Turbidometric-Microbiological assay,AOAC 940.33; AOAC 960.46
11
+ Niacin,Turbidometric-Microbiological assay,AOAC 985.34; 960.46
12
+ Pantothenic acid,RP-HPLC with UV detector,David & Harvey (2000)
13
+ Vitamin B6,HPLC-fluorometric detection,AOAC 985.32; Ollilainen (2008)
14
+ Biotin,U-HPLC and LC-ESI-IT-MS method,Holler et al. (2006)
15
+ Vitamin B9,Trienzyme Extraction and U-HPLC - UV or fluorescence detection,Finglas et al. (1999); Vahteristo et al. (1996); AOAC 2011.06; AOAC 2013.13
16
+ Vitamin C,RP-HPLC,AOAC 985.33; Keating & Haddad (1982)
17
+ Vitamin E,HPLC,AOAC 992.03; AOAC 2012.10
18
+ Vitamin A,HPLC,AOAC 974.29; Bieri et al. (1979)
19
+ Carotenoids,HPLC,Delia & Mieko (2004)
20
+ Vitamin D2 & D3,RP- HPLC-APCI-MS.,AOAC 982.29
21
+ Vitamin K1 & K2,RP- HPLC-APCI-MS,AOAC 992.27
22
+ Free sugars,HPLC-RID,AOAC 2013.12
23
+ Starch,Calculated from the increase in the amount of glucose by using conversion factor,Casterline et al. (1998)
24
+ "Oligosaccharides (Raffinose, Stachyose, Verbascose and Ajugose)",HPLC,Frias et al. (1994); Johansen et al. (1996); Sanchez-Mata et al. (1998)
25
+ "Iron, Zinc, Copper, Manganese, Potassium, Magnesium, Sodium, Calcium",Atomic Absorption Spectrophotometry (AAS),
26
+ "Aluminium",Atomic Absorption Spectrophotometry (AAS); Inductively Coupled Plasma Mass Spectrometry (ICP-MS),AOAC 2013.06
27
+ "Heavy and trace metals Lead, Cadmium, Nickel, Cobalt, Chromium, Lithium, Molybdenum",Graphite furnace Atomic Absorption Spectrophotometry; Inductively Coupled Plasma Mass Spectrometry (ICP-MS),AOAC 968.08; AOAC 999.10; AOAC 999.11; AOAC 2013.06
28
+ "Heavy and trace metals Arsenic, Antimony, Mercury, and Selenium",Atomic Absorption Spectrophotometry (Hydride generation); Inductively Coupled Plasma Mass Spectrometry (ICP-MS),AOAC 2013.06
29
+ Phosphorus,Colorimetry,AOAC 935.45; AOAC 995.11; Fiske & Subbarow (1925)
30
+ "Citric acid, Malic acid, Fumaric acid, Succinic acid, Lactic acid, Cis-Aconitic acid, Tartaric acid and Quninic acid",HPLC,AOAC 969.30; AOAC 950.35; AOAC 948.14
31
+ "Oxalic acid (Total), Soluble oxalic acid, Insoluble oxalic acid",Fast- HPLC,Moreau & Savage (2009)
32
+ Fatty acid profile,Gas Chromatography with Flame Ionization Detector,AOAC 996.06; AOAC 996.01; AOAC 2012.13
33
+ Amino acid profile,Amino acid analyzer (Ion exchange chromatography),AOAC 994.12; AOAC 985.28; Landry & Delhaye (1992)
34
+ "Stigmasterol, β-Sitosterol, Campesterol, Ergosterol, 5-alpha-Cholestenol",Gas Chromatography (GC),AOAC 922.06; Sorenson & Sullivan (2007)
35
+ Polyphenols,HPLC,Sakakibara et al. (2003)
36
+ Phyates,Ion Exchange and Spectrophotometry,AOAC 986.11-1988
37
+ Total Saponin,Colorimetry,Dini et al. (2009)
@@ -0,0 +1,39 @@
1
+ import { type SetupTableOptions } from "@nodef/extra-sql";
2
+ /** Analytical methods for nutrient and bioactive component. */ export interface Method {
3
+ /** Analyte. */ analyte: string;
4
+ /** Method. */ method: string;
5
+ /** Reference. */ reference: string;
6
+ }
7
+ /**
8
+ * Load the methods corpus from the file.
9
+ * @returns methods corpus
10
+ */ export declare function loadMethods(): Promise<Map<string, Method>>;
11
+ /**
12
+ * Get the path to the methods CSV file.
13
+ * @returns CSV file URL
14
+ */ export declare function methodsCsv(): string;
15
+ /**
16
+ * Obtain SQL command to create and populate the methods table.
17
+ * @param tab table name
18
+ * @param opt options for the table
19
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
20
+ */ export declare function methodsSql(tab?: string, opt?: SetupTableOptions): Promise<string>;
21
+ /**
22
+ * Find matching methods of a column:code/name/tags query.
23
+ * @param txt column:code/name/tags query
24
+ * @returns `{analyte, method, reference}` if found, else null
25
+ * @example
26
+ * ```javascript
27
+ * ifct2017.methods('soluble oxalic acid');
28
+ * ifct2017.methods('Insoluble Oxalic Acid');
29
+ * // → { analyte: 'Oxalic acid (Total), Soluble oxalic acid, Insoluble oxalic acid',
30
+ * // → method: 'Fast- HPLC',
31
+ * // → reference: 'Moreau & Savage (2009)' }
32
+ *
33
+ * ifct2017.methods('what is analytical method of saponin?');
34
+ * ifct2017.methods('how is total saponin measured?');
35
+ * // → { analyte: 'Total Saponin',
36
+ * // → method: 'Colorimetry',
37
+ * // → reference: 'Dini et al. (2009)' }
38
+ * ```
39
+ */ export declare function methods(txt: string): Method | null;
@@ -0,0 +1,196 @@
1
+ // Copyright (C) 2025-26 Subhajit Sahu
2
+ // SPDX-License-Identifier: AGPL-3.0-or-later
3
+ // See LICENSE for full terms
4
+ import * as csv from "@std/csv";
5
+ import lunr from "lunr"; // @deno-types="npm:@types/lunr@2.3.7"
6
+ import { setupTable } from "@nodef/extra-sql";
7
+ import { loadColumns, columns } from "../columns/index.js";
8
+ //#endregion
9
+ //#region CONSTANTS
10
+ const OVERRIDE = new Map([
11
+ [
12
+ 'crypxb',
13
+ 'Carotenoids'
14
+ ],
15
+ [
16
+ 'cartg',
17
+ 'Carotenoids'
18
+ ],
19
+ [
20
+ 'carta',
21
+ 'Carotenoids'
22
+ ],
23
+ [
24
+ 'cartb',
25
+ 'Carotenoids'
26
+ ],
27
+ [
28
+ 'cholc',
29
+ 'Stigmasterol, β-Sitosterol, Campesterol, Ergosterol, 5-alpha-Cholestenol'
30
+ ],
31
+ [
32
+ 'phytac',
33
+ 'Phyates'
34
+ ],
35
+ [
36
+ 'vitb',
37
+ null
38
+ ],
39
+ [
40
+ 'vitd',
41
+ 'Vitamin D2 & D3'
42
+ ],
43
+ [
44
+ 'vitk',
45
+ 'Vitamin K1 & K2'
46
+ ],
47
+ [
48
+ 'olsac',
49
+ 'Oligosaccharides (Raffinose, Stachyose, Verbascose and Ajugose)'
50
+ ],
51
+ [
52
+ 'phystr',
53
+ 'Stigmasterol, β-Sitosterol, Campesterol, Ergosterol, 5-alpha-Cholestenol'
54
+ ],
55
+ [
56
+ 'mnrleq',
57
+ null
58
+ ],
59
+ [
60
+ 'mnrlet',
61
+ null
62
+ ],
63
+ [
64
+ 'mnrlpet',
65
+ null
66
+ ],
67
+ [
68
+ 'mnrlnet',
69
+ null
70
+ ],
71
+ [
72
+ 'mnrltx',
73
+ null
74
+ ],
75
+ [
76
+ 'vit',
77
+ null
78
+ ]
79
+ ]);
80
+ //#endregion
81
+ //#region GLOBALS
82
+ let corpus = null;
83
+ let index = null;
84
+ //#endregion
85
+ //#region FUNCTIONS
86
+ function bestMatchIndex(index, analyte) {
87
+ const txt = analyte.replace(/\W/g, ' ');
88
+ const ms = index.search(txt);
89
+ let max = 0;
90
+ for (const m of ms)max = Math.max(max, Object.keys(m.matchData.metadata).length);
91
+ for (const m of ms)if (Object.keys(m.matchData.metadata).length === max) return m.ref;
92
+ return -1;
93
+ }
94
+ /**
95
+ * Load the methods corpus from CSV file.
96
+ * @param file CSV file path
97
+ * @returns methods corpus
98
+ */ async function loadFromCsv(records, index) {
99
+ const map = new Map();
100
+ const ccolumns = await loadColumns();
101
+ let i = -1;
102
+ for (const c of ccolumns.values()){
103
+ if (OVERRIDE.has(c.code)) {
104
+ const analyte = OVERRIDE.get(c.code);
105
+ i = analyte != null ? bestMatchIndex(index, analyte) : -1;
106
+ } else {
107
+ let tags = `${c.code} ${c.code} ${c.code} ${c.name} ${c.name} ${c.tags}`;
108
+ tags = tags.replace(/\W+/g, ' ').toLowerCase().trim();
109
+ i = bestMatchIndex(index, tags);
110
+ // if (c.code==='as') console.log(c, tags, ms);
111
+ }
112
+ if (i >= 0) map.set(c.code, records[i]);
113
+ // if (index>=0) console.log(c.code, '->', array[index].analyte, tags);
114
+ // if (c.code==='facis') console.log(ms);
115
+ }
116
+ return map;
117
+ }
118
+ /**
119
+ * Setup the lunr index for the methods corpus.
120
+ * @param records records from CSV file
121
+ * @returns lunr index
122
+ */ function setupIndex(records) {
123
+ return lunr(function() {
124
+ this.ref('index');
125
+ this.field('analyte');
126
+ this.pipeline.remove(lunr.stopWordFilter);
127
+ for(let i = 0, I = records.length; i < I; i++)this.add({
128
+ index: i,
129
+ analyte: records[i].analyte.replace(/\W+/g, ' ')
130
+ });
131
+ });
132
+ }
133
+ /**
134
+ * Load the methods corpus from the file.
135
+ * @returns methods corpus
136
+ */ export async function loadMethods() {
137
+ if (corpus) return corpus;
138
+ const data = await (await fetch(methodsCsv())).text();
139
+ const records = csv.parse(data, {
140
+ skipFirstRow: true,
141
+ comment: '#'
142
+ });
143
+ index = setupIndex(records);
144
+ corpus = await loadFromCsv(records, index);
145
+ return corpus;
146
+ }
147
+ /**
148
+ * Get the path to the methods CSV file.
149
+ * @returns CSV file URL
150
+ */ export function methodsCsv() {
151
+ return import.meta.resolve('./index.csv');
152
+ }
153
+ /**
154
+ * Obtain SQL command to create and populate the methods table.
155
+ * @param tab table name
156
+ * @param opt options for the table
157
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
158
+ */ export async function methodsSql(tab = "methods", opt = {}) {
159
+ return setupTable(tab, {
160
+ analyte: "TEXT",
161
+ method: "TEXT",
162
+ reference: "TEXT"
163
+ }, (await loadMethods()).values(), Object.assign({
164
+ pk: "analyte",
165
+ index: true,
166
+ tsvector: {
167
+ analyte: "A",
168
+ method: "B",
169
+ reference: "C"
170
+ }
171
+ }, opt));
172
+ }
173
+ /**
174
+ * Find matching methods of a column:code/name/tags query.
175
+ * @param txt column:code/name/tags query
176
+ * @returns `{analyte, method, reference}` if found, else null
177
+ * @example
178
+ * ```javascript
179
+ * ifct2017.methods('soluble oxalic acid');
180
+ * ifct2017.methods('Insoluble Oxalic Acid');
181
+ * // → { analyte: 'Oxalic acid (Total), Soluble oxalic acid, Insoluble oxalic acid',
182
+ * // → method: 'Fast- HPLC',
183
+ * // → reference: 'Moreau & Savage (2009)' }
184
+ *
185
+ * ifct2017.methods('what is analytical method of saponin?');
186
+ * ifct2017.methods('how is total saponin measured?');
187
+ * // → { analyte: 'Total Saponin',
188
+ * // → method: 'Colorimetry',
189
+ * // → reference: 'Dini et al. (2009)' }
190
+ * ```
191
+ */ export function methods(txt) {
192
+ if (index == null) return null;
193
+ const cs = columns(txt);
194
+ return cs.length > 0 ? corpus?.get(cs[0].code) || null : null;
195
+ } //#endregion
196
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9pZmN0MjAxNy9pZmN0MjAxNy9tZXRob2RzL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoQykgMjAyNS0yNiBTdWJoYWppdCBTYWh1XG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb3ItbGF0ZXJcbi8vIFNlZSBMSUNFTlNFIGZvciBmdWxsIHRlcm1zXG5pbXBvcnQgKiBhcyBjc3YgIGZyb20gXCJAc3RkL2NzdlwiO1xuaW1wb3J0IGx1bnIgZnJvbSBcImx1bnJcIjsgIC8vIEBkZW5vLXR5cGVzPVwibnBtOkB0eXBlcy9sdW5yQDIuMy43XCJcbmltcG9ydCB7dHlwZSBSb3dEYXRhLCB0eXBlIFNldHVwVGFibGVPcHRpb25zLCBzZXR1cFRhYmxlfSBmcm9tIFwiQG5vZGVmL2V4dHJhLXNxbFwiO1xuaW1wb3J0IHtsb2FkQ29sdW1ucywgY29sdW1uc30gZnJvbSBcIi4uL2NvbHVtbnMvaW5kZXguanNcIjtcblxuXG5cblxuLy8jcmVnaW9uIFRZUEVTXG4vKiogQW5hbHl0aWNhbCBtZXRob2RzIGZvciBudXRyaWVudCBhbmQgYmlvYWN0aXZlIGNvbXBvbmVudC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0aG9kIHtcbiAgLyoqIEFuYWx5dGUuICovXG4gIGFuYWx5dGU6IHN0cmluZyxcbiAgLyoqIE1ldGhvZC4gKi9cbiAgbWV0aG9kOiBzdHJpbmcsXG4gIC8qKiBSZWZlcmVuY2UuICovXG4gIHJlZmVyZW5jZTogc3RyaW5nXG59O1xuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBDT05TVEFOVFNcbmNvbnN0IE9WRVJSSURFID0gbmV3IE1hcChbXG4gIFsnY3J5cHhiJywgICdDYXJvdGVub2lkcyddLFxuICBbJ2NhcnRnJywgICAnQ2Fyb3Rlbm9pZHMnXSxcbiAgWydjYXJ0YScsICAgJ0Nhcm90ZW5vaWRzJ10sXG4gIFsnY2FydGInLCAgICdDYXJvdGVub2lkcyddLFxuICBbJ2Nob2xjJywgICAnU3RpZ21hc3Rlcm9sLCDOsi1TaXRvc3Rlcm9sLCBDYW1wZXN0ZXJvbCwgRXJnb3N0ZXJvbCwgNS1hbHBoYS1DaG9sZXN0ZW5vbCddLFxuICBbJ3BoeXRhYycsICAnUGh5YXRlcyddLFxuICBbJ3ZpdGInLCAgICBudWxsXSxcbiAgWyd2aXRkJywgICAgJ1ZpdGFtaW4gRDIgJiBEMyddLFxuICBbJ3ZpdGsnLCAgICAnVml0YW1pbiBLMSAmIEsyJ10sXG4gIFsnb2xzYWMnLCAgICdPbGlnb3NhY2NoYXJpZGVzIChSYWZmaW5vc2UsIFN0YWNoeW9zZSwgVmVyYmFzY29zZSBhbmQgQWp1Z29zZSknXSxcbiAgWydwaHlzdHInLCAgJ1N0aWdtYXN0ZXJvbCwgzrItU2l0b3N0ZXJvbCwgQ2FtcGVzdGVyb2wsIEVyZ29zdGVyb2wsIDUtYWxwaGEtQ2hvbGVzdGVub2wnXSxcbiAgWydtbnJsZXEnLCAgbnVsbF0sXG4gIFsnbW5ybGV0JywgIG51bGxdLFxuICBbJ21ucmxwZXQnLCBudWxsXSxcbiAgWydtbnJsbmV0JywgbnVsbF0sXG4gIFsnbW5ybHR4JywgIG51bGxdLFxuICBbJ3ZpdCcsICAgICBudWxsXSxcbl0pO1xuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBHTE9CQUxTXG5sZXQgY29ycHVzOiBNYXA8c3RyaW5nLCBNZXRob2Q+IHwgbnVsbCA9IG51bGw7XG5sZXQgaW5kZXg6IGx1bnIuSW5kZXggfCBudWxsID0gbnVsbDtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gRlVOQ1RJT05TXG5mdW5jdGlvbiBiZXN0TWF0Y2hJbmRleChpbmRleDogbHVuci5JbmRleCwgYW5hbHl0ZTogc3RyaW5nKSB7XG4gIGNvbnN0IHR4dCA9IGFuYWx5dGUucmVwbGFjZSgvXFxXL2csICcgJyk7XG4gIGNvbnN0IG1zICA9IGluZGV4LnNlYXJjaCh0eHQpOyBsZXQgbWF4ID0gMDtcbiAgZm9yIChjb25zdCBtIG9mIG1zKVxuICAgIG1heCA9IE1hdGgubWF4KG1heCwgT2JqZWN0LmtleXMobS5tYXRjaERhdGEubWV0YWRhdGEpLmxlbmd0aCk7XG4gIGZvciAoY29uc3QgbSBvZiBtcylcbiAgICBpZiAoT2JqZWN0LmtleXMobS5tYXRjaERhdGEubWV0YWRhdGEpLmxlbmd0aD09PW1heCkgcmV0dXJuIG0ucmVmO1xuICByZXR1cm4gLTE7XG59XG5cblxuLyoqXG4gKiBMb2FkIHRoZSBtZXRob2RzIGNvcnB1cyBmcm9tIENTViBmaWxlLlxuICogQHBhcmFtIGZpbGUgQ1NWIGZpbGUgcGF0aFxuICogQHJldHVybnMgbWV0aG9kcyBjb3JwdXNcbiAqL1xuYXN5bmMgZnVuY3Rpb24gbG9hZEZyb21Dc3YocmVjb3JkczogTWV0aG9kW10sIGluZGV4OiBsdW5yLkluZGV4KSB7XG4gIGNvbnN0IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBNZXRob2Q+KCk7XG4gIGNvbnN0IGNjb2x1bW5zID0gYXdhaXQgbG9hZENvbHVtbnMoKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCBjIG9mIGNjb2x1bW5zLnZhbHVlcygpKSB7XG4gICAgaWYgKE9WRVJSSURFLmhhcyhjLmNvZGUpKSB7XG4gICAgICBjb25zdCBhbmFseXRlID0gT1ZFUlJJREUuZ2V0KGMuY29kZSk7XG4gICAgICBpID0gYW5hbHl0ZSE9bnVsbD8gYmVzdE1hdGNoSW5kZXgoaW5kZXgsIGFuYWx5dGUpIDogLTE7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgbGV0IHRhZ3MgPSBgJHtjLmNvZGV9ICR7Yy5jb2RlfSAke2MuY29kZX0gJHtjLm5hbWV9ICR7Yy5uYW1lfSAke2MudGFnc31gO1xuICAgICAgdGFncyA9IHRhZ3MucmVwbGFjZSgvXFxXKy9nLCAnICcpLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgaSA9IGJlc3RNYXRjaEluZGV4KGluZGV4LCB0YWdzKTtcbiAgICAgIC8vIGlmIChjLmNvZGU9PT0nYXMnKSBjb25zb2xlLmxvZyhjLCB0YWdzLCBtcyk7XG4gICAgfVxuICAgIGlmIChpID49IDApIG1hcC5zZXQoYy5jb2RlLCByZWNvcmRzW2ldKTtcbiAgICAvLyBpZiAoaW5kZXg+PTApIGNvbnNvbGUubG9nKGMuY29kZSwgJy0+JywgYXJyYXlbaW5kZXhdLmFuYWx5dGUsIHRhZ3MpO1xuICAgIC8vIGlmIChjLmNvZGU9PT0nZmFjaXMnKSBjb25zb2xlLmxvZyhtcyk7XG4gIH1cbiAgcmV0dXJuIG1hcDtcbn1cblxuXG4vKipcbiAqIFNldHVwIHRoZSBsdW5yIGluZGV4IGZvciB0aGUgbWV0aG9kcyBjb3JwdXMuXG4gKiBAcGFyYW0gcmVjb3JkcyByZWNvcmRzIGZyb20gQ1NWIGZpbGVcbiAqIEByZXR1cm5zIGx1bnIgaW5kZXhcbiAqL1xuZnVuY3Rpb24gc2V0dXBJbmRleChyZWNvcmRzOiBNZXRob2RbXSkge1xuICByZXR1cm4gbHVucihmdW5jdGlvbih0aGlzOiBsdW5yLkJ1aWxkZXIpIHtcbiAgICB0aGlzLnJlZignaW5kZXgnKTtcbiAgICB0aGlzLmZpZWxkKCdhbmFseXRlJyk7XG4gICAgdGhpcy5waXBlbGluZS5yZW1vdmUobHVuci5zdG9wV29yZEZpbHRlcik7XG4gICAgZm9yIChsZXQgaT0wLCBJPXJlY29yZHMubGVuZ3RoOyBpPEk7IGkrKylcbiAgICAgIHRoaXMuYWRkKHtpbmRleDogaSwgYW5hbHl0ZTogcmVjb3Jkc1tpXS5hbmFseXRlLnJlcGxhY2UoL1xcVysvZywgJyAnKX0pO1xuICB9KTtcbn1cblxuXG4vKipcbiAqIExvYWQgdGhlIG1ldGhvZHMgY29ycHVzIGZyb20gdGhlIGZpbGUuXG4gKiBAcmV0dXJucyBtZXRob2RzIGNvcnB1c1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9hZE1ldGhvZHMoKTogUHJvbWlzZTxNYXA8c3RyaW5nLCBNZXRob2Q+PiB7XG4gIGlmIChjb3JwdXMpIHJldHVybiBjb3JwdXM7XG4gIGNvbnN0IGRhdGEgPSBhd2FpdCAoYXdhaXQgZmV0Y2gobWV0aG9kc0NzdigpKSkudGV4dCgpO1xuICBjb25zdCByZWNvcmRzID0gY3N2LnBhcnNlKGRhdGEsIHtza2lwRmlyc3RSb3c6IHRydWUsIGNvbW1lbnQ6ICcjJ30pIGFzIHVua25vd24gYXMgTWV0aG9kW107XG4gIGluZGV4ICA9IHNldHVwSW5kZXgocmVjb3Jkcyk7XG4gIGNvcnB1cyA9IGF3YWl0IGxvYWRGcm9tQ3N2KHJlY29yZHMsIGluZGV4KTtcbiAgcmV0dXJuIGNvcnB1cztcbn1cblxuXG4vKipcbiAqIEdldCB0aGUgcGF0aCB0byB0aGUgbWV0aG9kcyBDU1YgZmlsZS5cbiAqIEByZXR1cm5zIENTViBmaWxlIFVSTFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWV0aG9kc0NzdigpOiBzdHJpbmcge1xuICByZXR1cm4gaW1wb3J0Lm1ldGEucmVzb2x2ZSgnLi9pbmRleC5jc3YnKTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiBTUUwgY29tbWFuZCB0byBjcmVhdGUgYW5kIHBvcHVsYXRlIHRoZSBtZXRob2RzIHRhYmxlLlxuICogQHBhcmFtIHRhYiB0YWJsZSBuYW1lXG4gKiBAcGFyYW0gb3B0IG9wdGlvbnMgZm9yIHRoZSB0YWJsZVxuICogQHJldHVybnMgQ1JFQVRFIFRBQkxFLCBJTlNFUlQsIENSRUFURSBWSUVXLCBDUkVBVEUgSU5ERVggc3RhdGVtZW50c1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWV0aG9kc1NxbCh0YWI6IHN0cmluZz1cIm1ldGhvZHNcIiwgb3B0OiBTZXR1cFRhYmxlT3B0aW9ucz17fSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBzZXR1cFRhYmxlKHRhYiwge2FuYWx5dGU6IFwiVEVYVFwiLCBtZXRob2Q6IFwiVEVYVFwiLCByZWZlcmVuY2U6IFwiVEVYVFwifSxcbiAgICAoYXdhaXQgbG9hZE1ldGhvZHMoKSkudmFsdWVzKCkgYXMgSXRlcmFibGU8Um93RGF0YT4sXG4gICAgT2JqZWN0LmFzc2lnbih7cGs6IFwiYW5hbHl0ZVwiLCBpbmRleDogdHJ1ZSwgdHN2ZWN0b3I6IHthbmFseXRlOiBcIkFcIiwgbWV0aG9kOiBcIkJcIiwgcmVmZXJlbmNlOiBcIkNcIn19LCBvcHQpKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgbWF0Y2hpbmcgbWV0aG9kcyBvZiBhIGNvbHVtbjpjb2RlL25hbWUvdGFncyBxdWVyeS5cbiAqIEBwYXJhbSB0eHQgY29sdW1uOmNvZGUvbmFtZS90YWdzIHF1ZXJ5XG4gKiBAcmV0dXJucyBge2FuYWx5dGUsIG1ldGhvZCwgcmVmZXJlbmNlfWAgaWYgZm91bmQsIGVsc2UgbnVsbFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGlmY3QyMDE3Lm1ldGhvZHMoJ3NvbHVibGUgb3hhbGljIGFjaWQnKTtcbiAqIGlmY3QyMDE3Lm1ldGhvZHMoJ0luc29sdWJsZSBPeGFsaWMgQWNpZCcpO1xuICogLy8g4oaSIHsgYW5hbHl0ZTogJ094YWxpYyBhY2lkIChUb3RhbCksIFNvbHVibGUgb3hhbGljIGFjaWQsIEluc29sdWJsZSBveGFsaWMgYWNpZCcsXG4gKiAvLyDihpIgICBtZXRob2Q6ICdGYXN0LSBIUExDJyxcbiAqIC8vIOKGkiAgIHJlZmVyZW5jZTogJ01vcmVhdSAmIFNhdmFnZSAoMjAwOSknIH1cbiAqXG4gKiBpZmN0MjAxNy5tZXRob2RzKCd3aGF0IGlzIGFuYWx5dGljYWwgbWV0aG9kIG9mIHNhcG9uaW4/Jyk7XG4gKiBpZmN0MjAxNy5tZXRob2RzKCdob3cgaXMgdG90YWwgc2Fwb25pbiBtZWFzdXJlZD8nKTtcbiAqIC8vIOKGkiB7IGFuYWx5dGU6ICdUb3RhbCBTYXBvbmluJyxcbiAqIC8vIOKGkiAgIG1ldGhvZDogJ0NvbG9yaW1ldHJ5JyxcbiAqIC8vIOKGkiAgIHJlZmVyZW5jZTogJ0RpbmkgZXQgYWwuICgyMDA5KScgfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRob2RzKHR4dDogc3RyaW5nKTogTWV0aG9kIHwgbnVsbCB7XG4gIGlmIChpbmRleCA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgY3MgPSBjb2x1bW5zKHR4dCk7XG4gIHJldHVybiBjcy5sZW5ndGg+MD8gY29ycHVzPy5nZXQoY3NbMF0uY29kZSkgfHwgbnVsbCA6IG51bGw7XG59XG4vLyNlbmRyZWdpb25cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxzQ0FBc0M7QUFDdEMsNkNBQTZDO0FBQzdDLDZCQUE2QjtBQUM3QixZQUFZLFNBQVUsV0FBVztBQUNqQyxPQUFPLFVBQVUsT0FBTyxDQUFFLHNDQUFzQztBQUNoRSxTQUE4QyxVQUFVLFFBQU8sbUJBQW1CO0FBQ2xGLFNBQVEsV0FBVyxFQUFFLE9BQU8sUUFBTyxzQkFBc0I7QUFlekQsWUFBWTtBQUtaLG1CQUFtQjtBQUNuQixNQUFNLFdBQVcsSUFBSSxJQUFJO0VBQ3ZCO0lBQUM7SUFBVztHQUFjO0VBQzFCO0lBQUM7SUFBVztHQUFjO0VBQzFCO0lBQUM7SUFBVztHQUFjO0VBQzFCO0lBQUM7SUFBVztHQUFjO0VBQzFCO0lBQUM7SUFBVztHQUEyRTtFQUN2RjtJQUFDO0lBQVc7R0FBVTtFQUN0QjtJQUFDO0lBQVc7R0FBSztFQUNqQjtJQUFDO0lBQVc7R0FBa0I7RUFDOUI7SUFBQztJQUFXO0dBQWtCO0VBQzlCO0lBQUM7SUFBVztHQUFrRTtFQUM5RTtJQUFDO0lBQVc7R0FBMkU7RUFDdkY7SUFBQztJQUFXO0dBQUs7RUFDakI7SUFBQztJQUFXO0dBQUs7RUFDakI7SUFBQztJQUFXO0dBQUs7RUFDakI7SUFBQztJQUFXO0dBQUs7RUFDakI7SUFBQztJQUFXO0dBQUs7RUFDakI7SUFBQztJQUFXO0dBQUs7Q0FDbEI7QUFDRCxZQUFZO0FBS1osaUJBQWlCO0FBQ2pCLElBQUksU0FBcUM7QUFDekMsSUFBSSxRQUEyQjtBQUMvQixZQUFZO0FBS1osbUJBQW1CO0FBQ25CLFNBQVMsZUFBZSxLQUFpQixFQUFFLE9BQWU7RUFDeEQsTUFBTSxNQUFNLFFBQVEsT0FBTyxDQUFDLE9BQU87RUFDbkMsTUFBTSxLQUFNLE1BQU0sTUFBTSxDQUFDO0VBQU0sSUFBSSxNQUFNO0VBQ3pDLEtBQUssTUFBTSxLQUFLLEdBQ2QsTUFBTSxLQUFLLEdBQUcsQ0FBQyxL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
@@ -0,0 +1,13 @@
1
+ Indian Food Composition Tables 2017
2
+ T. Longvah, R. Ananthan, K. Bhaskarachary and K. Venkaiah
3
+
4
+ Copyright © 2017 by National Institute of Nutrition
5
+ Indian Council of Medical Research
6
+ Department of Health Research Ministry of Health and Family Welfare, Government of India
7
+ Jamai Osmania (PO), Hyderabad – 500 007
8
+ Telangana, India Phone: +91 40 27197334, Fax: +91 40 27000339, Email: nin@ap.nic.in
9
+
10
+ ANALYTICAL METHODS OF NUTRIENT AND BIOACTIVE COMPONENTS
11
+ - Analyte
12
+ - Method
13
+ - Reference
package/package.json CHANGED
@@ -1,68 +1,20 @@
1
1
  {
2
2
  "name": "ifct2017",
3
- "version": "2.0.14",
4
- "description": "The Indian Food Composition tables (IFCT 2017) provides nutritional values for 528 key foods.",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "node ./build && node ./test",
8
- "build": "node ./build",
9
- "publish-docs": "node ./build publish-docs",
10
- "publish-packages": "node ./build publish-packages"
3
+ "version": "2.1.0",
4
+ "type": "module",
5
+ "license": "AGPL-3.0-or-later",
6
+ "main": "./index.js",
7
+ "types": "./index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./index.js",
12
+ "default": "./index.js"
13
+ }
11
14
  },
12
- "keywords": [
13
- "ifct",
14
- "2017",
15
- "indian",
16
- "food",
17
- "composition",
18
- "tables",
19
- "database",
20
- "carbohydrates",
21
- "proteins",
22
- "fats",
23
- "amino",
24
- "acids",
25
- "vitamins",
26
- "minerals",
27
- "national",
28
- "institute",
29
- "nutrition",
30
- "research"
31
- ],
32
- "author": "wolfram77@gmail.com",
33
- "license": "MIT",
34
- "repository": {
35
- "type": "git",
36
- "url": "git+https://github.com/ifct2017/ifct2017.git"
37
- },
38
- "bugs": {
39
- "url": "https://github.com/ifct2017/ifct2017/issues"
40
- },
41
- "homepage": "https://github.com/ifct2017/ifct2017#readme",
42
15
  "dependencies": {
43
- "@ifct2017/abbreviations": "^2.0.22",
44
- "@ifct2017/about": "^2.0.18",
45
- "@ifct2017/carbohydrates": "^2.0.13",
46
- "@ifct2017/codes": "^2.0.8",
47
- "@ifct2017/columns": "^2.0.13",
48
- "@ifct2017/compositingcentres": "^2.0.14",
49
- "@ifct2017/compositions": "^2.0.8",
50
- "@ifct2017/contents": "^2.0.27",
51
- "@ifct2017/descriptions": "^2.0.7",
52
- "@ifct2017/energies": "^2.0.12",
53
- "@ifct2017/frequencydistribution": "^2.0.15",
54
- "@ifct2017/groups": "^2.0.11",
55
- "@ifct2017/hierarchy": "^2.0.9",
56
- "@ifct2017/intakes": "^2.0.9",
57
- "@ifct2017/jonesfactors": "^2.0.11",
58
- "@ifct2017/languages": "^2.0.12",
59
- "@ifct2017/methods": "^2.0.11",
60
- "@ifct2017/nutrients": "^2.0.8",
61
- "@ifct2017/regions": "^2.0.12",
62
- "@ifct2017/representations": "^2.0.11",
63
- "@ifct2017/samplingunits": "^2.0.14"
64
- },
65
- "devDependencies": {
66
- "extra-build": "^2.2.29"
16
+ "@jsr/nodef__extra-sql": "^0.1.2",
17
+ "@jsr/std__csv": "^1.0.6",
18
+ "lunr": "^2.3.9"
67
19
  }
68
- }
20
+ }
@@ -0,0 +1,7 @@
1
+ region,states
2
+ Central,Chhattisgarh;Madhya Pradesh;Uttar Pradesh;Uttaranchal
3
+ East,Bihar;Jharkhand;Orissa;West Bengal
4
+ North,Chandigarh;Delhi;Haryana;Himachal Pradesh;Jammu & Kashmir;Punjab;Rajasthan
5
+ Northeast,Arunachal Pradesh;Assam;Manipur;Mizoram;Meghalaya;Nagaland;Sikkim;Tripura
6
+ South,Andaman & Nicobar Islands;Andhra Pradesh;Karnataka;Kerala;Lakshadweep;Pondicherry;Telangana;Tamil Nadu
7
+ West,Dadra & Nagar Haveli;Daman & Diu;Goa;Gujarat;Maharashtra
@@ -0,0 +1,36 @@
1
+ import { type SetupTableOptions } from "@nodef/extra-sql";
2
+ /** Categorization of the States/UTs into six different regions. */ export interface Region {
3
+ /** Region. */ region: string;
4
+ /** States/UTs. */ states: string;
5
+ }
6
+ /**
7
+ * Load the regions corpus from the file.
8
+ * @returns regions corpus
9
+ */ export declare function loadRegions(): Promise<Map<string, Region>>;
10
+ /**
11
+ * Get the path to the regions CSV file.
12
+ * @returns CSV file URL
13
+ */ export declare function regionsCsv(): string;
14
+ /**
15
+ * Obtain SQL command to create and populate the regions table.
16
+ * @param tab table name
17
+ * @param opt options for the table
18
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
19
+ */ export declare function regionsSql(tab?: string, opt?: SetupTableOptions): Promise<string>;
20
+ /**
21
+ * Find matching regions of a region/states query.
22
+ * @param txt region/states query
23
+ * @returns matches `[{region, states}]`
24
+ * @example
25
+ * ```javascript
26
+ * ifct2017.regions('central');
27
+ * ifct2017.regions('Uttaranchal');
28
+ * // → [ { region: 'Central',
29
+ * // → states: 'Chhattisgarh;Madhya Pradesh;Uttar Pradesh;Uttaranchal' } ]
30
+ *
31
+ * ifct2017.regions('which region andhra pradesh belongs to?');
32
+ * ifct2017.regions('details of south region');
33
+ * // → [ { region: 'South',
34
+ * // → states: 'Andaman & Nicobar Islands;Andhra Pradesh;Karnataka;Kerala;Lakshadweep;Pondicherry;Telangana;Tamil Nadu' } ]
35
+ * ```
36
+ */ export declare function regions(txt: string): Region[];
@@ -0,0 +1,100 @@
1
+ // Copyright (C) 2025-26 Subhajit Sahu
2
+ // SPDX-License-Identifier: AGPL-3.0-or-later
3
+ // See LICENSE for full terms
4
+ import * as csv from "@std/csv";
5
+ import lunr from "lunr"; // @deno-types="npm:@types/lunr@2.3.7"
6
+ import { setupTable } from "@nodef/extra-sql";
7
+ //#endregion
8
+ //#region GLOBALS
9
+ let corpus = null;
10
+ let index = null;
11
+ //#endregion
12
+ //#region FUNCTIONS
13
+ /**
14
+ * Load the regions corpus from CSV file.
15
+ * @param file CSV file path
16
+ * @returns regions corpus
17
+ */ async function loadFromCsv(file) {
18
+ const map = new Map();
19
+ const data = await (await fetch(file)).text();
20
+ const records = csv.parse(data, {
21
+ skipFirstRow: true,
22
+ comment: "#"
23
+ });
24
+ for (const r of records)map.set(r.region, r);
25
+ return map;
26
+ }
27
+ /**
28
+ * Setup the lunr index for the regions corpus.
29
+ * @returns lunr index
30
+ */ function setupIndex(corpus) {
31
+ return lunr(function() {
32
+ this.ref('region');
33
+ this.field('region');
34
+ this.field('states');
35
+ for (const r of corpus.values())this.add({
36
+ region: r.region,
37
+ states: r.states.replace(/\W/g, ' ')
38
+ });
39
+ });
40
+ }
41
+ /**
42
+ * Load the regions corpus from the file.
43
+ * @returns regions corpus
44
+ */ export async function loadRegions() {
45
+ if (corpus) return corpus;
46
+ corpus = await loadFromCsv(regionsCsv());
47
+ index = setupIndex(corpus);
48
+ return corpus;
49
+ }
50
+ /**
51
+ * Get the path to the regions CSV file.
52
+ * @returns CSV file URL
53
+ */ export function regionsCsv() {
54
+ return import.meta.resolve('./index.csv');
55
+ }
56
+ /**
57
+ * Obtain SQL command to create and populate the regions table.
58
+ * @param tab table name
59
+ * @param opt options for the table
60
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
61
+ */ export async function regionsSql(tab = "regions", opt = {}) {
62
+ return setupTable(tab, {
63
+ region: "TEXT",
64
+ states: "TEXT"
65
+ }, (await loadRegions()).values(), Object.assign({
66
+ pk: "region",
67
+ index: true,
68
+ tsvector: {
69
+ region: "A",
70
+ states: "B"
71
+ }
72
+ }, opt));
73
+ }
74
+ /**
75
+ * Find matching regions of a region/states query.
76
+ * @param txt region/states query
77
+ * @returns matches `[{region, states}]`
78
+ * @example
79
+ * ```javascript
80
+ * ifct2017.regions('central');
81
+ * ifct2017.regions('Uttaranchal');
82
+ * // → [ { region: 'Central',
83
+ * // → states: 'Chhattisgarh;Madhya Pradesh;Uttar Pradesh;Uttaranchal' } ]
84
+ *
85
+ * ifct2017.regions('which region andhra pradesh belongs to?');
86
+ * ifct2017.regions('details of south region');
87
+ * // → [ { region: 'South',
88
+ * // → states: 'Andaman & Nicobar Islands;Andhra Pradesh;Karnataka;Kerala;Lakshadweep;Pondicherry;Telangana;Tamil Nadu' } ]
89
+ * ```
90
+ */ export function regions(txt) {
91
+ if (index == null) return [];
92
+ const a = [];
93
+ txt = txt.replace(/\W/g, ' ');
94
+ const mats = index.search(txt);
95
+ let max = 0;
96
+ for (const mat of mats)max = Math.max(max, Object.keys(mat.matchData.metadata).length);
97
+ for (const mat of mats)if (Object.keys(mat.matchData.metadata).length === max) a.push(corpus?.get(mat.ref) || {});
98
+ return a;
99
+ } //#endregion
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9pZmN0MjAxNy9pZmN0MjAxNy9yZWdpb25zL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoQykgMjAyNS0yNiBTdWJoYWppdCBTYWh1XG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb3ItbGF0ZXJcbi8vIFNlZSBMSUNFTlNFIGZvciBmdWxsIHRlcm1zXG5pbXBvcnQgKiBhcyBjc3YgIGZyb20gXCJAc3RkL2NzdlwiO1xuaW1wb3J0IGx1bnIgZnJvbSBcImx1bnJcIjsgIC8vIEBkZW5vLXR5cGVzPVwibnBtOkB0eXBlcy9sdW5yQDIuMy43XCJcbmltcG9ydCB7dHlwZSBSb3dEYXRhLCB0eXBlIFNldHVwVGFibGVPcHRpb25zLCBzZXR1cFRhYmxlfSBmcm9tIFwiQG5vZGVmL2V4dHJhLXNxbFwiO1xuXG5cblxuXG4vLyNyZWdpb24gVFlQRVNcbi8qKiBDYXRlZ29yaXphdGlvbiBvZiB0aGUgU3RhdGVzL1VUcyBpbnRvIHNpeCBkaWZmZXJlbnQgcmVnaW9ucy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaW9uIHtcbiAgLyoqIFJlZ2lvbi4gKi9cbiAgcmVnaW9uOiBzdHJpbmcsXG4gIC8qKiBTdGF0ZXMvVVRzLiAqL1xuICBzdGF0ZXM6IHN0cmluZ1xufTtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gR0xPQkFMU1xubGV0IGNvcnB1czogTWFwPHN0cmluZywgUmVnaW9uPiB8IG51bGwgPSBudWxsO1xubGV0IGluZGV4OiBsdW5yLkluZGV4IHwgbnVsbCA9IG51bGw7XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIEZVTkNUSU9OU1xuLyoqXG4gKiBMb2FkIHRoZSByZWdpb25zIGNvcnB1cyBmcm9tIENTViBmaWxlLlxuICogQHBhcmFtIGZpbGUgQ1NWIGZpbGUgcGF0aFxuICogQHJldHVybnMgcmVnaW9ucyBjb3JwdXNcbiAqL1xuYXN5bmMgZnVuY3Rpb24gbG9hZEZyb21Dc3YoZmlsZTogc3RyaW5nKSB7XG4gIGNvbnN0IG1hcCAgPSBuZXcgTWFwPHN0cmluZywgUmVnaW9uPigpO1xuICBjb25zdCBkYXRhID0gYXdhaXQgKGF3YWl0IGZldGNoKGZpbGUpKS50ZXh0KCk7XG4gIGNvbnN0IHJlY29yZHMgPSBjc3YucGFyc2UoZGF0YSwge3NraXBGaXJzdFJvdzogdHJ1ZSwgY29tbWVudDogXCIjXCJ9KTtcbiAgZm9yIChjb25zdCByIG9mIHJlY29yZHMpXG4gICAgbWFwLnNldChyLnJlZ2lvbiwgciBhcyB1bmtub3duIGFzIFJlZ2lvbik7XG4gIHJldHVybiBtYXA7XG59XG5cblxuLyoqXG4gKiBTZXR1cCB0aGUgbHVuciBpbmRleCBmb3IgdGhlIHJlZ2lvbnMgY29ycHVzLlxuICogQHJldHVybnMgbHVuciBpbmRleFxuICovXG5mdW5jdGlvbiBzZXR1cEluZGV4KGNvcnB1czogTWFwPHN0cmluZywgUmVnaW9uPikge1xuICByZXR1cm4gbHVucihmdW5jdGlvbih0aGlzOiBsdW5yLkJ1aWxkZXIpIHtcbiAgICB0aGlzLnJlZigncmVnaW9uJyk7XG4gICAgdGhpcy5maWVsZCgncmVnaW9uJyk7XG4gICAgdGhpcy5maWVsZCgnc3RhdGVzJyk7XG4gICAgZm9yIChjb25zdCByIG9mIGNvcnB1cy52YWx1ZXMoKSlcbiAgICAgIHRoaXMuYWRkKHtyZWdpb246IHIucmVnaW9uLCBzdGF0ZXM6IHIuc3RhdGVzLnJlcGxhY2UoL1xcVy9nLCAnICcpfSk7XG4gIH0pO1xufVxuXG5cbi8qKlxuICogTG9hZCB0aGUgcmVnaW9ucyBjb3JwdXMgZnJvbSB0aGUgZmlsZS5cbiAqIEByZXR1cm5zIHJlZ2lvbnMgY29ycHVzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkUmVnaW9ucygpOiBQcm9taXNlPE1hcDxzdHJpbmcsIFJlZ2lvbj4+IHtcbiAgaWYgKGNvcnB1cykgcmV0dXJuIGNvcnB1cztcbiAgY29ycHVzID0gYXdhaXQgbG9hZEZyb21Dc3YocmVnaW9uc0NzdigpKTtcbiAgaW5kZXggID0gc2V0dXBJbmRleChjb3JwdXMpO1xuICByZXR1cm4gY29ycHVzO1xufVxuXG5cbi8qKlxuICogR2V0IHRoZSBwYXRoIHRvIHRoZSByZWdpb25zIENTViBmaWxlLlxuICogQHJldHVybnMgQ1NWIGZpbGUgVVJMXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpb25zQ3N2KCk6IHN0cmluZyB7XG4gIHJldHVybiBpbXBvcnQubWV0YS5yZXNvbHZlKCcuL2luZGV4LmNzdicpO1xufVxuXG5cbi8qKlxuICogT2J0YWluIFNRTCBjb21tYW5kIHRvIGNyZWF0ZSBhbmQgcG9wdWxhdGUgdGhlIHJlZ2lvbnMgdGFibGUuXG4gKiBAcGFyYW0gdGFiIHRhYmxlIG5hbWVcbiAqIEBwYXJhbSBvcHQgb3B0aW9ucyBmb3IgdGhlIHRhYmxlXG4gKiBAcmV0dXJucyBDUkVBVEUgVEFCTEUsIElOU0VSVCwgQ1JFQVRFIFZJRVcsIENSRUFURSBJTkRFWCBzdGF0ZW1lbnRzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWdpb25zU3FsKHRhYjogc3RyaW5nPVwicmVnaW9uc1wiLCBvcHQ6IFNldHVwVGFibGVPcHRpb25zPXt9KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIHNldHVwVGFibGUodGFiLCB7cmVnaW9uOiBcIlRFWFRcIiwgc3RhdGVzOiBcIlRFWFRcIn0sXG4gICAgKGF3YWl0IGxvYWRSZWdpb25zKCkpLnZhbHVlcygpIGFzIEl0ZXJhYmxlPFJvd0RhdGE+LFxuICAgIE9iamVjdC5hc3NpZ24oe3BrOiBcInJlZ2lvblwiLCBpbmRleDogdHJ1ZSwgdHN2ZWN0b3I6IHtyZWdpb246IFwiQVwiLCBzdGF0ZXM6IFwiQlwifX0sIG9wdCkpO1xufVxuXG5cbi8qKlxuICogRmluZCBtYXRjaGluZyByZWdpb25zIG9mIGEgcmVnaW9uL3N0YXRlcyBxdWVyeS5cbiAqIEBwYXJhbSB0eHQgcmVnaW9uL3N0YXRlcyBxdWVyeVxuICogQHJldHVybnMgbWF0Y2hlcyBgW3tyZWdpb24sIHN0YXRlc31dYFxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGlmY3QyMDE3LnJlZ2lvbnMoJ2NlbnRyYWwnKTtcbiAqIGlmY3QyMDE3LnJlZ2lvbnMoJ1V0dGFyYW5jaGFsJyk7XG4gKiAvLyDihpIgWyB7IHJlZ2lvbjogJ0NlbnRyYWwnLFxuICogLy8g4oaSICAgICBzdGF0ZXM6ICdDaGhhdHRpc2dhcmg7TWFkaHlhIFByYWRlc2g7VXR0YXIgUHJhZGVzaDtVdHRhcmFuY2hhbCcgfSBdXG4gKlxuICogaWZjdDIwMTcucmVnaW9ucygnd2hpY2ggcmVnaW9uIGFuZGhyYSBwcmFkZXNoIGJlbG9uZ3MgdG8/Jyk7XG4gKiBpZmN0MjAxNy5yZWdpb25zKCdkZXRhaWxzIG9mIHNvdXRoIHJlZ2lvbicpO1xuICogLy8g4oaSIFsgeyByZWdpb246ICdTb3V0aCcsXG4gKiAvLyDihpIgICAgIHN0YXRlczogJ0FuZGFtYW4gJiBOaWNvYmFyIElzbGFuZHM7QW5kaHJhIFByYWRlc2g7S2FybmF0YWthO0tlcmFsYTtMYWtzaGFkd2VlcDtQb25kaWNoZXJyeTtUZWxhbmdhbmE7VGFtaWwgTmFkdScgfSBdXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lvbnModHh0OiBzdHJpbmcpOiBSZWdpb25bXSB7XG4gIGlmIChpbmRleCA9PSBudWxsKSByZXR1cm4gW107XG4gIGNvbnN0IGE6IFJlZ2lvbltdID0gW107IHR4dCA9IHR4dC5yZXBsYWNlKC9cXFcvZywgJyAnKTtcbiAgY29uc3QgbWF0cyA9IGluZGV4LnNlYXJjaCh0eHQpOyBsZXQgbWF4ID0gMDtcbiAgZm9yIChjb25zdCBtYXQgb2YgbWF0cylcbiAgICBtYXggPSBNYXRoLm1heChtYXgsIE9iamVjdC5rZXlzKG1hdC5tYXRjaERhdGEubWV0YWRhdGEpLmxlbmd0aCk7XG4gIGZvciAoY29uc3QgbWF0IG9mIG1hdHMpXG4gICAgaWYgKE9iamVjdC5rZXlzKG1hdC5tYXRjaERhdGEubWV0YWRhdGEpLmxlbmd0aCA9PT0gbWF4KSBhLnB1c2goY29ycHVzPy5nZXQobWF0LnJlZikgfHwge30gYXMgUmVnaW9uKTtcbiAgcmV0dXJuIGE7XG59XG4vLyNlbmRyZWdpb25cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxzQ0FBc0M7QUFDdEMsNkNBQTZDO0FBQzdDLDZCQUE2QjtBQUM3QixZQUFZLFNBQVUsV0FBVztBQUNqQyxPQUFPLFVBQVUsT0FBTyxDQUFFLHNDQUFzQztBQUNoRSxTQUE4QyxVQUFVLFFBQU8sbUJBQW1CO0FBYWxGLFlBQVk7QUFLWixpQkFBaUI7QUFDakIsSUFBSSxTQUFxQztBQUN6QyxJQUFJLFFBQTJCO0FBQy9CLFlBQVk7QUFLWixtQkFBbUI7QUFDbkI7Ozs7Q0FJQyxHQUNELGVBQWUsWUFBWSxJQUFZO0VBQ3JDLE1BQU0sTUFBTyxJQUFJO0VBQ2pCLE1BQU0sT0FBTyxNQUFNLENBQUMsTUFBTSxNQUFNLEtBQUssRUFBRSxJQUFJO0VBQzNDLE1BQU0sVUFBVSxJQUFJLEtBQUssQ0FBQyxNQUFNO0lBQUMsY0FBYztJQUFNLFNBQVM7RUFBRztFQUNqRSxLQUFLLE1BQU0sS0FBSyxRQUNkLElBQUksR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFO0VBQ3BCLE9BQU87QUFDVDtBQUdBOzs7Q0FHQyxHQUNELFNBQVMsV0FBVyxNQUEyQjtFQUM3QyxPQUFPLEtBQUs7SUFDVixJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ1QsSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNYLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDWCxLQUFLLE1BQU0sS0FBSyxPQUFPLE1BQU0sR0FDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQztNQUFDLFFBQVEsRUFBRSxNQUFNO01BQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTztJQUFJO0VBQ3BFO0FBQ0Y7QUFHQTs7O0NBR0MsR0FDRCxPQUFPLGVBQWU7RUFDcEIsSUFBSSxRQUFRLE9BQU87RUFDbkIsU0FBUyxNQUFNLFlBQVk7RUFDM0IsUUFBUyxXQUFXO0VBQ3BCLE9BQU87QUFDVDtBQUdBOzs7Q0FHQyxHQUNELE9BQU8sU0FBUztFQUNkLE9BQU8sWUFBWSxPQUFPLENBQUM7QUFDN0I7QUFHQTs7Ozs7Q0FLQyxHQUNELE9BQU8sZUFBZSxXQUFXLE1BQVksU0FBUyxFQUFFLE1BQXVCLENBQUMsQ0FBQztFQUMvRSxPQUFPLFdBQVcsS0FBSztJQUFDLFFBQVE7SUFBUSxRQUFRO0VBQU0sR0FDcEQsQ0FBQyxNQUFNLGFBQWEsRUFBRSxNQUFNLElBQzVCLE9BQU8sTUFBTSxDQUFDO0lBQUMsSUFBSTtJQUFVLE9BQU87SUFBTSxVQUFVO01BQUMsUUFBUTtNQUFLLFFBQVE7SUFBRztFQUFDLEdBQUc7QUFDckY7QUFHQTs7Ozs7Ozs7Ozs7Ozs7OztDQWdCQyxHQUNELE9BQU8sU0FBUyxRQUFRLEdBQVc7RUFDakMsSUFBSSxTQUFTLE1BQU0sT0FBTyxFQUFFO0VBQzVCLE1BQU0sSUFBYyxFQUFFO0VBQUUsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPO0VBQ2pELE1BQU0sT0FBTyxNQUFNLE1BQU0sQ0FBQztFQUFNLElBQUksTUFBTTtFQUMxQyxLQUFLLE1BQU0sT0FBTyxLQUNoQixNQUFNLEtBQUssR0FBRyxDQUFDLEtBQUssT0FBTyxJQUFJLENBQUMsSUFBSSxTQUFTLENBQUMsUUFBUSxFQUFFLE1BQU07RUFDaEUsS0FBSyxNQUFNLE9BQU8sS0FDaEIsSUFBSSxPQUFPLElBQUksQ0FBQyxJQUFJLFNBQVMsQ0FBQyxRQUFRLEVBQUUsTUFBTSxLQUFLLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksR0FBRyxLQUFLLENBQUM7RUFDMUYsT0FBTztBQUNULEVBQ0EsWUFBWSJ9
@@ -0,0 +1,12 @@
1
+ Indian Food Composition Tables 2017
2
+ T. Longvah, R. Ananthan, K. Bhaskarachary and K. Venkaiah
3
+
4
+ Copyright © 2017 by National Institute of Nutrition
5
+ Indian Council of Medical Research
6
+ Department of Health Research Ministry of Health and Family Welfare, Government of India
7
+ Jamai Osmania (PO), Hyderabad – 500 007
8
+ Telangana, India Phone: +91 40 27197334, Fax: +91 40 27000339, Email: nin@ap.nic.in
9
+
10
+ CATEGORIZATION OF THE STATES/UTS INTO SIX DIFFERENT REGIONS
11
+ - Region
12
+ - States/UTs