filegrc 0.3.2 → 0.3.3

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "filegrc",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Zero-dependency Git-native GRC engine",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/build.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { FAVICON_PNG } from "./favicon.js";
3
+ import { FAVICON_PNG, LOGO_MARK_PNG } from "./favicon.js";
4
4
  import { resolveWorkspacePath, resolveWorkspaceRoot } from "./paths.js";
5
5
  import { createAppState } from "./state.js";
6
6
  import { APP_SCRIPT, APP_STYLES, renderIndex } from "./web.js";
@@ -12,6 +12,7 @@ export async function buildWorkspace(input = process.cwd(), options = {}) {
12
12
  const paths = {
13
13
  html: resolveWorkspacePath(root, join(outputOption, "index.html")),
14
14
  favicon: resolveWorkspacePath(root, join(outputOption, "favicon.png")),
15
+ logoMark: resolveWorkspacePath(root, join(outputOption, "logo-mark-white.png")),
15
16
  script: resolveWorkspacePath(root, join(outputOption, "filegrc-app.js")),
16
17
  styles: resolveWorkspacePath(root, join(outputOption, "filegrc.css"))
17
18
  };
@@ -20,6 +21,7 @@ export async function buildWorkspace(input = process.cwd(), options = {}) {
20
21
  await Promise.all([
21
22
  writeFile(paths.html, renderIndex(state), "utf8"),
22
23
  writeFile(paths.favicon, FAVICON_PNG),
24
+ writeFile(paths.logoMark, LOGO_MARK_PNG),
23
25
  writeFile(paths.script, APP_SCRIPT, "utf8"),
24
26
  writeFile(paths.styles, APP_STYLES, "utf8")
25
27
  ]);
package/src/cli.js CHANGED
@@ -29,6 +29,7 @@ import { markdownEntries } from "./resource-markdown.js";
29
29
  import { searchResources } from "./search.js";
30
30
  import { serveWorkspace } from "./server.js";
31
31
  import { planWorkspaceSetup, setupWorkspace, summarizeSetupResult } from "./setup.js";
32
+ import { printGithubStarMessage } from "./startup.js";
32
33
  import { createAppState } from "./state.js";
33
34
  import { currentCalendarDate } from "./time.js";
34
35
  import { validateWorkspace } from "./validate.js";
@@ -64,13 +65,19 @@ export async function runCli(argv = process.argv.slice(2)) {
64
65
  host: flags.host ?? process.env.FILEGRC_HOST,
65
66
  port: flags.port ?? process.env.FILEGRC_PORT
66
67
  });
67
- console.log(`filegrc workspace: ${result.url}`);
68
- console.log(`Data: ${result.root}/data`);
69
- return await new Promise((resolvePromise) => {
70
- const stop = () => result.server.close(resolvePromise);
68
+ const stopped = new Promise((resolvePromise) => {
69
+ const stop = () => {
70
+ process.removeListener("SIGINT", stop);
71
+ process.removeListener("SIGTERM", stop);
72
+ result.server.close(resolvePromise);
73
+ };
71
74
  process.once("SIGINT", stop);
72
75
  process.once("SIGTERM", stop);
73
76
  });
77
+ console.log(`filegrc workspace: ${result.url}`);
78
+ console.log(`Data: ${result.root}/data`);
79
+ printGithubStarMessage();
80
+ return await stopped;
74
81
  }
75
82
  if (command === "setup") {
76
83
  const payload = positionals[0] ? await readSetupPayload(positionals[0]) : {};
package/src/favicon.js CHANGED
@@ -1,109 +1,4 @@
1
- import { deflateSync } from "node:zlib";
1
+ import { readFileSync } from "node:fs";
2
2
 
3
- const SIZE = 64;
4
- const WHITE = [248, 249, 255, 255];
5
-
6
- export const FAVICON_PNG = createFavicon();
7
-
8
- function createFavicon() {
9
- const pixels = Buffer.alloc(SIZE * SIZE * 4);
10
-
11
- for (let y = 0; y < SIZE; y += 1) {
12
- for (let x = 0; x < SIZE; x += 1) {
13
- if (!insideRoundedSquare(x, y, 11)) continue;
14
- setPixel(pixels, x, y, backgroundColor(x, y));
15
- }
16
- }
17
-
18
- drawStroke(pixels, [
19
- [18, 8],
20
- [39, 8],
21
- [51, 20],
22
- [51, 50],
23
- [50, 53],
24
- [47, 55],
25
- [17, 55],
26
- [14, 54],
27
- [12, 51],
28
- [12, 13],
29
- [14, 10],
30
- [18, 8]
31
- ], 2.3, WHITE);
32
- drawStroke(pixels, [[39, 8], [39, 20], [51, 20]], 2.3, WHITE);
33
-
34
- const rows = Buffer.alloc((SIZE * 4 + 1) * SIZE);
35
- for (let y = 0; y < SIZE; y += 1) {
36
- const rowOffset = y * (SIZE * 4 + 1);
37
- rows[rowOffset] = 0;
38
- pixels.copy(rows, rowOffset + 1, y * SIZE * 4, (y + 1) * SIZE * 4);
39
- }
40
-
41
- const header = Buffer.alloc(13);
42
- header.writeUInt32BE(SIZE, 0);
43
- header.writeUInt32BE(SIZE, 4);
44
- header.set([8, 6, 0, 0, 0], 8);
45
-
46
- return Buffer.concat([
47
- Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
48
- pngChunk("IHDR", header),
49
- pngChunk("IDAT", deflateSync(rows)),
50
- pngChunk("IEND", Buffer.alloc(0))
51
- ]);
52
- }
53
-
54
- function insideRoundedSquare(x, y, radius) {
55
- const cornerX = x < radius ? radius - 1 : x >= SIZE - radius ? SIZE - radius : x;
56
- const cornerY = y < radius ? radius - 1 : y >= SIZE - radius ? SIZE - radius : y;
57
- return Math.hypot(x - cornerX, y - cornerY) <= radius;
58
- }
59
-
60
- function backgroundColor(x, y) {
61
- const progress = Math.min(1, (x + y) / ((SIZE - 1) * 1.2));
62
- return [0, 0, Math.round(112 + (53 - 112) * progress), 255];
63
- }
64
-
65
- function drawStroke(pixels, points, radius, color) {
66
- for (let y = 0; y < SIZE; y += 1) {
67
- for (let x = 0; x < SIZE; x += 1) {
68
- const onStroke = points.slice(1).some((point, index) => (
69
- distanceToSegment(x, y, points[index], point) <= radius
70
- ));
71
- if (onStroke) setPixel(pixels, x, y, color);
72
- }
73
- }
74
- }
75
-
76
- function distanceToSegment(x, y, start, end) {
77
- const dx = end[0] - start[0];
78
- const dy = end[1] - start[1];
79
- const lengthSquared = dx * dx + dy * dy;
80
- const progress = lengthSquared
81
- ? Math.max(0, Math.min(1, ((x - start[0]) * dx + (y - start[1]) * dy) / lengthSquared))
82
- : 0;
83
- return Math.hypot(x - (start[0] + progress * dx), y - (start[1] + progress * dy));
84
- }
85
-
86
- function setPixel(pixels, x, y, color) {
87
- pixels.set(color, (y * SIZE + x) * 4);
88
- }
89
-
90
- function pngChunk(type, data) {
91
- const typeBuffer = Buffer.from(type, "ascii");
92
- const chunk = Buffer.alloc(data.length + 12);
93
- chunk.writeUInt32BE(data.length, 0);
94
- typeBuffer.copy(chunk, 4);
95
- data.copy(chunk, 8);
96
- chunk.writeUInt32BE(crc32(Buffer.concat([typeBuffer, data])), data.length + 8);
97
- return chunk;
98
- }
99
-
100
- function crc32(buffer) {
101
- let value = 0xffffffff;
102
- for (const byte of buffer) {
103
- value ^= byte;
104
- for (let bit = 0; bit < 8; bit += 1) {
105
- value = (value >>> 1) ^ (value & 1 ? 0xedb88320 : 0);
106
- }
107
- }
108
- return (value ^ 0xffffffff) >>> 0;
109
- }
3
+ export const FAVICON_PNG = readFileSync(new URL("./favicon.png", import.meta.url));
4
+ export const LOGO_MARK_PNG = readFileSync(new URL("./logo-mark-white.png", import.meta.url));
Binary file
Binary file
package/src/server.js CHANGED
@@ -5,7 +5,7 @@ import { getResourceDefinition } from "../model/index.js";
5
5
  import { prepareAuditWorkspace } from "./audit-preparation.js";
6
6
  import { generateEvidencePacket, prepareEvidencePacket } from "./evidence-packet.js";
7
7
  import { ensureEvidenceTestDrafts } from "./evidence-tests.js";
8
- import { FAVICON_PNG } from "./favicon.js";
8
+ import { FAVICON_PNG, LOGO_MARK_PNG } from "./favicon.js";
9
9
  import { createResource, deleteResource, updateContent, updateResource } from "./files.js";
10
10
  import { commitAndPushWorkspace, getFileHistory, pullWorkspace, pushWorkspace } from "./git.js";
11
11
  import { completeObligationOccurrence, createObligationEvent, planObligations } from "./obligations.js";
@@ -137,6 +137,7 @@ export function createFilegrcServer(input = process.cwd(), options = {}) {
137
137
  }
138
138
  }
139
139
  if (request.method === "GET" && url.pathname === "/favicon.png") return text(response, 200, FAVICON_PNG, "image/png");
140
+ if (request.method === "GET" && url.pathname === "/logo-mark-white.png") return text(response, 200, LOGO_MARK_PNG, "image/png");
140
141
  if (request.method === "GET" && url.pathname === "/filegrc-app.js") return text(response, 200, APP_SCRIPT, "text/javascript; charset=utf-8");
141
142
  if (request.method === "GET" && url.pathname === "/filegrc.css") return text(response, 200, APP_STYLES, "text/css; charset=utf-8");
142
143
  if (request.method === "GET" && url.pathname.startsWith("/packet/")) {
package/src/startup.js ADDED
@@ -0,0 +1,5 @@
1
+ const GITHUB_STAR_MESSAGE = "\n\x1b[38;2;255;184;0m⭐️ → ❤️ https://github.com/Sunpeak-AI/filegrc\x1b[0m\n";
2
+
3
+ export function printGithubStarMessage() {
4
+ console.log(GITHUB_STAR_MESSAGE);
5
+ }
package/src/web.js CHANGED
@@ -174,7 +174,7 @@ function buildNavigation(route) {
174
174
  const organizationCurrent = route.name === "organization" || route.name === "repository" || ["workspace", "renderer-settings"].includes(route.type);
175
175
  const organizationName = state.workspace.organizationName || "Organization";
176
176
  const initial = organizationName.trim().charAt(0).toUpperCase() || "O";
177
- return '<aside class="sidebar" id="sidebar-navigation"><button class="nav-close" type="button" aria-label="Close navigation">×</button><a href="#/" class="brand"' + (route.name === "home" ? ' aria-current="page"' : "") + '><img class="mark" src="./favicon.png" alt="" width="39" height="39"><span><strong>filegrc</strong><small>SOC 2 workspace</small></span></a><nav class="sidebar-nav">' + stages + '</nav><div class="sidebar-footer"><a class="organization-nav ' + (organizationCurrent ? "current" : "") + '" href="#/organization"><span class="organization-mark">' + esc(initial) + '</span><span><strong>' + esc(organizationName) + '</strong><small>Organization</small></span><span class="organization-arrow">›</span></a></div></aside><button class="nav-scrim" type="button" aria-label="Close navigation"></button>';
177
+ return '<aside class="sidebar" id="sidebar-navigation"><button class="nav-close" type="button" aria-label="Close navigation">×</button><a href="#/" class="brand"' + (route.name === "home" ? ' aria-current="page"' : "") + '><img class="mark" src="./logo-mark-white.png" alt="" width="39" height="39"><span><strong>filegrc</strong><small>SOC 2 workspace</small></span></a><nav class="sidebar-nav">' + stages + '</nav><div class="sidebar-footer"><a class="organization-nav ' + (organizationCurrent ? "current" : "") + '" href="#/organization"><span class="organization-mark">' + esc(initial) + '</span><span><strong>' + esc(organizationName) + '</strong><small>Organization</small></span><span class="organization-arrow">›</span></a></div></aside><button class="nav-scrim" type="button" aria-label="Close navigation"></button>';
178
178
  }
179
179
 
180
180
  function readinessStageForRoute(route) {