@delma/fylo 1.1.0 → 1.1.2

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.
@@ -1,113 +1,3 @@
1
- # FYLO Project Guidelines
1
+ Follow the shared workspace instructions in `../../INSTRUCTIONS.md`, shared context in `../../MEMORY.md`, and shared release process in `../../RELEASE.md`.
2
2
 
3
- ## Overview
4
-
5
- FYLO (`@vyckr/fylo`) is an S3-backed NoSQL document store with SQL parsing, Redis pub/sub for real-time events, and a CLI. Documents are stored as S3 key paths — not as file contents — with dual key layouts for data access and indexed queries.
6
-
7
- **Assume a serverless deployment model** (e.g., AWS Lambda, Cloudflare Workers). This means:
8
- - No persistent in-memory state across invocations — every request starts cold
9
- - Distributed coordination (e.g., TTID uniqueness) must use external stores like Redis, not in-process caches
10
- - Avoid long-lived connections, background threads, or singleton patterns that assume process longevity
11
- - Keep cold-start overhead minimal — lazy initialization over eager setup
12
-
13
- ## Architecture
14
-
15
- ### Key Storage Format
16
-
17
- - **Data keys**: `{ttid}/{field}/{value}` — keyed by document ID for full-doc retrieval
18
- - **Index keys**: `{field}/{value}/{ttid}` — keyed by field for query lookups
19
- - Nested objects flatten to path segments: `address/city/Toronto`
20
- - Forward slashes in values are escaped with an ASCII substitute
21
-
22
- ### Core Modules
23
-
24
- | Module | Responsibility |
25
- |--------|---------------|
26
- | `src/index.ts` | Main `Fylo` class — CRUD, SQL execution, joins, bulk ops |
27
- | `src/core/parser.ts` | SQL lexer/parser — tokenizes SQL into query objects |
28
- | `src/core/query.ts` | Converts `$ops` into glob patterns for S3 key matching |
29
- | `src/core/walker.ts` | S3 key traversal, document data retrieval, Redis event streaming |
30
- | `src/core/directory.ts` | Key extraction, reconstruction, rollback tracking |
31
- | `src/core/format.ts` | Console formatting for query output |
32
- | `src/adapters/s3.ts` | S3 adapter (Bun S3Client) |
33
- | `src/adapters/redis.ts` | Redis adapter (Bun RedisClient) |
34
- | `src/cli/index.ts` | CLI entry point (`fylo.query`) |
35
-
36
- ### Folder Structure
37
-
38
- ```
39
- src/
40
- index.ts # Public API — main Fylo class
41
- adapters/ # I/O boundary abstractions (S3, Redis)
42
- core/ # Internal domain logic (parser, query, walker, directory)
43
- cli/ # CLI entry point
44
- types/ # Type declarations (.d.ts only — separate from implementation)
45
- tests/
46
- data.ts # Shared test data URLs
47
- index.ts # Test barrel
48
- mocks/ # Mock adapters (S3, Redis) for testing
49
- schemas/ # CHEX-generated test schemas (.d.ts + .json)
50
- integration/ # End-to-end tests (CRUD, operators, joins, edge cases)
51
- ```
52
-
53
- ### Dependencies
54
-
55
- - **`@vyckr/ttid`** — Time-based unique ID system. `TTID.generate()` creates new IDs; `TTID.generate(existingId)` creates a versioned ID sharing the same creation-time prefix.
56
- - **`@vyckr/chex`** — Schema validation. Generates `interface` declarations in `.d.ts` files. Generic constraints must use `Record<string, any>` (not `Record<string, unknown>`) to accept these interfaces.
57
- - **`Bun.Glob`** — Pattern matching for queries. Does NOT support negation extglob `!(pattern)`. Operators like `$ne`, `$gt`, `$lt` use broad globs with post-filtering instead.
58
-
59
- ## Engineering Standards
60
-
61
- - **SOLID principles**: Single responsibility per class/method, depend on abstractions (e.g., S3/Redis adapters), open for extension without modifying core logic
62
- - **Clean code**: Descriptive naming, small focused functions, no dead code or commented-out blocks, DRY without premature abstraction
63
- - **Test discipline**: When changing `src/` code, update or add corresponding tests in `tests/` — never leave tests stale after a behaviour change
64
- - **Error handling**: Fail fast with meaningful errors at system boundaries; use rollback mechanisms for partial writes
65
- - **No magic values**: Use constants or environment variables; avoid hardcoded strings/numbers in logic
66
- - **Type safety**: Leverage TypeScript's type system fully — avoid `any` in implementation code, prefer narrow types, and validate at I/O boundaries
67
-
68
- ## Code Style
69
-
70
- - **Runtime**: Bun (ESNext target, ES modules)
71
- - **Strict TypeScript**: `strict: true`, `noImplicitReturns`, `isolatedModules`
72
- - **ESLint** enforces `@typescript-eslint/no-explicit-any` in `src/` and `tests/` — use it only in type declarations (`.d.ts`)
73
- - **No default exports** except the main `Fylo` class
74
- - Prefer `class` with `static` methods for modules (no standalone functions)
75
- - Use `_ttid` branded type for document IDs — never plain `string`
76
- - Prefix internal/test type names with underscore: `_post`, `_album`, `_storeQuery`
77
- - Type declarations live in `src/types/*.d.ts` — keep separate from implementation
78
-
79
- ## Build & Test
80
-
81
- ```bash
82
- bun test # Run all tests
83
- bun run build # Compile TypeScript
84
- bun run typecheck # Type-check without emitting
85
- bun run lint # ESLint
86
- ```
87
-
88
- - Tests use `bun:test` — `describe`, `test`, `expect`, `mock`, `beforeAll`, `afterAll`
89
- - S3 and Redis are mocked via `mock.module()` in every test file using `tests/mocks/s3.ts` and `tests/mocks/redis.ts`
90
- - Test schemas live in `tests/schemas/*.d.ts` as global `interface` declarations (generated by CHEX)
91
- - Test data URLs are centralized in `tests/data.ts`
92
-
93
- ## Conventions
94
-
95
- - Collection names may contain hyphens (e.g., `ec-test`, `jm-album`) — the parser supports this
96
- - Nested field access in SQL uses dot notation (`address.city`) which the parser converts to slash-separated paths (`address/city`)
97
- - `putData` creates documents; `patchDoc` updates them (deletes old keys, writes new ones)
98
- - `getDocData` retrieves keys for a specific TTID — filters by exact ID, not just prefix
99
- - Query `$ops` use OR semantics — a document matches if it satisfies at least one operator
100
- - `$limit` on queries without `$ops` uses S3 `maxKeys`; with `$ops` it post-filters after glob matching
101
-
102
- ## Environment Variables
103
-
104
- | Variable | Purpose |
105
- |----------|---------|
106
- | `BUCKET_PREFIX` | S3 bucket name prefix |
107
- | `S3_ACCESS_KEY_ID` / `AWS_ACCESS_KEY_ID` | S3 credentials |
108
- | `S3_SECRET_ACCESS_KEY` / `AWS_SECRET_ACCESS_KEY` | S3 credentials |
109
- | `S3_REGION` / `AWS_REGION` | S3 region |
110
- | `S3_ENDPOINT` / `AWS_ENDPOINT` | S3 endpoint (for compatible stores) |
111
- | `REDIS_URL` | Redis connection URL |
112
- | `LOGGING` | Enable debug logging |
113
- | `STRICT` | Enable schema validation via CHEX |
3
+ If a repo-local instruction file adds stricter rules, follow the repo-local rule.
@@ -1,49 +1,10 @@
1
1
  ---
2
- description: "Create a release branch, publish to npm via CI, then merge to main"
2
+ description: "Follow the shared workspace release process"
3
3
  agent: "agent"
4
4
  tools: [runInTerminal]
5
5
  ---
6
- Create a release branch, publish to npm via CI, then merge to main.
6
+ Follow the shared workspace release process in [../../../RELEASE.md](../../../RELEASE.md).
7
7
 
8
- 1. Run `bun test` and stop if any tests fail.
8
+ Use the repo's actual default branch. Do not assume it is `main`.
9
9
 
10
- 2. Determine the new version automatically based on unreleased commits:
11
- `git log $(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)..HEAD --oneline`
12
-
13
- Apply these rules to select the bump type:
14
- - **major** — any commit with a `!` breaking-change marker (e.g. `feat!:`, `fix!:`) or a `BREAKING CHANGE` footer.
15
- - **minor** — one or more `feat:` commits and no breaking changes.
16
- - **patch** — only `fix:`, `chore:`, `docs:`, `refactor:`, `test:`, or `perf:` commits.
17
-
18
- Compute the new version by incrementing the corresponding part of the current `"version"` in [package.json](package.json) and resetting lower parts to zero. Show the chosen version and the reasoning to the user before proceeding.
19
-
20
- 3. Update `"version"` in [package.json](package.json) to the new version.
21
-
22
- 4. Fetch the latest main and create a release branch from it:
23
- ```
24
- git fetch origin main
25
- git checkout -b release/<version> origin/main
26
- ```
27
-
28
- 5. Stage all changes and commit:
29
- `git add -A && git commit -m "chore: release v<version>"`
30
-
31
- 6. Push the branch:
32
- `git push -u origin release/<version>`
33
-
34
- 7. Tell the user that the `publish` workflow will now run on GitHub Actions:
35
- - It verifies the branch name matches `package.json` version.
36
- - It runs tests, publishes to npm, creates a git tag, and opens a GitHub release.
37
- - The NPM_TOKEN secret must be set in repo Settings → Secrets → Actions.
38
-
39
- 8. Once the workflow passes (user confirms), create a PR and merge it to main:
40
- ```
41
- gh pr create --title "chore: release v<version>" --body "Release v<version>" --base main --head release/<version>
42
- gh pr merge --merge --delete-branch
43
- ```
44
-
45
- 9. Switch back to main and pull:
46
- ```
47
- git checkout main
48
- git pull
49
- ```
10
+ If repo-local workflows impose stricter checks or branch requirements, follow the repo-local workflow and then update the shared release guide later if that rule becomes the new standard.
package/AGENTS.md ADDED
@@ -0,0 +1,3 @@
1
+ Follow the shared workspace instructions in [../INSTRUCTIONS.md](../INSTRUCTIONS.md), shared context in [../MEMORY.md](../MEMORY.md), and shared release process in [../RELEASE.md](../RELEASE.md).
2
+
3
+ Repo-local rules may add to or override the shared files when explicitly stated.
package/CLAUDE.md ADDED
@@ -0,0 +1,3 @@
1
+ Follow the shared workspace instructions in [../INSTRUCTIONS.md](../INSTRUCTIONS.md), shared context in [../MEMORY.md](../MEMORY.md), and shared release process in [../RELEASE.md](../RELEASE.md).
2
+
3
+ Repo-local rules may add to or override the shared files when explicitly stated.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delma/fylo",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/types/index.d.ts",
6
6
  "bin": {
@@ -25,8 +25,8 @@
25
25
  "prettier": "^3.0.0"
26
26
  },
27
27
  "dependencies": {
28
- "@vyckr/ttid": "1.3.1",
29
- "@vyckr/chex": "0.3.0"
28
+ "@delma/ttid": "1.3.4",
29
+ "@delma/chex": "0.3.3"
30
30
  },
31
31
  "type": "module",
32
32
  "peerDependencies": {
@@ -36,7 +36,7 @@
36
36
  "type": "git",
37
37
  "url": "git+https://github.com/Chidelma/Fylo.git"
38
38
  },
39
- "homepage": "https://fylo.vyckr.com",
39
+ "homepage": "https://fylo.del.ma",
40
40
  "license": "MIT",
41
41
  "keywords": [
42
42
  "storage",
@@ -1,5 +1,5 @@
1
1
  import { Walker } from "./walker"
2
- import TTID from "@vyckr/ttid"
2
+ import TTID from "@delma/ttid"
3
3
  import { S3 } from "../adapters/s3"
4
4
  import { Redis } from "../adapters/redis"
5
5
  import { Cipher } from "../adapters/cipher"
@@ -1,4 +1,4 @@
1
- import TTID from '@vyckr/ttid'
1
+ import TTID from '@delma/ttid'
2
2
 
3
3
  class Format {
4
4
  static table(docs: Record<string, any>) {
@@ -1,5 +1,5 @@
1
1
  import { S3 } from "../adapters/s3"
2
- import TTID from "@vyckr/ttid"
2
+ import TTID from "@delma/ttid"
3
3
  import { Redis } from "../adapters/redis"
4
4
 
5
5
  export class Walker {
package/src/index.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  import { Query } from './core/query'
3
3
  import { Parser } from './core/parser'
4
4
  import { Dir } from "./core/directory";
5
- import TTID from '@vyckr/ttid';
6
- import Gen from "@vyckr/chex"
5
+ import TTID from '@delma/ttid';
6
+ import Gen from "@delma/chex"
7
7
  import { Walker } from './core/walker';
8
8
  import { S3 } from "./adapters/s3"
9
9
  import { Cipher } from "./adapters/cipher"
@@ -26,7 +26,7 @@ interface Console {
26
26
 
27
27
  type _joinDocs<T, U> = _ttid[] | Record<string, _ttid[]> | Record<string, Record<_ttid, Partial<T | U>>> | Record<`${_ttid}, ${_ttid}`, T | U | (T & U) | (Partial<T> & Partial<U>)>
28
28
 
29
- declare module "@vyckr/fylo" {
29
+ declare module "@delma/fylo" {
30
30
 
31
31
  export default class {
32
32
 
@@ -1,3 +1,3 @@
1
1
  /// <reference path="./query.d.ts" />
2
2
  /// <reference path="./fylo.d.ts" />
3
- /// <reference types="@vyckr/ttid" />
3
+ /// <reference types="@delma/ttid" />
@@ -0,0 +1,31 @@
1
+ declare module "@delma/ttid" {
2
+
3
+ export type _ttid = string | `${string}-${string}` | `${string}-${string}-${string}`
4
+
5
+ export interface _timestamps {
6
+ createdAt: number
7
+ updatedAt?: number
8
+ deletedAt?: number
9
+ }
10
+
11
+ export default class TTID {
12
+ static isTTID(_id: string): Date | null
13
+ static isUUID(_id: string): RegExpMatchArray | null
14
+ static generate(_id?: string, del?: boolean): _ttid
15
+ static decodeTime(_id: string): _timestamps
16
+ }
17
+ }
18
+
19
+ declare module "@delma/chex" {
20
+
21
+ export default class Gen {
22
+ static generateDeclaration(json: unknown, interfaceName?: string): string
23
+ static sanitizePropertyName(key: string): string
24
+ static fromJsonString(jsonString: string, interfaceName?: string): string
25
+ static fromObject(obj: unknown, interfaceName?: string): string
26
+ static validateData<T extends Record<string, unknown>>(collection: string, data: T): Promise<T>
27
+ }
28
+ }
29
+
30
+ type _ttid = import("@delma/ttid")._ttid
31
+ type _timestamps = import("@delma/ttid")._timestamps
package/tests/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Redis } from '../src/adapters/redis'
2
- import ttid from '@vyckr/ttid'
2
+ import ttid from '@delma/ttid'
3
3
 
4
4
  const redisPub = new Redis()
5
5
  const redisSub = new Redis()
@@ -16,4 +16,4 @@ await Bun.sleep(1000)
16
16
 
17
17
  for await (const data of redisSub.subscribe("bun")) {
18
18
  console.log("Received:", data)
19
- }
19
+ }
@@ -1,6 +1,6 @@
1
1
  import { test, expect, describe, beforeAll, afterAll, mock } from 'bun:test'
2
2
  import Fylo from '../../src'
3
- import TTID from '@vyckr/ttid'
3
+ import TTID from '@delma/ttid'
4
4
  import S3Mock from '../mocks/s3'
5
5
  import RedisMock from '../mocks/redis'
6
6
 
package/tsconfig.json CHANGED
@@ -12,8 +12,8 @@
12
12
  "noFallthroughCasesInSwitch": true,
13
13
  "noImplicitReturns": true,
14
14
  "forceConsistentCasingInFileNames": true,
15
- "types": ["bun-types", "node", "@vyckr/ttid"],
15
+ "types": ["bun-types", "node"],
16
16
  "isolatedModules": true,
17
17
  "skipLibCheck": true
18
18
  }
19
- }
19
+ }
@@ -1,19 +0,0 @@
1
- ---
2
- description: "Create a GitHub issue for a bug or feature request"
3
- argument-hint: "Describe the bug or feature request"
4
- agent: "agent"
5
- tools: [runInTerminal]
6
- ---
7
- Create a GitHub issue. The user's description is provided as the argument.
8
-
9
- Determine whether the description sounds like a bug or a feature request, then create the issue with `gh issue create` using the following structure:
10
-
11
- **For a bug:**
12
- - Title: "fix: <short description>"
13
- - Body sections: **Describe the bug**, **Steps to reproduce**, **Expected behaviour**, **Actual behaviour**, **Possible cause** (reference relevant lines in `src/index.ts` if applicable), **Environment** (Bun version, TypeScript version, AWS/S3 endpoint details).
14
-
15
- **For a feature request:**
16
- - Title: "feat: <short description>"
17
- - Body sections: **Problem**, **Proposed solution**, **Alternatives considered**, **Affected API** (list any methods in `src/types/fylo.d.ts` or `src/types/query.d.ts` that would change).
18
-
19
- Apply the appropriate label (`bug` or `enhancement`) via `--label`. Print the issue URL when done.
@@ -1,18 +0,0 @@
1
- ---
2
- description: "Create a pull request for the current branch into main"
3
- agent: "agent"
4
- tools: [runInTerminal]
5
- ---
6
- Create a pull request for the current branch into `main`.
7
-
8
- 1. Run `git status` and stop if there are uncommitted changes — ask the user to commit or stash them first.
9
- 2. Run `git log main..HEAD --oneline` to list commits on this branch.
10
- 3. Run `git diff main...HEAD` to understand all changes.
11
- 4. Push the branch to origin if it has no upstream: `git push -u origin HEAD`.
12
- 5. Create the PR with `gh pr create` using:
13
- - A concise title (≤ 70 chars) derived from the branch name and commits.
14
- - A body with three sections:
15
- - **Summary** — bullet list of what changed and why.
16
- - **Test plan** — checklist of how to verify the changes (reference `bun test` where relevant).
17
- - **Breaking changes** — any changes to public API in [src/types/fylo.d.ts](src/types/fylo.d.ts) or [src/types/query.d.ts](src/types/query.d.ts); write "None" if there are none.
18
- 6. Print the PR URL.
@@ -1,19 +0,0 @@
1
- ---
2
- description: "Review a pull request by number or URL"
3
- argument-hint: "PR number or URL (e.g. 42)"
4
- agent: "agent"
5
- tools: [runInTerminal]
6
- ---
7
- Review the pull request given as an argument (PR number or URL).
8
-
9
- 1. Fetch the PR details: `gh pr view <arg> --json title,body,headRefName,baseRefName,files`
10
- 2. Fetch the diff: `gh pr diff <arg>`
11
- 3. Review the changes with focus on:
12
- - **Correctness** — logic errors, edge cases missed in query parsing ([src/core/parser.ts](src/core/parser.ts)), S3 operations ([src/adapters/s3.ts](src/adapters/s3.ts)), or directory/index management ([src/core/directory.ts](src/core/directory.ts)).
13
- - **Type safety** — use of `any` instead of `unknown`, missing type guards, incorrect use of types in [src/types/](src/types/).
14
- - **Tests** — whether new behaviour is covered in [tests/](tests/); flag any missing cases across document, collection, or schema tests.
15
- - **Public API** — unintended changes to [src/types/fylo.d.ts](src/types/fylo.d.ts) or [src/types/query.d.ts](src/types/query.d.ts).
16
- - **CI** — whether the workflow files in [.github/workflows/](.github/workflows/) are still valid for the change.
17
- 4. Post the review as inline comments using `gh pr review <arg> --comment --body "<feedback>"`.
18
- Group feedback by file. Prefix each point with **[suggestion]**, **[issue]**, or **[nit]**.
19
- 5. Summarise the overall verdict: Approve / Request changes / Comment only.
@@ -1,14 +0,0 @@
1
- ---
2
- description: "Rebase the current branch onto the latest main from origin"
3
- agent: "agent"
4
- tools: [runInTerminal]
5
- ---
6
- Safely bring the current branch up to date with the latest `main` from origin.
7
-
8
- 1. Confirm the current branch with `git branch --show-current`. If already on `main`, just run `git pull` and stop.
9
- 2. Stash any uncommitted changes with `git stash push -m "sync-main auto-stash"` and note whether anything was stashed.
10
- 3. Fetch the latest: `git fetch origin main`.
11
- 4. Rebase the current branch onto `origin/main`: `git rebase origin/main`.
12
- 5. If the rebase has conflicts, list the conflicting files and stop — ask the user to resolve them, then run `git rebase --continue`.
13
- 6. If a stash was created in step 2, restore it with `git stash pop`.
14
- 7. Report: commits rebased, files changed, any stash restored.