@wanasapps/deluge-core 1.2.0 → 1.3.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wanasapps/deluge-core",
3
- "version": "1.2.0",
4
- "description": "Deluge language tooling for every Zoho product: formatter, source transforms, TextMate grammar, snippets, an editor-agnostic linter, and AI-agent skills \u2014 a guide with runtime traps verified on a live org, plus a complete reference of every statement, data type, built-in function and integration task generated from Zoho's Deluge documentation. No I/O, no HTTP, no editor dependency.",
3
+ "version": "1.3.0",
4
+ "description": "Deluge language tooling for every Zoho product: formatter, source transforms, TextMate grammar, snippets, an editor-agnostic linter, and AI-agent skills a guide with runtime traps verified on a live org, plus a complete reference of every statement, data type, built-in function and integration task generated from Zoho's Deluge documentation. No I/O, no HTTP, no editor dependency.",
5
5
  "main": "src/index.js",
6
6
  "files": [
7
7
  "src",
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Refuse to publish before the @wanasapps packages this one depends on.
4
+ *
5
+ * These five packages are independent repos, not a workspace. Publishing a
6
+ * consumer before its cores yields a package npm cannot install — it has
7
+ * happened before (zone 0.4.3). CI runs this before `npm ci`, so the failure
8
+ * names the missing package instead of surfacing as a bare ETARGET.
9
+ */
10
+ 'use strict';
11
+ const cp = require('child_process');
12
+ const pj = require('../package.json');
13
+
14
+ const deps = { ...(pj.dependencies || {}), ...(pj.peerDependencies || {}) };
15
+ const wanas = Object.entries(deps).filter(([n]) => n.startsWith('@wanasapps'));
16
+
17
+ if (!wanas.length) {
18
+ console.log('no @wanasapps dependencies — nothing to check');
19
+ process.exit(0);
20
+ }
21
+
22
+ // A lockfile that records a local link resolves on the dev machine and
23
+ // nowhere else: `npm ci` creates the link, exits 0, and the module is
24
+ // missing at runtime. Caught zoho-api 1.1.1 in CI.
25
+ try {
26
+ const lock = require('../package-lock.json');
27
+ const linked = Object.entries(lock.packages || {})
28
+ .filter(([, v]) => v && v.link)
29
+ .map(([k]) => k.replace('node_modules/', ''));
30
+ if (linked.length) {
31
+ console.error(` LINKED ${linked.join(', ')} recorded as a local link in package-lock.json`);
32
+ console.error(' Regenerate it against the registry: npm install --package-lock-only');
33
+ process.exit(1);
34
+ }
35
+ } catch { /* no lockfile is fine */ }
36
+
37
+ let missing = 0;
38
+ for (const [name, range] of wanas) {
39
+ let found = '';
40
+ try {
41
+ // --json so a range matching several versions returns an array, rather
42
+ // than npm's "<name>@<ver> '<ver>'" lines, which are awkward to parse.
43
+ const raw = cp.execSync(`npm view ${name}@"${range}" version --json`, {
44
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore']
45
+ }).trim();
46
+ const parsed = raw ? JSON.parse(raw) : null;
47
+ found = Array.isArray(parsed) ? parsed[parsed.length - 1] : (parsed || '');
48
+ } catch { /* not published, or the range matches nothing */ }
49
+
50
+ if (found) {
51
+ console.log(` ok ${name}@${range} -> ${found}`);
52
+ } else {
53
+ console.error(` MISSING ${name}@${range} does not resolve on npm`);
54
+ missing++;
55
+ }
56
+ }
57
+
58
+ if (missing) {
59
+ console.error('\nPublish bottom-up:');
60
+ console.error(' deluge-core -> zoho-auth -> zoho-api -> zcrm-core -> wanas-zone-cli');
61
+ process.exit(1);
62
+ }
63
+ console.log('all @wanasapps dependencies resolve on npm');
@@ -55,10 +55,13 @@ const prodOrder = ['crm', ...[...taskByProd.keys()].filter((k) => k !== 'crm').s
55
55
  // ---------------------------------------------------------------------------
56
56
  // DELUGE_SKILL.md — guide + complete name index
57
57
  // ---------------------------------------------------------------------------
58
+ const fnCount = [...fnByCat.values()].reduce((n, v) => n + v.length, 0);
59
+ const taskCount = [...taskByProd.values()].reduce((n, v) => n + v.length, 0);
60
+
58
61
  const skill = [];
59
62
  skill.push(guide.trimEnd(), '', '---', '');
60
63
  skill.push('# Part 2 — Everything that exists (names only)', '');
61
- skill.push(`Every documented statement, built-in function and integration task, by name, generated from ${ref.source}. If a name is not here, it does not exist in Deluge do not invent one. For a function's exact syntax, parameters and return type, load the companion skill \`zoho-deluge-reference\` (or run \`zone llm deluge-reference\`).`, '');
64
+ skill.push(`What exists in Deluge, generated from ${ref.source}. Statements and data types are listed in full below because they are few. The ${fnCount} built-in functions and ${taskCount} integration tasks are summarised by category — **every one of them is named, with its exact syntax, parameters and return type, in the companion reference**: read \`references/REFERENCE.md\` in this skill folder, or run \`zone llm deluge-reference\`. If a name is not there, it does not exist in Deluge — do not invent one.`, '');
62
65
 
63
66
  skill.push('## Statements', '');
64
67
  skill.push((ref.statements || []).map((s) => `\`${s.name}\``).concat(['`invokeurl`', '`info`', '`return`']).join(' · '), '');
@@ -66,17 +69,16 @@ skill.push((ref.statements || []).map((s) => `\`${s.name}\``).concat(['`invokeur
66
69
  skill.push('## Data types', '');
67
70
  skill.push((ref.datatypes || []).map((d) => `\`${d.name}\``).join(' · '), '');
68
71
 
69
- skill.push('## Built-in functions', '');
70
- for (const cat of catOrder) {
71
- const names = fnByCat.get(cat).slice().sort(byName).map((f) => `\`${f.name}\``);
72
- skill.push(`**${cat}** (${names.length}): ${names.join(', ')}`, '');
73
- }
72
+ // Categories and counts, not 337 names. Every one of those names already
73
+ // appears in DELUGE_REFERENCE.md WITH its syntax, so listing them here bought
74
+ // nothing and cost ~1,800 tokens on every trigger — pushing the skill body over
75
+ // the Agent Skills spec's 5,000-token recommendation. The agent is told where
76
+ // to look instead, which preserves the "do not invent a name" guarantee.
77
+ skill.push('## Built-in functions — ' + fnCount + ' across ' + catOrder.length + ' categories', '');
78
+ skill.push(catOrder.map((cat) => `**${cat}** (${fnByCat.get(cat).length})`).join(' · '), '');
74
79
 
75
- skill.push('## Integration tasks', '');
76
- for (const prod of prodOrder) {
77
- const names = taskByProd.get(prod).slice().sort(byName).map((t) => `\`${t.name}\``);
78
- skill.push(`**${LABEL[prod] || prod}** (${names.length}): ${names.join(', ')}`, '');
79
- }
80
+ skill.push('## Integration tasks' + taskCount + ' across ' + prodOrder.length + ' products', '');
81
+ skill.push(prodOrder.map((prod) => `**${LABEL[prod] || prod}** (${taskByProd.get(prod).length})`).join(' · '), '');
80
82
 
81
83
  skill.push('## System variables', '');
82
84
  skill.push('`zoho.currentdate`, `zoho.currenttime`, `zoho.loginuser`, `zoho.loginuser.name` (Creator), `zoho.loginuserid`, `zoho.adminuser`, `zoho.adminuserid`, `zoho.appname` (Creator), `zoho.appuri` (Creator), `zoho.ipaddress`, `zoho.device.type` (Creator).', '');
@@ -1,70 +1,70 @@
1
- /**
2
- * Minimal parser for the *signature line* of a Deluge function script.
3
- *
4
- * Zoho stores a function's code with its signature on the first meaningful
5
- * line, e.g.:
6
- *
7
- * string standalone.Get_Assistants()
8
- * void automation.k_test(String Data)
9
- *
10
- * We only need the signature to learn the function's namespace + api name (to
11
- * build the test URL and enforce the standalone-only rule) and its declared
12
- * arguments (to prompt for values). The full script is still submitted verbatim
13
- * to Zoho — this parser never rewrites the code.
14
- */
15
-
16
- /**
17
- * Parse the signature of a Deluge script.
18
- * @param {string} scriptText - The full Deluge source.
19
- * @returns {{returnType: string|null, namespace: string|null, apiName: string|null, args: Array<{type:string,name:string}>}}
20
- */
21
- function parseSignature(scriptText) {
22
- const result = { returnType: null, namespace: null, apiName: null, args: [] };
23
- if (!scriptText || typeof scriptText !== 'string') return result;
24
-
25
- // Find the first non-comment, non-blank line — that's the signature.
26
- let sigLine = null;
27
- let inBlockComment = false;
28
- for (const raw of scriptText.split('\n')) {
29
- let line = raw.trim();
30
- if (!line) continue;
31
-
32
- if (inBlockComment) {
33
- const end = line.indexOf('*/');
34
- if (end === -1) continue;
35
- line = line.slice(end + 2).trim();
36
- inBlockComment = false;
37
- if (!line) continue;
38
- }
39
- if (line.startsWith('//')) continue;
40
- if (line.startsWith('/*')) {
41
- const end = line.indexOf('*/');
42
- if (end === -1) { inBlockComment = true; continue; }
43
- line = line.slice(end + 2).trim();
44
- if (!line) continue;
45
- }
46
- sigLine = line;
47
- break;
48
- }
49
- if (!sigLine) return result;
50
-
51
- // <returnType> <namespace>.<apiName>(<args>)
52
- const m = sigLine.match(/^(\w+)\s+([A-Za-z0-9_]+)\.([A-Za-z0-9_]+)\s*\(([^)]*)\)/);
53
- if (!m) return result;
54
-
55
- result.returnType = m[1];
56
- result.namespace = m[2];
57
- result.apiName = m[3];
58
-
59
- const argsRaw = m[4].trim();
60
- if (argsRaw) {
61
- for (const part of argsRaw.split(',')) {
62
- // each param is "<type> <name>" (e.g. "String Data", "int count")
63
- const am = part.trim().match(/^(\S+)\s+([A-Za-z0-9_]+)$/);
64
- if (am) result.args.push({ type: am[1], name: am[2] });
65
- }
66
- }
67
- return result;
68
- }
69
-
70
- module.exports = { parseSignature };
1
+ /**
2
+ * Minimal parser for the *signature line* of a Deluge function script.
3
+ *
4
+ * Zoho stores a function's code with its signature on the first meaningful
5
+ * line, e.g.:
6
+ *
7
+ * string standalone.Get_Assistants()
8
+ * void automation.k_test(String Data)
9
+ *
10
+ * We only need the signature to learn the function's namespace + api name (to
11
+ * build the test URL and enforce the standalone-only rule) and its declared
12
+ * arguments (to prompt for values). The full script is still submitted verbatim
13
+ * to Zoho — this parser never rewrites the code.
14
+ */
15
+
16
+ /**
17
+ * Parse the signature of a Deluge script.
18
+ * @param {string} scriptText - The full Deluge source.
19
+ * @returns {{returnType: string|null, namespace: string|null, apiName: string|null, args: Array<{type:string,name:string}>}}
20
+ */
21
+ function parseSignature(scriptText) {
22
+ const result = { returnType: null, namespace: null, apiName: null, args: [] };
23
+ if (!scriptText || typeof scriptText !== 'string') return result;
24
+
25
+ // Find the first non-comment, non-blank line — that's the signature.
26
+ let sigLine = null;
27
+ let inBlockComment = false;
28
+ for (const raw of scriptText.split('\n')) {
29
+ let line = raw.trim();
30
+ if (!line) continue;
31
+
32
+ if (inBlockComment) {
33
+ const end = line.indexOf('*/');
34
+ if (end === -1) continue;
35
+ line = line.slice(end + 2).trim();
36
+ inBlockComment = false;
37
+ if (!line) continue;
38
+ }
39
+ if (line.startsWith('//')) continue;
40
+ if (line.startsWith('/*')) {
41
+ const end = line.indexOf('*/');
42
+ if (end === -1) { inBlockComment = true; continue; }
43
+ line = line.slice(end + 2).trim();
44
+ if (!line) continue;
45
+ }
46
+ sigLine = line;
47
+ break;
48
+ }
49
+ if (!sigLine) return result;
50
+
51
+ // <returnType> <namespace>.<apiName>(<args>)
52
+ const m = sigLine.match(/^(\w+)\s+([A-Za-z0-9_]+)\.([A-Za-z0-9_]+)\s*\(([^)]*)\)/);
53
+ if (!m) return result;
54
+
55
+ result.returnType = m[1];
56
+ result.namespace = m[2];
57
+ result.apiName = m[3];
58
+
59
+ const argsRaw = m[4].trim();
60
+ if (argsRaw) {
61
+ for (const part of argsRaw.split(',')) {
62
+ // each param is "<type> <name>" (e.g. "String Data", "int count")
63
+ const am = part.trim().match(/^(\S+)\s+([A-Za-z0-9_]+)$/);
64
+ if (am) result.args.push({ type: am[1], name: am[2] });
65
+ }
66
+ }
67
+ return result;
68
+ }
69
+
70
+ module.exports = { parseSignature };