aboutsummaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
l---------frontend/.direnv/flake-profile1
-rw-r--r--frontend/.direnv/flake-profile.rc1473
-rw-r--r--frontend/elm-stuff/0.19.1/Cart.elmibin0 -> 4274 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Cart.elmobin0 -> 6973 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Catalog.elmibin0 -> 4112 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Catalog.elmobin0 -> 5002 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Login.elmibin0 -> 2307 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Login.elmobin0 -> 5241 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Main.elmibin0 -> 19391 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Main.elmobin0 -> 14316 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Product.elmibin0 -> 11250 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Product.elmobin0 -> 15801 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Signup.elmibin0 -> 3892 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/Signup.elmobin0 -> 8736 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/d.datbin0 -> 2696 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/i.datbin0 -> 122650 bytes
-rw-r--r--frontend/elm-stuff/0.19.1/lock0
-rw-r--r--frontend/elm-stuff/0.19.1/o.datbin0 -> 482300 bytes
-rw-r--r--frontend/elm.json27
-rw-r--r--frontend/src/Cart.elm164
-rw-r--r--frontend/src/Catalog.elm125
-rw-r--r--frontend/src/Login.elm119
-rw-r--r--frontend/src/Main.elm339
-rw-r--r--frontend/src/Product.elm302
-rw-r--r--frontend/src/Signup.elm194
25 files changed, 2744 insertions, 0 deletions
diff --git a/frontend/.direnv/flake-profile b/frontend/.direnv/flake-profile
new file mode 120000
index 0000000..6e8a8e9
--- /dev/null
+++ b/frontend/.direnv/flake-profile
@@ -0,0 +1 @@
/nix/store/m4z2i7h8x7xwac09q8gw4km9vhmi88ka-furby-env \ No newline at end of file
diff --git a/frontend/.direnv/flake-profile.rc b/frontend/.direnv/flake-profile.rc
new file mode 100644
index 0000000..dff177f
--- /dev/null
+++ b/frontend/.direnv/flake-profile.rc
@@ -0,0 +1,1473 @@
1unset shellHook
2nix_saved_PATH="$PATH"
3AR=ar
4export AR
5AS=as
6export AS
7BASH=/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash
8CC=gcc
9export CC
10CONFIG_SHELL=/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash
11export CONFIG_SHELL
12CXX=g++
13export CXX
14DIRSTACK=()
15GROUPS=()
16HOSTTYPE=x86_64
17HOST_PATH=/nix/store/603kisq28l3prqr92z5hffh7fmwwsc9f-elm-0.19.1/bin:/nix/store/amj35xgl7bhifnih0mh39j8kbvsvg2xn-node__at_elm-tooling_slash_elm-language-server-1.6.3/bin:/nix/store/hzxpv4ha44w9pg8ynkfsgjhi3kb13h27-elm-format-0.8.3/bin:/nix/store/w3sh9aki5wrchcrq2wlg2xb394f8brh4-node_elm-oracle-1.1.1/bin:/nix/store/3yl8y2fkc1wsyqm008is2pdw5dja2icy-node_elm-test-0.19.1-revision2/bin:/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/bin:/nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0/bin:/nix/store/dqq1bvpi3g0h4v05111b3i0ymqj4v5x1-diffutils-3.7/bin:/nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8/bin:/nix/store/b0vjq4r4sp9z4l2gbkc5dyyw5qfgyi3r-gnugrep-3.4/bin:/nix/store/c8balm59sxfkw9ik1fqbkadsvjqhmbx4-gawk-5.0.1/bin:/nix/store/g7dr83wnkx4gxa5ykcljc5jg04416z60-gnutar-1.32/bin:/nix/store/kkvgr3avpp7yd5hzmc4syh43jqj03sgb-gzip-1.10/bin:/nix/store/rw96psqzgyqrcd12qr6ivk9yiskjm3ab-bzip2-1.0.6.0.1-bin/bin:/nix/store/dp6y0n9cba79wwc54n1brg7xbjsq5hka-gnumake-4.2.1/bin:/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin:/nix/store/xac1zfclx1xxgcd84vqb6hy3apl171n8-patch-2.7.6/bin:/nix/store/mm0w8jc58rn01c4kz2n9jvwd6bibcihs-xz-5.2.4-bin/bin
18export HOST_PATH
19IFS=$' \t\n'
20IN_NIX_SHELL=impure
21export IN_NIX_SHELL
22LD=ld
23export LD
24MACHTYPE=x86_64-unknown-linux-gnu
25NIX_BINTOOLS=/nix/store/n48b8n251dwwb04q7f3fwxdmirsakllz-binutils-wrapper-2.31.1
26export NIX_BINTOOLS
27NIX_BINTOOLS_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST=1
28export NIX_BINTOOLS_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST
29NIX_BUILD_CORES=8
30export NIX_BUILD_CORES
31NIX_CC=/nix/store/m6h7zh8w6s52clnyskffj5lbkakqgywn-gcc-wrapper-9.2.0
32export NIX_CC
33NIX_CC_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST=1
34export NIX_CC_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST
35NIX_ENFORCE_NO_NATIVE=1
36export NIX_ENFORCE_NO_NATIVE
37NIX_HARDENING_ENABLE='fortify stackprotector pic strictoverflow format relro bindnow'
38export NIX_HARDENING_ENABLE
39NIX_INDENT_MAKE=1
40export NIX_INDENT_MAKE
41NIX_LDFLAGS='-rpath /home/np/code/elmstuff/app-furby/outputs/out/lib64 -rpath /home/np/code/elmstuff/app-furby/outputs/out/lib '
42export NIX_LDFLAGS
43NIX_LIB64_IN_SELF_RPATH=1
44NIX_NO_SELF_RPATH=1
45NIX_STORE=/nix/store
46export NIX_STORE
47NM=nm
48export NM
49OBJCOPY=objcopy
50export OBJCOPY
51OBJDUMP=objdump
52export OBJDUMP
53OPTERR=1
54OPTIND=1
55OSTYPE=linux-gnu
56PATH=/nix/store/71n1xcigc00w3z7yc836jqcx9cb2dys8-patchelf-0.9/bin:/nix/store/m6h7zh8w6s52clnyskffj5lbkakqgywn-gcc-wrapper-9.2.0/bin:/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/bin:/nix/store/0k65d30z9xsixil10yw3bwajbdk4yskv-glibc-2.30-bin/bin:/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/bin:/nix/store/n48b8n251dwwb04q7f3fwxdmirsakllz-binutils-wrapper-2.31.1/bin:/nix/store/hrkc2sf2883l16d5yq3zg0y339kfw4xv-binutils-2.31.1/bin:/nix/store/0k65d30z9xsixil10yw3bwajbdk4yskv-glibc-2.30-bin/bin:/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/bin:/nix/store/603kisq28l3prqr92z5hffh7fmwwsc9f-elm-0.19.1/bin:/nix/store/amj35xgl7bhifnih0mh39j8kbvsvg2xn-node__at_elm-tooling_slash_elm-language-server-1.6.3/bin:/nix/store/hzxpv4ha44w9pg8ynkfsgjhi3kb13h27-elm-format-0.8.3/bin:/nix/store/w3sh9aki5wrchcrq2wlg2xb394f8brh4-node_elm-oracle-1.1.1/bin:/nix/store/3yl8y2fkc1wsyqm008is2pdw5dja2icy-node_elm-test-0.19.1-revision2/bin:/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/bin:/nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0/bin:/nix/store/dqq1bvpi3g0h4v05111b3i0ymqj4v5x1-diffutils-3.7/bin:/nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8/bin:/nix/store/b0vjq4r4sp9z4l2gbkc5dyyw5qfgyi3r-gnugrep-3.4/bin:/nix/store/c8balm59sxfkw9ik1fqbkadsvjqhmbx4-gawk-5.0.1/bin:/nix/store/g7dr83wnkx4gxa5ykcljc5jg04416z60-gnutar-1.32/bin:/nix/store/kkvgr3avpp7yd5hzmc4syh43jqj03sgb-gzip-1.10/bin:/nix/store/rw96psqzgyqrcd12qr6ivk9yiskjm3ab-bzip2-1.0.6.0.1-bin/bin:/nix/store/dp6y0n9cba79wwc54n1brg7xbjsq5hka-gnumake-4.2.1/bin:/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin:/nix/store/xac1zfclx1xxgcd84vqb6hy3apl171n8-patch-2.7.6/bin:/nix/store/mm0w8jc58rn01c4kz2n9jvwd6bibcihs-xz-5.2.4-bin/bin
57export PATH
58PIPESTATUS=([0]="0")
59PS4='+ '
60RANLIB=ranlib
61export RANLIB
62READELF=readelf
63export READELF
64SHELL=/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash
65export SHELL
66SIZE=size
67export SIZE
68SOURCE_DATE_EPOCH=1
69export SOURCE_DATE_EPOCH
70STRINGS=strings
71export STRINGS
72STRIP=strip
73export STRIP
74_=export
75buildInputs='/nix/store/603kisq28l3prqr92z5hffh7fmwwsc9f-elm-0.19.1 /nix/store/amj35xgl7bhifnih0mh39j8kbvsvg2xn-node__at_elm-tooling_slash_elm-language-server-1.6.3 /nix/store/hzxpv4ha44w9pg8ynkfsgjhi3kb13h27-elm-format-0.8.3 /nix/store/w3sh9aki5wrchcrq2wlg2xb394f8brh4-node_elm-oracle-1.1.1 /nix/store/3yl8y2fkc1wsyqm008is2pdw5dja2icy-node_elm-test-0.19.1-revision2'
76export buildInputs
77builder=/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash
78export builder
79commonStripFlags=--enable-deterministic-archives
80configureFlags=
81export configureFlags
82defaultBuildInputs=
83defaultNativeBuildInputs='/nix/store/71n1xcigc00w3z7yc836jqcx9cb2dys8-patchelf-0.9 /nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh /nix/store/kxw6q8v6isaqjm702d71n2421cxamq68-make-symlinks-relative.sh /nix/store/rvg5a5nwa7cihpmbzlwzh931w3g4q108-compress-man-pages.sh /nix/store/4ygqr4w06zwcd2kcxa6w3441jijv0pvx-strip.sh /nix/store/g6hzqyjd3ricwbs0bbx4806fiwg15vnc-patch-shebangs.sh /nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh /nix/store/8zxndz5ag0p6s526c2xyllhk1nrn4c3i-audit-tmpdir.sh /nix/store/aknix5zw9cj7hd1m3h1d6nnmncl1vkvn-multiple-outputs.sh /nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh /nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh /nix/store/ngg1cv31c8c7bcm2n8ww4g06nq7s4zhm-set-source-date-epoch-to-latest.sh /nix/store/m6h7zh8w6s52clnyskffj5lbkakqgywn-gcc-wrapper-9.2.0'
84depsBuildBuild=
85export depsBuildBuild
86depsBuildBuildPropagated=
87export depsBuildBuildPropagated
88depsBuildTarget=
89export depsBuildTarget
90depsBuildTargetPropagated=
91export depsBuildTargetPropagated
92depsHostHost=
93export depsHostHost
94depsHostHostPropagated=
95export depsHostHostPropagated
96depsTargetTarget=
97export depsTargetTarget
98depsTargetTargetPropagated=
99export depsTargetTargetPropagated
100doCheck=
101export doCheck
102doInstallCheck=
103export doInstallCheck
104dontAddDisableDepTrack=1
105export dontAddDisableDepTrack
106envHostHostHooks=([0]="ccWrapper_addCVars" [1]="bintoolsWrapper_addLDVars")
107envHostTargetHooks=([0]="ccWrapper_addCVars" [1]="bintoolsWrapper_addLDVars")
108fixupOutputHooks=([0]="if [ -z \"\${dontPatchELF-}\" ]; then patchELF \"\$prefix\"; fi" [1]="_makeSymlinksRelative" [2]="if [ -z \"\${dontGzipMan-}\" ]; then compressManPages \"\$prefix\"; fi" [3]="_doStrip" [4]="patchShebangsAuto" [5]="_pruneLibtoolFiles" [6]="if [[ -z \"\${noAuditTmpdir-}\" && -e \"\$prefix\" ]]; then auditTmpdir \"\$prefix\"; fi" [7]="_moveSbin" [8]="_moveLib64")
109initialPath='/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31 /nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0 /nix/store/dqq1bvpi3g0h4v05111b3i0ymqj4v5x1-diffutils-3.7 /nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8 /nix/store/b0vjq4r4sp9z4l2gbkc5dyyw5qfgyi3r-gnugrep-3.4 /nix/store/c8balm59sxfkw9ik1fqbkadsvjqhmbx4-gawk-5.0.1 /nix/store/g7dr83wnkx4gxa5ykcljc5jg04416z60-gnutar-1.32 /nix/store/kkvgr3avpp7yd5hzmc4syh43jqj03sgb-gzip-1.10 /nix/store/rw96psqzgyqrcd12qr6ivk9yiskjm3ab-bzip2-1.0.6.0.1-bin /nix/store/dp6y0n9cba79wwc54n1brg7xbjsq5hka-gnumake-4.2.1 /nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23 /nix/store/xac1zfclx1xxgcd84vqb6hy3apl171n8-patch-2.7.6 /nix/store/mm0w8jc58rn01c4kz2n9jvwd6bibcihs-xz-5.2.4-bin'
110name=furby
111export name
112nativeBuildInputs=
113export nativeBuildInputs
114out=/home/np/code/elmstuff/app-furby/outputs/out
115export out
116outputBin=out
117outputDev=out
118outputDevdoc=REMOVE
119outputDevman=out
120outputDoc=out
121outputInclude=out
122outputInfo=out
123outputLib=out
124outputMan=out
125outputs=out
126export outputs
127patches=
128export patches
129pkg=/nix/store/m6h7zh8w6s52clnyskffj5lbkakqgywn-gcc-wrapper-9.2.0
130pkgsBuildHost=([0]="/nix/store/71n1xcigc00w3z7yc836jqcx9cb2dys8-patchelf-0.9" [1]="/nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh" [2]="/nix/store/kxw6q8v6isaqjm702d71n2421cxamq68-make-symlinks-relative.sh" [3]="/nix/store/rvg5a5nwa7cihpmbzlwzh931w3g4q108-compress-man-pages.sh" [4]="/nix/store/4ygqr4w06zwcd2kcxa6w3441jijv0pvx-strip.sh" [5]="/nix/store/g6hzqyjd3ricwbs0bbx4806fiwg15vnc-patch-shebangs.sh" [6]="/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh" [7]="/nix/store/8zxndz5ag0p6s526c2xyllhk1nrn4c3i-audit-tmpdir.sh" [8]="/nix/store/aknix5zw9cj7hd1m3h1d6nnmncl1vkvn-multiple-outputs.sh" [9]="/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh" [10]="/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh" [11]="/nix/store/ngg1cv31c8c7bcm2n8ww4g06nq7s4zhm-set-source-date-epoch-to-latest.sh" [12]="/nix/store/m6h7zh8w6s52clnyskffj5lbkakqgywn-gcc-wrapper-9.2.0" [13]="/nix/store/n48b8n251dwwb04q7f3fwxdmirsakllz-binutils-wrapper-2.31.1")
131pkgsHostTarget=([0]="/nix/store/603kisq28l3prqr92z5hffh7fmwwsc9f-elm-0.19.1" [1]="/nix/store/amj35xgl7bhifnih0mh39j8kbvsvg2xn-node__at_elm-tooling_slash_elm-language-server-1.6.3" [2]="/nix/store/hzxpv4ha44w9pg8ynkfsgjhi3kb13h27-elm-format-0.8.3" [3]="/nix/store/w3sh9aki5wrchcrq2wlg2xb394f8brh4-node_elm-oracle-1.1.1" [4]="/nix/store/3yl8y2fkc1wsyqm008is2pdw5dja2icy-node_elm-test-0.19.1-revision2")
132postFixupHooks=([0]="_multioutPropagateDev")
133postUnpackHooks=([0]="_updateSourceDateEpochFromSourceRoot")
134preConfigureHooks=([0]="_multioutConfig")
135preFixupHooks=([0]="_moveToShare" [1]="_multioutDocs" [2]="_multioutDevs")
136prefix=/home/np/code/elmstuff/app-furby/outputs/out
137propagatedBuildDepFiles=([0]="propagated-build-build-deps" [1]="propagated-native-build-inputs" [2]="propagated-build-target-deps")
138propagatedBuildInputs=
139export propagatedBuildInputs
140propagatedHostDepFiles=([0]="propagated-host-host-deps" [1]="propagated-build-inputs")
141propagatedNativeBuildInputs=
142export propagatedNativeBuildInputs
143propagatedTargetDepFiles=([0]="propagated-target-target-deps")
144shell=/nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash
145export shell
146src=./.
147export src
148stdenv=/nix/store/sm7kk5n84vaisqvhk1yfsjqls50j8s0m-stdenv-linux
149export stdenv
150strictDeps=
151export strictDeps
152system=x86_64-linux
153export system
154unpackCmdHooks=([0]="_defaultUnpack")
155PATH="$PATH:$nix_saved_PATH"
156_activatePkgs ()
157{
158 local -i hostOffset targetOffset;
159 local pkg;
160 for hostOffset in "${allPlatOffsets[@]}";
161 do
162 local pkgsVar="${pkgAccumVarVars[$hostOffset + 1]}";
163 for targetOffset in "${allPlatOffsets[@]}";
164 do
165 (( "$hostOffset" <= "$targetOffset" )) || continue;
166 local pkgsRef="${pkgsVar}[$targetOffset - $hostOffset]";
167 local pkgsSlice="${!pkgsRef}[@]";
168 for pkg in ${!pkgsSlice+"${!pkgsSlice}"};
169 do
170 activatePackage "$pkg" "$hostOffset" "$targetOffset";
171 done;
172 done;
173 done
174}
175_addRpathPrefix ()
176{
177 if [ "${NIX_NO_SELF_RPATH:-0}" != 1 ]; then
178 export NIX_LDFLAGS="-rpath $1/lib ${NIX_LDFLAGS-}";
179 if [ -n "${NIX_LIB64_IN_SELF_RPATH:-}" ]; then
180 export NIX_LDFLAGS="-rpath $1/lib64 ${NIX_LDFLAGS-}";
181 fi;
182 if [ -n "${NIX_LIB32_IN_SELF_RPATH:-}" ]; then
183 export NIX_LDFLAGS="-rpath $1/lib32 ${NIX_LDFLAGS-}";
184 fi;
185 fi
186}
187_addToEnv ()
188{
189 local -i depHostOffset depTargetOffset;
190 local pkg;
191 for depHostOffset in "${allPlatOffsets[@]}";
192 do
193 local hookVar="${pkgHookVarVars[$depHostOffset + 1]}";
194 local pkgsVar="${pkgAccumVarVars[$depHostOffset + 1]}";
195 for depTargetOffset in "${allPlatOffsets[@]}";
196 do
197 (( "$depHostOffset" <= "$depTargetOffset" )) || continue;
198 local hookRef="${hookVar}[$depTargetOffset - $depHostOffset]";
199 if [[ -z "${strictDeps-}" ]]; then
200 local visitedPkgs="";
201 for pkg in ${pkgsBuildBuild+"${pkgsBuildBuild[@]}"} ${pkgsBuildHost+"${pkgsBuildHost[@]}"} ${pkgsBuildTarget+"${pkgsBuildTarget[@]}"} ${pkgsHostHost+"${pkgsHostHost[@]}"} ${pkgsHostTarget+"${pkgsHostTarget[@]}"} ${pkgsTargetTarget+"${pkgsTargetTarget[@]}"};
202 do
203 if [[ "$visitedPkgs" = *"$pkg"* ]]; then
204 continue;
205 fi;
206 runHook "${!hookRef}" "$pkg";
207 visitedPkgs+=" $pkg";
208 done;
209 else
210 local pkgsRef="${pkgsVar}[$depTargetOffset - $depHostOffset]";
211 local pkgsSlice="${!pkgsRef}[@]";
212 for pkg in ${!pkgsSlice+"${!pkgsSlice}"};
213 do
214 runHook "${!hookRef}" "$pkg";
215 done;
216 fi;
217 done;
218 done
219}
220_allFlags ()
221{
222 for varName in $(awk 'BEGIN { for (v in ENVIRON) if (v ~ /^[a-z][a-zA-Z0-9_]*$/) print v }');
223 do
224 if (( "${NIX_DEBUG:-0}" >= 1 )); then
225 printf "@%s@ -> %q\n" "${varName}" "${!varName}";
226 fi;
227 args+=("--subst-var" "$varName");
228 done
229}
230_assignFirst ()
231{
232 local varName="$1";
233 local REMOVE=REMOVE;
234 shift;
235 while (( $# )); do
236 if [ -n "${!1-}" ]; then
237 eval "${varName}"="$1";
238 return;
239 fi;
240 shift;
241 done;
242 echo "Error: _assignFirst found no valid variant!";
243 return 1
244}
245_callImplicitHook ()
246{
247 local def="$1";
248 local hookName="$2";
249 if declare -F "$hookName" > /dev/null; then
250 "$hookName";
251 else
252 if type -p "$hookName" > /dev/null; then
253 source "$hookName";
254 else
255 if [ -n "${!hookName:-}" ]; then
256 eval "${!hookName}";
257 else
258 return "$def";
259 fi;
260 fi;
261 fi
262}
263_defaultUnpack ()
264{
265 local fn="$1";
266 if [ -d "$fn" ]; then
267 cp -pr --reflink=auto -- "$fn" "$(stripHash "$fn")";
268 else
269 case "$fn" in
270 *.tar.xz | *.tar.lzma | *.txz)
271 xz -d < "$fn" | tar xf -
272 ;;
273 *.tar | *.tar.* | *.tgz | *.tbz2 | *.tbz)
274 tar xf "$fn"
275 ;;
276 *)
277 return 1
278 ;;
279 esac;
280 fi
281}
282_doStrip ()
283{
284 local -ra flags=(dontStripHost dontStripTarget);
285 local -ra stripCmds=(STRIP TARGET_STRIP);
286 if [[ "${STRIP-}" == "${TARGET_STRIP-}" ]]; then
287 dontStripTarget+=1;
288 fi;
289 local i;
290 for i in ${!stripCmds[@]};
291 do
292 local -n flag="${flags[$i]}";
293 local -n stripCmd="${stripCmds[$i]}";
294 if [[ -n "${dontStrip-}" || -n "${flag-}" ]] || ! type -f "${stripCmd-}" 2> /dev/null; then
295 continue;
296 fi;
297 stripDebugList=${stripDebugList:-lib lib32 lib64 libexec bin sbin};
298 if [ -n "$stripDebugList" ]; then
299 stripDirs "$stripCmd" "$stripDebugList" "${stripDebugFlags:--S}";
300 fi;
301 stripAllList=${stripAllList:-};
302 if [ -n "$stripAllList" ]; then
303 stripDirs "$stripCmd" "$stripAllList" "${stripAllFlags:--s}";
304 fi;
305 done
306}
307_eval ()
308{
309 if declare -F "$1" > /dev/null 2>&1; then
310 "$@";
311 else
312 eval "$1";
313 fi
314}
315_makeSymlinksRelative ()
316{
317 local symlinkTarget;
318 if [ -n "${dontRewriteSymlinks-}" ]; then
319 return 0;
320 fi;
321 while IFS= read -r -d '' f; do
322 symlinkTarget=$(readlink "$f");
323 if [[ "$symlinkTarget"/ != "$prefix"/* ]]; then
324 continue;
325 fi;
326 if [ ! -e "$symlinkTarget" ]; then
327 echo "the symlink $f is broken, it points to $symlinkTarget (which is missing)";
328 fi;
329 echo "rewriting symlink $f to be relative to $prefix";
330 ln -snrf "$symlinkTarget" "$f";
331 done < <(find $prefix -type l -print0)
332}
333_moveLib64 ()
334{
335 if [ "${dontMoveLib64-}" = 1 ]; then
336 return;
337 fi;
338 if [ ! -e "$prefix/lib64" -o -L "$prefix/lib64" ]; then
339 return;
340 fi;
341 echo "moving $prefix/lib64/* to $prefix/lib";
342 mkdir -p $prefix/lib;
343 shopt -s dotglob;
344 for i in $prefix/lib64/*;
345 do
346 mv --no-clobber "$i" $prefix/lib;
347 done;
348 shopt -u dotglob;
349 rmdir $prefix/lib64;
350 ln -s lib $prefix/lib64
351}
352_moveSbin ()
353{
354 if [ "${dontMoveSbin-}" = 1 ]; then
355 return;
356 fi;
357 if [ ! -e "$prefix/sbin" -o -L "$prefix/sbin" ]; then
358 return;
359 fi;
360 echo "moving $prefix/sbin/* to $prefix/bin";
361 mkdir -p $prefix/bin;
362 shopt -s dotglob;
363 for i in $prefix/sbin/*;
364 do
365 mv "$i" $prefix/bin;
366 done;
367 shopt -u dotglob;
368 rmdir $prefix/sbin;
369 ln -s bin $prefix/sbin
370}
371_moveToShare ()
372{
373 forceShare=${forceShare:=man doc info};
374 if [ -z "$forceShare" -o -z "$out" ]; then
375 return;
376 fi;
377 for d in $forceShare;
378 do
379 if [ -d "$out/$d" ]; then
380 if [ -d "$out/share/$d" ]; then
381 echo "both $d/ and share/$d/ exist!";
382 else
383 echo "moving $out/$d to $out/share/$d";
384 mkdir -p $out/share;
385 mv $out/$d $out/share/;
386 fi;
387 fi;
388 done
389}
390_multioutConfig ()
391{
392 if [ "$outputs" = "out" ] || [ -z "${setOutputFlags-1}" ]; then
393 return;
394 fi;
395 if [ -z "$shareDocName" ]; then
396 local confScript="$configureScript";
397 if [ -z "$confScript" ] && [ -x ./configure ]; then
398 confScript=./configure;
399 fi;
400 if [ -f "$confScript" ]; then
401 local shareDocName="$(sed -n "s/^PACKAGE_TARNAME='\(.*\)'$/\1/p" < "$confScript")";
402 fi;
403 if [ -n "$shareDocName" ] || echo "$shareDocName" | grep -q '[^a-zA-Z0-9_-]'; then
404 shareDocName="$(echo "$name" | sed 's/-[^a-zA-Z].*//')";
405 fi;
406 fi;
407 configureFlags=" --bindir=${!outputBin}/bin --sbindir=${!outputBin}/sbin --includedir=${!outputInclude}/include --oldincludedir=${!outputInclude}/include --mandir=${!outputMan}/share/man --infodir=${!outputInfo}/share/info --docdir=${!outputDoc}/share/doc/${shareDocName} --libdir=${!outputLib}/lib --libexecdir=${!outputLib}/libexec --localedir=${!outputLib}/share/locale $configureFlags";
408 installFlags=" pkgconfigdir=${!outputDev}/lib/pkgconfig m4datadir=${!outputDev}/share/aclocal aclocaldir=${!outputDev}/share/aclocal $installFlags"
409}
410_multioutDevs ()
411{
412 if [ "$outputs" = "out" ] || [ -z "${moveToDev-1}" ]; then
413 return;
414 fi;
415 moveToOutput include "${!outputInclude}";
416 moveToOutput lib/pkgconfig "${!outputDev}";
417 moveToOutput share/pkgconfig "${!outputDev}";
418 moveToOutput lib/cmake "${!outputDev}";
419 moveToOutput share/aclocal "${!outputDev}";
420 for f in "${!outputDev}"/{lib,share}/pkgconfig/*.pc;
421 do
422 echo "Patching '$f' includedir to output ${!outputInclude}";
423 sed -i "/^includedir=/s,=\${prefix},=${!outputInclude}," "$f";
424 done
425}
426_multioutDocs ()
427{
428 local REMOVE=REMOVE;
429 moveToOutput share/info "${!outputInfo}";
430 moveToOutput share/doc "${!outputDoc}";
431 moveToOutput share/gtk-doc "${!outputDevdoc}";
432 moveToOutput share/devhelp/books "${!outputDevdoc}";
433 moveToOutput share/man "${!outputMan}";
434 moveToOutput share/man/man3 "${!outputDevman}"
435}
436_multioutPropagateDev ()
437{
438 if [ "$outputs" = "out" ]; then
439 return;
440 fi;
441 local outputFirst;
442 for outputFirst in $outputs;
443 do
444 break;
445 done;
446 local propagaterOutput="$outputDev";
447 if [ -z "$propagaterOutput" ]; then
448 propagaterOutput="$outputFirst";
449 fi;
450 if [ -z "${propagatedBuildOutputs+1}" ]; then
451 local po_dirty="$outputBin $outputInclude $outputLib";
452 set +o pipefail;
453 propagatedBuildOutputs=`echo "$po_dirty" | tr -s ' ' '\n' | grep -v -F "$propagaterOutput" | sort -u | tr '\n' ' ' `;
454 set -o pipefail;
455 fi;
456 if [ -z "$propagatedBuildOutputs" ]; then
457 return;
458 fi;
459 mkdir -p "${!propagaterOutput}"/nix-support;
460 for output in $propagatedBuildOutputs;
461 do
462 echo -n " ${!output}" >> "${!propagaterOutput}"/nix-support/propagated-build-inputs;
463 done
464}
465_overrideFirst ()
466{
467 if [ -z "${!1-}" ]; then
468 _assignFirst "$@";
469 fi
470}
471_pruneLibtoolFiles ()
472{
473 if [ "${dontPruneLibtoolFiles-}" ] || [ ! -e "$prefix" ]; then
474 return;
475 fi;
476 find "$prefix" -type f -name '*.la' -exec grep -q '^# Generated by .*libtool' {} \; -exec grep -q "^old_library=''" {} \; -exec sed -i {} -e "/^dependency_libs='[^']/ c dependency_libs='' #pruned" \;
477}
478_updateSourceDateEpochFromSourceRoot ()
479{
480 if [ -n "$sourceRoot" ]; then
481 updateSourceDateEpoch "$sourceRoot";
482 fi
483}
484activatePackage ()
485{
486 local pkg="$1";
487 local -ri hostOffset="$2";
488 local -ri targetOffset="$3";
489 (( "$hostOffset" <= "$targetOffset" )) || exit -1;
490 if [ -f "$pkg" ]; then
491 source "$pkg";
492 fi;
493 if [[ ( -z "${strictDeps-}" || "$hostOffset" -le -1 ) && -d "$pkg/bin" ]]; then
494 addToSearchPath _PATH "$pkg/bin";
495 fi;
496 if [[ "$hostOffset" -eq 0 && -d "$pkg/bin" ]]; then
497 addToSearchPath _HOST_PATH "$pkg/bin";
498 fi;
499 if [[ -f "$pkg/nix-support/setup-hook" ]]; then
500 source "$pkg/nix-support/setup-hook";
501 fi
502}
503addEnvHooks ()
504{
505 local depHostOffset="$1";
506 shift;
507 local pkgHookVarsSlice="${pkgHookVarVars[$depHostOffset + 1]}[@]";
508 local pkgHookVar;
509 for pkgHookVar in "${!pkgHookVarsSlice}";
510 do
511 eval "${pkgHookVar}s"'+=("$@")';
512 done
513}
514addToSearchPath ()
515{
516 addToSearchPathWithCustomDelimiter ":" "$@"
517}
518addToSearchPathWithCustomDelimiter ()
519{
520 local delimiter="$1";
521 local varName="$2";
522 local dir="$3";
523 if [ -d "$dir" ]; then
524 export "${varName}=${!varName:+${!varName}${delimiter}}${dir}";
525 fi
526}
527auditTmpdir ()
528{
529 local dir="$1";
530 [ -e "$dir" ] || return 0;
531 header "checking for references to $TMPDIR/ in $dir...";
532 local i;
533 while IFS= read -r -d '' i; do
534 if [[ "$i" =~ .build-id ]]; then
535 continue;
536 fi;
537 if isELF "$i"; then
538 if {
539 printf :;
540 patchelf --print-rpath "$i"
541 } | grep -q -F ":$TMPDIR/"; then
542 echo "RPATH of binary $i contains a forbidden reference to $TMPDIR/";
543 exit 1;
544 fi;
545 fi;
546 if isScript "$i"; then
547 if [ -e "$(dirname "$i")/.$(basename "$i")-wrapped" ]; then
548 if grep -q -F "$TMPDIR/" "$i"; then
549 echo "wrapper script $i contains a forbidden reference to $TMPDIR/";
550 exit 1;
551 fi;
552 fi;
553 fi;
554 done < <(find "$dir" -type f -print0);
555 stopNest
556}
557bintoolsWrapper_addLDVars ()
558{
559 local role_post role_pre;
560 getHostRoleEnvHook;
561 if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then
562 export NIX_${role_pre}LDFLAGS+=" -L$1/lib64";
563 fi;
564 if [[ -d "$1/lib" ]]; then
565 local -a glob=($1/lib/lib*);
566 if [ "${#glob[*]}" -gt 0 ]; then
567 export NIX_${role_pre}LDFLAGS+=" -L$1/lib";
568 fi;
569 fi
570}
571buildPhase ()
572{
573 runHook preBuild;
574 : ${makeFlags=};
575 if [[ -z "$makeFlags" && -z "${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ]]; then
576 echo "no Makefile, doing nothing";
577 else
578 foundMakefile=1;
579 local flagsArray=(${enableParallelBuilding:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} SHELL=$SHELL $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} $buildFlags ${buildFlagsArray+"${buildFlagsArray[@]}"});
580 echoCmd 'build flags' "${flagsArray[@]}";
581 make ${makefile:+-f $makefile} "${flagsArray[@]}";
582 unset flagsArray;
583 fi;
584 runHook postBuild
585}
586ccWrapper_addCVars ()
587{
588 local role_post role_pre;
589 getHostRoleEnvHook;
590 if [ -d "$1/include" ]; then
591 export NIX_${role_pre}CFLAGS_COMPILE+=" -isystem $1/include";
592 fi;
593 if [ -d "$1/Library/Frameworks" ]; then
594 export NIX_${role_pre}CFLAGS_COMPILE+=" -iframework $1/Library/Frameworks";
595 fi
596}
597checkPhase ()
598{
599 runHook preCheck;
600 if [[ -z "${foundMakefile:-}" ]]; then
601 echo "no Makefile or custom buildPhase, doing nothing";
602 runHook postCheck;
603 return;
604 fi;
605 if [[ -z "${checkTarget:-}" ]]; then
606 if make -n ${makefile:+-f $makefile} check > /dev/null 2>&1; then
607 checkTarget=check;
608 else
609 if make -n ${makefile:+-f $makefile} test > /dev/null 2>&1; then
610 checkTarget=test;
611 fi;
612 fi;
613 fi;
614 if [[ -z "${checkTarget:-}" ]]; then
615 echo "no check/test target in ${makefile:-Makefile}, doing nothing";
616 else
617 local flagsArray=(${enableParallelChecking:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} SHELL=$SHELL $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} ${checkFlags:-VERBOSE=y} ${checkFlagsArray+"${checkFlagsArray[@]}"} ${checkTarget});
618 echoCmd 'check flags' "${flagsArray[@]}";
619 make ${makefile:+-f $makefile} "${flagsArray[@]}";
620 unset flagsArray;
621 fi;
622 runHook postCheck
623}
624closeNest ()
625{
626 true
627}
628compressManPages ()
629{
630 local dir="$1";
631 if [ -L "$dir"/share ] || [ -L "$dir"/share/man ] || [ ! -d "$dir/share/man" ]; then
632 return;
633 fi;
634 echo "gzipping man pages under $dir/share/man/";
635 find "$dir"/share/man/ -type f -a '!' -regex '.*\.\(bz2\|gz\)$' -print0 | while IFS= read -r -d '' f; do
636 if gzip -c -n "$f" > "$f".gz; then
637 rm "$f";
638 else
639 rm "$f".gz;
640 fi;
641 done;
642 find "$dir"/share/man/ -type l -a '!' -regex '.*\.\(bz2\|gz\)$' -print0 | while IFS= read -r -d '' f; do
643 local target;
644 target="$(readlink -f "$f")";
645 if [ -f "$target".gz ]; then
646 ln -sf "$target".gz "$f".gz && rm "$f";
647 fi;
648 done
649}
650configurePhase ()
651{
652 runHook preConfigure;
653 : ${configureScript=};
654 : ${configureFlags=};
655 if [[ -z "$configureScript" && -x ./configure ]]; then
656 configureScript=./configure;
657 fi;
658 if [ -z "${dontFixLibtool:-}" ]; then
659 local i;
660 find . -iname "ltmain.sh" -print0 | while IFS='' read -r -d '' i; do
661 echo "fixing libtool script $i";
662 fixLibtool "$i";
663 done;
664 fi;
665 if [[ -z "${dontAddPrefix:-}" && -n "$prefix" ]]; then
666 configureFlags="${prefixKey:---prefix=}$prefix $configureFlags";
667 fi;
668 if [ -z "${dontAddDisableDepTrack:-}" ]; then
669 if [ -f "$configureScript" ] && grep -q dependency-tracking "$configureScript"; then
670 configureFlags="--disable-dependency-tracking $configureFlags";
671 fi;
672 fi;
673 if [ -z "${dontDisableStatic:-}" ]; then
674 if [ -f "$configureScript" ] && grep -q enable-static "$configureScript"; then
675 configureFlags="--disable-static $configureFlags";
676 fi;
677 fi;
678 if [ -n "$configureScript" ]; then
679 local flagsArray=($configureFlags ${configureFlagsArray+"${configureFlagsArray[@]}"});
680 echoCmd 'configure flags' "${flagsArray[@]}";
681 $configureScript "${flagsArray[@]}";
682 unset flagsArray;
683 else
684 echo "no configure script, doing nothing";
685 fi;
686 runHook postConfigure
687}
688consumeEntire ()
689{
690 if IFS='' read -r -N 0 $1; then
691 echo "consumeEntire(): ERROR: Input null bytes, won't process" 1>&2;
692 return 1;
693 fi
694}
695distPhase ()
696{
697 runHook preDist;
698 local flagsArray=($distFlags ${distFlagsArray+"${distFlagsArray[@]}"} ${distTarget:-dist});
699 echo 'dist flags: %q' "${flagsArray[@]}";
700 make ${makefile:+-f $makefile} "${flagsArray[@]}";
701 if [ "${dontCopyDist:-0}" != 1 ]; then
702 mkdir -p "$out/tarballs";
703 cp -pvd ${tarballs:-*.tar.gz} "$out/tarballs";
704 fi;
705 runHook postDist
706}
707dumpVars ()
708{
709 if [ "${noDumpEnvVars:-0}" != 1 ]; then
710 export > "$NIX_BUILD_TOP/env-vars" || true;
711 fi
712}
713echoCmd ()
714{
715 printf "%s:" "$1";
716 shift;
717 printf ' %q' "$@";
718 echo
719}
720exitHandler ()
721{
722 exitCode="$?";
723 set +e;
724 if [ -n "${showBuildStats:-}" ]; then
725 times > "$NIX_BUILD_TOP/.times";
726 local -a times=($(cat "$NIX_BUILD_TOP/.times"));
727 echo "build time elapsed: " "${times[@]}";
728 fi;
729 if (( "$exitCode" != 0 )); then
730 runHook failureHook;
731 if [ -n "${succeedOnFailure:-}" ]; then
732 echo "build failed with exit code $exitCode (ignored)";
733 mkdir -p "$out/nix-support";
734 printf "%s" "$exitCode" > "$out/nix-support/failed";
735 exit 0;
736 fi;
737 else
738 runHook exitHook;
739 fi;
740 exit "$exitCode"
741}
742findInputs ()
743{
744 local -r pkg="$1";
745 local -ri hostOffset="$2";
746 local -ri targetOffset="$3";
747 (( "$hostOffset" <= "$targetOffset" )) || exit -1;
748 local varVar="${pkgAccumVarVars[$hostOffset + 1]}";
749 local varRef="$varVar[\$targetOffset - \$hostOffset]";
750 local var="${!varRef}";
751 unset -v varVar varRef;
752 local varSlice="$var[*]";
753 case "${!varSlice-}" in
754 *" $pkg "*)
755 return 0
756 ;;
757 esac;
758 unset -v varSlice;
759 eval "$var"'+=("$pkg")';
760 if ! [ -e "$pkg" ]; then
761 echo "build input $pkg does not exist" 1>&2;
762 exit 1;
763 fi;
764 local -i mapOffsetResult;
765 function mapOffset ()
766 {
767 local -ri inputOffset="$1";
768 if (( "$inputOffset" <= 0 )); then
769 local -ri outputOffset="$inputOffset + $hostOffset";
770 else
771 local -ri outputOffset="$inputOffset - 1 + $targetOffset";
772 fi;
773 mapOffsetResult="$outputOffset"
774 };
775 local -i relHostOffset;
776 for relHostOffset in "${allPlatOffsets[@]}";
777 do
778 local files="${propagatedDepFilesVars[$relHostOffset + 1]}";
779 mapOffset relHostOffset;
780 local -i hostOffsetNext="$mapOffsetResult";
781 [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"* ]] || continue;
782 local -i relTargetOffset;
783 for relTargetOffset in "${allPlatOffsets[@]}";
784 do
785 (( "$relHostOffset" <= "$relTargetOffset" )) || continue;
786 local fileRef="${files}[$relTargetOffset - $relHostOffset]";
787 local file="${!fileRef}";
788 unset -v fileRef;
789 mapOffset relTargetOffset;
790 local -i targetOffsetNext="$mapOffsetResult";
791 [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]] || continue;
792 [[ -f "$pkg/nix-support/$file" ]] || continue;
793 local pkgNext;
794 read -r -d '' pkgNext < "$pkg/nix-support/$file" || true;
795 for pkgNext in $pkgNext;
796 do
797 findInputs "$pkgNext" "$hostOffsetNext" "$targetOffsetNext";
798 done;
799 done;
800 done
801}
802fixLibtool ()
803{
804 sed -i -e 's^eval sys_lib_.*search_path=.*^^' "$1"
805}
806fixupPhase ()
807{
808 local output;
809 for output in $outputs;
810 do
811 if [ -e "${!output}" ]; then
812 chmod -R u+w "${!output}";
813 fi;
814 done;
815 runHook preFixup;
816 local output;
817 for output in $outputs;
818 do
819 prefix="${!output}" runHook fixupOutput;
820 done;
821 declare -ra flatVars=(depsBuildBuildPropagated propagatedNativeBuildInputs depsBuildTargetPropagated depsHostHostPropagated propagatedBuildInputs depsTargetTargetPropagated);
822 declare -ra flatFiles=("${propagatedBuildDepFiles[@]}" "${propagatedHostDepFiles[@]}" "${propagatedTargetDepFiles[@]}");
823 local propagatedInputsIndex;
824 for propagatedInputsIndex in "${!flatVars[@]}";
825 do
826 local propagatedInputsSlice="${flatVars[$propagatedInputsIndex]}[@]";
827 local propagatedInputsFile="${flatFiles[$propagatedInputsIndex]}";
828 [[ -n "${!propagatedInputsSlice}" ]] || continue;
829 mkdir -p "${!outputDev}/nix-support";
830 printWords ${!propagatedInputsSlice} > "${!outputDev}/nix-support/$propagatedInputsFile";
831 done;
832 if [ -n "${setupHook:-}" ]; then
833 mkdir -p "${!outputDev}/nix-support";
834 substituteAll "$setupHook" "${!outputDev}/nix-support/setup-hook";
835 fi;
836 if [ -n "${setupHooks:-}" ]; then
837 mkdir -p "${!outputDev}/nix-support";
838 local hook;
839 for hook in $setupHooks;
840 do
841 local content;
842 consumeEntire content < "$hook";
843 substituteAllStream content "file '$hook'" >> "${!outputDev}/nix-support/setup-hook";
844 unset -v content;
845 done;
846 unset -v hook;
847 fi;
848 if [ -n "${propagatedUserEnvPkgs:-}" ]; then
849 mkdir -p "${!outputBin}/nix-support";
850 printWords $propagatedUserEnvPkgs > "${!outputBin}/nix-support/propagated-user-env-packages";
851 fi;
852 runHook postFixup
853}
854genericBuild ()
855{
856 if [ -f "${buildCommandPath:-}" ]; then
857 source "$buildCommandPath";
858 return;
859 fi;
860 if [ -n "${buildCommand:-}" ]; then
861 eval "$buildCommand";
862 return;
863 fi;
864 if [ -z "${phases:-}" ]; then
865 phases="${prePhases:-} unpackPhase patchPhase ${preConfigurePhases:-} configurePhase ${preBuildPhases:-} buildPhase checkPhase ${preInstallPhases:-} installPhase ${preFixupPhases:-} fixupPhase installCheckPhase ${preDistPhases:-} distPhase ${postPhases:-}";
866 fi;
867 for curPhase in $phases;
868 do
869 if [[ "$curPhase" = unpackPhase && -n "${dontUnpack:-}" ]]; then
870 continue;
871 fi;
872 if [[ "$curPhase" = configurePhase && -n "${dontConfigure:-}" ]]; then
873 continue;
874 fi;
875 if [[ "$curPhase" = buildPhase && -n "${dontBuild:-}" ]]; then
876 continue;
877 fi;
878 if [[ "$curPhase" = checkPhase && -z "${doCheck:-}" ]]; then
879 continue;
880 fi;
881 if [[ "$curPhase" = installPhase && -n "${dontInstall:-}" ]]; then
882 continue;
883 fi;
884 if [[ "$curPhase" = fixupPhase && -n "${dontFixup:-}" ]]; then
885 continue;
886 fi;
887 if [[ "$curPhase" = installCheckPhase && -z "${doInstallCheck:-}" ]]; then
888 continue;
889 fi;
890 if [[ "$curPhase" = distPhase && -z "${doDist:-}" ]]; then
891 continue;
892 fi;
893 if [[ -n $NIX_LOG_FD ]]; then
894 echo "@nix { \"action\": \"setPhase\", \"phase\": \"$curPhase\" }" 1>&$NIX_LOG_FD;
895 fi;
896 showPhaseHeader "$curPhase";
897 dumpVars;
898 eval "${!curPhase:-$curPhase}";
899 if [ "$curPhase" = unpackPhase ]; then
900 cd "${sourceRoot:-.}";
901 fi;
902 done
903}
904getHostRole ()
905{
906 getRole "$hostOffset"
907}
908getHostRoleEnvHook ()
909{
910 getRole "$depHostOffset"
911}
912getRole ()
913{
914 case $1 in
915 -1)
916 role_pre='BUILD_';
917 role_post='_FOR_BUILD'
918 ;;
919 0)
920 role_pre='';
921 role_post=''
922 ;;
923 1)
924 role_pre='TARGET_';
925 role_post='_FOR_TARGET'
926 ;;
927 *)
928 echo "binutils-wrapper-2.31.1: used as improper sort of dependency" > 2;
929 return 1
930 ;;
931 esac
932}
933getTargetRole ()
934{
935 getRole "$targetOffset"
936}
937getTargetRoleEnvHook ()
938{
939 getRole "$depTargetOffset"
940}
941getTargetRoleWrapper ()
942{
943 case $targetOffset in
944 -1)
945 export NIX_BINTOOLS_WRAPPER_x86_64_unknown_linux_gnu_TARGET_BUILD=1
946 ;;
947 0)
948 export NIX_BINTOOLS_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST=1
949 ;;
950 1)
951 export NIX_BINTOOLS_WRAPPER_x86_64_unknown_linux_gnu_TARGET_TARGET=1
952 ;;
953 *)
954 echo "binutils-wrapper-2.31.1: used as improper sort of dependency" > 2;
955 return 1
956 ;;
957 esac
958}
959header ()
960{
961 echo "$1"
962}
963installCheckPhase ()
964{
965 runHook preInstallCheck;
966 if [[ -z "${foundMakefile:-}" ]]; then
967 echo "no Makefile or custom buildPhase, doing nothing";
968 else
969 if [[ -z "${installCheckTarget:-}" ]] && ! make -n ${makefile:+-f $makefile} ${installCheckTarget:-installcheck} > /dev/null 2>&1; then
970 echo "no installcheck target in ${makefile:-Makefile}, doing nothing";
971 else
972 local flagsArray=(${enableParallelChecking:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} SHELL=$SHELL $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} $installCheckFlags ${installCheckFlagsArray+"${installCheckFlagsArray[@]}"} ${installCheckTarget:-installcheck});
973 echoCmd 'installcheck flags' "${flagsArray[@]}";
974 make ${makefile:+-f $makefile} "${flagsArray[@]}";
975 unset flagsArray;
976 fi;
977 fi;
978 runHook postInstallCheck
979}
980installPhase ()
981{
982 runHook preInstall;
983 if [ -n "$prefix" ]; then
984 mkdir -p "$prefix";
985 fi;
986 local flagsArray=(SHELL=$SHELL $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} $installFlags ${installFlagsArray+"${installFlagsArray[@]}"} ${installTargets:-install});
987 echoCmd 'install flags' "${flagsArray[@]}";
988 make ${makefile:+-f $makefile} "${flagsArray[@]}";
989 unset flagsArray;
990 runHook postInstall
991}
992isELF ()
993{
994 local fn="$1";
995 local fd;
996 local magic;
997 exec {fd}< "$fn";
998 read -r -n 4 -u "$fd" magic;
999 exec {fd}>&-;
1000 if [ "$magic" = 'ELF' ]; then
1001 return 0;
1002 else
1003 return 1;
1004 fi
1005}
1006isScript ()
1007{
1008 local fn="$1";
1009 local fd;
1010 local magic;
1011 exec {fd}< "$fn";
1012 read -r -n 2 -u "$fd" magic;
1013 exec {fd}>&-;
1014 if [[ "$magic" =~ \#! ]]; then
1015 return 0;
1016 else
1017 return 1;
1018 fi
1019}
1020mapOffset ()
1021{
1022 local -ri inputOffset="$1";
1023 if (( "$inputOffset" <= 0 )); then
1024 local -ri outputOffset="$inputOffset + $hostOffset";
1025 else
1026 local -ri outputOffset="$inputOffset - 1 + $targetOffset";
1027 fi;
1028 mapOffsetResult="$outputOffset"
1029}
1030moveToOutput ()
1031{
1032 local patt="$1";
1033 local dstOut="$2";
1034 local output;
1035 for output in $outputs;
1036 do
1037 if [ "${!output}" = "$dstOut" ]; then
1038 continue;
1039 fi;
1040 local srcPath;
1041 for srcPath in "${!output}"/$patt;
1042 do
1043 if [ ! -e "$srcPath" ] && [ ! -L "$srcPath" ]; then
1044 continue;
1045 fi;
1046 if [ "$dstOut" = REMOVE ]; then
1047 echo "Removing $srcPath";
1048 rm -r "$srcPath";
1049 else
1050 local dstPath="$dstOut${srcPath#${!output}}";
1051 echo "Moving $srcPath to $dstPath";
1052 if [ -d "$dstPath" ] && [ -d "$srcPath" ]; then
1053 rmdir "$srcPath" --ignore-fail-on-non-empty;
1054 if [ -d "$srcPath" ]; then
1055 mv -t "$dstPath" "$srcPath"/*;
1056 rmdir "$srcPath";
1057 fi;
1058 else
1059 mkdir -p "$(readlink -m "$dstPath/..")";
1060 mv "$srcPath" "$dstPath";
1061 fi;
1062 fi;
1063 local srcParent="$(readlink -m "$srcPath/..")";
1064 if rmdir "$srcParent"; then
1065 echo "Removing empty $srcParent/ and (possibly) its parents";
1066 rmdir -p --ignore-fail-on-non-empty "$(readlink -m "$srcParent/..")" 2> /dev/null || true;
1067 fi;
1068 done;
1069 done
1070}
1071patchELF ()
1072{
1073 local dir="$1";
1074 [ -e "$dir" ] || return 0;
1075 header "shrinking RPATHs of ELF executables and libraries in $dir";
1076 local i;
1077 while IFS= read -r -d '' i; do
1078 if [[ "$i" =~ .build-id ]]; then
1079 continue;
1080 fi;
1081 if ! isELF "$i"; then
1082 continue;
1083 fi;
1084 echo "shrinking $i";
1085 patchelf --shrink-rpath "$i" || true;
1086 done < <(find "$dir" -type f -print0);
1087 stopNest
1088}
1089patchPhase ()
1090{
1091 runHook prePatch;
1092 for i in ${patches:-};
1093 do
1094 header "applying patch $i" 3;
1095 local uncompress=cat;
1096 case "$i" in
1097 *.gz)
1098 uncompress="gzip -d"
1099 ;;
1100 *.bz2)
1101 uncompress="bzip2 -d"
1102 ;;
1103 *.xz)
1104 uncompress="xz -d"
1105 ;;
1106 *.lzma)
1107 uncompress="lzma -d"
1108 ;;
1109 esac;
1110 $uncompress < "$i" 2>&1 | patch ${patchFlags:--p1};
1111 done;
1112 runHook postPatch
1113}
1114patchShebangs ()
1115{
1116 local pathName;
1117 if [ "$1" = "--host" ]; then
1118 pathName=HOST_PATH;
1119 shift;
1120 else
1121 if [ "$1" = "--build" ]; then
1122 pathName=PATH;
1123 shift;
1124 fi;
1125 fi;
1126 echo "patching script interpreter paths in $@";
1127 local f;
1128 local oldPath;
1129 local newPath;
1130 local arg0;
1131 local args;
1132 local oldInterpreterLine;
1133 local newInterpreterLine;
1134 if [ $# -eq 0 ]; then
1135 echo "No arguments supplied to patchShebangs" > 0;
1136 return 0;
1137 fi;
1138 local f;
1139 while IFS= read -r -d '' f; do
1140 isScript "$f" || continue;
1141 oldInterpreterLine=$(head -1 "$f" | tail -c+3);
1142 read -r oldPath arg0 args <<< "$oldInterpreterLine";
1143 if [ -z "$pathName" ]; then
1144 if [ -n "$strictDeps" ] && [[ "$f" = "$NIX_STORE"* ]]; then
1145 pathName=HOST_PATH;
1146 else
1147 pathName=PATH;
1148 fi;
1149 fi;
1150 if $(echo "$oldPath" | grep -q "/bin/env$"); then
1151 if $(echo "$arg0" | grep -q -- "^-.*\|.*=.*"); then
1152 echo "$f: unsupported interpreter directive \"$oldInterpreterLine\" (set dontPatchShebangs=1 and handle shebang patching yourself)" > 0;
1153 exit 1;
1154 fi;
1155 newPath="$(PATH="${!pathName}" command -v "$arg0" || true)";
1156 else
1157 if [ "$oldPath" = "" ]; then
1158 oldPath="/bin/sh";
1159 fi;
1160 newPath="$(PATH="${!pathName}" command -v "$(basename "$oldPath")" || true)";
1161 args="$arg0 $args";
1162 fi;
1163 newInterpreterLine="$(echo "$newPath $args" | sed 's/[[:space:]]*$//')";
1164 if [ -n "$oldPath" -a "${oldPath:0:${#NIX_STORE}}" != "$NIX_STORE" ]; then
1165 if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
1166 echo "$f: interpreter directive changed from \"$oldInterpreterLine\" to \"$newInterpreterLine\"";
1167 escapedInterpreterLine=$(echo "$newInterpreterLine" | sed 's|\\|\\\\|g');
1168 timestamp=$(mktemp);
1169 touch -r "$f" "$timestamp";
1170 sed -i -e "1 s|.*|#\!$escapedInterpreterLine|" "$f";
1171 touch -r "$timestamp" "$f";
1172 rm "$timestamp";
1173 fi;
1174 fi;
1175 done < <(find "$@" -type f -perm -0100 -print0);
1176 stopNest
1177}
1178patchShebangsAuto ()
1179{
1180 if [ -z "${dontPatchShebangs-}" -a -e "$prefix" ]; then
1181 if [ "$output" != out ] && [ "$output" = "$outputDev" ]; then
1182 patchShebangs --build "$prefix";
1183 else
1184 patchShebangs --host "$prefix";
1185 fi;
1186 fi
1187}
1188printLines ()
1189{
1190 (( "$#" > 0 )) || return 0;
1191 printf '%s\n' "$@"
1192}
1193printWords ()
1194{
1195 (( "$#" > 0 )) || return 0;
1196 printf '%s ' "$@"
1197}
1198runHook ()
1199{
1200 local hookName="$1";
1201 shift;
1202 local hooksSlice="${hookName%Hook}Hooks[@]";
1203 local hook;
1204 for hook in "_callImplicitHook 0 $hookName" ${!hooksSlice+"${!hooksSlice}"};
1205 do
1206 _eval "$hook" "$@";
1207 done;
1208 return 0
1209}
1210runOneHook ()
1211{
1212 local hookName="$1";
1213 shift;
1214 local hooksSlice="${hookName%Hook}Hooks[@]";
1215 local hook ret=1;
1216 for hook in "_callImplicitHook 1 $hookName" ${!hooksSlice+"${!hooksSlice}"};
1217 do
1218 if _eval "$hook" "$@"; then
1219 ret=0;
1220 break;
1221 fi;
1222 done;
1223 return "$ret"
1224}
1225showPhaseHeader ()
1226{
1227 local phase="$1";
1228 case "$phase" in
1229 unpackPhase)
1230 header "unpacking sources"
1231 ;;
1232 patchPhase)
1233 header "patching sources"
1234 ;;
1235 configurePhase)
1236 header "configuring"
1237 ;;
1238 buildPhase)
1239 header "building"
1240 ;;
1241 checkPhase)
1242 header "running tests"
1243 ;;
1244 installPhase)
1245 header "installing"
1246 ;;
1247 fixupPhase)
1248 header "post-installation fixup"
1249 ;;
1250 installCheckPhase)
1251 header "running install tests"
1252 ;;
1253 *)
1254 header "$phase"
1255 ;;
1256 esac
1257}
1258stopNest ()
1259{
1260 true
1261}
1262stripDirs ()
1263{
1264 local cmd="$1";
1265 local dirs="$2";
1266 local stripFlags="$3";
1267 local dirsNew=;
1268 local d;
1269 for d in ${dirs};
1270 do
1271 if [ -d "$prefix/$d" ]; then
1272 dirsNew="${dirsNew} $prefix/$d ";
1273 fi;
1274 done;
1275 dirs=${dirsNew};
1276 if [ -n "${dirs}" ]; then
1277 header "stripping (with command $cmd and flags $stripFlags) in$dirs";
1278 find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} $cmd $commonStripFlags $stripFlags 2> /dev/null || true;
1279 stopNest;
1280 fi
1281}
1282stripHash ()
1283{
1284 local strippedName casematchOpt=0;
1285 strippedName="$(basename -- "$1")";
1286 shopt -q nocasematch && casematchOpt=1;
1287 shopt -u nocasematch;
1288 if [[ "$strippedName" =~ ^[a-z0-9]{32}- ]]; then
1289 echo "${strippedName:33}";
1290 else
1291 echo "$strippedName";
1292 fi;
1293 if (( casematchOpt )); then
1294 shopt -s nocasematch;
1295 fi
1296}
1297substitute ()
1298{
1299 local input="$1";
1300 local output="$2";
1301 shift 2;
1302 if [ ! -f "$input" ]; then
1303 echo "substitute(): ERROR: file '$input' does not exist" 1>&2;
1304 return 1;
1305 fi;
1306 local content;
1307 consumeEntire content < "$input";
1308 if [ -e "$output" ]; then
1309 chmod +w "$output";
1310 fi;
1311 substituteStream content "file '$input'" "$@" > "$output"
1312}
1313substituteAll ()
1314{
1315 local input="$1";
1316 local output="$2";
1317 local -a args=();
1318 _allFlags;
1319 substitute "$input" "$output" "${args[@]}"
1320}
1321substituteAllInPlace ()
1322{
1323 local fileName="$1";
1324 shift;
1325 substituteAll "$fileName" "$fileName" "$@"
1326}
1327substituteAllStream ()
1328{
1329 local -a args=();
1330 _allFlags;
1331 substituteStream "$1" "$2" "${args[@]}"
1332}
1333substituteInPlace ()
1334{
1335 local fileName="$1";
1336 shift;
1337 substitute "$fileName" "$fileName" "$@"
1338}
1339substituteStream ()
1340{
1341 local var=$1;
1342 local description=$2;
1343 shift 2;
1344 while (( "$#" )); do
1345 case "$1" in
1346 --replace)
1347 pattern="$2";
1348 replacement="$3";
1349 shift 3;
1350 local savedvar;
1351 savedvar="${!var}";
1352 eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}';
1353 if [ "$pattern" != "$replacement" ]; then
1354 if [ "${!var}" == "$savedvar" ]; then
1355 echo "substituteStream(): WARNING: pattern '$pattern' doesn't match anything in $description" 1>&2;
1356 fi;
1357 fi
1358 ;;
1359 --subst-var)
1360 local varName="$2";
1361 shift 2;
1362 if ! [[ "$varName" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then
1363 echo "substituteStream(): ERROR: substitution variables must be valid Bash names, \"$varName\" isn't." 1>&2;
1364 return 1;
1365 fi;
1366 if [ -z ${!varName+x} ]; then
1367 echo "substituteStream(): ERROR: variable \$$varName is unset" 1>&2;
1368 return 1;
1369 fi;
1370 pattern="@$varName@";
1371 replacement="${!varName}";
1372 eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}'
1373 ;;
1374 --subst-var-by)
1375 pattern="@$2@";
1376 replacement="$3";
1377 eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}';
1378 shift 3
1379 ;;
1380 *)
1381 echo "substituteStream(): ERROR: Invalid command line argument: $1" 1>&2;
1382 return 1
1383 ;;
1384 esac;
1385 done;
1386 printf "%s" "${!var}"
1387}
1388unpackFile ()
1389{
1390 curSrc="$1";
1391 header "unpacking source archive $curSrc" 3;
1392 if ! runOneHook unpackCmd "$curSrc"; then
1393 echo "do not know how to unpack source archive $curSrc";
1394 exit 1;
1395 fi
1396}
1397unpackPhase ()
1398{
1399 runHook preUnpack;
1400 if [ -z "${srcs:-}" ]; then
1401 if [ -z "${src:-}" ]; then
1402 echo 'variable $src or $srcs should point to the source';
1403 exit 1;
1404 fi;
1405 srcs="$src";
1406 fi;
1407 local dirsBefore="";
1408 for i in *;
1409 do
1410 if [ -d "$i" ]; then
1411 dirsBefore="$dirsBefore $i ";
1412 fi;
1413 done;
1414 for i in $srcs;
1415 do
1416 unpackFile "$i";
1417 done;
1418 : ${sourceRoot=};
1419 if [ -n "${setSourceRoot:-}" ]; then
1420 runOneHook setSourceRoot;
1421 else
1422 if [ -z "$sourceRoot" ]; then
1423 for i in *;
1424 do
1425 if [ -d "$i" ]; then
1426 case $dirsBefore in
1427 *\ $i\ *)
1428
1429 ;;
1430 *)
1431 if [ -n "$sourceRoot" ]; then
1432 echo "unpacker produced multiple directories";
1433 exit 1;
1434 fi;
1435 sourceRoot="$i"
1436 ;;
1437 esac;
1438 fi;
1439 done;
1440 fi;
1441 fi;
1442 if [ -z "$sourceRoot" ]; then
1443 echo "unpacker appears to have produced no directories";
1444 exit 1;
1445 fi;
1446 echo "source root is $sourceRoot";
1447 if [ "${dontMakeSourcesWritable:-0}" != 1 ]; then
1448 chmod -R u+w -- "$sourceRoot";
1449 fi;
1450 runHook postUnpack
1451}
1452updateSourceDateEpoch ()
1453{
1454 local path="$1";
1455 local -a res=($(find "$path" -type f -not -newer "$NIX_BUILD_TOP/.." -printf '%T@ %p\0' | sort -n --zero-terminated | tail -n1 --zero-terminated | head -c -1));
1456 local time="${res[0]//\.[0-9]*/}";
1457 local newestFile="${res[1]}";
1458 if [ "${time:-0}" -gt "$SOURCE_DATE_EPOCH" ]; then
1459 echo "setting SOURCE_DATE_EPOCH to timestamp $time of file $newestFile";
1460 export SOURCE_DATE_EPOCH="$time";
1461 local now="$(date +%s)";
1462 if [ "$time" -gt $((now - 60)) ]; then
1463 echo "warning: file $newestFile may be generated; SOURCE_DATE_EPOCH may be non-deterministic";
1464 fi;
1465 fi
1466}
1467
1468export NIX_BUILD_TOP="$(mktemp -d --tmpdir nix-shell.XXXXXX)"
1469export TMP="$NIX_BUILD_TOP"
1470export TMPDIR="$NIX_BUILD_TOP"
1471export TEMP="$NIX_BUILD_TOP"
1472export TEMPDIR="$NIX_BUILD_TOP"
1473eval "$shellHook"
diff --git a/frontend/elm-stuff/0.19.1/Cart.elmi b/frontend/elm-stuff/0.19.1/Cart.elmi
new file mode 100644
index 0000000..60bb740
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Cart.elmi
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Cart.elmo b/frontend/elm-stuff/0.19.1/Cart.elmo
new file mode 100644
index 0000000..0500a15
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Cart.elmo
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Catalog.elmi b/frontend/elm-stuff/0.19.1/Catalog.elmi
new file mode 100644
index 0000000..0610f11
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Catalog.elmi
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Catalog.elmo b/frontend/elm-stuff/0.19.1/Catalog.elmo
new file mode 100644
index 0000000..c5146fc
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Catalog.elmo
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Login.elmi b/frontend/elm-stuff/0.19.1/Login.elmi
new file mode 100644
index 0000000..75c4629
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Login.elmi
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Login.elmo b/frontend/elm-stuff/0.19.1/Login.elmo
new file mode 100644
index 0000000..9a173e3
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Login.elmo
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Main.elmi b/frontend/elm-stuff/0.19.1/Main.elmi
new file mode 100644
index 0000000..295ad17
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Main.elmi
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Main.elmo b/frontend/elm-stuff/0.19.1/Main.elmo
new file mode 100644
index 0000000..0dc3269
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Main.elmo
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Product.elmi b/frontend/elm-stuff/0.19.1/Product.elmi
new file mode 100644
index 0000000..396a174
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Product.elmi
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Product.elmo b/frontend/elm-stuff/0.19.1/Product.elmo
new file mode 100644
index 0000000..c387bed
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Product.elmo
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Signup.elmi b/frontend/elm-stuff/0.19.1/Signup.elmi
new file mode 100644
index 0000000..190d9de
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Signup.elmi
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/Signup.elmo b/frontend/elm-stuff/0.19.1/Signup.elmo
new file mode 100644
index 0000000..bcdb43d
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/Signup.elmo
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/d.dat b/frontend/elm-stuff/0.19.1/d.dat
new file mode 100644
index 0000000..244afff
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/d.dat
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/i.dat b/frontend/elm-stuff/0.19.1/i.dat
new file mode 100644
index 0000000..d1d1ac1
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/i.dat
Binary files differ
diff --git a/frontend/elm-stuff/0.19.1/lock b/frontend/elm-stuff/0.19.1/lock
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/lock
diff --git a/frontend/elm-stuff/0.19.1/o.dat b/frontend/elm-stuff/0.19.1/o.dat
new file mode 100644
index 0000000..f25f55b
--- /dev/null
+++ b/frontend/elm-stuff/0.19.1/o.dat
Binary files differ
diff --git a/frontend/elm.json b/frontend/elm.json
new file mode 100644
index 0000000..64ee788
--- /dev/null
+++ b/frontend/elm.json
@@ -0,0 +1,27 @@
1{
2 "type": "application",
3 "source-directories": [
4 "src"
5 ],
6 "elm-version": "0.19.1",
7 "dependencies": {
8 "direct": {
9 "elm/browser": "1.0.2",
10 "elm/core": "1.0.5",
11 "elm/html": "1.0.0",
12 "elm/http": "2.0.0",
13 "elm/json": "1.1.3",
14 "elm/url": "1.0.0"
15 },
16 "indirect": {
17 "elm/bytes": "1.0.8",
18 "elm/file": "1.0.5",
19 "elm/time": "1.0.0",
20 "elm/virtual-dom": "1.0.2"
21 }
22 },
23 "test-dependencies": {
24 "direct": {},
25 "indirect": {}
26 }
27}
diff --git a/frontend/src/Cart.elm b/frontend/src/Cart.elm
new file mode 100644
index 0000000..a1750f6
--- /dev/null
+++ b/frontend/src/Cart.elm
@@ -0,0 +1,164 @@
1module Cart exposing (..)
2
3import Browser
4import Browser.Navigation as Nav
5import Html exposing (..)
6import Html.Attributes exposing (..)
7import Html.Events exposing (..)
8import Http
9import Json.Decode as D
10import Json.Encode as Encode
11import Url
12import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
13
14
15type alias Product =
16 { id : Int
17 , name : String
18 , kind : Maybe String
19 , price : Float
20 , description : Maybe String
21 }
22
23
24type alias Model =
25 { pageStatus : Status
26 , products : List Product
27 }
28
29
30type Status
31 = Loading
32 | Loaded
33 | NotLoaded
34
35
36type Msg
37 = CartLoaded (Result Http.Error (List Product))
38 | FetchCartItems
39 | RemoveFromCart Int
40 | CartItemRemoved (Result Http.Error ())
41
42
43init : Model
44init =
45 Model NotLoaded []
46
47
48update : Msg -> Model -> ( Model, Cmd Msg )
49update msg model =
50 case msg of
51 CartLoaded res ->
52 case res of
53 Ok s ->
54 ( { model | products = s, pageStatus = Loaded }, Cmd.none )
55
56 Err e ->
57 let
58 _ =
59 Debug.log "error" e
60 in
61 ( { model | pageStatus = NotLoaded }, Cmd.none )
62
63 RemoveFromCart id ->
64 ( model, removeProduct id )
65
66 CartItemRemoved _ ->
67 ( { model | pageStatus = Loading }, fetchCartItems )
68
69 FetchCartItems ->
70 ( { model | pageStatus = Loading }, fetchCartItems )
71
72
73decodeProduct : D.Decoder Product
74decodeProduct =
75 D.map5 Product
76 (D.field "id" D.int)
77 (D.field "name" D.string)
78 (D.field "kind" (D.nullable D.string))
79 (D.field "price" D.float)
80 (D.field "description" (D.nullable D.string))
81
82
83decodeResponse : D.Decoder (List Product)
84decodeResponse =
85 D.list decodeProduct
86
87
88removeProduct : Int -> Cmd Msg
89removeProduct id =
90 let
91 _ =
92 Debug.log "cart" "fetching cart items"
93 in
94 Http.riskyRequest
95 { method = "POST"
96 , headers = []
97 , url = "http://127.0.0.1:7878/cart/remove"
98 , body = Http.stringBody "application/json" <| String.fromInt id
99 , expect = Http.expectWhatever CartItemRemoved
100 , timeout = Nothing
101 , tracker = Nothing
102 }
103
104
105fetchCartItems : Cmd Msg
106fetchCartItems =
107 let
108 _ =
109 Debug.log "cart" "fetching cart items"
110 in
111 Http.riskyRequest
112 { method = "GET"
113 , headers = []
114 , url = "http://127.0.0.1:7878/cart/items"
115 , body = Http.emptyBody
116 , expect = Http.expectJson CartLoaded decodeResponse
117 , timeout = Nothing
118 , tracker = Nothing
119 }
120
121
122viewStatus : Status -> String
123viewStatus s =
124 case s of
125 Loading ->
126 "Loading"
127
128 Loaded ->
129 "Ready!"
130
131 NotLoaded ->
132 "Not loaded ..."
133
134
135viewProduct : Product -> Html Msg
136viewProduct p =
137 div []
138 [ text p.name
139 , div [] [ text <| Maybe.withDefault "" p.kind ]
140 , div [] [ text <| Maybe.withDefault "" p.description ]
141 , div [] [ text <| String.fromFloat p.price ]
142 , div [] [ button [ onClick (RemoveFromCart p.id) ] [ text "Remove" ] ]
143 , div [] [ a [ href ("/product/" ++ String.fromInt p.id) ] [ text "View Product" ] ]
144 ]
145
146
147view : Model -> Html Msg
148view model =
149 case model.pageStatus of
150 Loading ->
151 div [] [ text <| viewStatus Loading ]
152
153 _ ->
154 div []
155 [ let
156 cart =
157 List.map viewProduct model.products
158 in
159 if List.isEmpty cart then
160 text "No items in cart"
161
162 else
163 ul [] cart
164 ]
diff --git a/frontend/src/Catalog.elm b/frontend/src/Catalog.elm
new file mode 100644
index 0000000..80e5e38
--- /dev/null
+++ b/frontend/src/Catalog.elm
@@ -0,0 +1,125 @@
1module Catalog exposing (..)
2
3import Browser
4import Browser.Navigation as Nav
5import Html exposing (..)
6import Html.Attributes exposing (..)
7import Html.Events exposing (..)
8import Http
9import Json.Decode as D
10import Json.Encode as Encode
11import Url
12import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
13
14
15type alias Product =
16 { id : Int
17 , name : String
18 , kind : Maybe String
19 , price : Float
20 , description : Maybe String
21 }
22
23
24type alias Model =
25 { pageStatus : Status
26 , products : List Product
27 }
28
29
30type Status
31 = Loading
32 | Loaded
33 | NotLoaded
34
35
36type Msg
37 = ProductsLoaded (Result Http.Error (List Product))
38 | FetchProducts
39
40
41init : Model
42init =
43 Model NotLoaded []
44
45
46update : Msg -> Model -> ( Model, Cmd Msg )
47update msg model =
48 case msg of
49 ProductsLoaded res ->
50 case res of
51 Ok s ->
52 ( { model | products = s, pageStatus = Loaded }, Cmd.none )
53
54 Err e ->
55 let
56 _ =
57 Debug.log "error" e
58 in
59 ( { model | pageStatus = NotLoaded }, Cmd.none )
60
61 FetchProducts ->
62 ( { model | pageStatus = Loading }, fetchProducts )
63
64
65decodeProduct : D.Decoder Product
66decodeProduct =
67 D.map5 Product
68 (D.field "id" D.int)
69 (D.field "name" D.string)
70 (D.field "kind" (D.nullable D.string))
71 (D.field "price" D.float)
72 (D.field "description" (D.nullable D.string))
73
74
75decodeResponse : D.Decoder (List Product)
76decodeResponse =
77 D.list decodeProduct
78
79
80fetchProducts : Cmd Msg
81fetchProducts =
82 let
83 _ =
84 Debug.log "err" "fetching products"
85 in
86 Http.get
87 { url = "http://127.0.0.1:7878/product/catalog"
88 , expect = Http.expectJson ProductsLoaded decodeResponse
89 }
90
91
92viewStatus : Status -> String
93viewStatus s =
94 case s of
95 Loading ->
96 "Loading"
97
98 Loaded ->
99 "Ready!"
100
101 NotLoaded ->
102 "Not loaded ..."
103
104
105viewProduct : Product -> Html Msg
106viewProduct p =
107 div []
108 [ text p.name
109 , text <| Maybe.withDefault "" p.kind
110 , text <| Maybe.withDefault "" p.description
111 , text <| String.fromFloat p.price
112 , a [ href ("/product/" ++ String.fromInt p.id) ] [ text "View Product" ]
113 ]
114
115
116view : Model -> Html Msg
117view model =
118 case model.pageStatus of
119 Loading ->
120 div [] [ text <| viewStatus Loading ]
121
122 _ ->
123 div []
124 [ ul [] (List.map viewProduct model.products)
125 ]
diff --git a/frontend/src/Login.elm b/frontend/src/Login.elm
new file mode 100644
index 0000000..dd168f0
--- /dev/null
+++ b/frontend/src/Login.elm
@@ -0,0 +1,119 @@
1module Login exposing (..)
2
3import Browser
4import Browser.Navigation as Nav
5import Html exposing (..)
6import Html.Attributes exposing (..)
7import Html.Events exposing (..)
8import Http
9import Json.Encode as Encode
10import Url
11import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
12
13
14type alias Model =
15 { username : String
16 , password : String
17 , loginStatus : LoginStatus
18 }
19
20
21type LoginStatus
22 = NotLoggedIn
23 | LoggedIn
24 | InvalidLogin
25 | LoggingIn
26
27
28type Msg
29 = PassEntered String
30 | UserEntered String
31 | LoginPressed
32 | LoginSuccess (Result Http.Error ())
33 | LoginFail
34
35
36init : Model
37init =
38 Model "" "" NotLoggedIn
39
40
41update : Msg -> Model -> ( Model, Cmd Msg )
42update msg model =
43 case msg of
44 PassEntered s ->
45 ( { model | password = s }
46 , Cmd.none
47 )
48
49 UserEntered s ->
50 ( { model | username = s }
51 , Cmd.none
52 )
53
54 LoginPressed ->
55 ( { model | loginStatus = LoggingIn }, tryLogin model )
56
57 LoginSuccess res ->
58 case res of
59 Ok s ->
60 ( { model | loginStatus = LoggedIn }, Cmd.none )
61
62 Err e ->
63 ( { model | loginStatus = InvalidLogin }, Cmd.none )
64
65 LoginFail ->
66 ( { model | loginStatus = InvalidLogin }, Cmd.none )
67
68
69encodeLogin : Model -> Encode.Value
70encodeLogin model =
71 Encode.object
72 [ ( "username", Encode.string model.username )
73 , ( "password", Encode.string model.password )
74 ]
75
76
77tryLogin : Model -> Cmd Msg
78tryLogin model =
79 Http.riskyRequest
80 { method = "POST"
81 , headers = []
82 , url = "http://127.0.0.1:7878/user/login"
83 , body = model |> encodeLogin |> Http.jsonBody
84 , expect = Http.expectWhatever LoginSuccess
85 , timeout = Nothing
86 , tracker = Nothing
87 }
88
89
90viewStatus : LoginStatus -> String
91viewStatus ls =
92 case ls of
93 NotLoggedIn ->
94 "Not Logged In"
95
96 InvalidLogin ->
97 "Invalid Login"
98
99 LoggedIn ->
100 "Logged in!"
101
102 LoggingIn ->
103 "Logging In ..."
104
105
106viewInput : String -> String -> String -> (String -> msg) -> Html msg
107viewInput t p v toMsg =
108 input [ type_ t, placeholder p, value v, onInput toMsg ] []
109
110
111view : Model -> Html Msg
112view model =
113 div []
114 [ div [] [ viewInput "text" "Enter name here" model.username UserEntered ]
115 , div [] [ viewInput "password" "Password" model.password PassEntered ]
116 , div [] [ button [ onClick LoginPressed ] [ text "Login" ] ]
117 , div [] [ text (viewStatus model.loginStatus) ]
118 , div [] [ text "Don't have an account? ", a [ href "/signup" ] [ text "Register now!" ] ]
119 ]
diff --git a/frontend/src/Main.elm b/frontend/src/Main.elm
new file mode 100644
index 0000000..bf1583c
--- /dev/null
+++ b/frontend/src/Main.elm
@@ -0,0 +1,339 @@
1module Main exposing (Model, Msg(..), init, main, subscriptions, update, view, viewLink)
2
3import Browser
4import Browser.Navigation as Nav
5import Cart
6import Catalog
7import Html exposing (..)
8import Html.Attributes exposing (..)
9import Html.Events exposing (..)
10import Http
11import Json.Encode as Encode
12import Login
13import Product
14import Signup
15import Url
16import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
17
18
19
20-- MAIN
21
22
23main : Program () Model Msg
24main =
25 Browser.application
26 { init = init
27 , view = view
28 , update = update
29 , subscriptions = subscriptions
30 , onUrlChange = UrlChanged
31 , onUrlRequest = LinkClicked
32 }
33
34
35
36-- MODEL
37
38
39type Route
40 = LoginPage
41 | SignupPage
42 | HomePage
43 | CatalogPage
44 | CartPage
45 | ProductPage Int
46 | NotFoundPage
47
48
49parseRoute : Parser (Route -> a) a
50parseRoute =
51 oneOf
52 [ P.map LoginPage (P.s "login")
53 , P.map HomePage P.top
54 , P.map CatalogPage (P.s "catalog")
55 , P.map CartPage (P.s "cart")
56 , P.map SignupPage (P.s "signup")
57 , P.map ProductPage (P.s "product" </> P.int)
58
59 --, P.map ProductPage (P.s "product" </> int)
60 ]
61
62
63type alias Model =
64 { key : Nav.Key
65 , url : Url.Url
66 , location : Route
67 , loginModel : Login.Model
68 , catalogModel : Catalog.Model
69 , productModel : Product.Model
70 , signupModel : Signup.Model
71 , cartModel : Cart.Model
72 }
73
74
75init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
76init flags url key =
77 let
78 start =
79 HomePage
80
81 login =
82 Login.init
83
84 catalog =
85 Catalog.init
86
87 product =
88 Product.init
89
90 signup =
91 Signup.init
92
93 cart =
94 Cart.init
95 in
96 ( Model key url start login catalog product signup cart, Cmd.none )
97
98
99
100-- UPDATE
101
102
103type Msg
104 = LinkClicked Browser.UrlRequest
105 | UrlChanged Url.Url
106 | LoginMessage Login.Msg
107 | CatalogMessage Catalog.Msg
108 | ProductMessage Product.Msg
109 | SignupMessage Signup.Msg
110 | CartMessage Cart.Msg
111 | LogoutPressed
112 | LogoutSuccess (Result Http.Error ())
113
114
115update : Msg -> Model -> ( Model, Cmd Msg )
116update msg model =
117 case msg of
118 LinkClicked urlRequest ->
119 case urlRequest of
120 Browser.Internal url ->
121 ( model, Nav.pushUrl model.key (Url.toString url) )
122
123 Browser.External href ->
124 ( model, Nav.load href )
125
126 LogoutPressed ->
127 ( model, tryLogout )
128
129 LogoutSuccess _ ->
130 ( model, Nav.replaceUrl model.key "/login" )
131
132 UrlChanged url ->
133 let
134 parsedUrl =
135 P.parse parseRoute url
136 in
137 case parsedUrl of
138 Just CatalogPage ->
139 ( { model | location = CatalogPage }, Cmd.map CatalogMessage Catalog.fetchProducts )
140
141 Just (ProductPage id) ->
142 let
143 cmds =
144 List.map (Cmd.map ProductMessage)
145 [ Product.fetchListing id
146 , Product.fetchRatings id
147 ]
148 in
149 ( { model | location = ProductPage id }, Cmd.batch cmds )
150
151 Just CartPage ->
152 let
153 cmd =
154 Cmd.map CartMessage Cart.fetchCartItems
155 in
156 ( { model | location = CartPage }, cmd )
157
158 Just p ->
159 ( { model | location = p }, Cmd.none )
160
161 Nothing ->
162 ( { model | location = NotFoundPage }, Cmd.none )
163
164 LoginMessage lm ->
165 let
166 ( lmn, cmd ) =
167 Login.update lm model.loginModel
168
169 redir =
170 case lmn.loginStatus of
171 Login.LoggedIn ->
172 Nav.replaceUrl model.key "/catalog"
173
174 _ ->
175 Cmd.none
176 in
177 ( { model | loginModel = lmn }, Cmd.batch [ Cmd.map LoginMessage cmd, redir ] )
178
179 SignupMessage sm ->
180 let
181 ( smn, cmd ) =
182 Signup.update sm model.signupModel
183
184 redir =
185 case smn.status of
186 Signup.CreatedSuccessfully ->
187 Nav.replaceUrl model.key "/login"
188
189 _ ->
190 Cmd.none
191 in
192 ( { model | signupModel = smn }, Cmd.batch [ Cmd.map SignupMessage cmd, redir ] )
193
194 CatalogMessage cm ->
195 let
196 ( cmn, cmd ) =
197 Catalog.update cm model.catalogModel
198 in
199 ( { model | catalogModel = cmn }, Cmd.map CatalogMessage cmd )
200
201 CartMessage cm ->
202 let
203 ( cmn, cmd ) =
204 Cart.update cm model.cartModel
205 in
206 ( { model | cartModel = cmn }, Cmd.map CartMessage cmd )
207
208 ProductMessage pm ->
209 let
210 ( pmn, cmd ) =
211 Product.update pm model.productModel
212
213 redir =
214 case pm of
215 Product.AddToCartSuccess _ ->
216 Nav.replaceUrl model.key "/cart"
217
218 _ ->
219 Cmd.none
220 in
221 ( { model | productModel = pmn }, Cmd.batch [ Cmd.map ProductMessage cmd, redir ] )
222
223
224tryLogout : Cmd Msg
225tryLogout =
226 Http.riskyRequest
227 { method = "POST"
228 , headers = []
229 , url = "http://127.0.0.1:7878/user/logout"
230 , body = Http.emptyBody
231 , expect = Http.expectWhatever LogoutSuccess
232 , timeout = Nothing
233 , tracker = Nothing
234 }
235
236
237
238-- SUBSCRIPTIONS
239
240
241subscriptions : Model -> Sub Msg
242subscriptions _ =
243 Sub.none
244
245
246
247-- VIEW
248
249
250view : Model -> Browser.Document Msg
251view model =
252 case model.location of
253 LoginPage ->
254 { title = "Login"
255 , body = [ Html.map LoginMessage (Login.view model.loginModel) ]
256 }
257
258 SignupPage ->
259 { title = "Signup"
260 , body = [ Html.map SignupMessage (Signup.view model.signupModel) ]
261 }
262
263 HomePage ->
264 { title = "URL Interceptor"
265 , body =
266 [ text "The current URL is: "
267 , b [] [ text (Url.toString model.url) ]
268 , ul []
269 [ viewLink "/login"
270 , viewLink "/catalog"
271 , viewLink "/cart"
272 , viewLink "/signup"
273 ]
274 ]
275 }
276
277 NotFoundPage ->
278 { title = "404 - Not Found"
279 , body =
280 [ text "404 - Not Found"
281 , a [ href "/" ] [ text "Go back >" ]
282 ]
283 }
284
285 CatalogPage ->
286 { title = "Catalog"
287 , body = pageWrap model (Html.map CatalogMessage (Catalog.view model.catalogModel))
288 }
289
290 CartPage ->
291 { title = "Cart"
292 , body = pageWrap model (Html.map CartMessage (Cart.view model.cartModel))
293 }
294
295 ProductPage item ->
296 { title = "Product " ++ String.fromInt item
297 , body = pageWrap model (Html.map ProductMessage (Product.view model.productModel))
298 }
299
300
301viewHeader : Model -> Html Msg
302viewHeader model =
303 let
304 links =
305 [ ( "Home", "/" )
306 , ( "Catalog", "/catalog" )
307 , ( "Cart", "/cart" )
308 ]
309 in
310 div []
311 [ List.map
312 (\( name, loc ) ->
313 li []
314 [ a [ href loc ] [ text name ]
315 ]
316 )
317 links
318 ++ [ if model.loginModel.loginStatus /= Login.LoggedIn then
319 li [] [ a [ href "/login" ] [ text "Login" ] ]
320
321 else
322 button [ onClick LogoutPressed ] [ text "Logout" ]
323 ]
324 |> ul []
325 ]
326
327
328pageWrap : Model -> Html Msg -> List (Html Msg)
329pageWrap model page =
330 [ div []
331 [ viewHeader model
332 , page
333 ]
334 ]
335
336
337viewLink : String -> Html msg
338viewLink path =
339 li [] [ a [ href path ] [ text path ] ]
diff --git a/frontend/src/Product.elm b/frontend/src/Product.elm
new file mode 100644
index 0000000..0ea0ce1
--- /dev/null
+++ b/frontend/src/Product.elm
@@ -0,0 +1,302 @@
1module Product exposing (..)
2
3import Browser
4import Browser.Navigation as Nav
5import Html exposing (..)
6import Html.Attributes exposing (..)
7import Html.Events exposing (..)
8import Http
9import Json.Decode as D
10import Json.Encode as Encode
11import Url
12import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
13
14
15type SubmitStatus
16 = SubmitSuccess
17 | SubmitFail
18 | Submitting
19 | NotSubmitted
20
21
22type alias Product =
23 { id : Int
24 , name : String
25 , kind : Maybe String
26 , price : Float
27 , description : Maybe String
28 }
29
30
31emptyProduct =
32 Product -1 "" Nothing 0 Nothing
33
34
35type alias Rating =
36 { commentDate : String
37 , commentText : Maybe String
38 , customerName : String
39 , productName : String
40 , stars : Int
41 }
42
43
44type alias Model =
45 { pageStatus : Status
46 , listing : Product
47 , ratings : List Rating
48 , ratingStars : Int
49 , ratingText : String
50 , addRatingStatus : SubmitStatus
51 }
52
53
54type Status
55 = Loading
56 | Loaded
57 | NotLoaded
58
59
60type Msg
61 = ListingLoaded (Result Http.Error Product)
62 | RatingsLoaded (Result Http.Error (List Rating))
63 | FetchProduct Int
64 | FetchRatings Int
65 | AddRatingStars Int
66 | AddRatingComment String
67 | AddRatingPressed
68 | AddRatingSuccess (Result Http.Error ())
69 | AddRatingFail
70 | AddToCartSuccess (Result Http.Error ())
71 | AddToCartPressed
72
73
74init : Model
75init =
76 Model NotLoaded emptyProduct [] 0 "" NotSubmitted
77
78
79update : Msg -> Model -> ( Model, Cmd Msg )
80update msg model =
81 case msg of
82 ListingLoaded res ->
83 case res of
84 Ok s ->
85 ( { model | listing = s, pageStatus = Loaded }, Cmd.none )
86
87 Err e ->
88 let
89 _ =
90 Debug.log "error" e
91 in
92 ( { model | pageStatus = NotLoaded }, Cmd.none )
93
94 RatingsLoaded res ->
95 case res of
96 Ok s ->
97 ( { model | ratings = s, pageStatus = Loaded }, Cmd.none )
98
99 Err e ->
100 let
101 _ =
102 Debug.log "error" e
103 in
104 ( { model | pageStatus = NotLoaded }, Cmd.none )
105
106 FetchProduct id ->
107 ( { model | pageStatus = Loading }, fetchListing id )
108
109 FetchRatings id ->
110 ( { model | pageStatus = Loading }, fetchRatings id )
111
112 AddRatingStars i ->
113 ( { model | ratingStars = i }, Cmd.none )
114
115 AddRatingComment s ->
116 ( { model | ratingText = s }, Cmd.none )
117
118 AddRatingPressed ->
119 ( { model | addRatingStatus = Submitting }
120 , submitRating model
121 )
122
123 AddRatingSuccess res ->
124 case res of
125 Ok _ ->
126 ( { model | addRatingStatus = SubmitSuccess }, fetchRatings model.listing.id )
127
128 Err _ ->
129 ( { model | addRatingStatus = SubmitFail }, Cmd.none )
130
131 AddRatingFail ->
132 ( { model | addRatingStatus = SubmitFail }, Cmd.none )
133
134 AddToCartPressed ->
135 ( model, addToCart model )
136
137 AddToCartSuccess _ ->
138 ( model, Cmd.none )
139
140
141decodeProduct : D.Decoder Product
142decodeProduct =
143 D.map5 Product
144 (D.field "id" D.int)
145 (D.field "name" D.string)
146 (D.field "kind" (D.nullable D.string))
147 (D.field "price" D.float)
148 (D.field "description" (D.nullable D.string))
149
150
151decodeRating : D.Decoder Rating
152decodeRating =
153 D.map5 Rating
154 (D.field "comment_date" D.string)
155 (D.field "comment_text" (D.nullable D.string))
156 (D.field "customer_name" D.string)
157 (D.field "product_name" D.string)
158 (D.field "stars" D.int)
159
160
161decodeRatings : D.Decoder (List Rating)
162decodeRatings =
163 D.list decodeRating
164
165
166fetchListing : Int -> Cmd Msg
167fetchListing id =
168 let
169 _ =
170 Debug.log "err" <| "fetching listing " ++ String.fromInt id
171 in
172 Http.get
173 { url = "http://127.0.0.1:7878/product/" ++ String.fromInt id
174 , expect = Http.expectJson ListingLoaded decodeProduct
175 }
176
177
178fetchRatings : Int -> Cmd Msg
179fetchRatings id =
180 let
181 _ =
182 Debug.log "err" <| "fetching ratings " ++ String.fromInt id
183 in
184 Http.get
185 { url = "http://127.0.0.1:7878/product/reviews/" ++ String.fromInt id
186 , expect = Http.expectJson RatingsLoaded decodeRatings
187 }
188
189
190encodeRatingForm : Model -> Encode.Value
191encodeRatingForm model =
192 Encode.object
193 [ ( "product_id", Encode.int model.listing.id )
194 , ( "stars", Encode.int model.ratingStars )
195 , ( "comment_text", Encode.string model.ratingText )
196 ]
197
198
199submitRating : Model -> Cmd Msg
200submitRating model =
201 let
202 _ =
203 Debug.log "err" <| "submitting rating for" ++ String.fromInt model.listing.id
204 in
205 Http.riskyRequest
206 { method = "POST"
207 , headers = []
208 , url = "http://127.0.0.1:7878/rating/add"
209 , body = model |> encodeRatingForm |> Http.jsonBody
210 , expect = Http.expectWhatever AddRatingSuccess
211 , timeout = Nothing
212 , tracker = Nothing
213 }
214
215
216addToCart : Model -> Cmd Msg
217addToCart model =
218 let
219 _ =
220 Debug.log "err" <| "adding to cart: " ++ String.fromInt model.listing.id
221 in
222 Http.riskyRequest
223 { method = "POST"
224 , headers = []
225 , url = "http://127.0.0.1:7878/cart/add"
226 , body = Http.stringBody "applcation/json" <| String.fromInt <| model.listing.id
227 , expect = Http.expectWhatever AddToCartSuccess
228 , timeout = Nothing
229 , tracker = Nothing
230 }
231
232
233viewStatus : Status -> String
234viewStatus s =
235 case s of
236 Loading ->
237 "Loading"
238
239 Loaded ->
240 "Ready!"
241
242 NotLoaded ->
243 "Not loaded ..."
244
245
246viewProduct : Product -> Html Msg
247viewProduct p =
248 div []
249 [ text p.name
250 , text <| Maybe.withDefault "" p.kind
251 , text <| Maybe.withDefault "" p.description
252 , text <| String.fromFloat p.price
253 ]
254
255
256viewRating : Rating -> Html Msg
257viewRating r =
258 div []
259 [ text <| r.customerName ++ " posted on "
260 , text <| r.commentDate ++ " "
261 , text <| Maybe.withDefault "" r.commentText
262 , text <| " Stars: " ++ String.fromInt r.stars
263 ]
264
265
266viewInput : String -> String -> String -> (String -> msg) -> Html msg
267viewInput t p v toMsg =
268 input [ type_ t, placeholder p, value v, onInput toMsg ] []
269
270
271viewStars : Html Msg
272viewStars =
273 ul []
274 (List.map
275 (\i -> button [ onClick (AddRatingStars i) ] [ text <| String.fromInt i ])
276 [ 0, 1, 2, 3, 4, 5 ]
277 )
278
279
280view : Model -> Html Msg
281view model =
282 case model.pageStatus of
283 Loading ->
284 div [] [ text <| viewStatus Loading ]
285
286 _ ->
287 div []
288 [ div [] [ viewProduct model.listing ]
289 , ul [] (List.map viewRating model.ratings)
290 , div [] [ text "Add Rating: " ]
291 , div []
292 [ viewStars
293 , viewInput "text" "Enter Comment Text" model.ratingText AddRatingComment
294 , button [ onClick AddRatingPressed ] [ text "Submit Rating" ]
295 ]
296 , div []
297 [ button [ onClick AddToCartPressed ] [ text "Add To Cart" ]
298 ]
299 , div []
300 [ a [ href "/catalog" ] [ text "Back to catalog" ]
301 ]
302 ]
diff --git a/frontend/src/Signup.elm b/frontend/src/Signup.elm
new file mode 100644
index 0000000..6395b57
--- /dev/null
+++ b/frontend/src/Signup.elm
@@ -0,0 +1,194 @@
1module Signup exposing (..)
2
3import Browser
4import Browser.Navigation as Nav
5import Html exposing (..)
6import Html.Attributes exposing (..)
7import Html.Events exposing (..)
8import Http
9import Json.Encode as Encode
10import Url
11import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
12
13
14type alias Model =
15 { username : String
16 , password : String
17 , phoneNumber : String
18 , emailId : String
19 , address : Maybe String
20 , status : Status
21 }
22
23
24type Status
25 = UsernameTaken
26 | InvalidPhone
27 | InvalidEmail
28 | CreatedSuccessfully
29 | CreatingUser
30 | Empty
31
32
33type Msg
34 = UserEntered String
35 | PassEntered String
36 | PhoneEntered String
37 | EmailEntered String
38 | AddressEntered String
39 | CreatePressed
40 | CreationSuccess (Result Http.Error ())
41 | UsernameExists (Result Http.Error String)
42 | CreationFail
43
44
45init : Model
46init =
47 Model "" "" "" "" Nothing Empty
48
49
50update : Msg -> Model -> ( Model, Cmd Msg )
51update msg model =
52 case msg of
53 UserEntered s ->
54 ( { model | username = s }
55 , Cmd.none
56 )
57
58 PassEntered s ->
59 ( { model | password = s }
60 , Cmd.none
61 )
62
63 PhoneEntered s ->
64 let
65 status =
66 if String.length s /= 10 || (List.all (not << Char.isDigit) <| String.toList s) then
67 InvalidPhone
68
69 else
70 Empty
71 in
72 ( { model | phoneNumber = s, status = status }
73 , Cmd.none
74 )
75
76 EmailEntered s ->
77 let
78 status =
79 if not <| String.contains "@" s then
80 InvalidEmail
81
82 else
83 Empty
84 in
85 ( { model | emailId = s, status = status }
86 , Cmd.none
87 )
88
89 AddressEntered s ->
90 ( { model | address = Just s }
91 , Cmd.none
92 )
93
94 CreatePressed ->
95 ( { model | status = CreatingUser }, checkExists model )
96
97 CreationSuccess res ->
98 case res of
99 Ok _ ->
100 ( { model | status = CreatedSuccessfully }, Cmd.none )
101
102 Err _ ->
103 ( model, Cmd.none )
104
105 CreationFail ->
106 ( init, Cmd.none )
107
108 UsernameExists res ->
109 case res of
110 Ok "true" ->
111 ( { model | status = UsernameTaken }, Cmd.none )
112
113 Ok "false" ->
114 let
115 _ =
116 Debug.log "signup" "Hit create user ..."
117 in
118 ( { model | status = CreatingUser }, createUser model )
119
120 _ ->
121 ( model, Cmd.none )
122
123
124encodeCreateUser : Model -> Encode.Value
125encodeCreateUser model =
126 Encode.object
127 [ ( "username", Encode.string model.username )
128 , ( "password", Encode.string model.password )
129 , ( "phone_number", Encode.string model.phoneNumber )
130 , ( "email_id", Encode.string model.emailId )
131 , ( "address", Encode.string <| Maybe.withDefault "" model.address )
132 ]
133
134
135checkExists : Model -> Cmd Msg
136checkExists model =
137 Http.post
138 { url = "http://127.0.0.1:7878/user/existing"
139 , body = Http.stringBody "application/json" model.username
140 , expect = Http.expectString UsernameExists
141 }
142
143
144createUser : Model -> Cmd Msg
145createUser model =
146 Http.riskyRequest
147 { method = "POST"
148 , headers = []
149 , url = "http://127.0.0.1:7878/user/new"
150 , body = model |> encodeCreateUser |> Http.jsonBody
151 , expect = Http.expectWhatever CreationSuccess
152 , timeout = Nothing
153 , tracker = Nothing
154 }
155
156
157viewStatus : Status -> String
158viewStatus s =
159 case s of
160 UsernameTaken ->
161 "This username is taken!"
162
163 InvalidPhone ->
164 "Invalid phone number!"
165
166 InvalidEmail ->
167 "Invalid email address!"
168
169 CreatedSuccessfully ->
170 "User created successfully"
171
172 CreatingUser ->
173 "Creating user ..."
174
175 Empty ->
176 ""
177
178
179viewInput : String -> String -> String -> (String -> msg) -> Html msg
180viewInput t p v toMsg =
181 input [ type_ t, placeholder p, value v, onInput toMsg ] []
182
183
184view : Model -> Html Msg
185view model =
186 div []
187 [ viewInput "text" "Enter Username" model.username UserEntered
188 , viewInput "password" "Password" model.password PassEntered
189 , viewInput "text" "Email" model.emailId EmailEntered
190 , viewInput "text" "Enter your Phone number" model.phoneNumber PhoneEntered
191 , viewInput "text" "Enter Shipping address" (Maybe.withDefault "" model.address) AddressEntered
192 , button [ onClick CreatePressed ] [ text "Create" ]
193 , text (viewStatus model.status)
194 ]