Skip to content

Commit 06ffd2a

Browse files
committed
feat: support yarn.lock
1 parent 897e2aa commit 06ffd2a

File tree

13 files changed

+462
-119
lines changed

13 files changed

+462
-119
lines changed

flake.nix

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,29 @@
1010
system:
1111
let
1212
nixpkgs = import pkgs { inherit system; };
13+
14+
yarn-v1 = nixpkgs.writeShellApplication {
15+
name = "yarn-v1";
16+
checkPhase = "";
17+
runtimeInputs = [ nixpkgs.yarn ];
18+
text = "yarn $@";
19+
};
20+
yarn-berry = nixpkgs.writeShellApplication {
21+
name = "yarn-berry";
22+
checkPhase = "";
23+
runtimeInputs = [ nixpkgs.yarn-berry ];
24+
text = "yarn $@";
25+
};
1326
in
1427
{
15-
packages = import ./tests.nix { inherit prisma-factory nixpkgs; };
28+
packages = nixpkgs.callPackage ./tests.nix {
29+
inherit
30+
prisma-factory
31+
nixpkgs
32+
yarn-v1
33+
yarn-berry
34+
;
35+
};
1636
devShells.default =
1737
let
1838
prisma = (
@@ -34,6 +54,8 @@
3454
nixpkgs.stdenv.cc.cc.lib
3555
prisma.package
3656
nixpkgs.nixfmt-rfc-style
57+
yarn-v1
58+
yarn-berry
3759
];
3860
shellHook = prisma.shellHook;
3961
};

lib/readYAML.nix

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# converts path to yaml file -> Nix Object
2+
{ runCommand, remarshal }:
3+
path:
4+
let
5+
jsonOutputDrv = runCommand "from-yaml" {
6+
nativeBuildInputs = [ remarshal ];
7+
} "remarshal -if yaml -i \"${path}\" -of json -o \"$out\"";
8+
in
9+
# perf: importing from / reading a file in a derivation (IFD: Import From Derivation) is known to be slow.
10+
builtins.fromJSON (builtins.readFile jsonOutputDrv)

prisma.nix

Lines changed: 192 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -15,117 +15,145 @@
1515
aarch64-darwin = "darwin-arm64";
1616
},
1717
}:
18+
let
19+
pkgs = nixpkgs; # remove this after renaming nixpkg -> pkgs
20+
inherit (pkgs) lib;
21+
lines = s: lib.strings.splitString "\n" s;
22+
23+
# example:
24+
# splitMultiple ["|" "," "-"] "a-|b,c-d"
25+
# -> ["a" "" "b" "c" "d"]
26+
splitMultiple = delims: s: _splitMultiple delims [ s ];
27+
# example:
28+
# _splitMultiple ["|" "," "-"] ["a-|b,c-d"]
29+
# -> ["a" "" "b" "c" "d"]
30+
_splitMultiple =
31+
delims: list:
32+
if builtins.length delims == 0 then
33+
list
34+
else
35+
let
36+
splitStr = map (str: lib.strings.splitString (builtins.elemAt delims 0) str) list;
37+
in
38+
_splitMultiple (lib.drop 1 delims) (lib.lists.concatLists splitStr);
39+
splitMultipleAndFilterEmpty = delims: s: builtins.filter (str: str != "") (splitMultiple delims s);
40+
afterLastDot = text: nixpkgs.lib.lists.last (nixpkgs.lib.strings.splitString "." text);
41+
42+
readYAML = pkgs.callPackage ./lib/readYAML.nix { };
43+
in
1844
rec {
1945
fromCommit =
2046
commit:
21-
let
22-
hostname = "binaries.prisma.sh";
23-
channel = "all_commits";
24-
binaryTarget = binaryTargetBySystem.${nixpkgs.system};
25-
isDarwin = nixpkgs.lib.strings.hasPrefix "darwin" binaryTarget;
26-
target = if isDarwin then binaryTarget else "${binaryTarget}-openssl-${opensslVersion}";
27-
baseUrl = "https://${hostname}/${channel}";
28-
files =
29-
[
30-
{
31-
name = "prisma-fmt";
32-
hash = prisma-fmt-hash;
33-
path = "bin/prisma-fmt";
34-
variable = "PRISMA_FMT_BINARY";
35-
}
36-
{
37-
name = "query-engine";
38-
hash = query-engine-hash;
39-
path = "bin/query-engine";
40-
variable = "PRISMA_QUERY_ENGINE_BINARY";
41-
}
42-
{
43-
name = if isDarwin then "libquery_engine.dylib.node" else "libquery_engine.so.node";
44-
hash = libquery-engine-hash;
45-
path = "lib/libquery_engine.node";
46-
variable = "PRISMA_QUERY_ENGINE_LIBRARY";
47+
if builtins.stringLength commit != 40 then
48+
throw "nvalid commit: got ${commit}"
49+
else
50+
let
51+
hostname = "binaries.prisma.sh";
52+
channel = "all_commits";
53+
binaryTarget = binaryTargetBySystem.${nixpkgs.system};
54+
isDarwin = nixpkgs.lib.strings.hasPrefix "darwin" binaryTarget;
55+
target = if isDarwin then binaryTarget else "${binaryTarget}-openssl-${opensslVersion}";
56+
baseUrl = "https://${hostname}/${channel}";
57+
files =
58+
[
59+
{
60+
name = "prisma-fmt";
61+
hash = prisma-fmt-hash;
62+
path = "bin/prisma-fmt";
63+
variable = "PRISMA_FMT_BINARY";
64+
}
65+
{
66+
name = "query-engine";
67+
hash = query-engine-hash;
68+
path = "bin/query-engine";
69+
variable = "PRISMA_QUERY_ENGINE_BINARY";
70+
}
71+
{
72+
name = if isDarwin then "libquery_engine.dylib.node" else "libquery_engine.so.node";
73+
hash = libquery-engine-hash;
74+
path = "lib/libquery_engine.node";
75+
variable = "PRISMA_QUERY_ENGINE_LIBRARY";
76+
}
77+
]
78+
++ (
79+
if introspection-engine-hash == null then
80+
[ ]
81+
else
82+
[
83+
{
84+
name = "introspection-engine";
85+
hash = introspection-engine-hash;
86+
path = "bin/introspection-engine";
87+
variable = "PRISMA_INTROSPECTION_ENGINE_BINARY";
88+
}
89+
]
90+
)
91+
++ (
92+
if migration-engine-hash == null then
93+
[ ]
94+
else
95+
[
96+
{
97+
name = "migration-engine";
98+
hash = migration-engine-hash;
99+
path = "bin/migration-engine";
100+
variable = "PRISMA_MIGRATION_ENGINE_BINARY";
101+
}
102+
]
103+
)
104+
++ (
105+
if schema-engine-hash == null then
106+
[ ]
107+
else
108+
[
109+
{
110+
name = "schema-engine";
111+
hash = schema-engine-hash;
112+
path = "bin/schema-engine";
113+
variable = "PRISMA_SCHEMA_ENGINE_BINARY";
114+
}
115+
]
116+
);
117+
downloadedFiles = builtins.map (
118+
file:
119+
file
120+
// {
121+
file = nixpkgs.fetchurl {
122+
name = "${baseUrl}/${commit}/${target}/${file.name}.gz";
123+
url = "${baseUrl}/${commit}/${target}/${file.name}.gz";
124+
hash = file.hash;
125+
};
47126
}
48-
]
49-
++ (
50-
if introspection-engine-hash == null then
51-
[ ]
52-
else
53-
[
54-
{
55-
name = "introspection-engine";
56-
hash = introspection-engine-hash;
57-
path = "bin/introspection-engine";
58-
variable = "PRISMA_INTROSPECTION_ENGINE_BINARY";
59-
}
60-
]
61-
)
62-
++ (
63-
if migration-engine-hash == null then
64-
[ ]
65-
else
66-
[
67-
{
68-
name = "migration-engine";
69-
hash = migration-engine-hash;
70-
path = "bin/migration-engine";
71-
variable = "PRISMA_MIGRATION_ENGINE_BINARY";
72-
}
73-
]
74-
)
75-
++ (
76-
if schema-engine-hash == null then
77-
[ ]
78-
else
79-
[
80-
{
81-
name = "schema-engine";
82-
hash = schema-engine-hash;
83-
path = "bin/schema-engine";
84-
variable = "PRISMA_SCHEMA_ENGINE_BINARY";
85-
}
86-
]
87-
);
88-
downloadedFiles = builtins.map (
89-
file:
90-
file
91-
// {
92-
file = nixpkgs.fetchurl {
93-
name = "${baseUrl}/${commit}/${target}/${file.name}.gz";
94-
url = "${baseUrl}/${commit}/${target}/${file.name}.gz";
95-
hash = file.hash;
96-
};
97-
}
98-
) files;
99-
unzipCommands = builtins.map (file: "gunzip -c ${file.file} > $out/${file.path}") downloadedFiles;
100-
exportCommands =
101-
package: builtins.map (file: "export ${file.variable}=${package}/${file.path}") files;
102-
in
103-
rec {
104-
package = nixpkgs.stdenv.mkDerivation {
105-
pname = "prisma-bin";
106-
version = commit;
107-
nativeBuildInputs = [
108-
nixpkgs.zlib
109-
openssl
110-
nixpkgs.stdenv.cc.cc.lib
111-
] ++ nixpkgs.lib.optionals (!isDarwin) [ nixpkgs.autoPatchelfHook ];
112-
phases = [
113-
"buildPhase"
114-
"postFixupHooks"
115-
];
116-
buildPhase = ''
117-
mkdir -p $out/bin
118-
mkdir -p $out/lib
119-
${nixpkgs.lib.concatStringsSep "\n" unzipCommands}
120-
chmod +x $out/bin/*
121-
'';
127+
) files;
128+
unzipCommands = builtins.map (file: "gunzip -c ${file.file} > $out/${file.path}") downloadedFiles;
129+
exportCommands =
130+
package: builtins.map (file: "export ${file.variable}=${package}/${file.path}") files;
131+
in
132+
rec {
133+
package = nixpkgs.stdenv.mkDerivation {
134+
pname = "prisma-bin";
135+
version = commit;
136+
nativeBuildInputs = [
137+
nixpkgs.zlib
138+
openssl
139+
nixpkgs.stdenv.cc.cc.lib
140+
] ++ nixpkgs.lib.optionals (!isDarwin) [ nixpkgs.autoPatchelfHook ];
141+
phases = [
142+
"buildPhase"
143+
"postFixupHooks"
144+
];
145+
buildPhase = ''
146+
mkdir -p $out/bin
147+
mkdir -p $out/lib
148+
${nixpkgs.lib.concatStringsSep "\n" unzipCommands}
149+
chmod +x $out/bin/*
150+
'';
151+
};
152+
shellHook = nixpkgs.lib.concatStringsSep "\n" (exportCommands package);
122153
};
123-
shellHook = nixpkgs.lib.concatStringsSep "\n" (exportCommands package);
124-
};
125154
# example:
126155
# a.b123c.d.e12345
127156
# => e12345
128-
afterLastDot = text: nixpkgs.lib.lists.last (nixpkgs.lib.strings.splitString "." text);
129157
fromPnpmLock =
130158
path:
131159
let
@@ -145,9 +173,7 @@ rec {
145173
"5" =
146174
pnpmLock:
147175
let
148-
version = builtins.elemAt (builtins.split ":" (
149-
builtins.elemAt (builtins.split ("@prisma/engines-version/") pnpmLock) 2
150-
)) 0;
176+
version = builtins.elemAt (builtins.split ":" (builtins.elemAt (builtins.split ("@prisma/engines-version/") pnpmLock) 2)) 0;
151177
in
152178
nixpkgs.lib.lists.last (nixpkgs.lib.strings.splitString "." version);
153179

@@ -156,9 +182,7 @@ rec {
156182
"6" =
157183
pnpmLock:
158184
let
159-
version = builtins.elemAt (builtins.split ":" (
160-
builtins.elemAt (builtins.split ("@prisma/engines-version@") pnpmLock) 2
161-
)) 0;
185+
version = builtins.elemAt (builtins.split ":" (builtins.elemAt (builtins.split ("@prisma/engines-version@") pnpmLock) 2)) 0;
162186
in
163187
nixpkgs.lib.lists.last (nixpkgs.lib.strings.splitString "." version);
164188

@@ -167,9 +191,7 @@ rec {
167191
"9" =
168192
pnpmLock:
169193
let
170-
version = builtins.elemAt (builtins.split "'" (
171-
builtins.elemAt (builtins.split ("@prisma/engines-version@") pnpmLock) 2
172-
)) 0;
194+
version = builtins.elemAt (builtins.split "'" (builtins.elemAt (builtins.split ("@prisma/engines-version@") pnpmLock) 2)) 0;
173195
in
174196
nixpkgs.lib.lists.last (nixpkgs.lib.strings.splitString "." version);
175197
};
@@ -191,6 +213,64 @@ rec {
191213
commit = nixpkgs.lib.lists.last (nixpkgs.lib.strings.splitString "." version);
192214
in
193215
fromCommit commit;
216+
fromYarnLock =
217+
path:
218+
let
219+
# find this line from yarn.lock:
220+
# "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0":
221+
yarnLockParser1 =
222+
file:
223+
let
224+
versionLine =
225+
lib.lists.findFirst
226+
(line: builtins.length (lib.strings.splitString "@prisma/engines-version" line) >= 2)
227+
# else
228+
(throw ''
229+
nix-prisma-utils/yarnLockParser1: package @prisma/engines-version not found in lockfile ${path} .
230+
please make sure you have installed `@prisma/client`.
231+
if you have already installed `@prisma/client` and still see this, please report this to nix-prisma-utils.
232+
'')
233+
(lines file);
234+
# "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0":
235+
# -> ["@prisma/engines-version@npm" "6" "3" "0-17" "acc0b9dd43eb689cbd20c9470515d719db10d0b0"]
236+
# -> acc0b9dd43eb689cbd20c9470515d719db10d0b0
237+
version = lib.lists.last (
238+
splitMultipleAndFilterEmpty [
239+
"\""
240+
":"
241+
"."
242+
] versionLine
243+
);
244+
in
245+
version;
246+
isYarnLockV1 =
247+
file:
248+
lib.lists.any (line: lib.strings.trim line == "# yarn lockfile v1") (
249+
lib.strings.splitString "\n" file
250+
);
251+
# example line:
252+
# "@prisma/engines-version@6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0":
253+
yarnV1LockParser = yarnLockParser1;
254+
# example line:
255+
# "@prisma/engines-version@npm:6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0":
256+
yarnBerryLockParsers = {
257+
"8" = yarnLockParser1;
258+
};
259+
260+
lockfile = builtins.readFile path;
261+
parse =
262+
if isYarnLockV1 lockfile then
263+
yarnV1LockParser
264+
else
265+
let
266+
lockfileVersion = builtins.toString (readYAML path).__metadata.version;
267+
in
268+
yarnBerryLockParsers.${lockfileVersion} or (throw ''
269+
nix-prisma-utils: unknown lockfile version ${lockfileVersion}.
270+
please report this to nix-prisma-utils with your lockfile.
271+
'');
272+
in
273+
fromCommit (parse lockfile);
194274
fromBunLock =
195275
path:
196276
let

0 commit comments

Comments
 (0)