@jamesaphoenix/tx-api-server 0.1.1

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.
Files changed (109) hide show
  1. package/dist/__tests__/api.test.d.ts +7 -0
  2. package/dist/__tests__/api.test.d.ts.map +1 -0
  3. package/dist/__tests__/api.test.js +184 -0
  4. package/dist/__tests__/api.test.js.map +1 -0
  5. package/dist/__tests__/auth.test.d.ts +7 -0
  6. package/dist/__tests__/auth.test.d.ts.map +1 -0
  7. package/dist/__tests__/auth.test.js +174 -0
  8. package/dist/__tests__/auth.test.js.map +1 -0
  9. package/dist/__tests__/body-limit.test.d.ts +7 -0
  10. package/dist/__tests__/body-limit.test.d.ts.map +1 -0
  11. package/dist/__tests__/body-limit.test.js +60 -0
  12. package/dist/__tests__/body-limit.test.js.map +1 -0
  13. package/dist/__tests__/health.test.d.ts.map +1 -0
  14. package/dist/__tests__/health.test.js.map +1 -0
  15. package/dist/__tests__/log-reader.test.d.ts +8 -0
  16. package/dist/__tests__/log-reader.test.d.ts.map +1 -0
  17. package/dist/__tests__/log-reader.test.js +55 -0
  18. package/dist/__tests__/log-reader.test.js.map +1 -0
  19. package/dist/__tests__/rate-limit.test.d.ts.map +1 -0
  20. package/dist/__tests__/rate-limit.test.js.map +1 -0
  21. package/dist/__tests__/server-lib.test.d.ts +10 -0
  22. package/dist/__tests__/server-lib.test.d.ts.map +1 -0
  23. package/dist/__tests__/server-lib.test.js +145 -0
  24. package/dist/__tests__/server-lib.test.js.map +1 -0
  25. package/dist/api.d.ts +1616 -0
  26. package/dist/api.d.ts.map +1 -0
  27. package/dist/api.js +566 -0
  28. package/dist/api.js.map +1 -0
  29. package/dist/index.d.ts +16 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +19 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/middleware/auth.d.ts +31 -0
  34. package/dist/middleware/auth.d.ts.map +1 -0
  35. package/dist/middleware/auth.js +65 -0
  36. package/dist/middleware/auth.js.map +1 -0
  37. package/dist/middleware/body-limit.d.ts +33 -0
  38. package/dist/middleware/body-limit.d.ts.map +1 -0
  39. package/dist/middleware/body-limit.js +50 -0
  40. package/dist/middleware/body-limit.js.map +1 -0
  41. package/dist/middleware/cors.d.ts +15 -0
  42. package/dist/middleware/cors.d.ts.map +1 -0
  43. package/dist/middleware/cors.js +31 -0
  44. package/dist/middleware/cors.js.map +1 -0
  45. package/dist/middleware/error.d.ts +26 -0
  46. package/dist/middleware/error.d.ts.map +1 -0
  47. package/dist/middleware/error.js +84 -0
  48. package/dist/middleware/error.js.map +1 -0
  49. package/dist/middleware/rate-limit.d.ts +59 -0
  50. package/dist/middleware/rate-limit.d.ts.map +1 -0
  51. package/dist/middleware/rate-limit.js +296 -0
  52. package/dist/middleware/rate-limit.js.map +1 -0
  53. package/dist/routes/attempts.d.ts +9 -0
  54. package/dist/routes/attempts.d.ts.map +1 -0
  55. package/dist/routes/attempts.js +26 -0
  56. package/dist/routes/attempts.js.map +1 -0
  57. package/dist/routes/claims.d.ts +9 -0
  58. package/dist/routes/claims.d.ts.map +1 -0
  59. package/dist/routes/claims.js +42 -0
  60. package/dist/routes/claims.js.map +1 -0
  61. package/dist/routes/docs.d.ts +9 -0
  62. package/dist/routes/docs.d.ts.map +1 -0
  63. package/dist/routes/docs.js +80 -0
  64. package/dist/routes/docs.js.map +1 -0
  65. package/dist/routes/health.d.ts +8 -0
  66. package/dist/routes/health.d.ts.map +1 -0
  67. package/dist/routes/health.js +101 -0
  68. package/dist/routes/health.js.map +1 -0
  69. package/dist/routes/invariants.d.ts +9 -0
  70. package/dist/routes/invariants.d.ts.map +1 -0
  71. package/dist/routes/invariants.js +64 -0
  72. package/dist/routes/invariants.js.map +1 -0
  73. package/dist/routes/learnings.d.ts +8 -0
  74. package/dist/routes/learnings.d.ts.map +1 -0
  75. package/dist/routes/learnings.js +93 -0
  76. package/dist/routes/learnings.js.map +1 -0
  77. package/dist/routes/runs.d.ts +8 -0
  78. package/dist/routes/runs.d.ts.map +1 -0
  79. package/dist/routes/runs.js +195 -0
  80. package/dist/routes/runs.js.map +1 -0
  81. package/dist/routes/sync.d.ts +8 -0
  82. package/dist/routes/sync.d.ts.map +1 -0
  83. package/dist/routes/sync.js +67 -0
  84. package/dist/routes/sync.js.map +1 -0
  85. package/dist/routes/tasks.d.ts +9 -0
  86. package/dist/routes/tasks.d.ts.map +1 -0
  87. package/dist/routes/tasks.js +167 -0
  88. package/dist/routes/tasks.js.map +1 -0
  89. package/dist/runtime.d.ts +10 -0
  90. package/dist/runtime.d.ts.map +1 -0
  91. package/dist/runtime.js +10 -0
  92. package/dist/runtime.js.map +1 -0
  93. package/dist/server-lib.d.ts +26 -0
  94. package/dist/server-lib.d.ts.map +1 -0
  95. package/dist/server-lib.js +123 -0
  96. package/dist/server-lib.js.map +1 -0
  97. package/dist/server.d.ts +14 -0
  98. package/dist/server.d.ts.map +1 -0
  99. package/dist/server.js +15 -0
  100. package/dist/server.js.map +1 -0
  101. package/dist/utils/log-reader.d.ts +26 -0
  102. package/dist/utils/log-reader.d.ts.map +1 -0
  103. package/dist/utils/log-reader.js +52 -0
  104. package/dist/utils/log-reader.js.map +1 -0
  105. package/dist/utils/transcript-parser.d.ts +40 -0
  106. package/dist/utils/transcript-parser.d.ts.map +1 -0
  107. package/dist/utils/transcript-parser.js +216 -0
  108. package/dist/utils/transcript-parser.js.map +1 -0
  109. package/package.json +75 -0
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Server Library Tests
3
+ *
4
+ * Tests for server configuration and module exports.
5
+ * Note: makeServerLive and route layers require bun:sqlite (via tx-core)
6
+ * and can only be tested with `bun test`. These tests cover the parts
7
+ * that work in Node.js vitest.
8
+ */
9
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
10
+ import { isAuthEnabled } from "../middleware/auth.js";
11
+ import { getCorsConfig } from "../middleware/cors.js";
12
+ // =============================================================================
13
+ // Auth Configuration Tests
14
+ // =============================================================================
15
+ describe("Server auth configuration", () => {
16
+ let savedEnv;
17
+ beforeEach(() => {
18
+ savedEnv = {
19
+ TX_API_PORT: process.env.TX_API_PORT,
20
+ TX_API_HOST: process.env.TX_API_HOST,
21
+ TX_DB_PATH: process.env.TX_DB_PATH,
22
+ TX_API_KEY: process.env.TX_API_KEY,
23
+ TX_API_CORS_ORIGIN: process.env.TX_API_CORS_ORIGIN,
24
+ TX_API_CORS_CREDENTIALS: process.env.TX_API_CORS_CREDENTIALS,
25
+ };
26
+ });
27
+ afterEach(() => {
28
+ for (const [key, value] of Object.entries(savedEnv)) {
29
+ if (value === undefined) {
30
+ delete process.env[key];
31
+ }
32
+ else {
33
+ process.env[key] = value;
34
+ }
35
+ }
36
+ });
37
+ it("should detect auth enabled via TX_API_KEY", () => {
38
+ process.env.TX_API_KEY = "my-secret-key";
39
+ expect(isAuthEnabled()).toBe(true);
40
+ });
41
+ it("should detect auth disabled when TX_API_KEY not set", () => {
42
+ delete process.env.TX_API_KEY;
43
+ expect(isAuthEnabled()).toBe(false);
44
+ });
45
+ it("should detect auth disabled for empty TX_API_KEY", () => {
46
+ process.env.TX_API_KEY = "";
47
+ expect(isAuthEnabled()).toBe(false);
48
+ });
49
+ });
50
+ // =============================================================================
51
+ // CORS Configuration Tests
52
+ // =============================================================================
53
+ describe("CORS configuration", () => {
54
+ let savedEnv;
55
+ beforeEach(() => {
56
+ savedEnv = {
57
+ TX_API_CORS_ORIGIN: process.env.TX_API_CORS_ORIGIN,
58
+ TX_API_CORS_CREDENTIALS: process.env.TX_API_CORS_CREDENTIALS,
59
+ };
60
+ });
61
+ afterEach(() => {
62
+ for (const [key, value] of Object.entries(savedEnv)) {
63
+ if (value === undefined) {
64
+ delete process.env[key];
65
+ }
66
+ else {
67
+ process.env[key] = value;
68
+ }
69
+ }
70
+ });
71
+ it("should default to localhost origins when TX_API_CORS_ORIGIN is not set", () => {
72
+ delete process.env.TX_API_CORS_ORIGIN;
73
+ const config = getCorsConfig();
74
+ expect(config.allowedOrigins).toEqual([
75
+ "http://localhost:3000",
76
+ "http://localhost:3001",
77
+ "http://localhost:5173",
78
+ "http://127.0.0.1:3000",
79
+ "http://127.0.0.1:3001",
80
+ "http://127.0.0.1:5173",
81
+ ]);
82
+ // Must NOT include wildcard by default
83
+ expect(config.allowedOrigins).not.toContain("*");
84
+ });
85
+ it("should allow wildcard only when explicitly set to *", () => {
86
+ process.env.TX_API_CORS_ORIGIN = "*";
87
+ const config = getCorsConfig();
88
+ expect(config.allowedOrigins).toEqual(["*"]);
89
+ });
90
+ it("should parse comma-separated origins", () => {
91
+ process.env.TX_API_CORS_ORIGIN = "https://app.example.com, https://admin.example.com";
92
+ const config = getCorsConfig();
93
+ expect(config.allowedOrigins).toEqual([
94
+ "https://app.example.com",
95
+ "https://admin.example.com",
96
+ ]);
97
+ });
98
+ it("should handle single custom origin", () => {
99
+ process.env.TX_API_CORS_ORIGIN = "https://myapp.com";
100
+ const config = getCorsConfig();
101
+ expect(config.allowedOrigins).toEqual(["https://myapp.com"]);
102
+ });
103
+ it("should enable credentials when TX_API_CORS_CREDENTIALS is true", () => {
104
+ process.env.TX_API_CORS_CREDENTIALS = "true";
105
+ const config = getCorsConfig();
106
+ expect(config.credentials).toBe(true);
107
+ });
108
+ it("should disable credentials by default", () => {
109
+ delete process.env.TX_API_CORS_CREDENTIALS;
110
+ const config = getCorsConfig();
111
+ expect(config.credentials).toBe(false);
112
+ });
113
+ });
114
+ // =============================================================================
115
+ // API Definition Exports Tests (no bun:sqlite dependency)
116
+ // =============================================================================
117
+ describe("API definition exports", () => {
118
+ it("should export TxApi class from api.ts", async () => {
119
+ const { TxApi } = await import("../api.js");
120
+ expect(TxApi).toBeDefined();
121
+ });
122
+ it("should export all error types from api.ts", async () => {
123
+ const { NotFound, BadRequest, InternalError, Unauthorized, Forbidden, ServiceUnavailable } = await import("../api.js");
124
+ expect(NotFound).toBeDefined();
125
+ expect(BadRequest).toBeDefined();
126
+ expect(InternalError).toBeDefined();
127
+ expect(Unauthorized).toBeDefined();
128
+ expect(Forbidden).toBeDefined();
129
+ expect(ServiceUnavailable).toBeDefined();
130
+ });
131
+ it("should export mapCoreError from api.ts", async () => {
132
+ const { mapCoreError } = await import("../api.js");
133
+ expect(mapCoreError).toBeDefined();
134
+ expect(typeof mapCoreError).toBe("function");
135
+ });
136
+ it("should export all API groups from api.ts", async () => {
137
+ const { HealthGroup, TasksGroup, LearningsGroup, RunsGroup, SyncGroup } = await import("../api.js");
138
+ expect(HealthGroup).toBeDefined();
139
+ expect(TasksGroup).toBeDefined();
140
+ expect(LearningsGroup).toBeDefined();
141
+ expect(RunsGroup).toBeDefined();
142
+ expect(SyncGroup).toBeDefined();
143
+ });
144
+ });
145
+ //# sourceMappingURL=server-lib.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-lib.test.js","sourceRoot":"","sources":["../../src/__tests__/server-lib.test.ts"],"names":[],"mappings":"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"}