@townco/core 0.0.27 → 0.0.29

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/dist/auth.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auth credentials stored in ~/.config/town/auth.json
3
+ */
4
+ export interface AuthCredentials {
5
+ access_token: string;
6
+ refresh_token: string;
7
+ expires_at: number;
8
+ user: {
9
+ id: string;
10
+ email: string;
11
+ };
12
+ shed_url: string;
13
+ }
14
+ /**
15
+ * Get the auth file path.
16
+ * Uses TOWN_AUTH_PATH env var if set, otherwise defaults to ~/.config/town/auth.json
17
+ */
18
+ export declare function getAuthFilePath(): string;
19
+ /**
20
+ * Load auth credentials from disk.
21
+ * Returns null if not logged in or file is invalid.
22
+ */
23
+ export declare function loadAuthCredentials(): AuthCredentials | null;
24
+ /**
25
+ * Check if access token is expired or about to expire (within 5 minutes)
26
+ */
27
+ export declare function isTokenExpired(credentials: AuthCredentials): boolean;
28
+ /**
29
+ * Check if user is logged in (has valid credentials file)
30
+ */
31
+ export declare function isLoggedIn(): boolean;
32
+ /**
33
+ * Save auth credentials to disk.
34
+ * Creates the config directory if it doesn't exist.
35
+ */
36
+ export declare function saveAuthCredentials(credentials: AuthCredentials): void;
37
+ /**
38
+ * Delete auth credentials (logout).
39
+ * Returns true if credentials were deleted, false if they didn't exist.
40
+ */
41
+ export declare function clearAuthCredentials(): boolean;
42
+ /**
43
+ * Get the shed URL from environment or default.
44
+ */
45
+ export declare function getShedUrl(): string;
package/dist/auth.js ADDED
@@ -0,0 +1,86 @@
1
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ /**
5
+ * Default path for auth credentials
6
+ */
7
+ const DEFAULT_AUTH_PATH = join(homedir(), ".config", "town", "auth.json");
8
+ /**
9
+ * Get the auth file path.
10
+ * Uses TOWN_AUTH_PATH env var if set, otherwise defaults to ~/.config/town/auth.json
11
+ */
12
+ export function getAuthFilePath() {
13
+ return process.env.TOWN_AUTH_PATH || DEFAULT_AUTH_PATH;
14
+ }
15
+ /**
16
+ * Load auth credentials from disk.
17
+ * Returns null if not logged in or file is invalid.
18
+ */
19
+ export function loadAuthCredentials() {
20
+ const authPath = getAuthFilePath();
21
+ if (!existsSync(authPath)) {
22
+ return null;
23
+ }
24
+ try {
25
+ const content = readFileSync(authPath, "utf-8");
26
+ return JSON.parse(content);
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ /**
33
+ * Check if access token is expired or about to expire (within 5 minutes)
34
+ */
35
+ export function isTokenExpired(credentials) {
36
+ const now = Math.floor(Date.now() / 1000);
37
+ const buffer = 5 * 60; // 5 minutes buffer
38
+ return credentials.expires_at <= now + buffer;
39
+ }
40
+ /**
41
+ * Check if user is logged in (has valid credentials file)
42
+ */
43
+ export function isLoggedIn() {
44
+ return loadAuthCredentials() !== null;
45
+ }
46
+ /**
47
+ * Save auth credentials to disk.
48
+ * Creates the config directory if it doesn't exist.
49
+ */
50
+ export function saveAuthCredentials(credentials) {
51
+ const authPath = getAuthFilePath();
52
+ const configDir = dirname(authPath);
53
+ if (!existsSync(configDir)) {
54
+ mkdirSync(configDir, { recursive: true });
55
+ }
56
+ try {
57
+ const content = JSON.stringify(credentials, null, 2);
58
+ writeFileSync(authPath, content, { mode: 0o600 });
59
+ }
60
+ catch (error) {
61
+ throw new Error(`Failed to save auth credentials: ${error instanceof Error ? error.message : String(error)}`);
62
+ }
63
+ }
64
+ /**
65
+ * Delete auth credentials (logout).
66
+ * Returns true if credentials were deleted, false if they didn't exist.
67
+ */
68
+ export function clearAuthCredentials() {
69
+ const authPath = getAuthFilePath();
70
+ if (!existsSync(authPath)) {
71
+ return false;
72
+ }
73
+ try {
74
+ unlinkSync(authPath);
75
+ return true;
76
+ }
77
+ catch (error) {
78
+ throw new Error(`Failed to clear auth credentials: ${error instanceof Error ? error.message : String(error)}`);
79
+ }
80
+ }
81
+ /**
82
+ * Get the shed URL from environment or default.
83
+ */
84
+ export function getShedUrl() {
85
+ return process.env.TOWN_SHED_URL || "http://localhost:3000";
86
+ }
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./logger.js";
2
+ export * from "./path.js";
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./logger.js";
2
+ export * from "./path.js";
package/dist/logger.js CHANGED
@@ -197,7 +197,12 @@ export class Logger {
197
197
  body: message,
198
198
  attributes: {
199
199
  service: this.service,
200
- ...(metadata && { "log.metadata": JSON.stringify(metadata) }),
200
+ // Flatten metadata into top-level attributes with "log." prefix
201
+ ...(metadata &&
202
+ Object.fromEntries(Object.entries(metadata).map(([key, value]) => [
203
+ `log.${key}`,
204
+ typeof value === "object" ? JSON.stringify(value) : value,
205
+ ]))),
201
206
  ...(activeSpan && {
202
207
  trace_id: activeSpan.spanContext().traceId,
203
208
  span_id: activeSpan.spanContext().spanId,
package/dist/path.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const findRoot: (dir?: string, rootMarker?: string) => Promise<string>;
package/dist/path.js ADDED
@@ -0,0 +1,12 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ const ROOT_MARKER = ".root";
4
+ export const findRoot = async (dir = process.cwd(), rootMarker = ROOT_MARKER) => {
5
+ const rootMarkerPath = path.join(dir, rootMarker);
6
+ if ((await fs.exists(rootMarkerPath)) &&
7
+ (await fs.stat(rootMarkerPath).then((stat) => stat.isFile())))
8
+ return dir;
9
+ if (dir === "/")
10
+ throw new Error(`Could not find root directory with marker '${rootMarker}'`);
11
+ return await findRoot(path.dirname(dir), rootMarker);
12
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@townco/core",
3
3
  "type": "module",
4
- "version": "0.0.27",
4
+ "version": "0.0.29",
5
5
  "description": "core",
6
6
  "license": "UNLICENSED",
7
7
  "main": "./dist/index.js",
@@ -14,6 +14,10 @@
14
14
  ".": {
15
15
  "import": "./dist/index.js",
16
16
  "require": "./dist/index.cjs"
17
+ },
18
+ "./auth": {
19
+ "import": "./dist/auth.js",
20
+ "types": "./dist/auth.d.ts"
17
21
  }
18
22
  },
19
23
  "dependencies": {
@@ -22,7 +26,7 @@
22
26
  },
23
27
  "devDependencies": {
24
28
  "typescript": "^5.9.3",
25
- "@townco/tsconfig": "0.1.46"
29
+ "@townco/tsconfig": "0.1.48"
26
30
  },
27
31
  "scripts": {
28
32
  "build": "tsc",