api.json 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. {
  2. "_note": "This file is the source for the Terminal in-app documentation panel. It is derived from mod/agi/README.md. Whenever README.md is updated, this file MUST also be updated to keep the in-app help in sync.",
  3. "_version": "3.0",
  4. "sections": [
  5. {
  6. "id": "core",
  7. "name": "Core",
  8. "desc": "Built-in functions always available without requirelib()",
  9. "functions": [
  10. {
  11. "name": "sendResp",
  12. "sig": "sendResp(content)",
  13. "desc": "Set the HTTP response body.",
  14. "ret": "void",
  15. "example": "sendResp(\"Hello from AGI\");"
  16. },
  17. {
  18. "name": "sendJSONResp",
  19. "sig": "sendJSONResp(objectOrJsonString)",
  20. "desc": "Set Content-Type to application/json and write a JSON response.",
  21. "ret": "void",
  22. "example": "sendJSONResp({ ok: true, items: [1, 2, 3] });"
  23. },
  24. {
  25. "name": "echo",
  26. "sig": "echo(content)",
  27. "desc": "Append text to the current HTTP_RESP.",
  28. "ret": "void",
  29. "example": "echo(\"Hello \");\necho(\"World\");"
  30. },
  31. {
  32. "name": "sendOK",
  33. "sig": "sendOK()",
  34. "desc": "Set response to the string \"ok\".",
  35. "ret": "void",
  36. "example": "sendOK();"
  37. },
  38. {
  39. "name": "requirelib",
  40. "sig": "requirelib(libname)",
  41. "desc": "Load an AGI library into the current VM. Returns true on success.",
  42. "ret": "bool",
  43. "example": "if (!requirelib(\"filelib\")) {\n sendResp(\"filelib not available\");\n}"
  44. },
  45. {
  46. "name": "includes",
  47. "sig": "includes(scriptName)",
  48. "desc": "Load and execute another script relative to the current script's directory.",
  49. "ret": "void",
  50. "example": "includes(\"helpers.js\");"
  51. },
  52. {
  53. "name": "delay",
  54. "sig": "delay(ms)",
  55. "desc": "Sleep for the given number of milliseconds. After websocket.upgrade(), also pumps incoming WebSocket messages.",
  56. "ret": "void",
  57. "example": "delay(500);"
  58. },
  59. {
  60. "name": "exit",
  61. "sig": "exit()",
  62. "desc": "Stop script execution immediately.",
  63. "ret": "void",
  64. "example": "if (!userIsAdmin()) exit();"
  65. },
  66. {
  67. "name": "execd",
  68. "sig": "execd(scriptName, payload)",
  69. "desc": "Execute another AGI script asynchronously as a detached process.",
  70. "ret": "void",
  71. "example": "execd(\"worker.agi\", JSON.stringify({ job: \"thumbs\" }));"
  72. },
  73. {
  74. "name": "console.log",
  75. "sig": "console.log(...args)",
  76. "desc": "Write a line to the server log. In Terminal sessions, output is captured and shown in yellow.",
  77. "ret": "void",
  78. "example": "console.log(\"Debug:\", someVariable);"
  79. }
  80. ]
  81. },
  82. {
  83. "id": "db",
  84. "name": "DB",
  85. "desc": "Key-value database functions, always available.",
  86. "functions": [
  87. {
  88. "name": "newDBTableIfNotExists",
  89. "sig": "newDBTableIfNotExists(tableName)",
  90. "desc": "Create a database table if it does not already exist.",
  91. "ret": "bool",
  92. "example": "newDBTableIfNotExists(\"my_table\");"
  93. },
  94. {
  95. "name": "DBTableExists",
  96. "sig": "DBTableExists(tableName)",
  97. "desc": "Return true if the table exists.",
  98. "ret": "bool",
  99. "example": "if (DBTableExists(\"my_table\")) sendOK();"
  100. },
  101. {
  102. "name": "writeDBItem",
  103. "sig": "writeDBItem(tableName, key, value)",
  104. "desc": "Write a string value to the given key.",
  105. "ret": "bool",
  106. "example": "writeDBItem(\"my_table\", \"theme\", \"dark\");"
  107. },
  108. {
  109. "name": "readDBItem",
  110. "sig": "readDBItem(tableName, key)",
  111. "desc": "Read a string value from the given key.",
  112. "ret": "string",
  113. "example": "var theme = readDBItem(\"my_table\", \"theme\");"
  114. },
  115. {
  116. "name": "listDBTable",
  117. "sig": "listDBTable(tableName)",
  118. "desc": "Return all key-value pairs in the table as an object.",
  119. "ret": "object",
  120. "example": "var kv = listDBTable(\"my_table\");\nsendJSONResp(kv);"
  121. },
  122. {
  123. "name": "deleteDBItem",
  124. "sig": "deleteDBItem(tableName, key)",
  125. "desc": "Delete a single key from the table.",
  126. "ret": "bool",
  127. "example": "deleteDBItem(\"my_table\", \"theme\");"
  128. },
  129. {
  130. "name": "dropDBTable",
  131. "sig": "dropDBTable(tableName)",
  132. "desc": "Delete the entire table.",
  133. "ret": "bool",
  134. "example": "dropDBTable(\"my_table\");"
  135. }
  136. ]
  137. },
  138. {
  139. "id": "user",
  140. "name": "User",
  141. "desc": "User management and permission functions.",
  142. "functions": [
  143. {
  144. "name": "pathCanWrite",
  145. "sig": "pathCanWrite(vpath)",
  146. "desc": "Return true if the current user can write to the virtual path.",
  147. "ret": "bool",
  148. "example": "if (pathCanWrite(\"user:/Documents\")) sendOK();"
  149. },
  150. {
  151. "name": "getUserPermissionGroup",
  152. "sig": "getUserPermissionGroup()",
  153. "desc": "Return a JSON string describing the current user's permission group.",
  154. "ret": "string (JSON)",
  155. "example": "var group = JSON.parse(getUserPermissionGroup());"
  156. },
  157. {
  158. "name": "userIsAdmin",
  159. "sig": "userIsAdmin()",
  160. "desc": "Return true if the current user is an administrator.",
  161. "ret": "bool",
  162. "example": "if (!userIsAdmin()) {\n sendResp(\"Admin only\");\n exit();\n}"
  163. },
  164. {
  165. "name": "userExists",
  166. "sig": "userExists(username)",
  167. "desc": "(Admin only) Return true if the username exists.",
  168. "ret": "bool",
  169. "example": "if (userExists(\"alice\")) echo(\"exists\");"
  170. },
  171. {
  172. "name": "createUser",
  173. "sig": "createUser(username, password, defaultGroup)",
  174. "desc": "(Admin only) Create a new user account.",
  175. "ret": "bool",
  176. "example": "createUser(\"alice\", \"StrongPass\", \"default\");"
  177. },
  178. {
  179. "name": "removeUser",
  180. "sig": "removeUser(username)",
  181. "desc": "(Admin only) Delete a user account.",
  182. "ret": "bool",
  183. "example": "removeUser(\"alice\");"
  184. }
  185. ]
  186. },
  187. {
  188. "id": "filelib",
  189. "name": "filelib",
  190. "desc": "Virtual filesystem read, write, and metadata operations.",
  191. "load": "requirelib(\"filelib\");",
  192. "functions": [
  193. {
  194. "name": "filelib.writeFile",
  195. "sig": "filelib.writeFile(vpath, content)",
  196. "desc": "Write text content to a virtual path. Creates the file if it does not exist.",
  197. "ret": "bool",
  198. "example": "requirelib(\"filelib\");\nfilelib.writeFile(\"user:/notes.txt\", \"Hello World\");"
  199. },
  200. {
  201. "name": "filelib.readFile",
  202. "sig": "filelib.readFile(vpath)",
  203. "desc": "Read text content from a virtual path.",
  204. "ret": "string | false",
  205. "example": "requirelib(\"filelib\");\nvar text = filelib.readFile(\"user:/notes.txt\");"
  206. },
  207. {
  208. "name": "filelib.deleteFile",
  209. "sig": "filelib.deleteFile(vpath)",
  210. "desc": "Delete a file at the virtual path.",
  211. "ret": "bool",
  212. "example": "requirelib(\"filelib\");\nfilelib.deleteFile(\"user:/notes.txt\");"
  213. },
  214. {
  215. "name": "filelib.walk",
  216. "sig": "filelib.walk(vpath, mode)",
  217. "desc": "Recursively list entries. mode: \"all\", \"file\", or \"folder\".",
  218. "ret": "string[]",
  219. "example": "requirelib(\"filelib\");\nvar files = filelib.walk(\"user:/\", \"file\");"
  220. },
  221. {
  222. "name": "filelib.glob",
  223. "sig": "filelib.glob(pattern, sortMode)",
  224. "desc": "Glob match files. sortMode: \"default\" or user-defined sort. Does not support ** patterns.",
  225. "ret": "string[]",
  226. "example": "requirelib(\"filelib\");\nvar jpgs = filelib.glob(\"user:/Desktop/*.jpg\", \"default\");"
  227. },
  228. {
  229. "name": "filelib.aglob",
  230. "sig": "filelib.aglob(pattern, sortMode)",
  231. "desc": "Advanced glob supporting ** recursive patterns. Cannot scan bare root dirs.",
  232. "ret": "string[]",
  233. "example": "requirelib(\"filelib\");\nvar pngs = filelib.aglob(\"user:/Desktop/**/*.png\", \"default\");"
  234. },
  235. {
  236. "name": "filelib.readdir",
  237. "sig": "filelib.readdir(vpath, sortMode)",
  238. "desc": "List directory entries. Returns array of {Filename, Filepath, Ext, Filesize, Modtime, IsDir}.",
  239. "ret": "object[]",
  240. "example": "requirelib(\"filelib\");\nvar entries = filelib.readdir(\"user:/Desktop\", \"default\");\nsendJSONResp(entries);"
  241. },
  242. {
  243. "name": "filelib.filesize",
  244. "sig": "filelib.filesize(vpath)",
  245. "desc": "Return file size in bytes.",
  246. "ret": "number",
  247. "example": "requirelib(\"filelib\");\nvar sz = filelib.filesize(\"user:/movie.mp4\");"
  248. },
  249. {
  250. "name": "filelib.fileExists",
  251. "sig": "filelib.fileExists(vpath)",
  252. "desc": "Return true if the path exists as a file.",
  253. "ret": "bool",
  254. "example": "requirelib(\"filelib\");\nif (filelib.fileExists(\"user:/a.txt\")) sendOK();"
  255. },
  256. {
  257. "name": "filelib.isDir",
  258. "sig": "filelib.isDir(vpath)",
  259. "desc": "Return true if the path is a directory.",
  260. "ret": "bool",
  261. "example": "requirelib(\"filelib\");\nif (filelib.isDir(\"user:/Desktop\")) sendOK();"
  262. },
  263. {
  264. "name": "filelib.mkdir",
  265. "sig": "filelib.mkdir(vpath)",
  266. "desc": "Create a directory (and parents) at the virtual path.",
  267. "ret": "bool",
  268. "example": "requirelib(\"filelib\");\nfilelib.mkdir(\"user:/newfolder\");"
  269. },
  270. {
  271. "name": "filelib.md5",
  272. "sig": "filelib.md5(vpath)",
  273. "desc": "Return the MD5 hash string of a file.",
  274. "ret": "string",
  275. "example": "requirelib(\"filelib\");\nvar hash = filelib.md5(\"user:/a.txt\");"
  276. },
  277. {
  278. "name": "filelib.mtime",
  279. "sig": "filelib.mtime(vpath, parseToUnix)",
  280. "desc": "Return file modification time. parseToUnix=true returns a Unix timestamp; otherwise a formatted string.",
  281. "ret": "number | string",
  282. "example": "requirelib(\"filelib\");\nvar ts = filelib.mtime(\"user:/a.txt\", true);"
  283. },
  284. {
  285. "name": "filelib.rootName",
  286. "sig": "filelib.rootName(vpath)",
  287. "desc": "Return the display name of the storage root that owns this path.",
  288. "ret": "string",
  289. "example": "requirelib(\"filelib\");\nvar root = filelib.rootName(\"user:/Desktop/a.txt\");"
  290. }
  291. ]
  292. },
  293. {
  294. "id": "imagelib",
  295. "name": "imagelib",
  296. "desc": "Image dimension, resize, crop, and EXIF operations.",
  297. "load": "requirelib(\"imagelib\");",
  298. "functions": [
  299. {
  300. "name": "imagelib.getImageDimension",
  301. "sig": "imagelib.getImageDimension(vpath)",
  302. "desc": "Return [width, height] of the image.",
  303. "ret": "[number, number]",
  304. "example": "requirelib(\"imagelib\");\nvar dim = imagelib.getImageDimension(\"user:/img.jpg\");"
  305. },
  306. {
  307. "name": "imagelib.resizeImage",
  308. "sig": "imagelib.resizeImage(src, dest, width, height)",
  309. "desc": "Resize an image and save to dest.",
  310. "ret": "bool",
  311. "example": "requirelib(\"imagelib\");\nimagelib.resizeImage(\"user:/img.jpg\", \"user:/img_small.jpg\", 800, 600);"
  312. },
  313. {
  314. "name": "imagelib.resizeImageBase64",
  315. "sig": "imagelib.resizeImageBase64(src, width, height, format)",
  316. "desc": "Resize an image and return it as a base64 data URL. format: \"jpeg\", \"png\".",
  317. "ret": "string (data URL)",
  318. "example": "requirelib(\"imagelib\");\nvar b64 = imagelib.resizeImageBase64(\"user:/img.jpg\", 320, 240, \"jpeg\");"
  319. },
  320. {
  321. "name": "imagelib.cropImage",
  322. "sig": "imagelib.cropImage(src, dest, x, y, width, height)",
  323. "desc": "Crop a region from an image and save to dest.",
  324. "ret": "bool",
  325. "example": "requirelib(\"imagelib\");\nimagelib.cropImage(\"user:/img.jpg\", \"user:/crop.jpg\", 10, 10, 200, 200);"
  326. },
  327. {
  328. "name": "imagelib.loadThumbString",
  329. "sig": "imagelib.loadThumbString(vpath)",
  330. "desc": "Return the cached thumbnail as a base64 string.",
  331. "ret": "string",
  332. "example": "requirelib(\"imagelib\");\nvar thumb = imagelib.loadThumbString(\"user:/img.jpg\");"
  333. },
  334. {
  335. "name": "imagelib.hasExif",
  336. "sig": "imagelib.hasExif(vpath)",
  337. "desc": "Return true if the image has EXIF metadata.",
  338. "ret": "bool",
  339. "example": "requirelib(\"imagelib\");\nif (imagelib.hasExif(\"user:/img.jpg\")) echo(\"has exif\");"
  340. },
  341. {
  342. "name": "imagelib.getExif",
  343. "sig": "imagelib.getExif(vpath)",
  344. "desc": "Return EXIF data as a JSON string.",
  345. "ret": "string (JSON)",
  346. "example": "requirelib(\"imagelib\");\nvar exif = JSON.parse(imagelib.getExif(\"user:/img.jpg\"));"
  347. }
  348. ]
  349. },
  350. {
  351. "id": "http",
  352. "name": "http",
  353. "desc": "Outbound HTTP request helpers.",
  354. "load": "requirelib(\"http\");",
  355. "functions": [
  356. {
  357. "name": "http.get",
  358. "sig": "http.get(url)",
  359. "desc": "Perform an HTTP GET and return the response body as a string.",
  360. "ret": "string",
  361. "example": "requirelib(\"http\");\nvar body = http.get(\"https://example.com/api\");"
  362. },
  363. {
  364. "name": "http.post",
  365. "sig": "http.post(url, jsonString)",
  366. "desc": "Perform an HTTP POST with JSON body and return the response body.",
  367. "ret": "string",
  368. "example": "requirelib(\"http\");\nvar resp = http.post(\"https://example.com/api\", JSON.stringify({a:1}));"
  369. },
  370. {
  371. "name": "http.head",
  372. "sig": "http.head(url, headerKey)",
  373. "desc": "Fetch response headers. Without headerKey returns all headers as JSON; with headerKey returns just that header.",
  374. "ret": "string (JSON)",
  375. "example": "requirelib(\"http\");\nvar headers = JSON.parse(http.head(\"https://example.com\"));"
  376. },
  377. {
  378. "name": "http.getCode",
  379. "sig": "http.getCode(url)",
  380. "desc": "Return the HTTP status code for the URL.",
  381. "ret": "number",
  382. "example": "requirelib(\"http\");\nvar code = http.getCode(\"https://example.com\");"
  383. },
  384. {
  385. "name": "http.download",
  386. "sig": "http.download(url, destDirVpath, filenameOptional)",
  387. "desc": "Download a URL into the destination virtual directory.",
  388. "ret": "bool",
  389. "example": "requirelib(\"http\");\nhttp.download(\"https://example.com/a.zip\", \"user:/Downloads\", \"a.zip\");"
  390. },
  391. {
  392. "name": "http.getb64",
  393. "sig": "http.getb64(url)",
  394. "desc": "Fetch a URL and return the raw bytes as a base64 string.",
  395. "ret": "string",
  396. "example": "requirelib(\"http\");\nvar raw = http.getb64(\"https://example.com/logo.png\");"
  397. },
  398. {
  399. "name": "http.redirect",
  400. "sig": "http.redirect(targetUrl, statusCode)",
  401. "desc": "Redirect the client. Default statusCode is 307.",
  402. "ret": "void",
  403. "example": "requirelib(\"http\");\nhttp.redirect(\"https://example.com/new\", 302);"
  404. }
  405. ]
  406. },
  407. {
  408. "id": "share",
  409. "name": "share",
  410. "desc": "Create and manage public file share links.",
  411. "load": "requirelib(\"share\");",
  412. "functions": [
  413. {
  414. "name": "share.shareFile",
  415. "sig": "share.shareFile(vpath, timeoutSec)",
  416. "desc": "Create a public share link. timeoutSec=0 means no expiry. Returns the share UUID.",
  417. "ret": "string (uuid)",
  418. "example": "requirelib(\"share\");\nvar uuid = share.shareFile(\"user:/report.pdf\", 3600);"
  419. },
  420. {
  421. "name": "share.removeShare",
  422. "sig": "share.removeShare(shareUUID)",
  423. "desc": "Remove an existing share link.",
  424. "ret": "bool",
  425. "example": "requirelib(\"share\");\nshare.removeShare(uuid);"
  426. },
  427. {
  428. "name": "share.checkShareExists",
  429. "sig": "share.checkShareExists(shareUUID)",
  430. "desc": "Return true if the share UUID is still valid.",
  431. "ret": "bool",
  432. "example": "requirelib(\"share\");\nif (share.checkShareExists(uuid)) sendOK();"
  433. },
  434. {
  435. "name": "share.fileIsShared",
  436. "sig": "share.fileIsShared(vpath)",
  437. "desc": "Return true if the file already has an active share link.",
  438. "ret": "bool",
  439. "example": "requirelib(\"share\");\nif (share.fileIsShared(\"user:/report.pdf\")) sendOK();"
  440. },
  441. {
  442. "name": "share.getFileShareUUID",
  443. "sig": "share.getFileShareUUID(vpath)",
  444. "desc": "Return the share UUID for the given file, or false if not shared.",
  445. "ret": "string | false",
  446. "example": "requirelib(\"share\");\nvar sid = share.getFileShareUUID(\"user:/report.pdf\");"
  447. }
  448. ]
  449. },
  450. {
  451. "id": "appdata",
  452. "name": "appdata",
  453. "desc": "Read-only access to web-root application data files.",
  454. "load": "requirelib(\"appdata\");",
  455. "functions": [
  456. {
  457. "name": "appdata.readFile",
  458. "sig": "appdata.readFile(relativePathFromWebRoot)",
  459. "desc": "Read a file relative to ./web/. Returns false on error.",
  460. "ret": "string | false",
  461. "example": "requirelib(\"appdata\");\nvar conf = appdata.readFile(\"MyApp/config.json\");"
  462. },
  463. {
  464. "name": "appdata.listDir",
  465. "sig": "appdata.listDir(relativeDirFromWebRoot)",
  466. "desc": "List files in a directory relative to ./web/. Returns an array of relative paths.",
  467. "ret": "string[]",
  468. "example": "requirelib(\"appdata\");\nvar files = appdata.listDir(\"MyApp\");\nsendJSONResp(files);"
  469. },
  470. {
  471. "name": "appdata.getModuleList",
  472. "sig": "appdata.getModuleList()",
  473. "desc": "Return an array of registered module objects.",
  474. "ret": "object[]",
  475. "example": "requirelib(\"appdata\");\nvar mods = appdata.getModuleList();"
  476. }
  477. ]
  478. },
  479. {
  480. "id": "sysinfo",
  481. "name": "sysinfo",
  482. "desc": "Real-time system resource information.",
  483. "load": "requirelib(\"sysinfo\");",
  484. "functions": [
  485. {
  486. "name": "sysinfo.getCPUUsage",
  487. "sig": "sysinfo.getCPUUsage()",
  488. "desc": "Return CPU usage as a percentage (0–100).",
  489. "ret": "number",
  490. "example": "requirelib(\"sysinfo\");\nvar cpu = sysinfo.getCPUUsage();"
  491. },
  492. {
  493. "name": "sysinfo.getRAMUsage",
  494. "sig": "sysinfo.getRAMUsage()",
  495. "desc": "Return {used, total, percent} memory statistics.",
  496. "ret": "object",
  497. "example": "requirelib(\"sysinfo\");\nvar ram = sysinfo.getRAMUsage();\nsendJSONResp(ram);"
  498. },
  499. {
  500. "name": "sysinfo.getNetworkUsage",
  501. "sig": "sysinfo.getNetworkUsage()",
  502. "desc": "Return {rxRate, txRate, rxTotal, txTotal} in bytes/bytes-per-second.",
  503. "ret": "object",
  504. "example": "requirelib(\"sysinfo\");\nvar net = sysinfo.getNetworkUsage();"
  505. },
  506. {
  507. "name": "sysinfo.getDiskInfo",
  508. "sig": "sysinfo.getDiskInfo()",
  509. "desc": "Return an array of logical disk info objects.",
  510. "ret": "object[]",
  511. "example": "requirelib(\"sysinfo\");\nvar disks = sysinfo.getDiskInfo();\nsendJSONResp(disks);"
  512. }
  513. ]
  514. },
  515. {
  516. "id": "ziplib",
  517. "name": "ziplib",
  518. "desc": "Archive creation and extraction (zip, tar, tar.gz, gz).",
  519. "load": "requirelib(\"ziplib\");",
  520. "functions": [
  521. {
  522. "name": "ziplib.extractZipFile",
  523. "sig": "ziplib.extractZipFile(src, destDir)",
  524. "desc": "Extract a ZIP archive into destDir.",
  525. "ret": "bool",
  526. "example": "requirelib(\"ziplib\");\nziplib.extractZipFile(\"user:/a.zip\", \"user:/out/\");"
  527. },
  528. {
  529. "name": "ziplib.createZipFile",
  530. "sig": "ziplib.createZipFile(sourcesArrayOrString, outputZip)",
  531. "desc": "Create a ZIP archive from one or more source paths.",
  532. "ret": "bool",
  533. "example": "requirelib(\"ziplib\");\nziplib.createZipFile([\"user:/a.txt\", \"user:/b.txt\"], \"user:/bundle.zip\");"
  534. },
  535. {
  536. "name": "ziplib.extractAnyFile",
  537. "sig": "ziplib.extractAnyFile(srcArchive, destDir)",
  538. "desc": "Auto-detect archive format and extract into destDir.",
  539. "ret": "bool",
  540. "example": "requirelib(\"ziplib\");\nziplib.extractAnyFile(\"user:/archive.tar.gz\", \"user:/out/\");"
  541. },
  542. {
  543. "name": "ziplib.createAnyZipFile",
  544. "sig": "ziplib.createAnyZipFile(sourcesArrayOrString, outputPath, format)",
  545. "desc": "Create an archive in any supported format. format: \"zip\", \"tar\", \"tar.gz\", \"gz\".",
  546. "ret": "bool",
  547. "example": "requirelib(\"ziplib\");\nziplib.createAnyZipFile([\"user:/folder\"], \"user:/bundle.tar.gz\", \"tar.gz\");"
  548. },
  549. {
  550. "name": "ziplib.isValidZipFile",
  551. "sig": "ziplib.isValidZipFile(vpath)",
  552. "desc": "Return true if the file is a recognisable archive.",
  553. "ret": "bool",
  554. "example": "requirelib(\"ziplib\");\nvar ok = ziplib.isValidZipFile(\"user:/a.zip\");"
  555. },
  556. {
  557. "name": "ziplib.listZipFileContents",
  558. "sig": "ziplib.listZipFileContents(zipPath)",
  559. "desc": "Return a JSON tree string of the archive's contents.",
  560. "ret": "string (JSON)",
  561. "example": "requirelib(\"ziplib\");\nvar tree = JSON.parse(ziplib.listZipFileContents(\"user:/a.zip\"));"
  562. },
  563. {
  564. "name": "ziplib.getFileFromZip",
  565. "sig": "ziplib.getFileFromZip(zipPath, filePathInZip)",
  566. "desc": "Extract one file to tmp:/ and return its virtual path.",
  567. "ret": "string (vpath)",
  568. "example": "requirelib(\"ziplib\");\nvar tmp = ziplib.getFileFromZip(\"user:/a.zip\", \"docs/readme.txt\");"
  569. }
  570. ]
  571. },
  572. {
  573. "id": "websocket",
  574. "name": "websocket",
  575. "desc": "Upgrade the HTTP connection to a persistent WebSocket session.",
  576. "load": "requirelib(\"websocket\");",
  577. "functions": [
  578. {
  579. "name": "websocket.upgrade",
  580. "sig": "websocket.upgrade(timeoutSec)",
  581. "desc": "Upgrade to WebSocket. Also overrides delay() with a message-pumping version. Returns false on failure.",
  582. "ret": "bool",
  583. "example": "requirelib(\"websocket\");\nif (!websocket.upgrade(120)) exit();\nwebsocket.send(\"Connected!\");"
  584. },
  585. {
  586. "name": "websocket.send",
  587. "sig": "websocket.send(text)",
  588. "desc": "Send a text frame to the client. Returns false if the connection is closed.",
  589. "ret": "bool",
  590. "example": "websocket.send(\"Hello client\");"
  591. },
  592. {
  593. "name": "websocket.read",
  594. "sig": "websocket.read(timeoutMs)",
  595. "desc": "Read next message. Returns string on message, null on timeout (still open), false if closed. Omit timeoutMs to block.",
  596. "ret": "string | null | false",
  597. "example": "var msg = websocket.read(5000);\nif (msg === false) { /* closed */ }\nif (msg === null) { /* timeout */ }"
  598. },
  599. {
  600. "name": "websocket.available",
  601. "sig": "websocket.available()",
  602. "desc": "Return count of buffered unread messages. Non-blocking.",
  603. "ret": "number",
  604. "example": "if (websocket.available() > 0) {\n var msg = websocket.read();\n}"
  605. },
  606. {
  607. "name": "websocket.isClosed",
  608. "sig": "websocket.isClosed()",
  609. "desc": "Return true when the connection is no longer active.",
  610. "ret": "bool",
  611. "example": "while (!websocket.isClosed()) {\n websocket.send(\"tick\");\n delay(1000);\n}"
  612. },
  613. {
  614. "name": "websocket.onMessage",
  615. "sig": "websocket.onMessage = function(msg) { ... }",
  616. "desc": "Assign a callback fired inside delay(). msg = { data, timestamp, type }. Set to null to stop and leave messages in buffer.",
  617. "ret": "void",
  618. "example": "var last = \"\";\nwebsocket.onMessage = function(msg) {\n last = msg.data;\n};\nwhile (!websocket.isClosed()) {\n if (last !== \"\") {\n websocket.send(\"Echo: \" + last);\n last = \"\";\n }\n delay(100);\n}"
  619. },
  620. {
  621. "name": "websocket.close",
  622. "sig": "websocket.close()",
  623. "desc": "Send a normal-closure frame and close the connection.",
  624. "ret": "bool",
  625. "example": "websocket.close();"
  626. }
  627. ]
  628. },
  629. {
  630. "id": "scheduler",
  631. "name": "scheduler",
  632. "desc": "Register and manage recurring background tasks for a webapp.",
  633. "load": "requirelib(\"scheduler\");",
  634. "functions": [
  635. {
  636. "name": "scheduler.hasPermission",
  637. "sig": "scheduler.hasPermission()",
  638. "desc": "Return true if the current user is allowed to create scheduled tasks.",
  639. "ret": "bool",
  640. "example": "requirelib(\"scheduler\");\nif (!scheduler.hasPermission()) sendResp(\"no_permission\");"
  641. },
  642. {
  643. "name": "scheduler.registered",
  644. "sig": "scheduler.registered(taskName, appName)",
  645. "desc": "Return true if the task is already registered for this user+app.",
  646. "ret": "bool",
  647. "example": "requirelib(\"scheduler\");\nif (scheduler.registered(\"MyApp_Sync\", \"MyApp\")) sendResp(\"already_registered\");"
  648. },
  649. {
  650. "name": "scheduler.register",
  651. "sig": "scheduler.register(taskName, appName, intervalSecs, description, scriptName)",
  652. "desc": "Register a new background task. scriptName defaults to \"cron.agi\".",
  653. "ret": "bool",
  654. "example": "requirelib(\"scheduler\");\nvar ok = scheduler.register(\"MyApp_Sync\", \"MyApp\", 3600, \"Hourly sync\", \"cron.agi\");"
  655. },
  656. {
  657. "name": "scheduler.unregister",
  658. "sig": "scheduler.unregister(taskName)",
  659. "desc": "Remove a registered task.",
  660. "ret": "bool",
  661. "example": "requirelib(\"scheduler\");\nscheduler.unregister(\"MyApp_Sync\");"
  662. }
  663. ]
  664. },
  665. {
  666. "id": "ffmpeg",
  667. "name": "ffmpeg",
  668. "desc": "Media conversion via ffmpeg. Only available when ffmpeg is installed on the host.",
  669. "load": "requirelib(\"ffmpeg\");",
  670. "functions": [
  671. {
  672. "name": "ffmpeg.convert",
  673. "sig": "ffmpeg.convert(input, output, compression)",
  674. "desc": "Generic media conversion.",
  675. "ret": "bool",
  676. "example": "requirelib(\"ffmpeg\");\nffmpeg.convert(\"user:/in.mov\", \"user:/out.mp4\", 0);"
  677. },
  678. {
  679. "name": "ffmpeg.videoConvert",
  680. "sig": "ffmpeg.videoConvert(input, output, resolution, compressionRate, progressFile)",
  681. "desc": "Convert video to the given resolution. progressFile is a virtual path for JSON progress updates.",
  682. "ret": "bool",
  683. "example": "requirelib(\"ffmpeg\");\nffmpeg.videoConvert(\"user:/in.mp4\", \"user:/out.mp4\", \"720p\", 55, \"tmp:/progress.json\");"
  684. },
  685. {
  686. "name": "ffmpeg.audioConvert",
  687. "sig": "ffmpeg.audioConvert(input, output, sampleRate, progressFile)",
  688. "desc": "Convert audio to the given sample rate.",
  689. "ret": "bool",
  690. "example": "requirelib(\"ffmpeg\");\nffmpeg.audioConvert(\"user:/in.wav\", \"user:/out.mp3\", 44100, \"tmp:/audio_progress.json\");"
  691. },
  692. {
  693. "name": "ffmpeg.imageConvert",
  694. "sig": "ffmpeg.imageConvert(input, output, scaleFactor, compressionRate)",
  695. "desc": "Convert/resize an image. scaleFactor 0.5 = 50% size.",
  696. "ret": "bool",
  697. "example": "requirelib(\"ffmpeg\");\nffmpeg.imageConvert(\"user:/in.png\", \"user:/out.jpg\", 0.5, 80);"
  698. }
  699. ]
  700. }
  701. ]
  702. }