Move to the new file-pointer syntax

Summary:
Harmonize file pointer behavior across JDD, sealious, sealgen

Remove ghosts of previous tests

Reviewers: #reviewers

Subscribers: jenkins-user

Differential Revision: https://hub.sealcode.org/D1446
This commit is contained in:
Kuba Orlik 2024-04-30 10:07:25 +02:00
parent 45c852e25d
commit 85fb1d29c7
20 changed files with 259 additions and 173 deletions

181
package-lock.json generated
View File

@ -14,11 +14,13 @@
"@hotwired/turbo": "^8.0.2",
"@koa/router": "^12.0.1",
"@playwright/test": "^1.36.1",
"@sealcode/jdd": "^0.3.5",
"@sealcode/sealgen": "^0.14.16",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/jdd": "^0.4.5",
"@sealcode/sealgen": "^0.15.6",
"@sealcode/ts-predicates": "^0.6.2",
"@types/kill-port": "^2.0.0",
"@types/leaflet": "^1.9.8",
"escape-goat": "^4.0.0",
"get-port": "^7.0.0",
"js-convert-case": "^4.2.0",
"koa-responsive-image-router": "^0.2.24",
@ -27,7 +29,7 @@
"nodemon": "^3.0.1",
"object-path": "^0.11.8",
"qs": "^6.12.0",
"sealious": "^0.18.3",
"sealious": "^0.19.6",
"stimulus": "^2.0.0",
"tempstream": "^0.3.15",
"vitest": "^1.1.0"
@ -304,9 +306,9 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz",
"integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz",
"integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@ -858,16 +860,30 @@
"ansi-html-stream": "index.js"
}
},
"node_modules/@sealcode/jdd": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@sealcode/jdd/-/jdd-0.3.5.tgz",
"integrity": "sha512-VE8FRfmLuSgXIxIWeNvJjND64531EiHXjquHgIBIlbPOUCjp3Vx+nUrEZgyFyI//QN5ieNJVZhwOIV7gnfGNxg==",
"node_modules/@sealcode/file-manager": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@sealcode/file-manager/-/file-manager-1.0.2.tgz",
"integrity": "sha512-BOMgC90QffE9cVFKkLVTjDbUJ5WB9YqcmS4fwqFxgnnC3YlH9xb9rff3iGXSkKOHm0kCeSjq0Ohasxtq/z72WQ==",
"dependencies": {
"@sealcode/ts-predicates": "^0.5.3",
"koa-responsive-image-router": "^0.2.19",
"locreq": "^2.4.1",
"marked": "^12.0.0",
"@types/mime-types": "^2.1.4",
"@types/uuid": "^9.0.8",
"locreq": "^3.0.0",
"mime-types": "^2.1.35",
"uuid": "^9.0.1"
}
},
"node_modules/@sealcode/jdd": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/@sealcode/jdd/-/jdd-0.4.5.tgz",
"integrity": "sha512-N4DWR/+WEosJwkaul4BGB6CuGRkNHAfbNF5hGTCwYZRIFStYCThMGg2odXt6zt8eWbf9Cwt9pPKIQ+ZQHgpJFA==",
"dependencies": {
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.5.3",
"escape-goat": "^4.0.0",
"koa-responsive-image-router": "^0.2.19",
"locreq": "^3.0.0",
"marked": "^12.0.0",
"mri": "^1.2.0",
"tempstream": "^0.3.4",
"uuid": "^9.0.1"
}
@ -877,29 +893,19 @@
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.5.3.tgz",
"integrity": "sha512-EZI7e8EY8gI1pw2bKdevjl+fBJbcSlpNkCZ8XoEOV3cHakPujiT6M4l775RDkfxJSbLX7jhOBkhgPNDfmCpZbg=="
},
"node_modules/@sealcode/jdd/node_modules/@types/node": {
"version": "14.18.63",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
"integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="
},
"node_modules/@sealcode/jdd/node_modules/locreq": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/locreq/-/locreq-2.4.1.tgz",
"integrity": "sha512-Itfhlus87Q9GcQKEK5LXZngD5YpUbANC9mr5UFghLSBIg6gVVG21AWX45+JVyaqBxILQkB+dBW0i2KlSVzGfeQ==",
"dependencies": {
"@types/node": "^14.14.16"
}
},
"node_modules/@sealcode/sealgen": {
"version": "0.14.16",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.14.16.tgz",
"integrity": "sha512-kWrykFO+LX6qFubetiSXk1fdPtXSFiYpUdX5PT2L/dlfVFX+F+YcPihIwsVucIC/MaYUDR4p5QiHQnt/WXWSFQ==",
"version": "0.15.6",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.15.6.tgz",
"integrity": "sha512-XVmgGwSjzxQXEscvvHiAT6CTcuIV9c4Klb0pDYqNRtXlvZsoJHbhTsp+1Uua9vQh0NRe6Y+V2airw8eLr+ZZpg==",
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"google-fonts-helper": "^3.4.1",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"locreq": "^3.0.0",
"md5": "^2.3.0",
@ -913,12 +919,12 @@
"yargs": "^17.6.2"
},
"bin": {
"sealgen": "dist/cli.js"
"sealgen": "lib/cli.js"
},
"peerDependencies": {
"koa": "^2.13.0",
"koa-responsive-image-router": "^0.2.24",
"sealious": "^0.18.1"
"sealious": "^0.19.7"
}
},
"node_modules/@sealcode/sealgen/node_modules/@sealcode/ts-predicates": {
@ -1100,9 +1106,9 @@
"integrity": "sha512-miV7Z8zvOnRn0ZjbP/D/qb1VWHrWkKOnfC764SJvnCeIziW4pZy3tPK/542seSgccGAXlPQd/seuNyVAS/p5Ug=="
},
"node_modules/@types/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-87W6MJCKZYDhLAx/J1ikW8niMvmGRyY+rpUxWpL1cO7F8Uu5CHuQoFv+R0/L5pgNdW4jTyda42kv60uwVIPjLw=="
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-hulKeREDdLFesGQjl96+4aoJSHY5b2GRjagzzcqCfIrWhe5vkCqIvrLbqzBaI1q94Vg8DNJZZqTR5ocdWmWclg=="
},
"node_modules/@types/connect": {
"version": "3.4.38",
@ -1314,6 +1320,11 @@
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
},
"node_modules/@types/mime-types": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz",
"integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w=="
},
"node_modules/@types/mjml": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/@types/mjml/-/mjml-4.7.4.tgz",
@ -1428,8 +1439,7 @@
"node_modules/@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
"dev": true
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="
},
"node_modules/@types/webidl-conversions": {
"version": "7.0.3",
@ -2531,9 +2541,9 @@
}
},
"node_modules/bson": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.5.0.tgz",
"integrity": "sha512-DXf1BTAS8vKyR90BO4x5v3rKVarmkdkzwOrnYDFdjAY694ILNDkmA3uRh1xXJEl+C1DAh8XCvAQ+Gh3kzubtpg==",
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.6.0.tgz",
"integrity": "sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==",
"engines": {
"node": ">=16.20.1"
}
@ -3627,9 +3637,9 @@
}
},
"node_modules/es-abstract": {
"version": "1.23.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz",
"integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==",
"version": "1.23.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
"integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
"arraybuffer.prototype.slice": "^1.0.3",
@ -3670,11 +3680,11 @@
"safe-regex-test": "^1.0.3",
"string.prototype.trim": "^1.2.9",
"string.prototype.trimend": "^1.0.8",
"string.prototype.trimstart": "^1.0.7",
"string.prototype.trimstart": "^1.0.8",
"typed-array-buffer": "^1.0.2",
"typed-array-byte-length": "^1.0.1",
"typed-array-byte-offset": "^1.0.2",
"typed-array-length": "^1.0.5",
"typed-array-length": "^1.0.6",
"unbox-primitive": "^1.0.2",
"which-typed-array": "^1.1.15"
},
@ -3803,11 +3813,11 @@
}
},
"node_modules/escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz",
"integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==",
"engines": {
"node": ">=10"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@ -5554,6 +5564,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-what": {
"version": "4.1.16",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@ -5854,9 +5875,9 @@
}
},
"node_modules/js-beautify/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@ -6677,17 +6698,14 @@
}
},
"node_modules/mime": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-4.0.1.tgz",
"integrity": "sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==",
"funding": [
"https://github.com/sponsors/broofa"
],
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"bin": {
"mime": "bin/cli.js"
"mime": "cli.js"
},
"engines": {
"node": ">=16"
"node": ">=4.0.0"
}
},
"node_modules/mime-db": {
@ -6881,9 +6899,9 @@
}
},
"node_modules/mjml-cli/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@ -7315,7 +7333,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"engines": {
"node": ">=4"
}
@ -8154,9 +8171,9 @@
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.1.tgz",
"integrity": "sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==",
"engines": {
"node": "14 || >=16.14"
}
@ -9033,11 +9050,12 @@
}
},
"node_modules/sealious": {
"version": "0.18.3",
"resolved": "https://registry.npmjs.org/sealious/-/sealious-0.18.3.tgz",
"integrity": "sha512-WxwThRgsTCHxIUVzp6MAK65jBp7lnqPqex8rLondalx62I6E9r2gg0uC1am3/ziZSWgFdpkGKQoiOry0FZyHuw==",
"version": "0.19.7",
"resolved": "https://registry.npmjs.org/sealious/-/sealious-0.19.7.tgz",
"integrity": "sha512-yhKSd+AsFqzCc7UUK4aBIk/YZS7XrvcGJLJyR9m8cVSzN9dmP3glx4xL+gogBOG+SirsDw6FQZz9VKdhshzVUA==",
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.1",
"@sealcode/ts-predicates": "^0.4.3",
"@types/bluebird": "^3.5.30",
"@types/boom": "^7.3.0",
@ -9079,7 +9097,6 @@
"koa-send": "^5.0.1",
"koa-static": "^5.0.0",
"locreq": "^3.0.0",
"mime": "^4.0.1",
"mjml": "^4.2.0",
"mongodb": "^6.5.0",
"nodemailer": "^6.4.6",
@ -10984,6 +11001,17 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/web-resource-inliner/node_modules/htmlparser2": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
@ -10998,17 +11026,6 @@
"url": "https://github.com/fb55/htmlparser2?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",

View File

@ -14,7 +14,7 @@
"watch": "multiple-scripts-tmux -p watch",
"reset-db": "docker-compose down && docker-compose up -d",
"install-test-deps": "npx playwright install firefox",
"pretest-cmd": "npm run build",
"pretest-cmd": "rm -rf dist && npm run build",
"test-cmd": "vitest --config ./src/back/vitest.config.ts",
"test-cmd-once": "vitest run --config ./src/back/vitest.config.ts",
"test": "npm run test-cmd -- --ui",
@ -38,11 +38,13 @@
"@hotwired/turbo": "^8.0.2",
"@koa/router": "^12.0.1",
"@playwright/test": "^1.36.1",
"@sealcode/jdd": "^0.3.5",
"@sealcode/sealgen": "^0.14.16",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/jdd": "^0.4.5",
"@sealcode/sealgen": "^0.15.6",
"@sealcode/ts-predicates": "^0.6.2",
"@types/kill-port": "^2.0.0",
"@types/leaflet": "^1.9.8",
"escape-goat": "^4.0.0",
"get-port": "^7.0.0",
"js-convert-case": "^4.2.0",
"koa-responsive-image-router": "^0.2.24",
@ -51,7 +53,7 @@
"nodemon": "^3.0.1",
"object-path": "^0.11.8",
"qs": "^6.12.0",
"sealious": "^0.18.3",
"sealious": "^0.19.6",
"stimulus": "^2.0.0",
"tempstream": "^0.3.15",
"vitest": "^1.1.0"

View File

@ -11,8 +11,10 @@ import {
MONGO_HOST,
MONGO_PORT,
PORT,
UPLOADS_FS_DIR,
} from "./config.js";
import ADMIN_CREDENTIALS from "./default-admin-credentials.js";
import { TheFileManager } from "./file-manager.js";
import { module_dirname } from "./utils/module_dirname.js";
const locreq = _locreq(module_dirname(import.meta.url));
@ -25,8 +27,9 @@ declare module "koa" {
}
export default class TheApp extends App {
FileManager = TheFileManager;
config = {
upload_path: locreq.resolve("uploaded_files"),
upload_path: UPLOADS_FS_DIR,
datastore_mongo: {
host: MONGO_HOST,
port: MONGO_PORT,

View File

@ -25,3 +25,6 @@ export const IMAGE_CACHE_FS_DIR =
process.env.IMAGE_CACHE_FS_DIR || locreq.resolve("cache/images");
export const SMARTCROP_CACHE_FS_DIR =
process.env.IMAGE_CACHE_FS_DIR || locreq.resolve("cache/smartcrop");
export const UPLOADS_FS_DIR =
process.env.UPLOADS_FS_DIR || locreq.resolve("uploaded_files");

7
src/back/file-manager.ts Normal file
View File

@ -0,0 +1,7 @@
import { FileManager } from "@sealcode/file-manager";
import { UPLOADS_FS_DIR } from "./config.js";
export const TheFileManager = new FileManager(
UPLOADS_FS_DIR,
"/api/v1/uploaded-files" // this value comes from Sealious, currently not customizable
);

View File

@ -1,7 +1,7 @@
import type { FlatTemplatable } from "tempstream";
import { TempstreamJSX } from "tempstream";
import type {
ExtractStructuredComponentArgumentsValues,
ExtractStructuredComponentArgumentsParsed,
JDDContext,
} from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
@ -31,7 +31,7 @@ export class AutoscrollingImages extends Component<typeof component_arguments> {
interval,
imagesPerPage,
images,
}: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
}: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>,
{ render_image }: JDDContext
): FlatTemplatable {
const imageNumberPerPage = parseInt(imagesPerPage);

View File

@ -1,7 +1,7 @@
import type { FlatTemplatable } from "tempstream";
import { TempstreamJSX } from "tempstream";
import type {
ExtractStructuredComponentArgumentsValues,
ExtractStructuredComponentArgumentsParsed,
JDDContext,
} from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
@ -35,7 +35,7 @@ export class FaqComponent extends Component<typeof component_arguments> {
content,
faq,
button,
}: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
}: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>,
{ render_markdown }: JDDContext
): FlatTemplatable {
const buttonText = button.buttonText.toUpperCase();

View File

@ -1,7 +1,7 @@
import type { FlatTemplatable } from "tempstream";
import { TempstreamJSX } from "tempstream";
import type {
ExtractStructuredComponentArgumentsValues,
ExtractStructuredComponentArgumentsParsed,
JDDContext,
} from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
@ -30,7 +30,7 @@ export class HeaderWithImage extends Component<typeof component_arguments> {
content,
image_with_alt,
button,
}: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
}: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>,
{ render_markdown, render_image }: JDDContext
): FlatTemplatable {
const buttonText = button.text.toUpperCase();

View File

@ -1,7 +1,7 @@
import type { FlatTemplatable } from "tempstream";
import { TempstreamJSX } from "tempstream";
import type {
ExtractStructuredComponentArgumentsValues,
ExtractStructuredComponentArgumentsParsed,
JDDContext,
} from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
@ -23,7 +23,7 @@ export class ImageDemo extends Component<typeof component_arguments> {
{
image_with_alt,
multiple_images,
}: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
}: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>,
{ render_image }: JDDContext
): FlatTemplatable {
return (

View File

@ -1,6 +1,6 @@
import type { FlatTemplatable } from "tempstream";
import { TempstreamJSX } from "tempstream";
import type { ExtractStructuredComponentArgumentsValues } from "@sealcode/jdd";
import type { ExtractStructuredComponentArgumentsParsed } from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
const coordinates = new ComponentArguments.ShortText();
@ -51,7 +51,7 @@ export class MapWithPins extends Component<typeof component_arguments> {
toHTML({
pins,
}: ExtractStructuredComponentArgumentsValues<
}: ExtractStructuredComponentArgumentsParsed<
typeof component_arguments
>): FlatTemplatable {
return (

View File

@ -1,6 +1,6 @@
import { TempstreamJSX } from "tempstream";
import type {
ExtractStructuredComponentArgumentsValues,
ExtractStructuredComponentArgumentsParsed,
JDDContext,
} from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
@ -27,7 +27,7 @@ export class NiceBox extends Component<typeof component_arguments> {
title,
content,
images,
}: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
}: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>,
{ render_markdown, render_image }: JDDContext
): Promise<Readable> {
return (

View File

@ -1,6 +1,6 @@
import type { FlatTemplatable } from "tempstream";
import { TempstreamJSX } from "tempstream";
import type { ExtractStructuredComponentArgumentsValues } from "@sealcode/jdd";
import type { ExtractStructuredComponentArgumentsParsed } from "@sealcode/jdd";
import { Component, ComponentArguments, isTableHeader } from "@sealcode/jdd";
const component_arguments = {
@ -25,7 +25,7 @@ export class Table extends Component<typeof component_arguments> {
toHTML({
table,
}: ExtractStructuredComponentArgumentsValues<
}: ExtractStructuredComponentArgumentsParsed<
typeof component_arguments
>): FlatTemplatable {
return (

16
src/back/jdd-context.ts Normal file
View File

@ -0,0 +1,16 @@
import type { JDDContext } from "@sealcode/jdd";
import type { FilePointer } from "@sealcode/file-manager";
import { makeSimpleJDDContext } from "@sealcode/jdd";
import { TheFileManager } from "./file-manager.js";
import { imageRouter } from "./image-router.js";
export const jdd_context: JDDContext = {
...makeSimpleJDDContext(TheFileManager),
render_image: async (image: string | FilePointer | null, args) => {
if (!image) {
return "";
}
const file = await TheFileManager.toPointer(image);
return imageRouter.image(await file.getPath(), args);
},
};

View File

@ -1,10 +1,12 @@
import type { Image } from "@sealcode/jdd";
import type { StatefulPage } from "@sealcode/sealgen";
import { TempstreamJSX } from "tempstream";
import { jdd_context } from "../../jdd-context.js";
import type { ComponentPreviewState } from "../components.sreact.js";
import { jdd_context } from "../jdd-context.js";
import type { ComponentPreviewActions } from "./component-preview-actions.js";
import { printArgPath } from "./print-arg-path.js";
import { htmlEscape } from "escape-goat";
import type { FilePointer } from "@sealcode/file-manager";
export function ComponentInputImage<State extends ComponentPreviewState>({
arg_path,
@ -14,7 +16,7 @@ export function ComponentInputImage<State extends ComponentPreviewState>({
state: State;
arg_path: string[];
arg: Image;
value: string;
value: FilePointer | null;
page: StatefulPage<ComponentPreviewState, typeof ComponentPreviewActions>;
}) {
return (
@ -43,9 +45,7 @@ export function ComponentInputImage<State extends ComponentPreviewState>({
<input
type="hidden"
name={`$.component_args${printArgPath(arg_path)}.old`}
value={(value || "")
.replaceAll('"', "&quot;")
.replaceAll("\n", "\\n")}
value={htmlEscape(value?.token || "")}
autocomplete="off"
/>
</div>

View File

@ -1,12 +1,14 @@
import type { List } from "@sealcode/jdd";
import type { ComponentArgument, List } from "@sealcode/jdd";
import type { StatefulPage } from "@sealcode/sealgen";
import { TempstreamJSX } from "tempstream";
import type { ComponentPreviewState } from "../components.sreact.js";
import { jdd_context } from "../jdd-context.js";
import { ComponentInput } from "./component-input.js";
import type { ComponentPreviewActions } from "./component-preview-actions.js";
export async function ComponentInputList<State extends ComponentPreviewState, T>({
export async function ComponentInputList<
State extends ComponentPreviewState,
T extends ComponentArgument<unknown>
>({
state,
arg_path,
arg,
@ -50,8 +52,7 @@ export async function ComponentInputList<State extends ComponentPreviewState, T>
action: "add_array_item",
label: "",
},
arg_path,
await arg.item_type.getExampleValue(jdd_context)
arg_path
)}
</fieldset>
);

View File

@ -3,7 +3,6 @@ import { isTableHeader } from "@sealcode/jdd";
import type { StatefulPage } from "@sealcode/sealgen";
import { TempstreamJSX } from "tempstream";
import type { ComponentPreviewState } from "../components.sreact.js";
import { jdd_context } from "../jdd-context.js";
import { ComponentInput } from "./component-input.js";
import type { ComponentPreviewActions } from "./component-preview-actions.js";
@ -35,8 +34,6 @@ export async function ComponentInputTable<
if (!value) {
value = arg.getEmptyValue();
}
const empty_cell_value = arg.cell_type.getExampleValue(jdd_context);
const empty_header_value = arg.header_type.getExampleValue(jdd_context);
return (
<fieldset>
@ -171,8 +168,7 @@ export async function ComponentInputTable<
src="${add_column_right_icon.url}"
/>`,
},
arg_path,
empty_cell_value
arg_path
)}
</td>
) : (
@ -197,7 +193,6 @@ export async function ComponentInputTable<
/>`,
},
arg_path,
empty_cell_value,
arg.getColumnsCount(value)
)}
{page.makeActionButton(
@ -212,7 +207,6 @@ export async function ComponentInputTable<
/>`,
},
arg_path,
empty_header_value,
arg.getColumnsCount(value),
"header"
)}

View File

@ -12,6 +12,7 @@ import { ComponentInputTable } from "./component-input-table.js";
import { printArgPath } from "./print-arg-path.js";
import type { ComponentPreviewActions } from "./component-preview-actions.js";
import { is, predicates } from "@sealcode/ts-predicates";
import type { FilePointer } from "@sealcode/file-manager";
export const actionName = "Components";
const absoluteUrlPattern = "http(s?)(://)((www.)?)(([^.]+).)?([a-zA-z0-9-_]+)";
@ -70,7 +71,7 @@ export function ComponentInput<State extends ComponentPreviewState, T>({
arg_path,
arg,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
value: value as string,
value: value as FilePointer,
page,
});
}

View File

@ -1,9 +1,9 @@
import type { TableData } from "@sealcode/jdd";
import type { ComponentArgument, List, Table, TableData } from "@sealcode/jdd";
import { isTableData, isTableRegularRow } from "@sealcode/jdd";
import objectPath from "object-path";
import { registry } from "../../jdd-components/components.js";
import { jdd_context } from "../../jdd-context.js";
import type { ComponentPreviewState } from "../components.sreact.js";
import { jdd_context } from "../jdd-context.js";
function moveElement<T>(array: Array<T>, fromIndex: number, toIndex: number): Array<T> {
const element = array.splice(fromIndex, 1)[0];
@ -12,17 +12,30 @@ function moveElement<T>(array: Array<T>, fromIndex: number, toIndex: number): Ar
}
export const ComponentPreviewActions = <const>{
add_array_item: (
add_array_item: async (
state: ComponentPreviewState,
_: Record<string, string>,
arg_path: string[],
empty_value: unknown
arg_path: string[]
) => {
const component_args = state.component_args;
const component = registry.get(state.component);
if (!component) {
console.error("unknown component: ", state.component);
return state;
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const argument = component.getArgumentAtPath(
arg_path,
state.component_args
) as List<ComponentArgument<unknown>> | null;
if (!argument) {
console.error("Didn't find a list argument at this path", arg_path);
return state;
}
objectPath.insert(
component_args,
arg_path,
empty_value,
await argument.item_type.getExampleValue(jdd_context),
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
((objectPath.get(component_args, arg_path) as unknown[]) || []).length
);
@ -67,22 +80,39 @@ export const ComponentPreviewActions = <const>{
component_args: (await component?.getExampleValues(jdd_context)) || {},
};
},
add_table_row: (
add_table_row: async (
state: ComponentPreviewState,
_: Record<string, string>,
arg_path: string[],
empty_value: unknown,
columns: number,
type: "header" | "row" = "row"
) => {
const component_args = state.component_args;
let row;
const component = registry.get(state.component);
if (!component) {
console.error("Unknown component: ", state.component);
return state;
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const argument = component.getArgumentAtPath(
arg_path,
state.component_args
) as Table<unknown, unknown> | null;
if (!argument) {
console.error("Unknown component at path", arg_path);
return state;
}
if (type == "header") {
row = { type: "header", header_content: empty_value };
row = {
type: "header",
header_content: await argument.header_type.getExampleValue(jdd_context),
};
} else {
const cells = [];
for (let i = 0; i < columns; i++) {
cells.push(empty_value);
// eslint-disable-next-line no-await-in-loop
cells.push(await argument.cell_type.getExampleValue(jdd_context));
}
row = { type: "row", cells };
}
@ -100,13 +130,22 @@ export const ComponentPreviewActions = <const>{
};
return result;
},
add_table_column: (
add_table_column: async (
state: ComponentPreviewState,
_: Record<string, string>,
arg_path: string[],
empty_value: unknown
arg_path: string[]
) => {
const component_args = state.component_args;
const component = registry.get(state.component);
if (!component) {
console.error("Unknown component: ", state.component);
return state;
}
const argument = component.getArgumentAtPath(arg_path, state.component_args);
if (!argument) {
console.error("Unknown component at path", arg_path);
return state;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const tableData: TableData<unknown, unknown> = objectPath.get(
component_args,
@ -119,7 +158,8 @@ export const ComponentPreviewActions = <const>{
for (const i in tableData.rows) {
const row = tableData.rows[i];
if (isTableRegularRow(row)) {
row.cells.push(empty_value);
// eslint-disable-next-line no-await-in-loop
row.cells.push(await argument.getExampleValue(jdd_context));
}
}
objectPath.set(component_args, arg_path, tableData);

View File

@ -1,14 +1,14 @@
import { render, renderEarlyAssets } from "@sealcode/jdd";
import { StatefulPage, to_base64 } from "@sealcode/sealgen";
import { StatefulPage } from "@sealcode/sealgen";
import { hasShape, predicates } from "@sealcode/ts-predicates";
import type { BaseContext } from "koa";
import type { Templatable } from "tempstream";
import { tempstream, TempstreamJSX } from "tempstream";
import html, { defaultHead } from "../html.js";
import { registry } from "../jdd-components/components.js";
import { jdd_context } from "../jdd-context.js";
import { ComponentInput } from "./component-preview/component-input.js";
import { ComponentPreviewActions } from "./component-preview/component-preview-actions.js";
import { jdd_context } from "./jdd-context.js";
export const actionName = "Components";
@ -33,6 +33,43 @@ export default new (class ComponentsPage extends StatefulPage<
return initial_state;
}
async serializeState(_context: BaseContext, state: ComponentPreviewState) {
const component = registry.get(state.component);
const result = JSON.stringify({
...state,
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
component_args: component
? await component.convertParsedToStorage(
jdd_context,
state.component_args
)
: {},
});
return result;
}
async deserializeState(_context: BaseContext, state_string: string) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const raw = JSON.parse(state_string);
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-member-access
const component = registry.get(raw.component as string);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const result = {
...raw,
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
component_args: component
? // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
await component.convertStorageToParsed(
jdd_context,
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
raw.component_args || {}
)
: {},
};
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return result as ComponentPreviewState;
}
wrapInLayout(
ctx: BaseContext,
content: Templatable,
@ -62,20 +99,6 @@ export default new (class ComponentsPage extends StatefulPage<
);
}
wrapInForm(state: ComponentPreviewState, content: Templatable): Templatable {
// overwriting this method in order to add enctype to form
return (
<form action="./" method="POST" enctype="multipart/form-data">
<input
name="state"
type="hidden"
value={to_base64(JSON.stringify(state))}
/>
{content}
</form>
);
}
async preprocessOverrides(
state: ComponentPreviewState,
overrides: Record<string, unknown>
@ -95,11 +118,7 @@ export default new (class ComponentsPage extends StatefulPage<
async ([arg_name, arg]) => {
const value = overrides.component_args[arg_name];
if (value) {
const new_value = await arg.parseFormInput(
jdd_context,
value,
arg_name
);
const new_value = await arg.receivedToParsed(jdd_context, value);
overrides.component_args[arg_name] = new_value;
}
}
@ -111,7 +130,7 @@ export default new (class ComponentsPage extends StatefulPage<
containerSizes = ["320", "600", "800", "1024", "1300", "1920"];
render(_ctx: BaseContext, state: ComponentPreviewState) {
render(ctx: BaseContext, state: ComponentPreviewState) {
const all_components = registry.getAll();
const component =
registry.get(state.component) || Object.values(all_components)[0];
@ -158,7 +177,7 @@ export default new (class ComponentsPage extends StatefulPage<
)}
<input type="submit" value="Preview" />
</fieldset>
<code>{JSON.stringify(state)}</code>
<code>{this.serializeState(ctx, state)}</code>
</div>
<div class="resize-gutter" data-component-debugger-target="gutter"></div>
<div class="component-preview" data-component-debugger-target="preview">

View File

@ -1,17 +0,0 @@
import type { JDDContext } from "@sealcode/jdd";
import { simpleJDDContext } from "@sealcode/jdd";
import { imageRouter } from "../image-router.js";
export const jdd_context: JDDContext = {
...simpleJDDContext,
render_image: async (image_id, args) => {
if (!image_id) {
return "";
}
const image_pointer = await simpleJDDContext.decode_file(image_id);
if (!image_pointer) {
return "";
}
return imageRouter.image(image_pointer.path, args);
},
};