package builder import ( "context" "strings" "testing" ) // A module's own packages (dependencies.go): installed into its own directory, in the toolchain, // before the compile, so the bundler inlines them — the SDK always the toolchain's. func buildWithPackageJSON(t *testing.T, pkg string, extra map[string]string, registry Npmrc) (*recorded, error) { t.Helper() files := map[string]string{"index.ts": "console.log(1)"} if pkg != "" { files["package.json"] = pkg } for k, v := range extra { files[k] = v } r, workspace := aRepository(t, aBundle, files) held := map[string]string{"mesh-tools/build": "registry.invalid/mesh-tools/build@sha256:" + strings.Repeat("b", 64)} _, err := Build(context.Background(), compiling{r}.run, r, "https://forge.invalid/greeter.git", "", "", workspace, held, registry, GitCredential{}, nil) return r, err } func installs(r *recorded) []string { var out []string for _, line := range r.ran { if strings.HasPrefix(line, "docker run") && strings.Contains(line, "npm ci") { out = append(out, line) } } return out } func compileIndex(r *recorded) int { for i, line := range r.ran { if strings.Contains(line, "--outDir") { return i } } return -1 } func TestAModulesOwnPackagesAreInstalledInTheToolchainBeforeTheCompile(t *testing.T) { r, err := buildWithPackageJSON(t, `{"type":"module","dependencies":{"@novox/mesh-sdk":"^0.1.0","pg":"^8"},"devDependencies":{"typescript":"^5"}}`, nil, Npmrc{Scope: "@novox", Registry: "https://forge.invalid/api/packages/novox/npm"}) if err != nil { t.Fatal(err) } got := installs(r) if len(got) != 1 { t.Fatalf("want one install of the module's own packages:\n%s", strings.Join(r.ran, "\n")) } line := got[0] for _, want := range []string{ "mesh-tools/build@sha256:", // in the toolchain image ":/app/modules/module", // into the module's own directory "--workdir /app/modules/module", // npmCache + ":/root/.npm", // npm's verified download cache, and only that "--omit=dev", "--ignore-scripts", // production packages, no build-node scripts "npm ci", "npm install", "--no-package-lock", // the lockfile when there is one, else the ranges "--@novox:registry=https://forge.invalid/api/packages/novox/npm/", // the scope from the mesh's registry "--network host", "@novox/mesh-sdk", // named, to be taken out of what is installed } { if !strings.Contains(line, want) { t.Errorf("the install lacks %q:\n%s", want, line) } } // The SDK is the toolchain's: never installed from the module's range, and any copy removed. if !strings.Contains(line, `delete p[k][sdk]`) || !strings.Contains(line, `-path "*/node_modules/@novox/mesh-sdk" -exec rm -rf`) { t.Errorf("the module's own SDK range could shadow the toolchain's SDK:\n%s", line) } if i, c := strings.Index(strings.Join(r.ran, "\n"), "npm ci"), compileIndex(r); c < 0 || i > strings.Index(strings.Join(r.ran, "\n"), "--outDir") { t.Fatalf("the install did not run before the compile:\n%s", strings.Join(r.ran, "\n")) } } // **A module with nothing beyond the SDK builds exactly as before**: the same commands, no install. func TestAModuleDependingOnlyOnTheSDKBuildsExactlyAsBefore(t *testing.T) { without, err := buildWithPackageJSON(t, "", nil, Npmrc{}) if err != nil { t.Fatal(err) } for _, pkg := range []string{ `{"type":"module","dependencies":{"@novox/mesh-sdk":"^0.1.0"},"devDependencies":{"typescript":"^5"}}`, `{"type":"module"}`, } { with, err := buildWithPackageJSON(t, pkg, map[string]string{"package-lock.json": "{}"}, Npmrc{Scope: "@novox", Registry: "https://forge.invalid/npm/"}) if err != nil { t.Fatal(err) } if strings.Contains(strings.Join(with.ran, "\n"), "npm ") { t.Fatalf("a module depending on nothing but the SDK ran npm:\n%s", strings.Join(with.ran, "\n")) } if len(with.ran) != len(without.ran) { t.Fatalf("a module depending only on the SDK built differently from one with no package.json:\n%s\n---\n%s", strings.Join(with.ran, "\n"), strings.Join(without.ran, "\n")) } } } // Without the mesh's registry a scoped package would resolve on the public one: refused by name. func TestAScopedPackageWithNoRegistryIsRefused(t *testing.T) { r, err := buildWithPackageJSON(t, `{"dependencies":{"@novox/mesh-sdk":"^0.1.0","@novox/other":"^1"}}`, nil, Npmrc{}) if err == nil || !strings.Contains(err.Error(), "@novox/other") { t.Fatalf("a scoped package was installed with no registry for its scope: %v", err) } if strings.Contains(strings.Join(r.ran, "\n"), "--outDir") { t.Fatal("the compile ran after the refusal") } // A public package installs without one, from the public registry and nothing else. r, err = buildWithPackageJSON(t, `{"dependencies":{"mssql":"^11"}}`, nil, Npmrc{}) if err != nil { t.Fatal(err) } if got := installs(r); len(got) != 1 || strings.Contains(got[0], ":registry=") || strings.Contains(got[0], "--network host") { t.Fatalf("a public package's install: %v", got) } } func TestAnUnreadablePackageJSONIsRefusedByName(t *testing.T) { _, err := buildWithPackageJSON(t, `{"dependencies":`, nil, Npmrc{}) if err == nil || !strings.Contains(err.Error(), "package.json") { t.Fatalf("a broken package.json was not refused by name: %v", err) } }