diff --git a/.gitignore b/.gitignore index 87f1d08..e31d13f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules .direnv +result +result-* diff --git a/flake.nix b/flake.nix index 3f0e607..be11a0f 100644 --- a/flake.nix +++ b/flake.nix @@ -41,6 +41,16 @@ formatter = treefmt.config.build.wrapper; checks = (pkgs.callPackages ./tests.nix { + fetcherMode = "new"; + inherit + pkgs + prisma-factory + yarn-v1 + yarn-berry + ; + }) + // (pkgs.callPackages ./tests.nix { + fetcherMode = "legacy"; inherit pkgs prisma-factory @@ -51,18 +61,19 @@ // { format = treefmt.config.build.check self; }; + packages.default = + (prisma-factory { + inherit pkgs; + hash = "sha256-R9PG286KQTbzF0r/PPcShUkMiYam2prRh/JICjmhCZA="; + _commit = "6a3747c37ff169c90047725a05a6ef02e32ac97e"; + }).package; devShells.default = let - prisma = ( - (prisma-factory { - inherit pkgs; - prisma-fmt-hash = "sha256-4zsJv0PW8FkGfiiv/9g0y5xWNjmRWD8Q2l2blSSBY3s="; - query-engine-hash = "sha256-6ILWB6ZmK4ac6SgAtqCkZKHbQANmcqpWO92U8CfkFzw="; - libquery-engine-hash = "sha256-n9IimBruqpDJStlEbCJ8nsk8L9dDW95ug+gz9DHS1Lc="; - schema-engine-hash = "sha256-j38xSXOBwAjIdIpbSTkFJijby6OGWCoAx+xZyms/34Q="; - }).fromCommit - "6a3747c37ff169c90047725a05a6ef02e32ac97e" - ); + prisma = prisma-factory { + inherit pkgs; + hash = "sha256-R9PG286KQTbzF0r/PPcShUkMiYam2prRh/JICjmhCZA="; + _commit = "6a3747c37ff169c90047725a05a6ef02e32ac97e"; + }; in pkgs.mkShell { buildInputs = [ diff --git a/lib/fetcher.nix b/lib/fetcher.nix new file mode 100644 index 0000000..c5dd463 --- /dev/null +++ b/lib/fetcher.nix @@ -0,0 +1,109 @@ +{ + lib, + stdenv, + zlib, + curl, + cacert, + autoPatchelfHook, + runCommand, + gzip, + # variables + commit, + openssl, + opensslVersion, + binaryTarget, + hash, + components, +}: +let + componentsToFetch = + if components != null then + components + else + [ + { + url = "prisma-fmt.gz"; + path = "bin/prisma-fmt"; + env = "PRISMA_FMT_BINARY"; + } + { + url = "query-engine.gz"; + path = "bin/query-engine"; + env = "PRISMA_QUERY_ENGINE_BINARY"; + } + { + url = if isDarwin then "libquery_engine.dylib.node.gz" else "libquery_engine.so.node.gz"; + path = "lib/libquery_engine.node"; + env = "PRISMA_QUERY_ENGINE_LIBRARY"; + } + { + url = "schema-engine.gz"; + path = "bin/schema-engine"; + env = "PRISMA_SCHEMA_ENGINE_BINARY"; + } + ]; + isDarwin = lib.strings.hasPrefix "darwin" binaryTarget; + target = if isDarwin then binaryTarget else "${binaryTarget}-openssl-${opensslVersion}"; + toUrl = url: "https://binaries.prisma.sh/all_commits/${commit}/${target}/${url}"; + deps = + runCommand "prisma-deps-bin" + { + nativeBuildInputs = [ + curl + cacert + gzip + ]; + outputHashAlgo = "sha256"; + outputHashMode = "recursive"; + outputHash = hash; + } + '' + export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt + export CURL_CA_BUNDLE=$SSL_CERT_FILE + mkdir -p $out $out/lib $out/bin + ${lib.concatLines ( + map (component: '' + curl "${toUrl component.url}" -L | gunzip > $out/${component.path} + '') componentsToFetch + )} + ''; + package = stdenv.mkDerivation { + pname = "prisma-bin"; + src = deps; + version = commit; + nativeBuildInputs = [ + zlib + openssl + stdenv.cc.cc.lib + ] ++ lib.optionals (!isDarwin) [ autoPatchelfHook ]; + phases = [ + "installPhase" + "postFixupHooks" + ]; + installPhase = '' + mkdir -p $out + cp -r $src/. $out/ + mkdir -p $out/bin + chmod -R u+w $out + find $out/bin -type f -exec chmod +x {} + + ''; + }; + toExportStyle = + attrset: + "\n" + + (lib.concatMapAttrsStringSep "\n" (name: value: "export ${name}=\"${value}\"") attrset) + + "\n"; + mkEnv = + package: + builtins.listToAttrs ( + builtins.map (c: { + name = c.env; + value = "${package}/${c.path}"; + }) componentsToFetch + ); + env = mkEnv package; +in +{ + inherit package env; + shellHook = toExportStyle env; +} diff --git a/lib/legacyFetcher.nix b/lib/legacyFetcher.nix new file mode 100644 index 0000000..70ea33a --- /dev/null +++ b/lib/legacyFetcher.nix @@ -0,0 +1,155 @@ +{ + # dependencies + lib, + fetchurl, + stdenv, + zlib, + autoPatchelfHook, + # variables + openssl, + commit, + opensslVersion, + binaryTarget, + # = hashes + prisma-fmt-hash, + query-engine-hash, + libquery-engine-hash, + introspection-engine-hash, + migration-engine-hash, + schema-engine-hash, +}: +let + hostname = "binaries.prisma.sh"; + channel = "all_commits"; + isDarwin = lib.strings.hasPrefix "darwin" binaryTarget; + target = if isDarwin then binaryTarget else "${binaryTarget}-openssl-${opensslVersion}"; + baseUrl = "https://${hostname}/${channel}"; + files = + [ + { + name = "prisma-fmt"; + hash = prisma-fmt-hash; + path = "bin/prisma-fmt"; + variable = "PRISMA_FMT_BINARY"; + } + { + name = "query-engine"; + hash = query-engine-hash; + path = "bin/query-engine"; + variable = "PRISMA_QUERY_ENGINE_BINARY"; + } + { + name = if isDarwin then "libquery_engine.dylib.node" else "libquery_engine.so.node"; + hash = libquery-engine-hash; + path = "lib/libquery_engine.node"; + variable = "PRISMA_QUERY_ENGINE_LIBRARY"; + } + ] + ++ ( + if introspection-engine-hash == null then + [ ] + else + [ + { + name = "introspection-engine"; + hash = introspection-engine-hash; + path = "bin/introspection-engine"; + variable = "PRISMA_INTROSPECTION_ENGINE_BINARY"; + } + ] + ) + ++ ( + if migration-engine-hash == null then + [ ] + else + [ + { + name = "migration-engine"; + hash = migration-engine-hash; + path = "bin/migration-engine"; + variable = "PRISMA_MIGRATION_ENGINE_BINARY"; + } + ] + ) + ++ ( + if schema-engine-hash == null then + [ ] + else + [ + { + name = "schema-engine"; + hash = schema-engine-hash; + path = "bin/schema-engine"; + variable = "PRISMA_SCHEMA_ENGINE_BINARY"; + } + ] + ); + downloadedFiles = builtins.map ( + file: + file + // { + file = fetchurl { + name = "${baseUrl}/${commit}/${target}/${file.name}.gz"; + url = "${baseUrl}/${commit}/${target}/${file.name}.gz"; + hash = file.hash; + }; + } + ) files; + unzipCommands = builtins.map (file: "gunzip -c ${file.file} > $out/${file.path}") downloadedFiles; + + mkEnv = + package: + builtins.listToAttrs ( + builtins.map (file: { + name = file.variable; + value = "${package}/${file.path}"; + }) files + ); + # polyfill: the function in nixpkgs is implemented on Dec 6, 2024. replace this with one from pkgs.lib after 24.11 reaches EOL. + concatMapAttrsStringSep = + sep: f: attrs: + lib.concatStringsSep sep (lib.attrValues (lib.mapAttrs f attrs)); + /** + This function converts attrset to bash export style. + return value contains leading and trailing newlines. + + # Example + ```nix + toExportStyle { foo = "bar"; baz = "abc"; } + => + '' + export foo="bar" + export baz="abc" + '' + ``` + + # Type + toExportStyle :: Attrset -> String + */ + toExportStyle = + attrset: + "\n" + (concatMapAttrsStringSep "\n" (name: value: "export ${name}=\"${value}\"") attrset) + "\n"; +in +rec { + package = stdenv.mkDerivation { + pname = "prisma-bin"; + version = commit; + nativeBuildInputs = [ + zlib + openssl + stdenv.cc.cc.lib + ] ++ lib.optionals (!isDarwin) [ autoPatchelfHook ]; + phases = [ + "buildPhase" + "postFixupHooks" + ]; + buildPhase = '' + mkdir -p $out/bin + mkdir -p $out/lib + ${lib.concatStringsSep "\n" unzipCommands} + chmod +x $out/bin/* + ''; + }; + env = mkEnv package; + shellHook = toExportStyle env; +} diff --git a/lib/parsers.nix b/lib/parsers.nix new file mode 100644 index 0000000..e5eb4f0 --- /dev/null +++ b/lib/parsers.nix @@ -0,0 +1,214 @@ +{ + lib, + callPackage, +}: +let + lines = s: lib.strings.splitString "\n" s; + + # example: + # splitMultiple ["|" "," "-"] "a-|b,c-d" + # -> ["a" "" "b" "c" "d"] + splitMultiple = delims: s: _splitMultiple delims [ s ]; + # example: + # _splitMultiple ["|" "," "-"] ["a-|b,c-d"] + # -> ["a" "" "b" "c" "d"] + _splitMultiple = + delims: list: + if builtins.length delims == 0 then + list + else + let + splitStr = map (str: lib.strings.splitString (builtins.elemAt delims 0) str) list; + in + _splitMultiple (lib.drop 1 delims) (lib.lists.concatLists splitStr); + splitMultipleAndFilterEmpty = delims: s: builtins.filter (str: str != "") (splitMultiple delims s); + # example: + # a.b123c.d.e12345 + # => e12345 + afterLastDot = text: lib.lists.last (lib.strings.splitString "." text); + + readYAML = callPackage ./readYAML.nix { }; +in +# polyfill: the function in nixis implemented on Dec 6, 2024. replace this with one from lib after 24.11 reaches EOL. +{ + parsePnpmLock = + path: + let + parsePnpmLockVersion = + pnpmLock: + if lib.strings.hasPrefix "lockfileVersion: 5" pnpmLock then + "5" + else if lib.strings.hasPrefix "lockfileVersion: '6" pnpmLock then + "6" + else + "9"; + pnpmLockParsers = { + # example line: + # /@prisma/engines-version/5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e: + "5" = + pnpmLock: + let + version = builtins.elemAt (builtins.split ":" (builtins.elemAt (builtins.split "@prisma/engines-version/" pnpmLock) 2)) 0; + in + lib.lists.last (lib.strings.splitString "." version); + + # example line: + # /@prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e: + "6" = + pnpmLock: + let + version = builtins.elemAt (builtins.split ":" (builtins.elemAt (builtins.split "@prisma/engines-version@" pnpmLock) 2)) 0; + in + lib.lists.last (lib.strings.splitString "." version); + + # exmple line: + # '@prisma/engines-version@5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022': + "9" = + pnpmLock: + let + version = builtins.elemAt (builtins.split "'" (builtins.elemAt (builtins.split "@prisma/engines-version@" pnpmLock) 2)) 0; + in + lib.lists.last (lib.strings.splitString "." version); + }; + pnpmLock = builtins.readFile path; + pnpmLockVersion = parsePnpmLockVersion pnpmLock; + pnpmLockParser = pnpmLockParsers.${pnpmLockVersion}; + commit = pnpmLockParser pnpmLock; + in + commit; + parseNpmLock = + path: + let + packageLock = builtins.fromJSON (builtins.readFile path); + version = + if builtins.hasAttr "dependencies" packageLock then + packageLock.dependencies.${"@prisma/engines-version"}.version + else + packageLock.packages.${"node_modules/@prisma/engines-version"}.version; + commit = lib.lists.last (lib.strings.splitString "." version); + in + commit; + parseYarnLock = + path: + let + # find this line from yarn.lock: + # "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": + yarnLockParser1 = + file: + let + versionLine = + lib.lists.findFirst + (line: builtins.length (lib.strings.splitString "@prisma/engines-version" line) >= 2) + # else + (throw '' + nix-prisma-utils/yarnLockParser1: package @prisma/engines-version not found in lockfile ${path} . + please make sure you have installed `@prisma/client`. + if you have already installed `@prisma/client` and still see this, please report this to nix-prisma-utils. + '') + (lines file); + # "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": + # -> ["@prisma/engines-version@npm" "6" "3" "0-17" "acc0b9dd43eb689cbd20c9470515d719db10d0b0"] + # -> acc0b9dd43eb689cbd20c9470515d719db10d0b0 + version = lib.lists.last ( + splitMultipleAndFilterEmpty [ + "\"" + ":" + "." + ] versionLine + ); + in + version; + isYarnLockV1 = + file: + lib.lists.any (line: lib.strings.trim line == "# yarn lockfile v1") ( + lib.strings.splitString "\n" file + ); + # example line: + # "@prisma/engines-version@6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": + yarnV1LockParser = yarnLockParser1; + # example line: + # "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": + yarnBerryLockParsers = { + "8" = yarnLockParser1; + }; + + lockfile = builtins.readFile path; + parse = + if isYarnLockV1 lockfile then + yarnV1LockParser + else + let + lockfileVersion = builtins.toString (readYAML path).__metadata.version; + in + yarnBerryLockParsers.${lockfileVersion} or (throw '' + nix-prisma-utils: unknown lockfile version ${lockfileVersion}. + please report this to nix-prisma-utils with your lockfile. + ''); + in + (parse lockfile); + parseBunLock = + path: + let + # HACK: nix doesn't support JSONC parsing, so currently doing + # 1. remove whitespace and newline + # 2. replace ",}" with "}" + # 3. replace ",]" with "]" + # to support JSON with trailing comma. + # Keep in mind that this removes all whitespaces / tab / newline in the key / value + # and doesn't support comments. + fromJSONWithTrailingComma = + jsonc: + builtins.fromJSON ( + builtins.replaceStrings + [ + ",}" + ",]" + ] + [ + "}" + "]" + ] + ( + builtins.replaceStrings + [ + " " + "\t" + "\n" + ] + [ + "" + "" + "" + ] + jsonc + ) + ); + bunLockParsers = { + # example: + # nu> open bun.lock | from json | get packages.@prisma/engines-version.0 + # @prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e + "0" = bunLockParsers."1"; + "1" = + lock: + afterLastDot ( + builtins.elemAt (lock."packages"."@prisma/engines-version" or (throw '' + nix-prisma-utils: lockfile parsing error: package @prisma/engines-version not found. + please make sure that you have @prisma/client installed. + '') + ) 0 + ); + }; + lockfile = fromJSONWithTrailingComma ( + assert builtins.typeOf path == "path"; + builtins.readFile path + ); + lockfileVersion = builtins.toString lockfile."lockfileVersion"; + parse = + bunLockParsers.${lockfileVersion} or (throw '' + nix-prisma-utils: Unsupported lockfile version: ${lockfileVersion} + nix-prisma-utils currently supports bun.lock version of 0 and 1. + ''); + commit = parse lockfile; + in + commit; +} diff --git a/prisma.nix b/prisma.nix index 3b05641..b7471aa 100644 --- a/prisma.nix +++ b/prisma.nix @@ -4,11 +4,20 @@ pkgs ? nixpkgs, opensslVersion ? "3.0.x", # can be 3.0.x, 1.1.x or 1.0.x openssl ? pkgs.openssl, # the openssl package to use + # new fetcher args + hash ? null, + components ? null, # components to fetch + _commit ? null, # because package `commit` exists in nixpkgs + npmLock ? null, + yarnLock ? null, + pnpmLock ? null, + bunLock ? null, + # legacy fetcher args introspection-engine-hash ? null, migration-engine-hash ? null, - prisma-fmt-hash, - query-engine-hash, - libquery-engine-hash, + prisma-fmt-hash ? null, + query-engine-hash ? null, + libquery-engine-hash ? null, schema-engine-hash ? null, binaryTargetBySystem ? { x86_64-linux = "debian"; @@ -19,365 +28,76 @@ }: let inherit (pkgs) lib; - lines = s: lib.strings.splitString "\n" s; - - # example: - # splitMultiple ["|" "," "-"] "a-|b,c-d" - # -> ["a" "" "b" "c" "d"] - splitMultiple = delims: s: _splitMultiple delims [ s ]; - # example: - # _splitMultiple ["|" "," "-"] ["a-|b,c-d"] - # -> ["a" "" "b" "c" "d"] - _splitMultiple = - delims: list: - if builtins.length delims == 0 then - list + parsers = pkgs.callPackage ./lib/parsers.nix { }; + binaryTarget = binaryTargetBySystem.${pkgs.system}; + commitValue = + if _commit != null then + _commit + else if npmLock != null then + fromNpmLock npmLock + else if yarnLock != null then + fromYarnLock yarnLock + else if pnpmLock != null then + fromPnpmLock pnpmLock + else if bunLock != null then + fromBunLock bunLock else - let - splitStr = map (str: lib.strings.splitString (builtins.elemAt delims 0) str) list; - in - _splitMultiple (lib.drop 1 delims) (lib.lists.concatLists splitStr); - splitMultipleAndFilterEmpty = delims: s: builtins.filter (str: str != "") (splitMultiple delims s); - # example: - # a.b123c.d.e12345 - # => e12345 - afterLastDot = text: lib.lists.last (lib.strings.splitString "." text); - - readYAML = pkgs.callPackage ./lib/readYAML.nix { }; - # polyfill: the function in nixpkgs is implemented on Dec 6, 2024. replace this with one from pkgs.lib after 24.11 reaches EOL. - concatMapAttrsStringSep = - let - inherit (pkgs) lib; - in - sep: f: attrs: - lib.concatStringsSep sep (lib.attrValues (lib.mapAttrs f attrs)); - + null; + fromCommit = + commit: + if builtins.stringLength commit != 40 then + throw "invalid commit: got ${commit}" + else if hash != null then + pkgs.callPackage ./lib/fetcher.nix { + inherit + commit + openssl + opensslVersion + binaryTarget + hash + components + ; + } + # use new fetcher + else + pkgs.callPackage ./lib/legacyFetcher.nix { + inherit + commit + openssl + opensslVersion + binaryTarget + prisma-fmt-hash + query-engine-hash + libquery-engine-hash + introspection-engine-hash + migration-engine-hash + schema-engine-hash + ; + }; + fromNpmLock = file: fromCommit (parsers.parseNpmLock file); + fromPnpmLock = file: fromCommit (parsers.parsePnpmLock file); + fromYarnLock = file: fromCommit (parsers.parseYarnLock file); + fromBunLock = file: fromCommit (parsers.parseBunLock file); in -pkgs.lib.warnIf (nixpkgs != null) +lib.warnIf (nixpkgs != null) '' `nixpkgs` argument in nix-prisma-utils is deprecated. please replace it with `pkgs`. examples: if your code has `inherit nixpkgs;`, replace it with `pkgs = nixpkgs;`. if your code has `nixpkgs = pkgs;`, replace it with `pkgs = pkgs;` or `inherit pkgs;`. '' - rec { - fromCommit = - commit: - if builtins.stringLength commit != 40 then - throw "nvalid commit: got ${commit}" - else - let - hostname = "binaries.prisma.sh"; - channel = "all_commits"; - binaryTarget = binaryTargetBySystem.${pkgs.system}; - isDarwin = pkgs.lib.strings.hasPrefix "darwin" binaryTarget; - target = if isDarwin then binaryTarget else "${binaryTarget}-openssl-${opensslVersion}"; - baseUrl = "https://${hostname}/${channel}"; - files = - [ - { - name = "prisma-fmt"; - hash = prisma-fmt-hash; - path = "bin/prisma-fmt"; - variable = "PRISMA_FMT_BINARY"; - } - { - name = "query-engine"; - hash = query-engine-hash; - path = "bin/query-engine"; - variable = "PRISMA_QUERY_ENGINE_BINARY"; - } - { - name = if isDarwin then "libquery_engine.dylib.node" else "libquery_engine.so.node"; - hash = libquery-engine-hash; - path = "lib/libquery_engine.node"; - variable = "PRISMA_QUERY_ENGINE_LIBRARY"; - } - ] - ++ ( - if introspection-engine-hash == null then - [ ] - else - [ - { - name = "introspection-engine"; - hash = introspection-engine-hash; - path = "bin/introspection-engine"; - variable = "PRISMA_INTROSPECTION_ENGINE_BINARY"; - } - ] - ) - ++ ( - if migration-engine-hash == null then - [ ] - else - [ - { - name = "migration-engine"; - hash = migration-engine-hash; - path = "bin/migration-engine"; - variable = "PRISMA_MIGRATION_ENGINE_BINARY"; - } - ] - ) - ++ ( - if schema-engine-hash == null then - [ ] - else - [ - { - name = "schema-engine"; - hash = schema-engine-hash; - path = "bin/schema-engine"; - variable = "PRISMA_SCHEMA_ENGINE_BINARY"; - } - ] - ); - downloadedFiles = builtins.map ( - file: - file - // { - file = pkgs.fetchurl { - name = "${baseUrl}/${commit}/${target}/${file.name}.gz"; - url = "${baseUrl}/${commit}/${target}/${file.name}.gz"; - hash = file.hash; - }; - } - ) files; - unzipCommands = builtins.map (file: "gunzip -c ${file.file} > $out/${file.path}") downloadedFiles; - - mkEnv = - package: - builtins.listToAttrs ( - builtins.map (file: { - name = file.variable; - value = "${package}/${file.path}"; - }) files - ); - /** - This function converts attrset to bash export style. - return value contains leading and trailing newlines. - - # Example - ```nix - toExportStyle { foo = "bar"; baz = "abc"; } - => - '' - export foo="bar" - export baz="abc" - '' - ``` - - # Type - toExportStyle :: Attrset -> String - */ - toExportStyle = - attrset: - "\n" + (concatMapAttrsStringSep "\n" (name: value: "export ${name}=\"${value}\"") attrset) + "\n"; - in - rec { - package = pkgs.stdenv.mkDerivation { - pname = "prisma-bin"; - version = commit; - nativeBuildInputs = [ - pkgs.zlib - openssl - pkgs.stdenv.cc.cc.lib - ] ++ pkgs.lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ]; - phases = [ - "buildPhase" - "postFixupHooks" - ]; - buildPhase = '' - mkdir -p $out/bin - mkdir -p $out/lib - ${pkgs.lib.concatStringsSep "\n" unzipCommands} - chmod +x $out/bin/* - ''; - }; - env = mkEnv package; - shellHook = toExportStyle env; - }; - fromPnpmLock = - path: - let - textAfter = keyword: text: builtins.elemAt (builtins.split keyword text) 1; - textBefore = keyword: text: builtins.elemAt (builtins.split keyword text) 0; - parsePnpmLockVersion = - pnpmLock: - if pkgs.lib.strings.hasPrefix "lockfileVersion: 5" pnpmLock then - "5" - else if pkgs.lib.strings.hasPrefix "lockfileVersion: '6" pnpmLock then - "6" - else - "9"; - pnpmLockParsers = { - # example line: - # /@prisma/engines-version/5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e: - "5" = - pnpmLock: - let - version = builtins.elemAt (builtins.split ":" (builtins.elemAt (builtins.split ("@prisma/engines-version/") pnpmLock) 2)) 0; - in - pkgs.lib.lists.last (pkgs.lib.strings.splitString "." version); - - # example line: - # /@prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e: - "6" = - pnpmLock: - let - version = builtins.elemAt (builtins.split ":" (builtins.elemAt (builtins.split ("@prisma/engines-version@") pnpmLock) 2)) 0; - in - pkgs.lib.lists.last (pkgs.lib.strings.splitString "." version); - - # exmple line: - # '@prisma/engines-version@5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022': - "9" = - pnpmLock: - let - version = builtins.elemAt (builtins.split "'" (builtins.elemAt (builtins.split ("@prisma/engines-version@") pnpmLock) 2)) 0; - in - pkgs.lib.lists.last (pkgs.lib.strings.splitString "." version); - }; - pnpmLock = builtins.readFile path; - pnpmLockVersion = parsePnpmLockVersion pnpmLock; - pnpmLockParser = pnpmLockParsers.${pnpmLockVersion}; - commit = pnpmLockParser pnpmLock; - in - fromCommit commit; - fromNpmLock = - path: - let - packageLock = builtins.fromJSON (builtins.readFile path); - version = - if builtins.hasAttr "dependencies" packageLock then - packageLock.dependencies.${"@prisma/engines-version"}.version - else - packageLock.packages.${"node_modules/@prisma/engines-version"}.version; - commit = pkgs.lib.lists.last (pkgs.lib.strings.splitString "." version); - in - fromCommit commit; - fromYarnLock = - path: - let - # find this line from yarn.lock: - # "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": - yarnLockParser1 = - file: - let - versionLine = - lib.lists.findFirst - (line: builtins.length (lib.strings.splitString "@prisma/engines-version" line) >= 2) - # else - (throw '' - nix-prisma-utils/yarnLockParser1: package @prisma/engines-version not found in lockfile ${path} . - please make sure you have installed `@prisma/client`. - if you have already installed `@prisma/client` and still see this, please report this to nix-prisma-utils. - '') - (lines file); - # "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": - # -> ["@prisma/engines-version@npm" "6" "3" "0-17" "acc0b9dd43eb689cbd20c9470515d719db10d0b0"] - # -> acc0b9dd43eb689cbd20c9470515d719db10d0b0 - version = lib.lists.last ( - splitMultipleAndFilterEmpty [ - "\"" - ":" - "." - ] versionLine - ); - in - version; - isYarnLockV1 = - file: - lib.lists.any (line: lib.strings.trim line == "# yarn lockfile v1") ( - lib.strings.splitString "\n" file - ); - # example line: - # "@prisma/engines-version@6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": - yarnV1LockParser = yarnLockParser1; - # example line: - # "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0": - yarnBerryLockParsers = { - "8" = yarnLockParser1; - }; - - lockfile = builtins.readFile path; - parse = - if isYarnLockV1 lockfile then - yarnV1LockParser - else - let - lockfileVersion = builtins.toString (readYAML path).__metadata.version; - in - yarnBerryLockParsers.${lockfileVersion} or (throw '' - nix-prisma-utils: unknown lockfile version ${lockfileVersion}. - please report this to nix-prisma-utils with your lockfile. - ''); - in - fromCommit (parse lockfile); - fromBunLock = - path: - let - # HACK: nix doesn't support JSONC parsing, so currently doing - # 1. remove whitespace and newline - # 2. replace ",}" with "}" - # 3. replace ",]" with "]" - # to support JSON with trailing comma. - # Keep in mind that this removes all whitespaces / tab / newline in the key / value - # and doesn't support comments. - fromJSONWithTrailingComma = - jsonc: - builtins.fromJSON ( - builtins.replaceStrings - [ - ",}" - ",]" - ] - [ - "}" - "]" - ] - ( - builtins.replaceStrings - [ - " " - "\t" - "\n" - ] - [ - "" - "" - "" - ] - jsonc - ) - ); - bunLockParsers = { - # example: - # nu> open bun.lock | from json | get packages.@prisma/engines-version.0 - # @prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e - "0" = bunLockParsers."1"; - "1" = - lock: - afterLastDot ( - builtins.elemAt (lock."packages"."@prisma/engines-version" or (throw '' - nix-prisma-utils: lockfile parsing error: package @prisma/engines-version not found. - please make sure that you have @prisma/client installed. - '') - ) 0 - ); - }; - lockfile = fromJSONWithTrailingComma ( - assert builtins.typeOf path == "path"; - builtins.readFile path - ); - lockfileVersion = builtins.toString lockfile."lockfileVersion"; - parse = - bunLockParsers.${lockfileVersion} or (throw '' - nix-prisma-utils: Unsupported lockfile version: ${lockfileVersion} - nix-prisma-utils currently supports bun.lock version of 0 and 1. - ''); - commit = parse lockfile; - in - fromCommit commit; - } + ( + if commitValue != null then # direct fetch + fromCommit commitValue + else + { + # builder pattern + inherit + fromCommit + fromNpmLock + fromYarnLock + fromPnpmLock + fromBunLock + ; + } + ) diff --git a/readme.md b/readme.md index af7b979..df2c480 100644 --- a/readme.md +++ b/readme.md @@ -20,6 +20,42 @@ With nix-prisma-utils it's the other way around. You can simply install prisma t ## Let's go +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + prisma-utils.url = "github:VanCoding/nix-prisma-utils"; + }; + + outputs = + { nixpkgs, prisma-utils, ... }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + prisma = + prisma-utils.lib.prisma-factory { + inherit pkgs; + # leave the hash empty, nix will complain and tell you the right hash + hash = ""; + npmLock = ./package-lock.json # <--- path to our package-lock.json file that contains the version of prisma-engines + # if you use another package manager from npm, choose yours from + # yarnLock = ./yarn.lock; + # pnpmLock = ./pnpm-lock.yaml; + # bunLock = ./bun.lock; + }; + in + { + devShells.${system}.default = pkgs.mkShell { + env = prisma.env; + # or, you can use `shellHook` instead of `env` to load the same environment variables. + # shellHook = prisma.shellHook; + }; + }; +} +``` + +## Legacy fetchers & API + ### Using `npm` ```nix diff --git a/tests.nix b/tests.nix index fa3ff4d..a335ecd 100644 --- a/tests.nix +++ b/tests.nix @@ -2,7 +2,7 @@ pkgs, writeShellApplication, prisma-factory, - + fetcherMode, # legacy or new nodejs, pnpm, yarn-v1, @@ -10,32 +10,41 @@ bun, }: let - hashesBySystem = { - x86_64-linux = { - prisma-fmt-hash = "sha256-4zsJv0PW8FkGfiiv/9g0y5xWNjmRWD8Q2l2blSSBY3s="; - query-engine-hash = "sha256-6ILWB6ZmK4ac6SgAtqCkZKHbQANmcqpWO92U8CfkFzw="; - libquery-engine-hash = "sha256-n9IimBruqpDJStlEbCJ8nsk8L9dDW95ug+gz9DHS1Lc="; - schema-engine-hash = "sha256-j38xSXOBwAjIdIpbSTkFJijby6OGWCoAx+xZyms/34Q="; - }; - aarch64-linux = { - prisma-fmt-hash = "sha256-gqbgN9pZxzZEi6cBicUfH7qqlXWM+z28sGVuW/wKHb8="; - query-engine-hash = "sha256-q1HVbRtWhF3J5ScETrwvGisS8fXA27nryTvqFb+XIuo="; - libquery-engine-hash = "sha256-oalG9QKuxURtdgs5DgJZZtyWMz3ZpywHlov+d1ct2vA="; - schema-engine-hash = "sha256-5bp8iiq6kc9c37G8dNKVHKWJHvaxFaetR4DOR/0/eWs="; - }; - x86_64-darwin = { - prisma-fmt-hash = "sha256-Z0AIuCRW0GEd6QRiyYdVVS1Zb6d1aRH+jUE0JNXFgiQ="; - query-engine-hash = "sha256-TjJp72T9nmJcIrMLUIpnapzNlRyVpGp/jGaSuJ0nUDI="; - libquery-engine-hash = "sha256-cerpi9y9w6Fn1meXuj2VDRdIQz/MZvrQ7LZKa0Z70yM="; - schema-engine-hash = "sha256-tfR5B8s5GfmeE1kFlmYyxS7Kw1ELShBKsf+i5MmS+/o="; - }; - aarch64-darwin = { - prisma-fmt-hash = "sha256-UPig7U2zXOccalIUE0j07xJdmqAUJ7cpXFTo+2Gbsc8="; - query-engine-hash = "sha256-ihP1BEAvXQ+5XXHEXCYAVTnuETpfxmdtsIGRTljKtS0="; - libquery-engine-hash = "sha256-4T63O+OyoEIJ0TLKoOoil06whd+41QxiXXg+0cgpX/8="; - schema-engine-hash = "sha256-+O4IelHbZt4X+6UWol8TpL+BBDTS5JT+0hQR7ELVmZc="; - }; - }; + hashesBySystem = + if fetcherMode == "new" then + { + x86_64-linux.hash = "sha256-R9PG286KQTbzF0r/PPcShUkMiYam2prRh/JICjmhCZA="; + aarch64-linux.hash = "sha256-RvloEj41YTf+SwaHLqBlJ5Rpu00UPENprsQRHam3zic="; + x86_64-darwin.hash = "sha256-z1VypBp/JN4qipqTFDmVPb/H1I+TdQVcUU4EIsIPQJ8="; + aarch64-darwin.hash = "sha256-LxpKAAjnRn8eH7h9trOOYKf0WcY+aHGrzzVGW2aViek="; + } + else + { + x86_64-linux = { + prisma-fmt-hash = "sha256-4zsJv0PW8FkGfiiv/9g0y5xWNjmRWD8Q2l2blSSBY3s="; + query-engine-hash = "sha256-6ILWB6ZmK4ac6SgAtqCkZKHbQANmcqpWO92U8CfkFzw="; + libquery-engine-hash = "sha256-n9IimBruqpDJStlEbCJ8nsk8L9dDW95ug+gz9DHS1Lc="; + schema-engine-hash = "sha256-j38xSXOBwAjIdIpbSTkFJijby6OGWCoAx+xZyms/34Q="; + }; + aarch64-linux = { + prisma-fmt-hash = "sha256-gqbgN9pZxzZEi6cBicUfH7qqlXWM+z28sGVuW/wKHb8="; + query-engine-hash = "sha256-q1HVbRtWhF3J5ScETrwvGisS8fXA27nryTvqFb+XIuo="; + libquery-engine-hash = "sha256-oalG9QKuxURtdgs5DgJZZtyWMz3ZpywHlov+d1ct2vA="; + schema-engine-hash = "sha256-5bp8iiq6kc9c37G8dNKVHKWJHvaxFaetR4DOR/0/eWs="; + }; + x86_64-darwin = { + prisma-fmt-hash = "sha256-Z0AIuCRW0GEd6QRiyYdVVS1Zb6d1aRH+jUE0JNXFgiQ="; + query-engine-hash = "sha256-TjJp72T9nmJcIrMLUIpnapzNlRyVpGp/jGaSuJ0nUDI="; + libquery-engine-hash = "sha256-cerpi9y9w6Fn1meXuj2VDRdIQz/MZvrQ7LZKa0Z70yM="; + schema-engine-hash = "sha256-tfR5B8s5GfmeE1kFlmYyxS7Kw1ELShBKsf+i5MmS+/o="; + }; + aarch64-darwin = { + prisma-fmt-hash = "sha256-UPig7U2zXOccalIUE0j07xJdmqAUJ7cpXFTo+2Gbsc8="; + query-engine-hash = "sha256-ihP1BEAvXQ+5XXHEXCYAVTnuETpfxmdtsIGRTljKtS0="; + libquery-engine-hash = "sha256-4T63O+OyoEIJ0TLKoOoil06whd+41QxiXXg+0cgpX/8="; + schema-engine-hash = "sha256-+O4IelHbZt4X+6UWol8TpL+BBDTS5JT+0hQR7ELVmZc="; + }; + }; test-npm = let prisma = @@ -121,11 +130,9 @@ let }; in { - inherit - test-npm - test-pnpm - test-bun - test-yarn-v1 - test-yarn-berry - ; + "test-npm-${fetcherMode}" = test-npm; + "test-pnpm-${fetcherMode}" = test-pnpm; + "test-bun-${fetcherMode}" = test-bun; + "test-yarn-v1-${fetcherMode}" = test-yarn-v1; + "test-yarn-berry-${fetcherMode}" = test-yarn-berry; }