pepr 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "!src/fixtures/**",
17
17
  "!dist/**/*.test.d.ts*"
18
18
  ],
19
- "version": "1.3.0",
19
+ "version": "2.0.0",
20
20
  "main": "dist/lib.js",
21
21
  "types": "dist/lib.d.ts",
22
22
  "scripts": {
@@ -50,28 +50,32 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@types/ramda": "0.32.0",
53
- "@typescript-eslint/eslint-plugin": "8.63.0",
54
- "@typescript-eslint/parser": "8.63.0",
55
- "commander": "14.0.3",
56
- "eslint": "9.39.4",
53
+ "@typescript-eslint/eslint-plugin": "8.66.0",
54
+ "@typescript-eslint/parser": "8.66.0",
55
+ "commander": "15.0.0",
56
+ "eslint": "^10.8.0",
57
57
  "express": "5.2.1",
58
58
  "fast-json-patch": "3.1.1",
59
+ "globals": "17.9.0",
59
60
  "http-status-codes": "^2.3.0",
60
61
  "json-pointer": "^0.6.2",
61
- "kubernetes-fluent-client": "3.11.10",
62
+ "kubernetes-fluent-client": "3.11.11",
62
63
  "pino": "10.3.1",
63
64
  "pino-pretty": "13.1.3",
64
65
  "prom-client": "15.1.3",
65
- "quicktype-core": "^23.2.6",
66
+ "quicktype-core": "^26.0.0",
66
67
  "ramda": "0.32.0"
67
68
  },
68
69
  "devDependencies": {
69
70
  "@commitlint/cli": "21.2.1",
70
71
  "@commitlint/config-conventional": "21.2.0",
72
+ "@eslint/eslintrc": "^3.3.6",
73
+ "@eslint/js": "^10.0.1",
71
74
  "@types/command-line-args": "^5.2.3",
72
75
  "@types/express": "5.0.6",
73
76
  "@types/json-pointer": "^1.0.34",
74
77
  "@types/json-schema": "^7.0.15",
78
+ "@types/ms": "^2.1.0",
75
79
  "@types/node": "^24.13.3",
76
80
  "@types/node-forge": "1.3.14",
77
81
  "@types/readable-stream": "^4.0.21",
@@ -79,26 +83,26 @@
79
83
  "@types/ws": "^8.18.1",
80
84
  "@vitest/coverage-v8": "^4.0.4",
81
85
  "fast-check": "^4.0.0",
82
- "globals": "^17.0.0",
83
86
  "husky": "^9.1.6",
84
- "js-yaml": "^4.1.0",
87
+ "js-yaml": "^5.2.1",
88
+ "ms": "^2.1.3",
89
+ "prettier": "^3.6.2",
85
90
  "selfsigned": "^5.5.0",
86
91
  "shellcheck": "^4.1.0",
87
92
  "tsx": "^4.20.3",
88
- "undici": "8.7.0",
93
+ "undici": "8.10.0",
89
94
  "vitest": "^4.0.4"
90
95
  },
91
96
  "overrides": {
92
- "brace-expansion": "^5.0.7",
93
- "ip-address": "^10.1.1",
97
+ "brace-expansion": "^5.0.9",
98
+ "ip-address": "^10.5.0",
94
99
  "tar": "^7.5.16",
95
- "fast-uri": "^3.1.4"
100
+ "fast-uri": "^3.1.5"
96
101
  },
97
102
  "peerDependencies": {
98
103
  "@types/prompts": "^2.4.9",
99
104
  "esbuild": "^0.28.0",
100
105
  "node-forge": "^1.4.0",
101
- "prettier": "^3.6.2",
102
106
  "prompts": "^2.4.2",
103
107
  "typescript": "^5.8.3",
104
108
  "uuid": "^13.0.0"
@@ -5,7 +5,6 @@ import { execFileSync } from "child_process";
5
5
  import { BuildOptions, analyzeMetafile } from "esbuild";
6
6
  import { basename, extname, resolve } from "path";
7
7
  import { dependencies } from "../init/templates";
8
- import { peprFormat } from "../format";
9
8
  import { watchForChanges } from "./build.helpers";
10
9
  import { PeprConfig, Reloader } from "../types";
11
10
  import { BuildContext } from "esbuild";
@@ -70,8 +69,6 @@ export async function buildModule(
70
69
  const { cfg, modulePath, path: loadedPath, uuid } = await loadModule(outputDir, entryPoint);
71
70
  const { format, path } = resolveFormatAndPath(embed, requestedFormat, loadedPath);
72
71
 
73
- await checkFormat();
74
-
75
72
  // Resolve node_modules folder (in support of npm workspaces!) and run tsc
76
73
  const npmRoot = execFileSync("npm", ["root"]).toString().trim();
77
74
  execFileSync(`${npmRoot}/.bin/tsc`, [
@@ -187,14 +184,3 @@ function handleModuleBuildError(e: BuildModuleResult): void {
187
184
  });
188
185
  }
189
186
  }
190
-
191
- async function checkFormat(): Promise<void> {
192
- const validFormat = await peprFormat(true);
193
-
194
- if (!validFormat) {
195
- console.info(
196
- "\x1b[33m%s\x1b[0m",
197
- "Formatting errors were found. The build will continue, but you may want to run `npx pepr format` to address any issues.",
198
- );
199
- }
200
- }
@@ -102,8 +102,8 @@ export default function (program: Command): void {
102
102
  )
103
103
  .addOption(
104
104
  new Option(
105
- "-I, --registry-info <registry/username>",
106
- "Provide the image registry and username for building and pushing a custom WASM container. Requires authentication. Conflicts with --custom-image and --registry. Builds and pushes `'<registry/username>/custom-pepr-controller:<current-version>'`.",
105
+ "-I, --registry-info <registry[/namespace]>",
106
+ "Provide the image registry (and optional namespace) for building and pushing a custom WASM container. Requires authentication. Conflicts with --custom-image and --registry. Builds and pushes `'<registry[/namespace]>/custom-pepr-controller:<current-version>'` (e.g. docker.io/myuser, localhost:5000).",
107
107
  ).conflicts(["customImage", "registry"]),
108
108
  )
109
109
  .option("-P, --with-pull-secret <name>", "Use image pull secret for controller Deployment.", "")
@@ -43,7 +43,13 @@ export type peprPackageJSON = {
43
43
  scripts: { "k3d-setup": string };
44
44
  dependencies: { pepr: string; undici: string };
45
45
  devDependencies: {
46
+ "@eslint/eslintrc": string;
47
+ "@eslint/js": string;
48
+ "@typescript-eslint/eslint-plugin": string;
49
+ "@typescript-eslint/parser": string;
46
50
  "@types/node": string;
51
+ eslint: string;
52
+ globals: string;
47
53
  typescript: string;
48
54
  };
49
55
  };
@@ -99,7 +105,13 @@ export function genPkgJSON(opts: InitOptions): peprPackageJSON {
99
105
  undici: "^7.0.1",
100
106
  },
101
107
  devDependencies: {
108
+ "@eslint/eslintrc": devDependencies["@eslint/eslintrc"],
109
+ "@eslint/js": devDependencies["@eslint/js"],
110
+ "@typescript-eslint/eslint-plugin": dependencies["@typescript-eslint/eslint-plugin"],
111
+ "@typescript-eslint/parser": dependencies["@typescript-eslint/parser"],
102
112
  "@types/node": devDependencies["@types/node"],
113
+ eslint: dependencies.eslint,
114
+ globals: dependencies.globals,
103
115
  typescript,
104
116
  },
105
117
  overrides: {
@@ -38,7 +38,7 @@ export async function createDir(dir: string): Promise<void> {
38
38
  } catch (err) {
39
39
  // The directory already exists
40
40
  if (err && (err as NodeJS.ErrnoException).code === "EEXIST") {
41
- throw new Error(`Directory ${dir} already exists`);
41
+ throw new Error(`Directory ${dir} already exists`, { cause: err });
42
42
  } else {
43
43
  throw err;
44
44
  }
package/src/cli.ts CHANGED
@@ -7,7 +7,6 @@ import { banner } from "./cli/banner";
7
7
  import build from "./cli/build";
8
8
  import deploy from "./cli/deploy";
9
9
  import dev from "./cli/dev";
10
- import format from "./cli/format";
11
10
  import monitor from "./cli/monitor";
12
11
  import init from "./cli/init/index";
13
12
  import uuid from "./cli/uuid";
@@ -58,7 +57,6 @@ build(program);
58
57
  deploy(program);
59
58
  dev(program);
60
59
  update(program);
61
- format(program);
62
60
  monitor(program);
63
61
  uuid(program);
64
62
  kfc(program);
@@ -320,7 +320,8 @@ export class Assets {
320
320
  );
321
321
  }
322
322
  } catch (err) {
323
- throw new Error(`Error generating helm chart: ${err.message}`);
323
+ const message = err instanceof Error ? err.message : String(err);
324
+ throw new Error(`Error generating helm chart: ${message}`, { cause: err });
324
325
  }
325
326
  };
326
327
  }
@@ -1,13 +1,28 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { KubernetesObject } from "@kubernetes/client-node";
4
+ import { KubernetesObject, V1Probe } from "@kubernetes/client-node";
5
5
  import { kind } from "kubernetes-fluent-client";
6
6
  import { gzipSync } from "zlib";
7
7
  import { secretOverLimit } from "../helpers";
8
8
  import { Assets, isAdmission, isWatcher, norWatchOrAdmission } from "./assets";
9
9
  import { genEnv } from "./environment";
10
10
 
11
+ function defaultProbe(): V1Probe {
12
+ return {
13
+ httpGet: {
14
+ path: "/healthz",
15
+ port: 3000,
16
+ scheme: "HTTPS",
17
+ },
18
+ initialDelaySeconds: 10,
19
+ periodSeconds: 10,
20
+ timeoutSeconds: 1,
21
+ successThreshold: 1,
22
+ failureThreshold: 3,
23
+ };
24
+ }
25
+
11
26
  /** Generate the pepr-system namespace */
12
27
  export function getNamespace(namespaceLabels?: Record<string, string>): KubernetesObject {
13
28
  if (namespaceLabels) {
@@ -95,30 +110,9 @@ export function getWatcher(
95
110
  image,
96
111
  imagePullPolicy: "IfNotPresent",
97
112
  args: ["/app/node_modules/pepr/dist/controller.js", hash],
98
- startupProbe: {
99
- httpGet: {
100
- path: "/healthz",
101
- port: 3000,
102
- scheme: "HTTPS",
103
- },
104
- initialDelaySeconds: 10,
105
- },
106
- readinessProbe: {
107
- httpGet: {
108
- path: "/healthz",
109
- port: 3000,
110
- scheme: "HTTPS",
111
- },
112
- initialDelaySeconds: 10,
113
- },
114
- livenessProbe: {
115
- httpGet: {
116
- path: "/healthz",
117
- port: 3000,
118
- scheme: "HTTPS",
119
- },
120
- initialDelaySeconds: 10,
121
- },
113
+ startupProbe: defaultProbe(),
114
+ readinessProbe: defaultProbe(),
115
+ livenessProbe: defaultProbe(),
122
116
  ports: [
123
117
  {
124
118
  containerPort: 3000,
@@ -246,30 +240,9 @@ export function getDeployment(
246
240
  image,
247
241
  imagePullPolicy: "IfNotPresent",
248
242
  args: ["/app/node_modules/pepr/dist/controller.js", hash],
249
- startupProbe: {
250
- httpGet: {
251
- path: "/healthz",
252
- port: 3000,
253
- scheme: "HTTPS",
254
- },
255
- initialDelaySeconds: 10,
256
- },
257
- readinessProbe: {
258
- httpGet: {
259
- path: "/healthz",
260
- port: 3000,
261
- scheme: "HTTPS",
262
- },
263
- initialDelaySeconds: 10,
264
- },
265
- livenessProbe: {
266
- httpGet: {
267
- path: "/healthz",
268
- port: 3000,
269
- scheme: "HTTPS",
270
- },
271
- initialDelaySeconds: 10,
272
- },
243
+ startupProbe: defaultProbe(),
244
+ readinessProbe: defaultProbe(),
245
+ livenessProbe: defaultProbe(),
273
246
  ports: [
274
247
  {
275
248
  containerPort: 3000,
@@ -27,19 +27,18 @@ export type ChartOverrides = {
27
27
  name: string;
28
28
  image: string;
29
29
  };
30
+ type Probe = {
31
+ httpGet: { path: string; port: number; scheme: "HTTPS" };
32
+ initialDelaySeconds: number;
33
+ periodSeconds: number;
34
+ timeoutSeconds: number;
35
+ successThreshold: number;
36
+ failureThreshold: number;
37
+ };
30
38
  type Probes = {
31
- startupProbe: {
32
- httpGet: { path: string; port: number; scheme: "HTTPS" };
33
- initialDelaySeconds: number;
34
- };
35
- readinessProbe: {
36
- httpGet: { path: string; port: number; scheme: "HTTPS" };
37
- initialDelaySeconds: number;
38
- };
39
- livenessProbe: {
40
- httpGet: { path: string; port: number; scheme: "HTTPS" };
41
- initialDelaySeconds: number;
42
- };
39
+ startupProbe: Probe;
40
+ readinessProbe: Probe;
41
+ livenessProbe: Probe;
43
42
  };
44
43
  type Resources = {
45
44
  requests: { memory: string; cpu: string };
@@ -207,18 +206,20 @@ function runIdsForImage(image: string): { uid: number; gid: number; fsGroup: num
207
206
 
208
207
  function commonProbes(): Probes {
209
208
  return {
210
- startupProbe: {
211
- httpGet: { path: "/healthz", port: 3000, scheme: "HTTPS" },
212
- initialDelaySeconds: 10,
213
- },
214
- readinessProbe: {
215
- httpGet: { path: "/healthz", port: 3000, scheme: "HTTPS" },
216
- initialDelaySeconds: 10,
217
- },
218
- livenessProbe: {
219
- httpGet: { path: "/healthz", port: 3000, scheme: "HTTPS" },
220
- initialDelaySeconds: 10,
221
- },
209
+ startupProbe: defaultProbe(),
210
+ readinessProbe: defaultProbe(),
211
+ livenessProbe: defaultProbe(),
212
+ };
213
+ }
214
+
215
+ function defaultProbe(): Probe {
216
+ return {
217
+ httpGet: { path: "/healthz", port: 3000, scheme: "HTTPS" },
218
+ initialDelaySeconds: 10,
219
+ periodSeconds: 10,
220
+ timeoutSeconds: 1,
221
+ successThreshold: 1,
222
+ failureThreshold: 3,
222
223
  };
223
224
  }
224
225
 
@@ -51,6 +51,6 @@ export async function migrateAndSetupWatch(storeData: StoreMigration): Promise<v
51
51
  }
52
52
  }
53
53
  }
54
- storeCache = await sendUpdatesAndFlushCache(storeCache, namespace, name);
54
+ await sendUpdatesAndFlushCache(storeCache, namespace, name);
55
55
  setupWatch();
56
56
  }
@@ -184,8 +184,7 @@ const matchRegexToCapababilityNamespace = (
184
184
  capabilityNamespaces.length > 0
185
185
  ) {
186
186
  for (const regexNamespace of bindingRegexNamespaces) {
187
- let matches = false;
188
- matches =
187
+ const matches =
189
188
  regexNamespace !== "" &&
190
189
  capabilityNamespaces.some(capabilityNamespace =>
191
190
  matchesRegex(regexNamespace, capabilityNamespace),
@@ -46,7 +46,7 @@ function runModule(expectedHash: string): void {
46
46
  // Run the module
47
47
  fork(jsPath);
48
48
  } catch (e) {
49
- throw new Error(`Failed to decompress module: ${e}`);
49
+ throw new Error(`Failed to decompress module: ${e}`, { cause: e });
50
50
  }
51
51
  }
52
52
 
@@ -1,3 +0,0 @@
1
- import { ESLint } from "eslint";
2
- export declare function formatWithPrettier(results: ESLint.LintResult[], validateOnly: boolean): Promise<boolean>;
3
- //# sourceMappingURL=format.helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"format.helpers.d.ts","sourceRoot":"","sources":["../../../src/cli/format/format.helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,EAC5B,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
@@ -1,9 +0,0 @@
1
- import { Command } from "commander";
2
- export default function (program: Command): void;
3
- /**
4
- * Perform linting and formatting on the module
5
- * @param validateOnly
6
- * @returns success
7
- */
8
- export declare function peprFormat(validateOnly: boolean): Promise<boolean>;
9
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/format/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,CAAC,OAAO,WAAW,OAAO,EAAE,OAAO,GAAG,IAAI,CAmB/C;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAoCxE"}
@@ -1,27 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- import { ESLint } from "eslint";
5
- import { promises as fs } from "fs";
6
- import { format, resolveConfig } from "prettier";
7
-
8
- export async function formatWithPrettier(
9
- results: ESLint.LintResult[],
10
- validateOnly: boolean,
11
- ): Promise<boolean> {
12
- let hasFailure = false;
13
- for (const { filePath } of results) {
14
- const content = await fs.readFile(filePath, "utf8");
15
- const cfg = await resolveConfig(filePath);
16
- const formatted = await format(content, { filepath: filePath, ...cfg });
17
-
18
- // If in validate-only mode, check if the file is formatted correctly
19
- if (validateOnly && formatted !== content) {
20
- hasFailure = true;
21
- console.error(`File ${filePath} is not formatted correctly`);
22
- } else {
23
- await fs.writeFile(filePath, formatted);
24
- }
25
- }
26
- return hasFailure;
27
- }
@@ -1,72 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- import { ESLint } from "eslint";
5
- import { formatWithPrettier } from "./format.helpers";
6
-
7
- import { Command } from "commander";
8
- import Log from "../../lib/telemetry/logger";
9
-
10
- export default function (program: Command): void {
11
- program
12
- .command("format")
13
- .description("Lint and format this Pepr module")
14
- .option("-v, --validate-only", "Do not modify files, only validate formatting.")
15
- .action(async opts => {
16
- Log.warn(
17
- "DEPRECATION NOTICE: The pepr format command will be removed in summer 2026. " +
18
- "Once removed, module authors must run a linter separately from the pepr CLI.",
19
- );
20
-
21
- const success = await peprFormat(opts.validateOnly);
22
-
23
- if (success) {
24
- Log.info("Module formatted");
25
- } else {
26
- process.exit(1);
27
- }
28
- });
29
- }
30
-
31
- /**
32
- * Perform linting and formatting on the module
33
- * @param validateOnly
34
- * @returns success
35
- */
36
- export async function peprFormat(validateOnly: boolean): Promise<boolean> {
37
- {
38
- try {
39
- const eslint = new ESLint();
40
- const results = await eslint.lintFiles(["./**/*.ts"]);
41
-
42
- // Track if any files failed
43
- let hasFailure = false;
44
-
45
- results.forEach(async result => {
46
- const errorCount = result.fatalErrorCount + result.errorCount;
47
- if (errorCount > 0) {
48
- hasFailure = true;
49
- }
50
- });
51
-
52
- const formatter = await eslint.loadFormatter("stylish");
53
- const resultText = await formatter.format(results, {} as ESLint.LintResultData);
54
-
55
- if (resultText) {
56
- Log.info(resultText);
57
- }
58
-
59
- // Write the fixes if not in validate-only mode
60
- if (!validateOnly) {
61
- await ESLint.outputFixes(results);
62
- }
63
-
64
- hasFailure = hasFailure || (await formatWithPrettier(results, validateOnly));
65
-
66
- return !hasFailure;
67
- } catch (error) {
68
- Log.error(error, `Error formatting module:`);
69
- return false;
70
- }
71
- }
72
- }