@growthub/cli 0.3.44 → 0.3.45

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/README.md CHANGED
@@ -146,7 +146,7 @@ For the agent-facing extension workflow, see [docs/CLI_TEMPLATE_CONTRIBUTION_EXT
146
146
 
147
147
  ## Development Notes
148
148
 
149
- - `@growthub/cli` version: `0.3.44`
149
+ - `@growthub/cli` version: `0.3.45`
150
150
  - Node.js: `>=20`
151
151
  - Source of truth repo: [Growthub Local](https://github.com/Growthub-ai/growthub-local)
152
152
 
package/dist/index.js CHANGED
@@ -6657,9 +6657,9 @@ import pc2 from "picocolors";
6657
6657
  function printPaperclipCliBanner() {
6658
6658
  const lines = [
6659
6659
  "",
6660
- ...GROWTHUB_ART.map((line) => pc2.cyan(line)),
6661
- pc2.blue(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
6662
- pc2.bold(pc2.white(` ${TAGLINE}`)),
6660
+ ...GROWTHUB_ART,
6661
+ pc2.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
6662
+ pc2.bold(` ${TAGLINE}`),
6663
6663
  ""
6664
6664
  ];
6665
6665
  console.log(lines.join("\n"));
@@ -14727,7 +14727,7 @@ applyDataDirOverride(bootstrapOptions, {
14727
14727
  loadPaperclipEnvFile(bootstrapOptions.config);
14728
14728
  var bootstrapConfig = readConfig(resolveConfigPath(bootstrapOptions.config));
14729
14729
  var surfaceRuntime = initializeSurfaceRuntimeContract(resolveSurfaceProfile(bootstrapConfig) ?? void 0);
14730
- program.name("growthub").description("Growthub CLI \u2014 setup, configure, and run your local Growthub instance").version("0.3.43").addHelpText("after", `
14730
+ program.name("growthub").description("Growthub CLI \u2014 setup, configure, and run your local Growthub instance").version("0.3.45").addHelpText("after", `
14731
14731
  Worker Kits (agent execution environments):
14732
14732
 
14733
14733
  Discovery:
@@ -1,7 +1,5 @@
1
1
  import { Router } from "express";
2
2
  import multer from "multer";
3
- import createDOMPurify from "dompurify";
4
- import { JSDOM } from "jsdom";
5
3
  import { createAssetImageMetadataSchema } from "@paperclipai/shared";
6
4
  import { assetService, logActivity } from "../services/index.js";
7
5
  import { isAllowedContentType, MAX_ATTACHMENT_BYTES } from "../attachment-types.js";
@@ -15,53 +13,32 @@ const ALLOWED_COMPANY_LOGO_CONTENT_TYPES = new Set([
15
13
  "image/gif",
16
14
  SVG_CONTENT_TYPE,
17
15
  ]);
16
+ const DISALLOWED_SVG_TAGS = /<\/?\s*(script|foreignObject)\b[^>]*>/gi;
17
+ const DISALLOWED_SVG_BLOCKS = /<\s*(script|foreignObject)\b[^>]*>[\s\S]*?<\s*\/\s*\1\s*>/gi;
18
+ const XML_DECLARATIONS_AND_COMMENTS = /<\?(?:xml|[\s\S]*?)\?>|<!--[\s\S]*?-->|<!DOCTYPE[\s\S]*?>/gi;
19
+ const EVENT_HANDLER_ATTRS = /\s+on[\w:-]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi;
20
+ const STYLE_ATTRS = /\s+style\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi;
21
+ const HREF_ATTRS = /\s+(href|xlink:href)\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/gi;
22
+ const SVG_ROOT_PATTERN = /^<svg\b[\s\S]*<\/svg>$/i;
18
23
  function sanitizeSvgBuffer(input) {
19
24
  const raw = input.toString("utf8").trim();
20
25
  if (!raw)
21
26
  return null;
22
- const baseDom = new JSDOM("");
23
- const domPurify = createDOMPurify(baseDom.window);
24
- domPurify.addHook("uponSanitizeAttribute", (_node, data) => {
25
- const attrName = data.attrName.toLowerCase();
26
- const attrValue = (data.attrValue ?? "").trim();
27
- if (attrName.startsWith("on")) {
28
- data.keepAttr = false;
29
- return;
30
- }
31
- if ((attrName === "href" || attrName === "xlink:href") && attrValue && !attrValue.startsWith("#")) {
32
- data.keepAttr = false;
33
- }
34
- });
35
- let parsedDom = null;
36
27
  try {
37
- const sanitized = domPurify.sanitize(raw, {
38
- USE_PROFILES: { svg: true, svgFilters: true, html: false },
39
- FORBID_TAGS: ["script", "foreignObject"],
40
- FORBID_CONTENTS: ["script", "foreignObject"],
41
- RETURN_TRUSTED_TYPE: false,
42
- });
43
- parsedDom = new JSDOM(sanitized, { contentType: SVG_CONTENT_TYPE });
44
- const document = parsedDom.window.document;
45
- const root = document.documentElement;
46
- if (!root || root.tagName.toLowerCase() !== "svg")
28
+ const normalized = raw.replace(XML_DECLARATIONS_AND_COMMENTS, "").trim();
29
+ if (!SVG_ROOT_PATTERN.test(normalized))
47
30
  return null;
48
- for (const el of Array.from(root.querySelectorAll("script, foreignObject"))) {
49
- el.remove();
50
- }
51
- for (const el of Array.from(root.querySelectorAll("*"))) {
52
- for (const attr of Array.from(el.attributes)) {
53
- const attrName = attr.name.toLowerCase();
54
- const attrValue = attr.value.trim();
55
- if (attrName.startsWith("on")) {
56
- el.removeAttribute(attr.name);
57
- continue;
58
- }
59
- if ((attrName === "href" || attrName === "xlink:href") && attrValue && !attrValue.startsWith("#")) {
60
- el.removeAttribute(attr.name);
61
- }
62
- }
63
- }
64
- const output = root.outerHTML.trim();
31
+ const sanitized = normalized
32
+ .replace(DISALLOWED_SVG_BLOCKS, "")
33
+ .replace(DISALLOWED_SVG_TAGS, "")
34
+ .replace(EVENT_HANDLER_ATTRS, "")
35
+ .replace(STYLE_ATTRS, "")
36
+ .replace(HREF_ATTRS, (_match, attrName, _fullValue, doubleQuoted, singleQuoted, bare) => {
37
+ const attrValue = (doubleQuoted ?? singleQuoted ?? bare ?? "").trim();
38
+ return attrValue.startsWith("#") ? ` ${attrName}="${attrValue}"` : "";
39
+ })
40
+ .trim();
41
+ const output = sanitized.trim();
65
42
  if (!output || !/^<svg[\s>]/i.test(output))
66
43
  return null;
67
44
  return Buffer.from(output, "utf8");
@@ -69,10 +46,6 @@ function sanitizeSvgBuffer(input) {
69
46
  catch {
70
47
  return null;
71
48
  }
72
- finally {
73
- parsedDom?.window.close();
74
- baseDom.window.close();
75
- }
76
49
  }
77
50
  export function assetRoutes(db, storage) {
78
51
  const router = Router();
@@ -306,4 +279,4 @@ export function assetRoutes(db, storage) {
306
279
  });
307
280
  return router;
308
281
  }
309
- //# sourceMappingURL=assets.js.map
282
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1,21 @@
1
+ import pc from "picocolors";
2
+ const GROWTHUB_ART = [
3
+ " ██████╗ ██████╗ ██████╗ ██╗ ██╗████████╗██╗ ██╗██╗ ██╗██████╗ ",
4
+ "██╔════╝ ██╔══██╗██╔═══██╗██║ ██║╚══██╔══╝██║ ██║██║ ██║██╔══██╗",
5
+ "██║ ███╗██████╔╝██║ ██║██║ █╗ ██║ ██║ ███████║██║ ██║██████╔╝",
6
+ "██║ ██║██╔══██╗██║ ██║██║███╗██║ ██║ ██╔══██║██║ ██║██╔══██╗",
7
+ "╚██████╔╝██║ ██║╚██████╔╝╚███╔███╔╝ ██║ ██║ ██║╚██████╔╝██████╔╝",
8
+ " ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ",
9
+ ];
10
+ const TAGLINE = "Growth infrastructure over a stable agentic substrate";
11
+ export function printPaperclipCliBanner() {
12
+ const lines = [
13
+ "",
14
+ ...GROWTHUB_ART,
15
+ pc.dim(" ───────────────────────────────────────────────────────"),
16
+ pc.bold(` ${TAGLINE}`),
17
+ "",
18
+ ];
19
+ console.log(lines.join("\n"));
20
+ }
21
+ //# sourceMappingURL=banner.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growthub/cli",
3
- "version": "0.3.44",
3
+ "version": "0.3.45",
4
4
  "description": "Growthub CLI — orchestrate AI agent teams to run a business",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,20 +37,17 @@
37
37
  "dependencies": {
38
38
  "@aws-sdk/client-s3": "^3.888.0",
39
39
  "@clack/prompts": "^0.10.0",
40
- "@paperclipai/server": "0.3.1",
41
40
  "ajv": "^8.18.0",
42
41
  "ajv-formats": "^3.0.1",
43
42
  "better-auth": "1.4.18",
44
43
  "chokidar": "^4.0.3",
45
44
  "commander": "^13.1.0",
46
45
  "detect-port": "^2.1.0",
47
- "dompurify": "^3.3.2",
48
46
  "dotenv": "^17.0.1",
49
- "drizzle-orm": "0.38.4",
47
+ "drizzle-orm": "^0.45.2",
50
48
  "embedded-postgres": "^18.1.0-beta.16",
51
49
  "express": "^5.1.0",
52
50
  "hermes-paperclip-adapter": "0.1.1",
53
- "jsdom": "^28.1.0",
54
51
  "multer": "^2.0.2",
55
52
  "open": "^11.0.0",
56
53
  "picocolors": "^1.1.1",
@@ -59,6 +56,6 @@
59
56
  "pino-pretty": "^13.1.3",
60
57
  "postgres": "^3.4.5",
61
58
  "ws": "^8.19.0",
62
- "zod": "^3.24.2"
59
+ "zod": "^4.3.6"
63
60
  }
64
61
  }