@vllnt/convex-idempotency 0.1.0-canary.6abc175

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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/client/index.d.ts +135 -0
  4. package/dist/client/index.d.ts.map +1 -0
  5. package/dist/client/index.js +117 -0
  6. package/dist/client/index.js.map +1 -0
  7. package/dist/client/types.d.ts +78 -0
  8. package/dist/client/types.d.ts.map +1 -0
  9. package/dist/client/types.js +3 -0
  10. package/dist/client/types.js.map +1 -0
  11. package/dist/component/_generated/api.d.ts +40 -0
  12. package/dist/component/_generated/api.d.ts.map +1 -0
  13. package/dist/component/_generated/api.js +31 -0
  14. package/dist/component/_generated/api.js.map +1 -0
  15. package/dist/component/_generated/component.d.ts +65 -0
  16. package/dist/component/_generated/component.d.ts.map +1 -0
  17. package/dist/component/_generated/component.js +11 -0
  18. package/dist/component/_generated/component.js.map +1 -0
  19. package/dist/component/_generated/dataModel.d.ts +46 -0
  20. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  21. package/dist/component/_generated/dataModel.js +11 -0
  22. package/dist/component/_generated/dataModel.js.map +1 -0
  23. package/dist/component/_generated/server.d.ts +121 -0
  24. package/dist/component/_generated/server.d.ts.map +1 -0
  25. package/dist/component/_generated/server.js +78 -0
  26. package/dist/component/_generated/server.js.map +1 -0
  27. package/dist/component/convex.config.d.ts +3 -0
  28. package/dist/component/convex.config.d.ts.map +1 -0
  29. package/dist/component/convex.config.js +7 -0
  30. package/dist/component/convex.config.js.map +1 -0
  31. package/dist/component/crons.d.ts +16 -0
  32. package/dist/component/crons.d.ts.map +1 -0
  33. package/dist/component/crons.js +19 -0
  34. package/dist/component/crons.js.map +1 -0
  35. package/dist/component/mutations.d.ts +91 -0
  36. package/dist/component/mutations.d.ts.map +1 -0
  37. package/dist/component/mutations.js +177 -0
  38. package/dist/component/mutations.js.map +1 -0
  39. package/dist/component/queries.d.ts +9 -0
  40. package/dist/component/queries.d.ts.map +1 -0
  41. package/dist/component/queries.js +22 -0
  42. package/dist/component/queries.js.map +1 -0
  43. package/dist/component/schema.d.ts +26 -0
  44. package/dist/component/schema.d.ts.map +1 -0
  45. package/dist/component/schema.js +21 -0
  46. package/dist/component/schema.js.map +1 -0
  47. package/dist/component/validators.d.ts +80 -0
  48. package/dist/component/validators.d.ts.map +1 -0
  49. package/dist/component/validators.js +42 -0
  50. package/dist/component/validators.js.map +1 -0
  51. package/dist/shared.d.ts +17 -0
  52. package/dist/shared.d.ts.map +1 -0
  53. package/dist/shared.js +17 -0
  54. package/dist/shared.js.map +1 -0
  55. package/package.json +96 -0
  56. package/src/client/index.ts +251 -0
  57. package/src/client/types.ts +87 -0
  58. package/src/component/_generated/api.ts +56 -0
  59. package/src/component/_generated/component.ts +67 -0
  60. package/src/component/_generated/dataModel.ts +60 -0
  61. package/src/component/_generated/server.ts +156 -0
  62. package/src/component/convex.config.ts +9 -0
  63. package/src/component/crons.ts +23 -0
  64. package/src/component/mutations.ts +195 -0
  65. package/src/component/queries.ts +24 -0
  66. package/src/component/schema.ts +21 -0
  67. package/src/component/validators.ts +56 -0
  68. package/src/shared.ts +21 -0
  69. package/src/test.ts +12 -0
@@ -0,0 +1,21 @@
1
+ import { defineSchema, defineTable } from "convex/server";
2
+ import { v } from "convex/values";
3
+ import { jsonValue } from "./validators";
4
+
5
+ /**
6
+ * Sandboxed tables — the idempotency ledger's own concern. A `key` is unique
7
+ * within a `scope`; `result` carries the opaque host-owned outcome (never
8
+ * inspected). `expiresAt` is an absolute ms timestamp that bounds the grace
9
+ * window after which a key may be re-minted.
10
+ */
11
+ export default defineSchema({
12
+ keys: defineTable({
13
+ key: v.string(),
14
+ scope: v.string(),
15
+ status: v.union(v.literal("inflight"), v.literal("done")),
16
+ result: v.optional(jsonValue),
17
+ expiresAt: v.number(),
18
+ })
19
+ .index("by_scope_key", ["scope", "key"])
20
+ .index("by_expires", ["expiresAt"]),
21
+ });
@@ -0,0 +1,56 @@
1
+ import { v } from "convex/values";
2
+
3
+ /**
4
+ * Opaque host-owned outcome stored against a completed key. The component never
5
+ * inspects it — last-resort arbitrary data, aliased here rather than left bare
6
+ * in function signatures. The host narrows it at the {@link Idempotency} client
7
+ * boundary via an optional `resultValidator`.
8
+ *
9
+ * This is the single documented `v.any()` escape hatch in the component; the
10
+ * lint rule `convex-rules/no-bare-v-any` is satisfied by routing every arbitrary
11
+ * payload through this alias instead of a bare `v.any()`.
12
+ */
13
+ export const jsonValue = v.any();
14
+
15
+ /**
16
+ * Result of {@link begin}. `fresh` — the key was just minted, the caller should
17
+ * do the work and then `complete`. `inflight` — another attempt holds the key;
18
+ * `expiresAt` is when the lease frees and `retryAfterMs` how long to back off
19
+ * before retrying. `done` — a prior attempt already completed; `result` carries
20
+ * the recorded outcome for a short-circuit replay.
21
+ */
22
+ export const beginResult = v.union(
23
+ v.object({ state: v.literal("fresh") }),
24
+ v.object({
25
+ state: v.literal("inflight"),
26
+ expiresAt: v.number(),
27
+ retryAfterMs: v.number(),
28
+ }),
29
+ v.object({ state: v.literal("done"), result: v.optional(jsonValue) }),
30
+ );
31
+
32
+ /**
33
+ * Result of {@link complete}. `recorded: true` — the outcome was written.
34
+ * `recorded: false` — the claim was lost; `reason` distinguishes a never-claimed
35
+ * key (`missing`), a lease that expired before completion (`expired`), and a key
36
+ * already marked done by a prior attempt (`already_done`). A host that sees
37
+ * `recorded: false` knows its work finished but the ledger row was gone.
38
+ */
39
+ export const completeResult = v.union(
40
+ v.object({ recorded: v.literal(true) }),
41
+ v.object({
42
+ recorded: v.literal(false),
43
+ reason: v.union(
44
+ v.literal("missing"),
45
+ v.literal("expired"),
46
+ v.literal("already_done"),
47
+ ),
48
+ }),
49
+ );
50
+
51
+ /** Stored projection of a key returned by {@link get}. */
52
+ export const keyState = v.object({
53
+ status: v.union(v.literal("inflight"), v.literal("done")),
54
+ result: v.optional(jsonValue),
55
+ expiresAt: v.number(),
56
+ });
package/src/shared.ts ADDED
@@ -0,0 +1,21 @@
1
+ /** Shared constants used by both `client/` and `component/`. */
2
+
3
+ export const COMPONENT_NAME = "idempotency";
4
+
5
+ /** Default namespace when the host does not scope a key. */
6
+ export const DEFAULT_SCOPE = "global";
7
+
8
+ /**
9
+ * Default inflight lease: 60 seconds, in milliseconds. Short by design so a
10
+ * crashed worker's claim self-heals quickly and the key can be re-minted.
11
+ */
12
+ export const DEFAULT_INFLIGHT_TTL_MS = 60_000;
13
+
14
+ /**
15
+ * Default done grace window: 24 hours, in milliseconds. How long a recorded
16
+ * outcome replays before the key may be re-minted.
17
+ */
18
+ export const DEFAULT_DONE_TTL_MS = 86_400_000;
19
+
20
+ /** Default page size for a `purge` pass before the sweep self-reschedules. */
21
+ export const DEFAULT_PURGE_BATCH = 200;
package/src/test.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { TestConvex } from "convex-test";
2
+ import schema from "./component/schema";
3
+
4
+ const modules = import.meta.glob("./component/**/*.ts");
5
+
6
+ /**
7
+ * Register this component with a `convex-test` instance so consuming apps can
8
+ * test integration: `import { register } from "@vllnt/convex-idempotency/test"`.
9
+ */
10
+ export function register(t: TestConvex<typeof schema>, name = "idempotency"): void {
11
+ t.registerComponent(name, schema, modules);
12
+ }