From dd09b39a74c748e8fec83552ad8d7e059b576ed6 Mon Sep 17 00:00:00 2001 From: Quixos Template Publisher Date: Sat, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH] Export template source from ba8d4f92667f39bb02d542cb492b71a32ec914bf:quixos-instance/packages/web-studio-canvas-runtime --- .gitignore | 3 + .quixos-template-source.json | 4 + .yarn/plugins/yarn-plugin-nixify.cjs | 1 + .yarnrc.yml | 29 +++ bindings.json | 12 + descriptor.quixos-package.txtpb | 6 + flake.lock | 80 ++++++ flake.nix | 32 +++ package.json | 22 ++ package.qx | 20 ++ quixos.check.json | 16 ++ quixos.lock | 10 + quixos.migrations.json | 6 + quixos.scaffold.json | 18 ++ quixos.toolchain.json | 4 + src/canvas.impl.ts | 52 ++++ src/gen/qx.ts | 237 ++++++++++++++++++ src/impl/createCanvas.ts | 2 + src/impl/createPlacement.ts | 2 + src/messages.ts | 10 + src/migrate.ts | 3 + src/server.ts | 9 + test/canvas.test.mjs | 35 +++ tsconfig.build.json | 7 + tsconfig.json | 17 ++ yarn-project.nix | 171 +++++++++++++ yarn.lock | 353 +++++++++++++++++++++++++++ 27 files changed, 1161 insertions(+) create mode 100644 .gitignore create mode 100644 .quixos-template-source.json create mode 100644 .yarn/plugins/yarn-plugin-nixify.cjs create mode 100644 .yarnrc.yml create mode 100644 bindings.json create mode 100644 descriptor.quixos-package.txtpb create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 package.json create mode 100644 package.qx create mode 100644 quixos.check.json create mode 100644 quixos.lock create mode 100644 quixos.migrations.json create mode 100644 quixos.scaffold.json create mode 100644 quixos.toolchain.json create mode 100644 src/canvas.impl.ts create mode 100644 src/gen/qx.ts create mode 100644 src/impl/createCanvas.ts create mode 100644 src/impl/createPlacement.ts create mode 100644 src/messages.ts create mode 100644 src/migrate.ts create mode 100644 src/server.ts create mode 100644 test/canvas.test.mjs create mode 100644 tsconfig.build.json create mode 100644 tsconfig.json create mode 100644 yarn-project.nix create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d3ac825 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.yarn/install-state.gz +node_modules +result diff --git a/.quixos-template-source.json b/.quixos-template-source.json new file mode 100644 index 0000000..cd3e064 --- /dev/null +++ b/.quixos-template-source.json @@ -0,0 +1,4 @@ +{ + "monorepoCommit": "ba8d4f92667f39bb02d542cb492b71a32ec914bf", + "sourcePath": "quixos-instance/packages/web-studio-canvas-runtime" +} diff --git a/.yarn/plugins/yarn-plugin-nixify.cjs b/.yarn/plugins/yarn-plugin-nixify.cjs new file mode 100644 index 0000000..44f7f79 --- /dev/null +++ b/.yarn/plugins/yarn-plugin-nixify.cjs @@ -0,0 +1 @@ +module.exports={name:"yarn-plugin-nixify",factory:function(e){var t;return(()=>{"use strict";var n={d:(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};n.r(r),n.d(r,{default:()=>E});const a=e("@yarnpkg/core"),o=e("clipanion");class i extends o.Command{constructor(...e){super(...e),this.locator=o.Option.String({required:!1})}async execute(){const e=await a.Configuration.find(this.context.cwd,this.context.plugins),{project:t}=await a.Project.find(e,this.context.cwd),n=await a.Cache.find(e),r=e.makeFetcher();return(await a.StreamReport.start({configuration:e,stdout:this.context.stdout},(async e=>{if(this.locator){const{locatorHash:o}=a.structUtils.parseLocator(this.locator,!0),i=t.originalPackages.get(o);if(!i)return void e.reportError(0,`Invalid locator: ${this.locator}`);await r.fetch(i,{checksums:t.storedChecksums,project:t,cache:n,fetcher:r,report:e})}else await e.startTimerPromise("Resolution step",(async()=>{await t.resolveEverything({report:e,lockfileOnly:!0})})),await e.startTimerPromise("Fetch step",(async()=>{await t.fetchEverything({cache:n,report:e,fetcher:r})}))}))).exitCode()}}i.paths=[["nixify","fetch"]];const s=e("@yarnpkg/fslib"),c=e("crypto");class l extends o.Command{constructor(...e){super(...e),this.locator=o.Option.String(),this.source=o.Option.String(),this.installLocation=o.Option.String()}async execute(){const e=await a.Configuration.find(this.context.cwd,this.context.plugins),{project:t}=await a.Project.find(e,this.context.cwd);return await t.restoreInstallState({restoreResolutions:!1}),(await a.StreamReport.start({configuration:e,stdout:this.context.stdout},(async n=>{await t.resolveEverything({report:n,lockfileOnly:!0});const r=a.structUtils.parseLocator(this.locator,!0),o=t.storedPackages.get(r.locatorHash);if(!o)return void n.reportError(0,`Invalid locator: ${this.locator}`);const i=s.ppath.join(t.cwd,this.installLocation);await s.xfs.mkdirpPromise(s.ppath.dirname(i)),await a.execUtils.execvp("cp",["-R",this.source,i],{cwd:t.cwd,strict:!0}),await a.execUtils.execvp("chmod",["-R","u+w",i],{cwd:t.cwd,strict:!0});const l=(0,c.createHash)("sha512");l.update(process.versions.node),e.triggerHook((e=>e.globalHashGeneration),t,(e=>{l.update("\0"),l.update(e)}));const d=l.digest("hex"),p=new Map,h=e=>{let n=p.get(e.locatorHash);if(void 0!==n)return n;const r=t.storedPackages.get(e.locatorHash);if(void 0===r)throw new Error("Assertion failed: The package should have been registered");const o=(0,c.createHash)("sha512");o.update(e.locatorHash),p.set(e.locatorHash,"");for(const e of r.dependencies.values()){const n=t.storedResolutions.get(e.descriptorHash);if(void 0===n)throw new Error(`Assertion failed: The resolution (${a.structUtils.prettyDescriptor(t.configuration,e)}) should have been registered`);const r=t.storedPackages.get(n);if(void 0===r)throw new Error("Assertion failed: The package should have been registered");o.update(h(r))}return n=o.digest("hex"),p.set(e.locatorHash,n),n},u=(0,c.createHash)("sha512").update(d).update(h(o)).update(i).digest("hex");t.storedBuildState.set(o.locatorHash,u),await t.persistInstallStateFile()}))).exitCode()}}l.paths=[["nixify","inject-build"]];const d=e("@yarnpkg/plugin-pnp"),p=JSON.stringify,h=(e,t,n=!1)=>t.split("\n").map((t=>t||n?e+t:t)).join("\n"),u=(e,t)=>{let n=e;for(const[e,r]of Object.entries(t))if("string"==typeof r&&(n=n.replace(new RegExp(`@@${e}@@`,"g"),r)),"boolean"==typeof r)for(;;){const t=n.split("\n"),a=t.indexOf(`#@@ IF ${e}`),o=t.indexOf(`#@@ ENDIF ${e}`);if(-1===a||o{if(!n)return;const o=s.npath.toPortablePath(this.binDir);for(const[r,a]of n.manifest.bin){const n=s.ppath.join(o,r),i=s.ppath.join(t.cwd,s.npath.toPortablePath(a));await this.writeWrapper(n,i,{configuration:e,project:t})}if(e.get("installNixBinariesForDependencies")){await t.resolveEverything({report:r,lockfileOnly:!0});const n=await a.scriptUtils.getPackageAccessibleBinaries(t.topLevelWorkspace.anchoredLocator,{project:t});for(const[r,[a,i]]of n.entries()){const n=s.ppath.join(o,r);await this.writeWrapper(n,s.npath.toPortablePath(i),{configuration:e,project:t})}}}))).exitCode()}async writeWrapper(e,t,{configuration:n,project:r}){let a;switch(n.get("nodeLinker")){case"pnp":{const e=(0,d.getPnpPath)(r),n=[];await s.xfs.existsPromise(e.cjs)&&n.push(`--require "${s.npath.fromPortablePath(e.cjs)}"`),await s.xfs.existsPromise(e.esmLoader)&&n.push(`--experimental-loader "${(0,f.pathToFileURL)(s.npath.fromPortablePath(e.esmLoader)).href}"`),a=u("#!/bin/sh\nexport NODE_OPTIONS='@@NODE_OPTIONS@@'\nexec '@@NODE_PATH@@' '@@BINARY_PATH@@' \"$@\"\n",{NODE_PATH:process.execPath,NODE_OPTIONS:n.join(" "),BINARY_PATH:t});break}case"node-modules":a=u("#!/bin/sh\nexec '@@NODE_PATH@@' '@@BINARY_PATH@@' \"$@\"\n",{NODE_PATH:process.execPath,BINARY_PATH:t});break;default:throw Error("Assertion failed: Invalid nodeLinker")}await s.xfs.writeFilePromise(e,a),await s.xfs.chmodPromise(e,493)}}g.paths=[["nixify","install-bin"]];const m=e("os"),y=e("@yarnpkg/plugin-patch"),b=(e,t)=>(0,c.createHash)(e).update(t).digest(),x=(e,t,{storePath:n="/nix/store",recursive:r=!1}={})=>{const[a,o]=t.split("-"),i=Buffer.from(o,"base64").toString("hex"),c=b("sha256",`fixed:out:${r?"r:":""}${a}:${i}:`).toString("hex"),l=(e=>{let t="",n=[...e].reverse().map((e=>e.toString(2).padStart(8,"0"))).join("");for(;n;)t+="0123456789abcdfghijklmnpqrsvwxyz"[parseInt(n.slice(0,5),2)],n=n.slice(5);return t})(((e,t)=>{const n=Buffer.alloc(20);for(let t=0;te.replace(/^\.+/,"").replace(/[^a-zA-Z0-9+._?=-]+/g,"-").slice(0,207)||"unknown",w=(e,t="sha512")=>t+"-"+Buffer.from(e,"hex").toString("base64"),k=e=>Buffer.from(e.split("-")[1],"base64").toString("hex"),I=2**32-1,P=(e,...t)=>{let n=0;const r=t.map((e=>{const t=Buffer.from(e);if(t.byteLength>I)throw Error(`NAR string too long: ${t.byteLength}`);return n+=8+8*Math.ceil(t.byteLength/8),t})),a=Buffer.alloc(n);let o=0;for(const e of r)a.writeUInt32LE(e.byteLength,o),e.copy(a,o+8),o+=8+8*Math.ceil(e.byteLength/8);e.write(a)},$=async(e,t,n)=>{if(t>I)throw Error(`NAR string too long: ${t}`);const r=Buffer.alloc(8);r.writeUInt32LE(t),e.write(r);for await(const t of n)e.write(t);const a=8-t%8;8!==a&&e.write(Buffer.alloc(a))},N=a.YarnVersion?.startsWith("3.")||!1,E={commands:[i,l,g],hooks:{afterAllInstalled:async(e,t)=>{!1!==t.persistProject&&e.configuration.get("enableNixify")&&await(async(e,t)=>{const{configuration:n,cwd:r}=e,{cache:o,report:i}=t,l=await s.xfs.realpathPromise(s.npath.toPortablePath((0,m.tmpdir)()));if(e.cwd.startsWith(l))return void i.reportInfo(0,`Skipping Nixify, because ${e.cwd} appears to be a temporary directory`);const d=n.get("nixExprPath"),f=n.get("yarnPath");let g;if(null===f){let e=(await s.xfs.readFilePromise(process.argv[1])).toString();if(e.startsWith("#!/nix/store/")){const t=e.substring(e.indexOf("\n")+1);e=`#!/usr/bin/env node\n${t}`}const t=a.hashUtils.makeHash(Buffer.from(e));g=["fetchurl {",` url = "https://repo.yarnpkg.com/${a.YarnVersion}/packages/yarnpkg-cli/bin/yarn.js";`,` hash = "${w(t)}";`,"}"].join("\n ")}else f.startsWith(r)?g="./"+s.ppath.relative(s.ppath.dirname(d),f):(g=p(f),i.reportWarning(0,`The Yarn path ${f} is outside the project - it may not be reachable by the Nix build`));const b=n.get("cacheFolder");let I;if(b.startsWith(r))I=p(s.ppath.relative(r,b));else{if(N||!n.get("enableGlobalCache"))throw Error(`The cache folder ${b} is outside the project, this is currently not supported`);I='".yarn/cache"'}const E=new Set;for(const e of n.sources.values())for(const t of e.split(", "))t.startsWith("<")||E.add(t);for(const e of E)s.ppath.resolve(r,e).startsWith(r)||i.reportWarning(0,`The config file ${e} is outside the project - it may not be reachable by the Nix build`);const D="./"+s.ppath.relative(s.ppath.dirname(d),s.ppath.resolve(r,"yarn.lock")),S=new Map,_=new Set(await s.xfs.readdirPromise(o.cwd)),L={unstablePackages:e.conditionalLocators};for(const t of e.storedPackages.values()){const{locatorHash:n}=t,r=e.storedChecksums.get(n),a=N?o.getLocatorPath(t,r||null,L):o.getLocatorPath(t,r||null);if(!a)continue;if(!_.has(s.ppath.basename(a)))continue;const i=r?o.getChecksumFilename(t,r):o.getVersionFilename(t);S.set(i,{pkg:t,checksum:r,cachePath:a})}const O=new Map,A=n.get("individualNixPackaging");let j="",T="";if(A){for(const[e,{pkg:t,checksum:n,cachePath:r}]of S.entries()){const o=a.structUtils.stringifyLocator(t),i=n?n.split("/").pop():await a.hashUtils.checksumFile(r);O.set(o,{cachePath:r,filename:e,hash:w(i)})}j="cacheEntries = {\n";for(const e of[...O.keys()].sort()){const t=O.get(e);j+=`${p(e)} = { ${[`filename = ${p(t.filename)};`,`hash = "${t.hash}";`].join(" ")} };\n`}j+="};"}else{const e=(0,c.createHash)("sha512");P(e,"nix-archive-1","(","type","directory");for(const t of[...S.keys()].sort()){const{cachePath:n}=S.get(t),{size:r}=await s.xfs.statPromise(n);P(e,"entry","(","name",t,"node","(","type","regular","contents"),await $(e,r,s.xfs.createReadStream(n)),P(e,")",")")}P(e,")"),e.end();for await(const t of e)T=w(t)}const C=n.get("isolatedNixBuilds");let R=new Set,F=[],B=[];const H=n.get("nodeLinker"),U=n.get("pnpUnpluggedFolder"),M=(t,n=new Set)=>{const r=a.structUtils.stringifyLocator(t);if(O.has(r)&&n.add(r),a.structUtils.isVirtualLocator(t)){const r=e.storedPackages.get(a.structUtils.devirtualizeLocator(t).locatorHash);if(!r)throw Error("Assertion failed: The locator should have been registered");M(r,n)}if(t.reference.startsWith("patch:")){const r=e.storedPackages.get(y.patchUtils.parseLocator(t).sourceLocator.locatorHash);if(!r)throw Error("Assertion failed: The locator should have been registered");M(r,n)}for(const r of t.dependencies.values()){const t=e.storedResolutions.get(r.descriptorHash);if(!t)throw Error("Assertion failed: The descriptor should have been registered");const a=e.storedPackages.get(t);if(!a)throw Error("Assertion failed: The locator should have been registered");M(a,n)}return n};for(const t of e.storedBuildState.keys()){const n=e.storedPackages.get(t);if(!n)throw Error("Assertion failed: The locator should have been registered");if(!C.includes(n.name))continue;let r;if("pnp"!==H)throw Error(`The nodeLinker ${H} is not supported for isolated Nix builds`);r=s.ppath.relative(e.cwd,s.ppath.join(U,a.structUtils.slugifyLocator(n),a.structUtils.getIdentVendorPath(n)));let o=n;if(a.structUtils.isVirtualLocator(o)){const{locatorHash:t}=a.structUtils.devirtualizeLocator(o),n=e.storedPackages.get(t);if(!n)throw Error("Assertion failed: The locator should have been registered");o=n}const i=a.structUtils.stringifyLocator(o),c=a.structUtils.stringifyLocator(n),l=`isolated.${p(i)}`;if(!R.has(o)){R.add(o);const e=[`pname = ${p(n.name)};`,`version = ${p(n.version)};`,`reference = ${p(o.reference)};`];if(A){const t=[...M(n)].sort().map((e=>`${p(e)}\n`)).join("");t&&e.push(`locators = [\n${t}];`)}const t=`override${V=n.name,V.split(/[^a-zA-Z0-9]+/g).filter((e=>e)).map((e=>{return(t=e).slice(0,1).toUpperCase()+t.slice(1);var t})).join("")}Attrs`;B.push(`${l} = optionalOverride (args.${t} or null) (mkIsolatedBuild { ${e.join(" ")} });`)}0===F.length&&F.push("# Copy in isolated builds."),F.push(`echo 'injecting build for ${n.name}'`,"yarn nixify inject-build \\",` ${p(c)} \\`,` \${${l}} \\`,` ${p(r)}`)}var V;if(F.length>0&&F.push("echo 'running yarn install'"),null==t.mode||0===C.length){const t=e.topLevelWorkspace.manifest.name,o=t?a.structUtils.stringifyIdent(t):"workspace",c=u("# This file is generated by running \"yarn install\" inside your project.\n# Manual changes might be lost - proceed with caution!\n\n{ lib, stdenv, nodejs, git, cacert, fetchurl, writeShellScript, writeShellScriptBin }:\n{ src, overrideAttrs ? null, ... } @ args:\n\nlet\n\n yarnBin = @@YARN_BIN@@;\n\n cacheFolder = @@CACHE_FOLDER@@;\n lockfile = @@LOCKFILE@@;\n\n # Call overrideAttrs on a derivation if a function is provided.\n optionalOverride = fn: drv:\n if fn == null then drv else drv.overrideAttrs fn;\n\n # Simple stub that provides the global yarn command.\n yarn = writeShellScriptBin \"yarn\" ''\n exec '${nodejs}/bin/node' '${yarnBin}' \"$@\"\n '';\n\n # Common attributes between Yarn derivations.\n drvCommon = {\n # Make sure the build uses the right Node.js version everywhere.\n buildInputs = [ nodejs yarn ];\n # All dependencies should already be cached.\n yarn_enable_network = \"0\";\n # Tell node-gyp to use the provided Node.js headers for native code builds.\n npm_config_nodedir = nodejs;\n };\n\n # Comman variables that we set in a Nix build, but not in a Nix shell.\n buildVars = ''\n # Make Yarn produce friendlier logging for automated builds.\n export CI=1\n # Tell node-pre-gyp to never fetch binaries / always build from source.\n export npm_config_build_from_source=true\n '';\n\n#@@ IF COMBINED_DRV\n cacheDrv = stdenv.mkDerivation {\n name = \"yarn-cache\";\n buildInputs = [ yarn git cacert ];\n buildCommand = ''\n cp --reflink=auto --recursive '${src}' ./src\n cd ./src/\n ${buildVars}\n HOME=\"$TMP\" yarn_enable_global_cache=false yarn_cache_folder=\"$out\" \\\n yarn nixify fetch\n rm $out/.gitignore\n '';\n outputHashMode = \"recursive\";\n outputHash = \"@@COMBINED_HASH@@\";\n };\n#@@ ENDIF COMBINED_DRV\n#@@ IF INDIVIDUAL_DRVS\n # Create derivations for fetching dependencies.\n cacheDrvs = let\n in lib.mapAttrs (locator: { filename, hash }: stdenv.mkDerivation {\n name = lib.strings.sanitizeDerivationName locator;\n buildInputs = [ yarn git cacert ];\n buildCommand = ''\n cd '${src}'\n ${buildVars}\n HOME=\"$TMP\" yarn_enable_global_cache=false yarn_cache_folder=\"$TMP\" \\\n yarn nixify fetch ${lib.escapeShellArg locator}\n # Because we change the cache dir, Yarn may generate a different name.\n mv \"$TMP/$(sed 's/-[^-]*\\.[^-]*$//' <<< \"$outputFilename\")\"-* $out\n '';\n outputFilename = filename;\n outputHash = hash;\n }) cacheEntries;\n\n # Create a shell snippet to copy dependencies from a list of derivations.\n mkCacheBuilderForDrvs = drvs:\n writeShellScript \"collect-yarn-cache\" (lib.concatMapStrings (drv: ''\n cp --reflink=auto ${drv} '${drv.outputFilename}'\n '') drvs);\n#@@ ENDIF INDIVIDUAL_DRVS\n\n#@@ IF NEED_ISOLATED_BUILD_SUPPRORT\n#@@ IF INDIVIDUAL_DRVS\n # Create a shell snippet to copy dependencies from a list of locators.\n mkCacheBuilderForLocators = let\n pickCacheDrvs = map (locator: cacheDrvs.${locator});\n in locators:\n mkCacheBuilderForDrvs (pickCacheDrvs locators);\n#@@ ENDIF INDIVIDUAL_DRVS\n\n # Create a derivation that builds a module in isolation.\n mkIsolatedBuild = { pname, version, reference, locators ? [] }: stdenv.mkDerivation (drvCommon // {\n inherit pname version;\n dontUnpack = true;\n\n configurePhase = ''\n ${buildVars}\n unset yarn_enable_nixify # plugin is not present\n '';\n\n buildPhase = ''\n mkdir -p .yarn/cache\n#@@ IF COMBINED_DRV\n cp --reflink=auto --recursive ${cacheDrv}/* .yarn/cache/\n#@@ ENDIF COMBINED_DRV\n#@@ IF INDIVIDUAL_DRVS\n pushd .yarn/cache > /dev/null\n source ${mkCacheBuilderForLocators locators}\n popd > /dev/null\n#@@ ENDIF INDIVIDUAL_DRVS\n\n echo '{ \"dependencies\": { \"${pname}\": \"${reference}\" } }' > package.json\n install -m 0600 ${lockfile} ./yarn.lock\n export yarn_global_folder=\"$TMP\"\n export yarn_enable_global_cache=false\n export yarn_enable_immutable_installs=false\n yarn\n '';\n\n installPhase = ''\n unplugged=( .yarn/unplugged/${pname}-*/node_modules/* )\n if [[ ! -e \"''${unplugged[@]}\" ]]; then\n echo >&2 \"Could not find the unplugged path for ${pname}\"\n exit 1\n fi\n\n mv \"$unplugged\" $out\n '';\n });\n#@@ ENDIF NEED_ISOLATED_BUILD_SUPPRORT\n\n # Main project derivation.\n project = stdenv.mkDerivation (drvCommon // {\n inherit src;\n name = @@PROJECT_NAME@@;\n\n configurePhase = ''\n ${buildVars}\n\n # Copy over the Yarn cache.\n rm -fr '${cacheFolder}'\n mkdir -p '${cacheFolder}'\n#@@ IF COMBINED_DRV\n cp --reflink=auto --recursive ${cacheDrv}/* '${cacheFolder}/'\n#@@ ENDIF COMBINED_DRV\n#@@ IF INDIVIDUAL_DRVS\n pushd '${cacheFolder}' > /dev/null\n source ${mkCacheBuilderForDrvs (lib.attrValues cacheDrvs)}\n popd > /dev/null\n#@@ ENDIF INDIVIDUAL_DRVS\n\n # Yarn may need a writable home directory.\n export yarn_global_folder=\"$TMP\"\n\n # Ensure global cache is disabled. Cache must be part of our output.\n touch .yarnrc.yml\n sed -i -e '/^enableGlobalCache/d' .yarnrc.yml\n echo 'enableGlobalCache: false' >> .yarnrc.yml\n\n # Some node-gyp calls may call out to npm, which could fail due to an\n # read-only home dir.\n export HOME=\"$TMP\"\n\n # running preConfigure after the cache is populated allows for\n # preConfigure to contain substituteInPlace for dependencies as well as the\n # main project. This is necessary for native bindings that maybe have\n # hardcoded values.\n runHook preConfigure\n\n@@ISOLATED_INTEGRATION@@\n\n # Run normal Yarn install to complete dependency installation.\n yarn install --immutable --immutable-cache\n\n runHook postConfigure\n '';\n\n buildPhase = ''\n runHook preBuild\n runHook postBuild\n '';\n\n installPhase = ''\n runHook preInstall\n\n # Move the package contents to the output directory.\n if grep -q '\"workspaces\"' package.json; then\n # We can't use `yarn pack` in a workspace setup, because it only\n # packages the outer workspace.\n mkdir -p \"$out/libexec\"\n mv $PWD \"$out/libexec/$name\"\n else\n # - If the package.json has a `files` field, only files matching those patterns are copied\n # - Otherwise all files are copied.\n yarn pack --out package.tgz\n mkdir -p \"$out/libexec/$name\"\n tar xzf package.tgz --directory \"$out/libexec/$name\" --strip-components=1\n\n cp --reflink=auto .yarnrc* \"$out/libexec/$name\"\n cp --reflink=auto ${lockfile} \"$out/libexec/$name/yarn.lock\"\n cp --reflink=auto --recursive .yarn \"$out/libexec/$name\"\n\n # Copy the Yarn linker output into the package.\n#@@ IF USES_PNP_LINKER\n cp --reflink=auto .pnp.* \"$out/libexec/$name\"\n#@@ ENDIF USES_PNP_LINKER\n#@@ IF USES_NM_LINKER\n cp --reflink=auto --recursive node_modules \"$out/libexec/$name\"\n#@@ ENDIF USES_NM_LINKER\n fi\n\n cd \"$out/libexec/$name\"\n\n # Invoke a plugin internal command to setup binaries.\n mkdir -p \"$out/bin\"\n yarn nixify install-bin $out/bin\n\n#@@ IF USES_NM_LINKER\n # A package with node_modules doesn't need the cache\n yarn cache clean\n#@@ ENDIF USES_NM_LINKER\n\n runHook postInstall\n '';\n\n passthru = {\n inherit nodejs;\n yarn-freestanding = yarn;\n yarn = writeShellScriptBin \"yarn\" ''\n exec '${yarn}/bin/yarn' --cwd '${overriddenProject}/libexec/${overriddenProject.name}' \"$@\"\n '';\n };\n });\n\n overriddenProject = optionalOverride overrideAttrs project;\n\n@@CACHE_ENTRIES@@\n@@ISOLATED@@\nin overriddenProject\n",{PROJECT_NAME:p(o),YARN_BIN:g,LOCKFILE:D,INDIVIDUAL_DRVS:A,COMBINED_DRV:!A,COMBINED_HASH:T,CACHE_FOLDER:I,CACHE_ENTRIES:j,ISOLATED:B.join("\n"),ISOLATED_INTEGRATION:h(" ",F.join("\n")),NEED_ISOLATED_BUILD_SUPPRORT:F.length>0,USES_PNP_LINKER:"pnp"===n.get("nodeLinker"),USES_NM_LINKER:"node-modules"===n.get("nodeLinker")}).replace(/\n\n\n+/g,"\n\n");if(await s.xfs.mkdirpPromise(s.ppath.dirname(d)),await s.xfs.writeFilePromise(d,c),n.get("generateDefaultNix")){const e=s.ppath.join(r,"default.nix"),t=s.ppath.join(r,"flake.nix");s.xfs.existsSync(e)||s.xfs.existsSync(t)||(await s.xfs.writeFilePromise(e,"# This is a minimal `default.nix` by yarn-plugin-nixify. You can customize it\n# as needed, it will not be overwritten by the plugin.\n\n{ pkgs ? import { } }:\n\npkgs.callPackage ./yarn-project.nix { } { src = ./.; }\n"),i.reportInfo(0,"A minimal default.nix was created. You may want to customize it."))}}n.get("enableNixPreload")&&s.xfs.existsSync(s.npath.toPortablePath("/nix/store"))&&await s.xfs.mktempPromise((async t=>{const n=["--add-fixed","sha512"],r=[];if(A)for(const[e,{cachePath:n,hash:a}]of O.entries()){const o=v(e),i=x(o,a);if(!s.xfs.existsSync(i)){const e=s.ppath.join(t,k(a).slice(0,7));await s.xfs.mkdirPromise(e);const i=s.ppath.join(e,o);await s.xfs.copyFilePromise(n,i),r.push(i)}}else{n.unshift("--recursive");const e=x("yarn-cache",T,{recursive:!0});if(!s.xfs.existsSync(e)){const e=s.ppath.join(t,"yarn-cache");await s.xfs.mkdirPromise(e);for(const[t,{cachePath:n}]of S.entries()){const r=s.ppath.join(e,t);await s.xfs.copyFilePromise(n,r)}r.push(e)}}try{const t=r.length;for(;0!==r.length;){const t=r.splice(0,100);await a.execUtils.execvp("nix-store",[...n,...t],{cwd:e.cwd,strict:!0})}0!==t&&i.reportInfo(0,A?`Preloaded ${t} packages into the Nix store`:"Preloaded cache into the Nix store")}catch(e){if("ENOENT"!==e.code)throw e}}))})(e,t)}},configuration:{enableNixify:{description:"If false, disables the Nixify plugin hook that generates Nix expressions",type:a.SettingsType.BOOLEAN,default:!0},nixExprPath:{description:"Path of the file where the project Nix expression will be written to",type:a.SettingsType.ABSOLUTE_PATH,default:"./yarn-project.nix"},generateDefaultNix:{description:"If true, a default.nix will be generated if it does not exist",type:a.SettingsType.BOOLEAN,default:!0},enableNixPreload:{description:"If true, cached packages will be preloaded into the Nix store",type:a.SettingsType.BOOLEAN,default:!0},individualNixPackaging:{description:"If true, generate one Nix derivation per package. If false, use a single derivation for the entire cache folder.",type:a.SettingsType.BOOLEAN,default:!1},isolatedNixBuilds:{description:"Dependencies with a build step that can be built in an isolated derivation",type:a.SettingsType.STRING,default:[],isArray:!0},installNixBinariesForDependencies:{description:"If true, the Nix output 'bin' directory will also contain executables for binaries defined by dependencies",type:a.SettingsType.BOOLEAN,default:!1}}};t=r})(),t}}; \ No newline at end of file diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..da4124a --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,29 @@ +approvedGitRepositories: + - "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/*" + +enableScripts: true + +generateDefaultNix: false + +individualNixPackaging: true + +nodeLinker: node-modules + +supportedArchitectures: + os: + - current + - linux + cpu: + - current + - x64 + - arm64 + libc: + - current + - glibc + +npmMinimalAgeGate: 0 + +plugins: + - checksum: 271de9a785321a37c564b8e2a6b5cd689850b20572d5fee8ec0a6b8e7a5d4cfb59e533524af2b4a537e00da12828abd062eaec6978556e3dd9149a020db2591b + path: .yarn/plugins/yarn-plugin-nixify.cjs + spec: "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/yarn-plugin-nixify-patched/raw/commit/4528fdd20b30d869262443b3f044549810e75fb8/dist/yarn-plugin-nixify.js" diff --git a/bindings.json b/bindings.json new file mode 100644 index 0000000..a922a4d --- /dev/null +++ b/bindings.json @@ -0,0 +1,12 @@ +{ + "messages": { + "org.quixos.web-studio.CanvasPosition": { + "module": "../messages.js", + "export": "positionBinding" + }, + "org.quixos.web-studio.CanvasSize": { + "module": "../messages.js", + "export": "sizeBinding" + } + } +} diff --git a/descriptor.quixos-package.txtpb b/descriptor.quixos-package.txtpb new file mode 100644 index 0000000..93eafa9 --- /dev/null +++ b/descriptor.quixos-package.txtpb @@ -0,0 +1,6 @@ +# Generated by qx-scaffold-v1 +package_id: "package:org.quixos.web-studio:canvas-runtime" +package_revision_id: "package:org.quixos.web-studio:canvas-runtime@1" +runtime_protocol_version: "quixos-capabilities-v1" +exports: { export_id: "export:org.quixos.web-studio.canvas-runtime:create-canvas" runtime_symbol: "createCanvas" } +exports: { export_id: "export:org.quixos.web-studio.canvas-runtime:create-placement" runtime_symbol: "createPlacement" } diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..2b0e74b --- /dev/null +++ b/flake.lock @@ -0,0 +1,80 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1788531059, + "narHash": "sha256-hLD4l3QOGBQhkVp3mQ2lJ/YbEi99qUgKapb40KovZ88=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "801bef6abd86b91e51083066b83fb354a11fc640", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "quixosNixHelpers": { + "flake": false, + "locked": { + "lastModified": 1789364768, + "narHash": "sha256-6tINqOSLd3TTACk/HAfhXqo07H69yjX3Q/DrrAPWzus=", + "ref": "refs/tags/quixos-reachability/cf7945abb6ee2533a34dff4a7d4a956e70efe007", + "rev": "cf7945abb6ee2533a34dff4a7d4a956e70efe007", + "revCount": 22, + "type": "git", + "url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git" + }, + "original": { + "ref": "refs/tags/quixos-reachability/cf7945abb6ee2533a34dff4a7d4a956e70efe007", + "rev": "cf7945abb6ee2533a34dff4a7d4a956e70efe007", + "type": "git", + "url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "quixosNixHelpers": "quixosNixHelpers" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3b30661 --- /dev/null +++ b/flake.nix @@ -0,0 +1,32 @@ +{ + description = "Quixos Web Studio canvas runtime package"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + quixosNixHelpers = { + url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/cf7945abb6ee2533a34dff4a7d4a956e70efe007&rev=cf7945abb6ee2533a34dff4a7d4a956e70efe007"; + flake = false; + }; + }; + + outputs = inputs@{ nixpkgs, flake-utils, quixosNixHelpers, ... }: + let + quixosHelpers = import "${quixosNixHelpers}/quixos-package-helpers.nix"; + in + quixosHelpers.mkCaminoTsYarnNixifyFlake { + inherit inputs nixpkgs flake-utils; + packageRoot = ./.; + migrationEntrypoint = "dist/migrate.js"; + bindingOptions = builtins.fromJSON (builtins.readFile ./bindings.json); + promptName = "web-studio-canvas-runtime"; + bundle = { + entry = "dist/server.js"; + }; + installServer = { + libexecName = "web-studio-canvas-runtime"; + descriptorPath = "descriptor.quixos-package.txtpb"; + }; + }; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2e7914a --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "@quixos/web-studio-canvas-runtime", + "version": "0.1.0", + "private": true, + "packageManager": "yarn@4.18.0", + "type": "module", + "bin": { + "server": "dist/server.js" + }, + "scripts": { + "build": "rm -rf dist && tsc -p tsconfig.build.json", + "test": "yarn build && node --test test/*.test.mjs", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@quixos/camino-package-runtime": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=d3d050d9cb84421fd8043ebe34fd0cae9132f6a2" + }, + "devDependencies": { + "@types/node": "^24", + "typescript": "^7.0.2" + } +} diff --git a/package.qx b/package.qx new file mode 100644 index 0000000..8c387db --- /dev/null +++ b/package.qx @@ -0,0 +1,20 @@ +import interface WebStudioCanvasPlacement; +external atom WebStudioCanvas id "atom:org.quixos.web-studio:canvas"; +external atom WebStudioCanvasPlacement id "atom:org.quixos.web-studio:canvas-placement"; +external interface WebStudioCanvasInterface revision "interface:org.quixos.web-studio.canvas@1"; +external interface WebStudioPlaceable revision "interface:org.quixos.web-studio.placeable@1"; + +package WebStudioCanvasRuntime id "package:org.quixos.web-studio:canvas-runtime" revision "package:org.quixos.web-studio:canvas-runtime@1" { + constructor createCanvas id "export:org.quixos.web-studio.canvas-runtime:create-canvas" constructs WebStudioCanvas : unit; + constructor createPlacement id "export:org.quixos.web-studio.canvas-runtime:create-placement" constructs WebStudioCanvasPlacement : record { + canvas_id: interface-ref; + subject_id: interface-ref; + x: double; + y: double; + width: double; + height: double; + z: int32; + } requires { + interface placement id "port:web-studio-placement-constructor:placement" : WebStudioCanvasPlacement; + }; +} diff --git a/quixos.check.json b/quixos.check.json new file mode 100644 index 0000000..a2bfcfc --- /dev/null +++ b/quixos.check.json @@ -0,0 +1,16 @@ +{ + "backend": "typescript", + "bindingOutput": "src/gen/qx.ts", + "options": { + "messages": { + "org.quixos.web-studio.CanvasPosition": { + "module": "../messages.js", + "export": "positionBinding" + }, + "org.quixos.web-studio.CanvasSize": { + "module": "../messages.js", + "export": "sizeBinding" + } + } + } +} diff --git a/quixos.lock b/quixos.lock new file mode 100644 index 0000000..814b112 --- /dev/null +++ b/quixos.lock @@ -0,0 +1,10 @@ +quixos-lock version 1 { + quixos source { + repository "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git"; + commit "ba8d4f92667f39bb02d542cb492b71a32ec914bf"; + } + interface WebStudioCanvasPlacement source { + repository "https://repos.quixos.org/org-quixos-web-studio/interface-canvas-placement.git"; + commit "0000000000000000000000000000000000000025"; + } +} diff --git a/quixos.migrations.json b/quixos.migrations.json new file mode 100644 index 0000000..cf8d17d --- /dev/null +++ b/quixos.migrations.json @@ -0,0 +1,6 @@ +{ + "generatedBy": "qx-scaffold-v1", + "schemaVersion": 1, + "contracts": {}, + "migrations": [] +} diff --git a/quixos.scaffold.json b/quixos.scaffold.json new file mode 100644 index 0000000..3d0adef --- /dev/null +++ b/quixos.scaffold.json @@ -0,0 +1,18 @@ +{ + "generatedBy": "qx-scaffold-v1", + "name": "WebStudioCanvasRuntime", + "id": "package:org.quixos.web-studio:canvas-runtime", + "revision": "package:org.quixos.web-studio:canvas-runtime@1", + "exports": [ + { + "name": "createCanvas", + "id": "export:org.quixos.web-studio.canvas-runtime:create-canvas", + "file": "src/impl/createCanvas.ts" + }, + { + "name": "createPlacement", + "id": "export:org.quixos.web-studio.canvas-runtime:create-placement", + "file": "src/impl/createPlacement.ts" + } + ] +} diff --git a/quixos.toolchain.json b/quixos.toolchain.json new file mode 100644 index 0000000..dd3c7fa --- /dev/null +++ b/quixos.toolchain.json @@ -0,0 +1,4 @@ +{ + "generatedBy": "qx-scaffold-v1", + "nixifyPluginUrl": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/yarn-plugin-nixify-patched/raw/commit/4528fdd20b30d869262443b3f044549810e75fb8/dist/yarn-plugin-nixify.js" +} diff --git a/src/canvas.impl.ts b/src/canvas.impl.ts new file mode 100644 index 0000000..895ca9e --- /dev/null +++ b/src/canvas.impl.ts @@ -0,0 +1,52 @@ +import { + objectRef, + type QxObjectRef, +} from "@quixos/camino-package-runtime"; +import type { Contexts } from "./gen/qx.js"; + +export type PlacementInput = { + canvas_id: QxObjectRef; + subject_id: QxObjectRef; + x: number; + y: number; + width: number; + height: number; + z: number; +}; + +const finiteNumber = (value: unknown, fallback: number) => + typeof value === "number" && Number.isFinite(value) ? value : fallback; + +const objectId = (value: unknown, field: string) => { + try { + return objectRef(value as QxObjectRef); + } catch { + throw new Error(`${field} must be a managed object reference`); + } +}; + +export const normalizePlacementInput = ( + input: Record, +): PlacementInput => ({ + canvas_id: objectId(input.canvas_id, "canvas_id"), + subject_id: objectId(input.subject_id, "subject_id"), + x: finiteNumber(input.x, 0), + y: finiteNumber(input.y, 0), + width: Math.max(220, finiteNumber(input.width, 420)), + height: Math.max(150, finiteNumber(input.height, 320)), + z: Math.trunc(finiteNumber(input.z, 0)), +}); + +export const createCanvas = ({ objectId }: Contexts["createCanvas"]) => objectId; + +export const createPlacement = async (context: Contexts["createPlacement"]) => { + const input = normalizePlacementInput(context.input); + await Promise.all([ + context.ports.placement["position.set"]({ x: input.x, y: input.y }), + context.ports.placement["size.set"]({ width: input.width, height: input.height }), + context.ports.placement["z.set"](input.z), + ]); + await context.ports.placement["subject.connect"](context.input.subject_id); + await context.ports.placement["canvas.connect"](context.input.canvas_id); + return context.objectId; +}; diff --git a/src/gen/qx.ts b/src/gen/qx.ts new file mode 100644 index 0000000..48da257 --- /dev/null +++ b/src/gen/qx.ts @@ -0,0 +1,237 @@ +// Generated by quixos-codegen-ts. Do not edit. Binding ABI version 1. +import { bindQxHandler, type BindingValue, type QxObjectRef, type QxHandler, type QxContextLifecycle, type QxLiveValue, type QxHandlerSpec, type QxMessages } from "@quixos/camino-package-runtime"; +import { positionBinding as message0 } from "../messages.js"; +import { sizeBinding as message1 } from "../messages.js"; +export const packageRevisionId = "package:org.quixos.web-studio:canvas-runtime@1"; +export type Contexts = { "createCanvas": { "objectId": QxObjectRef<"atom:atom:org.quixos.web-studio:canvas">; "input": null; "ports": { } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:org.quixos.web-studio:canvas">; "input": null; "ports": { } } & {signal?: AbortSignal}>; "createPlacement": { "objectId": QxObjectRef<"atom:atom:org.quixos.web-studio:canvas-placement">; "input": { "canvas_id": QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">; "subject_id": QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">; "x": number; "y": number; "width": number; "height": number; "z": number }; "ports": { "placement": { "objectId": QxObjectRef<"interface:interface:org.quixos.web-studio.canvas-placement@1">; "live": { "position.get": () => Promise; "position.set": (input: BindingValue) => Promise; "size.get": () => Promise; "size.set": (input: BindingValue) => Promise; "z.get": () => Promise; "z.set": (input: number) => Promise; "subject.resolve": () => Promise; "subject.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "subject.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "canvas.resolve": () => Promise; "canvas.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise; "canvas.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise }; "position.get": () => Promise>; "position.set": (input: BindingValue) => Promise; "size.get": () => Promise>; "size.set": (input: BindingValue) => Promise; "z.get": () => Promise; "z.set": (input: number) => Promise; "subject.resolve": () => Promise>; "subject.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "subject.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "canvas.resolve": () => Promise>; "canvas.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise; "canvas.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise } } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:org.quixos.web-studio:canvas-placement">; "input": { "canvas_id": QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">; "subject_id": QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">; "x": number; "y": number; "width": number; "height": number; "z": number }; "ports": { "placement": { "objectId": QxObjectRef<"interface:interface:org.quixos.web-studio.canvas-placement@1">; "live": { "position.get": () => Promise; "position.set": (input: BindingValue) => Promise; "size.get": () => Promise; "size.set": (input: BindingValue) => Promise; "z.get": () => Promise; "z.set": (input: number) => Promise; "subject.resolve": () => Promise; "subject.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "subject.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "canvas.resolve": () => Promise; "canvas.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise; "canvas.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise }; "position.get": () => Promise>; "position.set": (input: BindingValue) => Promise; "size.get": () => Promise>; "size.set": (input: BindingValue) => Promise; "z.get": () => Promise; "z.set": (input: number) => Promise; "subject.resolve": () => Promise>; "subject.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "subject.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.placeable@1">) => Promise; "canvas.resolve": () => Promise>; "canvas.connect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise; "canvas.disconnect": (input: QxObjectRef<"interface:interface:org.quixos.web-studio.canvas@1">) => Promise } } } & {signal?: AbortSignal}> }; +export type Implementation = { "createCanvas": QxHandler>; "createPlacement": QxHandler> }; +const messages = { "org.quixos.web-studio.CanvasPosition": message0, "org.quixos.web-studio.CanvasSize": message1 } satisfies QxMessages; +const specs = { + "createCanvas": { + "inputType": { + "kind": "builtin", + "name": "unit" + }, + "outputType": { + "kind": "object-ref", + "expectation": { + "kind": "atom", + "atomId": "atom:org.quixos.web-studio:canvas" + } + }, + "ports": {} + }, + "createPlacement": { + "inputType": { + "kind": "record", + "fields": { + "canvas_id": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.canvas@1" + } + }, + "subject_id": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.placeable@1" + } + }, + "x": { + "kind": "scalar", + "name": "double" + }, + "y": { + "kind": "scalar", + "name": "double" + }, + "width": { + "kind": "scalar", + "name": "double" + }, + "height": { + "kind": "scalar", + "name": "double" + }, + "z": { + "kind": "scalar", + "name": "int32" + } + } + }, + "outputType": { + "kind": "object-ref", + "expectation": { + "kind": "atom", + "atomId": "atom:org.quixos.web-studio:canvas-placement" + } + }, + "ports": { + "placement": { + "kind": "interface", + "id": "port:web-studio-placement-constructor:placement", + "operations": { + "position.get": { + "id": "operation:org.quixos.web-studio.canvas-placement:position:get", + "inputType": { + "kind": "builtin", + "name": "unit" + }, + "outputType": { + "kind": "message", + "descriptorId": "org.quixos.web-studio.CanvasPosition" + } + }, + "position.set": { + "id": "operation:org.quixos.web-studio.canvas-placement:position:set", + "inputType": { + "kind": "message", + "descriptorId": "org.quixos.web-studio.CanvasPosition" + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + }, + "size.get": { + "id": "operation:org.quixos.web-studio.canvas-placement:size:get", + "inputType": { + "kind": "builtin", + "name": "unit" + }, + "outputType": { + "kind": "message", + "descriptorId": "org.quixos.web-studio.CanvasSize" + } + }, + "size.set": { + "id": "operation:org.quixos.web-studio.canvas-placement:size:set", + "inputType": { + "kind": "message", + "descriptorId": "org.quixos.web-studio.CanvasSize" + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + }, + "z.get": { + "id": "operation:org.quixos.web-studio.canvas-placement:z:get", + "inputType": { + "kind": "builtin", + "name": "unit" + }, + "outputType": { + "kind": "scalar", + "name": "int32" + } + }, + "z.set": { + "id": "operation:org.quixos.web-studio.canvas-placement:z:set", + "inputType": { + "kind": "scalar", + "name": "int32" + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + }, + "subject.resolve": { + "id": "operation:org.quixos.web-studio.canvas-placement:subject:resolve", + "inputType": { + "kind": "builtin", + "name": "unit" + }, + "outputType": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.placeable@1" + } + } + }, + "subject.connect": { + "id": "operation:org.quixos.web-studio.canvas-placement:subject:connect", + "inputType": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.placeable@1" + } + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + }, + "subject.disconnect": { + "id": "operation:org.quixos.web-studio.canvas-placement:subject:disconnect", + "inputType": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.placeable@1" + } + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + }, + "canvas.resolve": { + "id": "operation:org.quixos.web-studio.canvas-placement:canvas:resolve", + "inputType": { + "kind": "builtin", + "name": "unit" + }, + "outputType": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.canvas@1" + } + } + }, + "canvas.connect": { + "id": "operation:org.quixos.web-studio.canvas-placement:canvas:connect", + "inputType": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.canvas@1" + } + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + }, + "canvas.disconnect": { + "id": "operation:org.quixos.web-studio.canvas-placement:canvas:disconnect", + "inputType": { + "kind": "object-ref", + "expectation": { + "kind": "interface", + "interfaceRevisionId": "interface:org.quixos.web-studio.canvas@1" + } + }, + "outputType": { + "kind": "builtin", + "name": "unit" + } + } + } + } + } + } +} satisfies Record; +export const createRuntime = (implementation: Implementation) => ({ + packageRevisionId, + exports: { + "export:org.quixos.web-studio.canvas-runtime:create-canvas": bindQxHandler(specs["createCanvas"], implementation["createCanvas"], messages), + "export:org.quixos.web-studio.canvas-runtime:create-placement": bindQxHandler(specs["createPlacement"], implementation["createPlacement"], messages), + }, +}); diff --git a/src/impl/createCanvas.ts b/src/impl/createCanvas.ts new file mode 100644 index 0000000..6bbb4d3 --- /dev/null +++ b/src/impl/createCanvas.ts @@ -0,0 +1,2 @@ +// This adapter keeps the implementation file hand-authored. +export {createCanvas as handler} from "../canvas.impl.js"; diff --git a/src/impl/createPlacement.ts b/src/impl/createPlacement.ts new file mode 100644 index 0000000..4a9ecf5 --- /dev/null +++ b/src/impl/createPlacement.ts @@ -0,0 +1,2 @@ +// This adapter keeps the implementation file hand-authored. +export {createPlacement as handler} from "../canvas.impl.js"; diff --git a/src/messages.ts b/src/messages.ts new file mode 100644 index 0000000..fd9782b --- /dev/null +++ b/src/messages.ts @@ -0,0 +1,10 @@ +import { encodeQxValue, decodeQxValue, type MessageBinding, type QxValueType } from "@quixos/camino-package-runtime"; + +const position: QxValueType = {kind: "record", fields: {x: {kind: "scalar", name: "double"}, y: {kind: "scalar", name: "double"}}}; +const size: QxValueType = {kind: "record", fields: {width: {kind: "scalar", name: "double"}, height: {kind: "scalar", name: "double"}}}; +export const positionBinding: MessageBinding<{x: number; y: number}> = { + encode: value => encodeQxValue(position, value, {}), decode: value => decodeQxValue(position, value, {}), +}; +export const sizeBinding: MessageBinding<{width: number; height: number}> = { + encode: value => encodeQxValue(size, value, {}), decode: value => decodeQxValue(size, value, {}), +}; diff --git a/src/migrate.ts b/src/migrate.ts new file mode 100644 index 0000000..c740a2c --- /dev/null +++ b/src/migrate.ts @@ -0,0 +1,3 @@ +// Generated by qx-scaffold-v1 +import {serveMigration} from "@quixos/camino-package-runtime"; +await serveMigration({}); diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..776c809 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,9 @@ +// Generated by qx-scaffold-v1 +import {servePackageRuntime} from "@quixos/camino-package-runtime"; +import {createRuntime} from "./gen/qx.js"; +import {handler as impl0} from "./impl/createCanvas.js"; +import {handler as impl1} from "./impl/createPlacement.js"; +servePackageRuntime(createRuntime({ + "createCanvas": impl0, + "createPlacement": impl1, +})); diff --git a/test/canvas.test.mjs b/test/canvas.test.mjs new file mode 100644 index 0000000..f38d634 --- /dev/null +++ b/test/canvas.test.mjs @@ -0,0 +1,35 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { normalizePlacementInput } from "../dist/canvas.impl.js"; +import { protoValueToJs } from "@quixos/camino-package-runtime"; + +const reference = (objectId) => protoValueToJs({kind: {case: "refValue", value: {objectId}}}); +const canvas = reference("obj:canvas"), subject = reference("obj:subject"); + +test("placement input is bounded and normalized", () => { + assert.deepEqual(normalizePlacementInput({ + canvas_id: canvas, + subject_id: subject, + x: 12.5, + y: -30, + width: 12, + height: 80, + z: 3.8, + }), { + canvas_id: canvas, + subject_id: subject, + x: 12.5, + y: -30, + width: 220, + height: 150, + z: 3, + }); +}); + +test("placement input requires Camino object references", () => { + assert.throws( + () => normalizePlacementInput({ canvas_id: "canvas", subject_id: "obj:subject" }), + /canvas_id must be a managed object reference/, + ); + assert.throws(() => normalizePlacementInput({canvas_id: "obj:canvas", subject_id: subject}), /managed object reference/); +}); diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..5adb3bc --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "sourceMap": true + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7c72f4b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "preserveSymlinks": true, + "resolveJsonModule": true, + "types": ["node"], + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/yarn-project.nix b/yarn-project.nix new file mode 100644 index 0000000..3c38646 --- /dev/null +++ b/yarn-project.nix @@ -0,0 +1,171 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +{ lib, stdenv, nodejs, git, cacert, fetchurl, writeShellScript, writeShellScriptBin }: +{ src, overrideAttrs ? null, ... } @ args: + +let + + yarnBin = fetchurl { + url = "https://repo.yarnpkg.com/4.18.0/packages/yarnpkg-cli/bin/yarn.js"; + hash = "sha512-/Lhxb+fNDuzhQf/Bi5IZOp35IEwbqDGJwoiDUiP8C75kr0c7qw1emSen2utcryuwfrJ4fMkzjKBA6hJfKh8vfg=="; + }; + + cacheFolder = ".yarn/cache"; + lockfile = ./yarn.lock; + + # Call overrideAttrs on a derivation if a function is provided. + optionalOverride = fn: drv: + if fn == null then drv else drv.overrideAttrs fn; + + # Simple stub that provides the global yarn command. + yarn = writeShellScriptBin "yarn" '' + exec '${nodejs}/bin/node' '${yarnBin}' "$@" + ''; + + # Common attributes between Yarn derivations. + drvCommon = { + # Make sure the build uses the right Node.js version everywhere. + buildInputs = [ nodejs yarn ]; + # All dependencies should already be cached. + yarn_enable_network = "0"; + # Tell node-gyp to use the provided Node.js headers for native code builds. + npm_config_nodedir = nodejs; + }; + + # Comman variables that we set in a Nix build, but not in a Nix shell. + buildVars = '' + # Make Yarn produce friendlier logging for automated builds. + export CI=1 + # Tell node-pre-gyp to never fetch binaries / always build from source. + export npm_config_build_from_source=true + ''; + + # Create derivations for fetching dependencies. + cacheDrvs = let + in lib.mapAttrs (locator: { filename, hash }: stdenv.mkDerivation { + name = lib.strings.sanitizeDerivationName locator; + buildInputs = [ yarn git cacert ]; + buildCommand = '' + cd '${src}' + ${buildVars} + HOME="$TMP" yarn_enable_global_cache=false yarn_cache_folder="$TMP" \ + yarn nixify fetch ${lib.escapeShellArg locator} + # Because we change the cache dir, Yarn may generate a different name. + mv "$TMP/$(sed 's/-[^-]*\.[^-]*$//' <<< "$outputFilename")"-* $out + ''; + outputFilename = filename; + outputHash = hash; + }) cacheEntries; + + # Create a shell snippet to copy dependencies from a list of derivations. + mkCacheBuilderForDrvs = drvs: + writeShellScript "collect-yarn-cache" (lib.concatMapStrings (drv: '' + cp --reflink=auto ${drv} '${drv.outputFilename}' + '') drvs); + + # Main project derivation. + project = stdenv.mkDerivation (drvCommon // { + inherit src; + name = "@quixos/web-studio-canvas-runtime"; + + configurePhase = '' + ${buildVars} + + # Copy over the Yarn cache. + rm -fr '${cacheFolder}' + mkdir -p '${cacheFolder}' + pushd '${cacheFolder}' > /dev/null + source ${mkCacheBuilderForDrvs (lib.attrValues cacheDrvs)} + popd > /dev/null + + # Yarn may need a writable home directory. + export yarn_global_folder="$TMP" + + # Ensure global cache is disabled. Cache must be part of our output. + touch .yarnrc.yml + sed -i -e '/^enableGlobalCache/d' .yarnrc.yml + echo 'enableGlobalCache: false' >> .yarnrc.yml + + # Some node-gyp calls may call out to npm, which could fail due to an + # read-only home dir. + export HOME="$TMP" + + # running preConfigure after the cache is populated allows for + # preConfigure to contain substituteInPlace for dependencies as well as the + # main project. This is necessary for native bindings that maybe have + # hardcoded values. + runHook preConfigure + + # Run normal Yarn install to complete dependency installation. + yarn install --immutable --immutable-cache + + runHook postConfigure + ''; + + buildPhase = '' + runHook preBuild + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + # Move the package contents to the output directory. + if grep -q '"workspaces"' package.json; then + # We can't use `yarn pack` in a workspace setup, because it only + # packages the outer workspace. + mkdir -p "$out/libexec" + mv $PWD "$out/libexec/$name" + else + # - If the package.json has a `files` field, only files matching those patterns are copied + # - Otherwise all files are copied. + yarn pack --out package.tgz + mkdir -p "$out/libexec/$name" + tar xzf package.tgz --directory "$out/libexec/$name" --strip-components=1 + + cp --reflink=auto .yarnrc* "$out/libexec/$name" + cp --reflink=auto ${lockfile} "$out/libexec/$name/yarn.lock" + cp --reflink=auto --recursive .yarn "$out/libexec/$name" + + # Copy the Yarn linker output into the package. + cp --reflink=auto --recursive node_modules "$out/libexec/$name" + fi + + cd "$out/libexec/$name" + + # Invoke a plugin internal command to setup binaries. + mkdir -p "$out/bin" + yarn nixify install-bin $out/bin + + # A package with node_modules doesn't need the cache + yarn cache clean + + runHook postInstall + ''; + + passthru = { + inherit nodejs; + yarn-freestanding = yarn; + yarn = writeShellScriptBin "yarn" '' + exec '${yarn}/bin/yarn' --cwd '${overriddenProject}/libexec/${overriddenProject.name}' "$@" + ''; + }; + }); + + overriddenProject = optionalOverride overrideAttrs project; + +cacheEntries = { +"@bufbuild/protobuf@npm:2.14.1" = { filename = "@bufbuild-protobuf-npm-2.14.1-78e9ea56a2-3f913aca03.zip"; hash = "sha512-P5E6ygPfhBnEsh2ADqVNf2yDalND5l1vaGJ57DVmxJB3KZOO8vlKXifZLo0/StzW4CcRi6Kbp2TSHhxjfN3HAg=="; }; +"@connectrpc/connect-node@npm:2.1.2" = { filename = "@connectrpc-connect-node-npm-2.1.2-021434d5d5-ba8b0c9384.zip"; hash = "sha512-uosMk4TDgps3eqeoJtwM1Qpgk1J9LscBRgSRKDYzbqlgSitazqQrEEd/i+RWnknd7WbKD8d/X1sCcDXgKeE+qQ=="; }; +"@connectrpc/connect@npm:2.1.2" = { filename = "@connectrpc-connect-npm-2.1.2-ab34825de3-4e15000890.zip"; hash = "sha512-ThUACJAjt1Lv1E+pQKWuHh+gDhvrxLoM7ScruTWSDYw7hbd0UOZErUQruMqaJ1sMFxNviWuo7/A2F4Ex2wHWFQ=="; }; +"@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=d3d050d9cb84421fd8043ebe34fd0cae9132f6a2" = { filename = "@quixos-camino-package-runtime-https-08b8790f1a-5bde059ead.zip"; hash = "sha512-W94Fnq0rn4MyBqRUUhH0ZcTzVv9MfF59dHtwpFLhg+/jK4QG5wi/uNgRR3xEVszpN8yrBWO6uiJGlkGmNnrczA=="; }; +"@types/node@npm:24.13.3" = { filename = "@types-node-npm-24.13.3-b512a0bbeb-a5bc08f49b.zip"; hash = "sha512-pbwI9JuVgdzcqQ4CzXcZejx5mECAdmSULlzVFhpVPU0q6AZPfjKUQQ10jX0Ji1wYSL5/pQwG8pxBk6sWvk5Z6w=="; }; +"@typescript/typescript-linux-arm64@npm:7.0.2" = { filename = "@typescript-typescript-linux-arm64-npm-7.0.2-9cacfc53a0-10c0.zip"; hash = "sha512-s4c7nGT/lQIw6x0IfrL0b3ECy/D0g7UoDLdiIWJoM6EGXk5N/dmXdxUdA8Cr3hV/3nO2BYKTQ6Ai8/zGhiSQ3A=="; }; +"@typescript/typescript-linux-x64@npm:7.0.2" = { filename = "@typescript-typescript-linux-x64-npm-7.0.2-8dd7ff8d24-10c0.zip"; hash = "sha512-k9EUK5CZ3OOPnyslp8SAAonHJpnpPmlaulppI/NmFyCzNs3UN/TLPUkyQia3KIxgbyTzKoXI5L5fl8Uj9bJ7Cg=="; }; +"typescript@npm:7.0.2" = { filename = "typescript-npm-7.0.2-0bde2bcec5-3dcee51ec8.zip"; hash = "sha512-Pc7lHsjDMkkjJbzb999ItmZodR8SfmIq59QbbHFusZGEQkpF4U93UPUPNAIyOItp5ih4WRVfBqXOLfdvEssxzw=="; }; +"typescript@patch:typescript@npm%3A7.0.2#optional!builtin::version=7.0.2&hash=3bafbf" = { filename = "typescript-patch-4859cbaf66-6b3cdc369c.zip"; hash = "sha512-azzcNpzYKdRuAHNOpkIz7oRBnCglrY/kCJFa3ed6vO1LeiQB9+7VF9VKek9dHBhpdTy5kBjfHCFZx2HZ8zSDpg=="; }; +"undici-types@npm:7.18.2" = { filename = "undici-types-npm-7.18.2-3e6d69d829-85a7918911.zip"; hash = "sha512-haeRiRE6I4lZ16ZHNo5PfFVZw6QE69uPxEiBRc6UJvzYIlKoRKMCeY38Djfm+xeP9IHtA7xMr2NMV1fZ70NSHQ=="; }; +}; + +in overriddenProject diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..10707ec --- /dev/null +++ b/yarn.lock @@ -0,0 +1,353 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 10 + cacheKey: 10c0 + +"@bufbuild/protobuf@npm:^2.12.1": + version: 2.14.1 + resolution: "@bufbuild/protobuf@npm:2.14.1" + checksum: 10c0/3f913aca03df8419c4b21d800ea54d7f6c836a5343e65d6f686279ec3566c4907729938ef2f94a5e27d92e8d3f4adcd6e027118ba29ba764d21e1c637cddc702 + languageName: node + linkType: hard + +"@connectrpc/connect-node@npm:^2.1.2": + version: 2.1.2 + resolution: "@connectrpc/connect-node@npm:2.1.2" + peerDependencies: + "@bufbuild/protobuf": ^2.7.0 + "@connectrpc/connect": 2.1.2 + checksum: 10c0/ba8b0c9384c3829b377aa7a826dc0cd50a6093527d2ec7014604912836336ea9604a2b5acea42b10477f8be4569e49dded66ca0fc77f5f5b027035e029e13ea9 + languageName: node + linkType: hard + +"@connectrpc/connect@npm:^2.1.2": + version: 2.1.2 + resolution: "@connectrpc/connect@npm:2.1.2" + peerDependencies: + "@bufbuild/protobuf": ^2.7.0 + checksum: 10c0/4e1500089023b752efd44fa940a5ae1e1fa00e1bebc4ba0ced272bb935920d8c3b85b77450e644ad442bb8ca9a275b0c17136f896ba8eff036178131db01d615 + languageName: node + linkType: hard + +"@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=d3d050d9cb84421fd8043ebe34fd0cae9132f6a2": + version: 0.1.0 + resolution: "@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=d3d050d9cb84421fd8043ebe34fd0cae9132f6a2" + dependencies: + "@bufbuild/protobuf": "npm:^2.12.1" + "@connectrpc/connect": "npm:^2.1.2" + "@connectrpc/connect-node": "npm:^2.1.2" + checksum: 10c0/5bde059ead2b9f833206a4545211f465c4f356ff4c7c5e7d747b70a452e183efe32b8406e708bfb8d811477c4456cce937ccab0563baba22469641a6367adccc + languageName: node + linkType: hard + +"@quixos/web-studio-canvas-runtime@workspace:.": + version: 0.0.0-use.local + resolution: "@quixos/web-studio-canvas-runtime@workspace:." + dependencies: + "@quixos/camino-package-runtime": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=d3d050d9cb84421fd8043ebe34fd0cae9132f6a2" + "@types/node": "npm:^24" + typescript: "npm:^7.0.2" + bin: + server: dist/server.js + languageName: unknown + linkType: soft + +"@types/node@npm:^24": + version: 24.13.3 + resolution: "@types/node@npm:24.13.3" + dependencies: + undici-types: "npm:~7.18.0" + checksum: 10c0/a5bc08f49b9581dcdca90e02cd77197a3c799840807664942e5cd5161a553d4d2ae8064f7e3294410d748d7d098b5c1848be7fa50c06f29c4193ab16be4e59eb + languageName: node + linkType: hard + +"@typescript/typescript-aix-ppc64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-aix-ppc64@npm:7.0.2" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@typescript/typescript-darwin-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-darwin-arm64@npm:7.0.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-darwin-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-darwin-x64@npm:7.0.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-freebsd-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-freebsd-arm64@npm:7.0.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-freebsd-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-freebsd-x64@npm:7.0.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-arm64@npm:7.0.2" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-arm@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-arm@npm:7.0.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@typescript/typescript-linux-loong64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-loong64@npm:7.0.2" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-mips64el@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-mips64el@npm:7.0.2" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@typescript/typescript-linux-ppc64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-ppc64@npm:7.0.2" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-riscv64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-riscv64@npm:7.0.2" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-s390x@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-s390x@npm:7.0.2" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@typescript/typescript-linux-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-x64@npm:7.0.2" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-netbsd-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-netbsd-arm64@npm:7.0.2" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-netbsd-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-netbsd-x64@npm:7.0.2" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-openbsd-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-openbsd-arm64@npm:7.0.2" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-openbsd-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-openbsd-x64@npm:7.0.2" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-sunos-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-sunos-x64@npm:7.0.2" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-win32-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-win32-arm64@npm:7.0.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-win32-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-win32-x64@npm:7.0.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"typescript@npm:^7.0.2": + version: 7.0.2 + resolution: "typescript@npm:7.0.2" + dependencies: + "@typescript/typescript-aix-ppc64": "npm:7.0.2" + "@typescript/typescript-darwin-arm64": "npm:7.0.2" + "@typescript/typescript-darwin-x64": "npm:7.0.2" + "@typescript/typescript-freebsd-arm64": "npm:7.0.2" + "@typescript/typescript-freebsd-x64": "npm:7.0.2" + "@typescript/typescript-linux-arm": "npm:7.0.2" + "@typescript/typescript-linux-arm64": "npm:7.0.2" + "@typescript/typescript-linux-loong64": "npm:7.0.2" + "@typescript/typescript-linux-mips64el": "npm:7.0.2" + "@typescript/typescript-linux-ppc64": "npm:7.0.2" + "@typescript/typescript-linux-riscv64": "npm:7.0.2" + "@typescript/typescript-linux-s390x": "npm:7.0.2" + "@typescript/typescript-linux-x64": "npm:7.0.2" + "@typescript/typescript-netbsd-arm64": "npm:7.0.2" + "@typescript/typescript-netbsd-x64": "npm:7.0.2" + "@typescript/typescript-openbsd-arm64": "npm:7.0.2" + "@typescript/typescript-openbsd-x64": "npm:7.0.2" + "@typescript/typescript-sunos-x64": "npm:7.0.2" + "@typescript/typescript-win32-arm64": "npm:7.0.2" + "@typescript/typescript-win32-x64": "npm:7.0.2" + dependenciesMeta: + "@typescript/typescript-aix-ppc64": + optional: true + "@typescript/typescript-darwin-arm64": + optional: true + "@typescript/typescript-darwin-x64": + optional: true + "@typescript/typescript-freebsd-arm64": + optional: true + "@typescript/typescript-freebsd-x64": + optional: true + "@typescript/typescript-linux-arm": + optional: true + "@typescript/typescript-linux-arm64": + optional: true + "@typescript/typescript-linux-loong64": + optional: true + "@typescript/typescript-linux-mips64el": + optional: true + "@typescript/typescript-linux-ppc64": + optional: true + "@typescript/typescript-linux-riscv64": + optional: true + "@typescript/typescript-linux-s390x": + optional: true + "@typescript/typescript-linux-x64": + optional: true + "@typescript/typescript-netbsd-arm64": + optional: true + "@typescript/typescript-netbsd-x64": + optional: true + "@typescript/typescript-openbsd-arm64": + optional: true + "@typescript/typescript-openbsd-x64": + optional: true + "@typescript/typescript-sunos-x64": + optional: true + "@typescript/typescript-win32-arm64": + optional: true + "@typescript/typescript-win32-x64": + optional: true + bin: + tsc: bin/tsc + checksum: 10c0/3dcee51ec8c332492325bcdbf7df48b66668751f127e622ae7d41b6c716eb19184424a45e14f7750f50f340232388b69e6287859155f06a5ce2df76f12cb31cf + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A^7.0.2#optional!builtin": + version: 7.0.2 + resolution: "typescript@patch:typescript@npm%3A7.0.2#optional!builtin::version=7.0.2&hash=3bafbf" + dependencies: + "@typescript/typescript-aix-ppc64": "npm:7.0.2" + "@typescript/typescript-darwin-arm64": "npm:7.0.2" + "@typescript/typescript-darwin-x64": "npm:7.0.2" + "@typescript/typescript-freebsd-arm64": "npm:7.0.2" + "@typescript/typescript-freebsd-x64": "npm:7.0.2" + "@typescript/typescript-linux-arm": "npm:7.0.2" + "@typescript/typescript-linux-arm64": "npm:7.0.2" + "@typescript/typescript-linux-loong64": "npm:7.0.2" + "@typescript/typescript-linux-mips64el": "npm:7.0.2" + "@typescript/typescript-linux-ppc64": "npm:7.0.2" + "@typescript/typescript-linux-riscv64": "npm:7.0.2" + "@typescript/typescript-linux-s390x": "npm:7.0.2" + "@typescript/typescript-linux-x64": "npm:7.0.2" + "@typescript/typescript-netbsd-arm64": "npm:7.0.2" + "@typescript/typescript-netbsd-x64": "npm:7.0.2" + "@typescript/typescript-openbsd-arm64": "npm:7.0.2" + "@typescript/typescript-openbsd-x64": "npm:7.0.2" + "@typescript/typescript-sunos-x64": "npm:7.0.2" + "@typescript/typescript-win32-arm64": "npm:7.0.2" + "@typescript/typescript-win32-x64": "npm:7.0.2" + dependenciesMeta: + "@typescript/typescript-aix-ppc64": + optional: true + "@typescript/typescript-darwin-arm64": + optional: true + "@typescript/typescript-darwin-x64": + optional: true + "@typescript/typescript-freebsd-arm64": + optional: true + "@typescript/typescript-freebsd-x64": + optional: true + "@typescript/typescript-linux-arm": + optional: true + "@typescript/typescript-linux-arm64": + optional: true + "@typescript/typescript-linux-loong64": + optional: true + "@typescript/typescript-linux-mips64el": + optional: true + "@typescript/typescript-linux-ppc64": + optional: true + "@typescript/typescript-linux-riscv64": + optional: true + "@typescript/typescript-linux-s390x": + optional: true + "@typescript/typescript-linux-x64": + optional: true + "@typescript/typescript-netbsd-arm64": + optional: true + "@typescript/typescript-netbsd-x64": + optional: true + "@typescript/typescript-openbsd-arm64": + optional: true + "@typescript/typescript-openbsd-x64": + optional: true + "@typescript/typescript-sunos-x64": + optional: true + "@typescript/typescript-win32-arm64": + optional: true + "@typescript/typescript-win32-x64": + optional: true + bin: + tsc: bin/tsc + checksum: 10c0/6b3cdc369cd829d46e00734ea64233ee84419c2825ad8fe408915adde77abced4b7a2401f7eed517d54a7a4f5d1c1869753cb99018df1c2159c761d9f33483a6 + languageName: node + linkType: hard + +"undici-types@npm:~7.18.0": + version: 7.18.2 + resolution: "undici-types@npm:7.18.2" + checksum: 10c0/85a79189113a238959d7a647368e4f7c5559c3a404ebdb8fc4488145ce9426fcd82252a844a302798dfc0e37e6fb178ff481ed03bc4caf634c5757d9ef43521d + languageName: node + linkType: hard