@jimhoyd/urlcode 0.4.0-alpha.1 → 0.4.0-alpha.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.
- package/.claude/skills/urlcode-authoring/SKILL.md +24 -8
- package/.claude/skills/urlcode-operations/SKILL.md +10 -16
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +75 -62
- package/ROADMAP.md +61 -16
- package/SECURITY.md +23 -8
- package/dist/BUILD-MANIFEST.json +38 -43
- package/dist/agents-guide.js +18 -18
- package/dist/build-static.js +134 -0
- package/dist/capabilities.js +85 -31
- package/dist/capability-query.js +0 -1
- package/dist/cli.js +23 -31
- package/dist/compliance-rules/baseline.js +2 -10
- package/dist/compliance-rules/privacy.js +5 -16
- package/dist/compliance-rules/shared.js +0 -2
- package/dist/compliance.js +6 -8
- package/dist/config.js +15 -8
- package/dist/context.js +9 -10
- package/dist/examples.js +2 -2
- package/dist/explain-cli.js +3 -3
- package/dist/explain.js +5 -6
- package/dist/extensions.js +61 -2
- package/dist/function-sources.js +34 -2
- package/dist/function-worker.js +3 -1
- package/dist/functions.js +84 -13
- package/dist/guest-api.js +29 -3
- package/dist/index.js +3 -6
- package/dist/manifest.js +5 -7
- package/dist/mcp.js +1 -1
- package/dist/observability.js +1 -21
- package/dist/policies/cache.js +8 -3
- package/dist/policy.js +28 -9
- package/dist/project-tests.js +3 -3
- package/dist/readiness.js +32 -9
- package/dist/router.js +5 -7
- package/dist/runtime.js +77 -58
- package/dist/sandbox.js +48 -0
- package/dist/scaffold.js +0 -0
- package/dist/scripts/operational-drills.js +12 -54
- package/dist/server.js +3 -29
- package/dist/tooling.js +1 -1
- package/dist/trusted-functions.js +210 -0
- package/dist/types/build-static.d.ts +43 -0
- package/dist/types/capabilities.d.ts +14 -5
- package/dist/types/compliance-rules/shared.d.ts +0 -2
- package/dist/types/compliance.d.ts +0 -3
- package/dist/types/config.d.ts +2 -1
- package/dist/types/context.d.ts +2 -1
- package/dist/types/examples.d.ts +1 -1
- package/dist/types/extensions.d.ts +55 -0
- package/dist/types/function-sources.d.ts +4 -0
- package/dist/types/functions.d.ts +48 -5
- package/dist/types/guest-api.d.ts +1 -0
- package/dist/types/index.d.ts +3 -6
- package/dist/types/manifest.d.ts +1 -3
- package/dist/types/observability.d.ts +1 -14
- package/dist/types/project-tests.d.ts +1 -2
- package/dist/types/readiness.d.ts +10 -3
- package/dist/types/router.d.ts +2 -1
- package/dist/types/runtime.d.ts +0 -27
- package/dist/types/sandbox.d.ts +12 -0
- package/dist/types/scaffold.d.ts +0 -2
- package/dist/types/server.d.ts +1 -4
- package/dist/types/tooling.d.ts +3 -3
- package/dist/types/trusted-functions.d.ts +29 -0
- package/dist/types/types.d.ts +14 -7
- package/dist/types/verify-deployment.d.ts +2 -2
- package/dist/types.js +17 -4
- package/dist/typescript-authoring.js +55 -17
- package/dist/verify-deployment.js +3 -3
- package/docs/AI-AUTHORING.md +104 -9
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +3 -2
- package/docs/CAPABILITIES.md +29 -16
- package/docs/CAPACITY.md +128 -31
- package/docs/CLOUDFLARE.md +1 -2
- package/docs/COMPLIANCE.md +6 -9
- package/docs/DEPLOYMENT-CHECKS.md +1 -1
- package/docs/EXTENSIONS.md +183 -11
- package/docs/FRAMEWORK.md +35 -19
- package/docs/FUNCTION-SECURITY.md +129 -32
- package/docs/INSTALL.md +0 -5
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/MIDDLEWARE.md +27 -16
- package/docs/MONITORING.md +2 -19
- package/docs/NEXT-PHASE-PLAN.md +12 -4
- package/docs/NEXT-STEPS.md +259 -40
- package/docs/OBSERVABILITY.md +7 -16
- package/docs/OPEN-DECISIONS.md +212 -0
- package/docs/OPERATIONAL-PROOF.md +26 -30
- package/docs/OPERATIONS.md +23 -32
- package/docs/POLICIES.md +15 -4
- package/docs/PRERENDER.md +2 -2
- package/docs/PROJECT-DIRECTION.md +34 -9
- package/docs/README.md +13 -11
- package/docs/RELEASE-READINESS.md +49 -29
- package/docs/RELEASE-SECURITY.md +89 -3
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +8 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +40 -0
- package/docs/SPECIFICATION.md +60 -26
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +287 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +8 -0
- package/docs/SPIKE-CORE-LAYERING.md +337 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +209 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +2 -2
- package/docs/SPIKE-EXTENSIONS.md +5 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +4 -2
- package/docs/SPIKE-MONOREPO.md +322 -0
- package/docs/STARTERS.md +1 -1
- package/docs/STATIC.md +94 -0
- package/docs/TOOLING.md +13 -9
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +27 -12
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/USABILITY-REVIEW.md +7 -1
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +205 -0
- package/docs/YAML-GUIDE.md +0 -3
- package/docs/YAML-REFERENCE.md +16 -6
- package/docs/policies/cache.md +13 -0
- package/examples/assets/example.yaml +1 -1
- package/examples/aws/example.yaml +1 -1
- package/examples/cloudflare/example.yaml +1 -1
- package/examples/conditions/example.yaml +1 -1
- package/examples/cookbook/example.yaml +1 -1
- package/examples/cookbook/middleware/bucket.mjs +12 -2
- package/examples/cookbook/middleware/locale.mjs +7 -3
- package/examples/egress/example.yaml +1 -1
- package/examples/extensions/example.yaml +1 -1
- package/examples/prerender/README.md +2 -2
- package/examples/prerender/example.yaml +1 -1
- package/examples/provider-conformance/example.yaml +1 -1
- package/examples/vercel/example.yaml +1 -1
- package/llms-full.txt +594 -219
- package/llms.txt +23 -12
- package/package.json +10 -3
- package/packaging/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +24 -8
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +10 -16
- package/recipes/authenticated-json-api/recipe.yaml +1 -1
- package/recipes/contact-form/recipe.yaml +1 -1
- package/recipes/cors-api/recipe.yaml +1 -1
- package/recipes/health-page/recipe.yaml +1 -1
- package/recipes/json-api/recipe.yaml +1 -1
- package/recipes/middleware/middleware/bucket.mjs +12 -2
- package/recipes/middleware/middleware/locale.mjs +7 -3
- package/recipes/middleware/recipe.yaml +1 -1
- package/recipes/protected-download/recipe.yaml +1 -1
- package/recipes/redirect/recipe.yaml +1 -1
- package/recipes/static-plus-api/recipe.yaml +1 -1
- package/recipes/typescript/README.md +2 -1
- package/recipes/typescript/recipe.yaml +1 -1
- package/recipes/webhook-receiver/README.md +5 -1
- package/recipes/webhook-receiver/recipe.yaml +2 -1
- package/recipes/webhook-receiver/urlcode.yaml +7 -0
- package/schemas/recipe.schema.json +4 -3
- package/schemas/urlcode.schema.json +14 -41
- package/skills/urlcode/SKILL.md +29 -8
- package/starters/default/AGENTS.md +18 -18
- package/starters/default/urlcode.yaml +0 -1
- package/dist/link-api.js +0 -136
- package/dist/link-cli.js +0 -141
- package/dist/link-events.js +0 -76
- package/dist/link-records.js +0 -31
- package/dist/link-store-worker.js +0 -150
- package/dist/link-store.js +0 -250
- package/dist/management-policy.js +0 -40
- package/dist/sqlite-version.js +0 -6
- package/dist/types/link-api.d.ts +0 -30
- package/dist/types/link-cli.d.ts +0 -37
- package/dist/types/link-events.d.ts +0 -27
- package/dist/types/link-records.d.ts +0 -11
- package/dist/types/link-store-worker.d.ts +0 -1
- package/dist/types/link-store.d.ts +0 -130
- package/dist/types/management-policy.d.ts +0 -8
- package/dist/types/sqlite-version.d.ts +0 -1
- package/docs/DYNAMIC-LINKS.md +0 -61
- package/docs/MANAGEMENT-SECURITY.md +0 -82
- package/docs/links/cli.md +0 -110
- package/docs/links/limits.md +0 -175
- package/docs/links/management-api.md +0 -80
- package/docs/links/pools.md +0 -75
- package/docs/links/setup.md +0 -135
- package/docs/yaml/links.md +0 -30
- package/examples/live-links/README.md +0 -11
- package/examples/live-links/example.yaml +0 -21
- package/examples/live-links/tests/requests.json +0 -6
- package/examples/live-links/urlcode.yaml +0 -16
package/docs/links/pools.md
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Dynamic links: Reader and writer pools
|
|
2
|
-
|
|
3
|
-
Part of [dynamic links](../DYNAMIC-LINKS.md), which indexes every page.
|
|
4
|
-
|
|
5
|
-
## Separate reader and writer pools
|
|
6
|
-
|
|
7
|
-
Pool sizes are operator infrastructure settings, not portable behavior YAML.
|
|
8
|
-
`dynamicLinks: true` and logical collection names stay the same across targets.
|
|
9
|
-
|
|
10
|
-
```sh
|
|
11
|
-
urlcode serve --project ./my-links \
|
|
12
|
-
--link-store links=/absolute/links.sqlite \
|
|
13
|
-
--link-readers 4 --link-read-limit 32
|
|
14
|
-
|
|
15
|
-
urlcode links api --project ./my-links \
|
|
16
|
-
--store /absolute/links.sqlite --token-file /absolute/link-admin.token \
|
|
17
|
-
--link-readers 2 --link-read-limit 16 --link-write-limit 8
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
| Control | Default | Meaning |
|
|
21
|
-
|---|---|---|
|
|
22
|
-
| `--link-readers` / JS `readers` | 2 | 1–8 read-only connections per store instance |
|
|
23
|
-
| `--link-read-limit` / JS `maxReads` | 32 | 1–32 admitted reads across all readers, not per reader |
|
|
24
|
-
| `--link-write-limit` / JS `maxWrites` | 32 | 1–32 admitted mutations across the single writer |
|
|
25
|
-
|
|
26
|
-
`get` and `list` use the least-busy healthy reader. `create`, `update` and `delete`
|
|
27
|
-
use the writer. Each worker serializes its own accepted operations. There is no
|
|
28
|
-
additional unbounded acquisition queue. A read flood cannot take writer admission
|
|
29
|
-
and a mutation backlog cannot take reader admission. CPU, disk, database locks
|
|
30
|
-
and the event loop remain shared resources: separation is not an isolation SLA.
|
|
31
|
-
A write response resolves after commit; a subsequent awaited read sees committed
|
|
32
|
-
data on the same database. Reads started before the commit may see the old value.
|
|
33
|
-
There is no replica lag or application cache in this adapter.
|
|
34
|
-
|
|
35
|
-
`openLinkStore({file, project, readOnly, readers, maxReads, maxWrites})` exposes
|
|
36
|
-
`stats()` with separate read/write connection counts, healthy counts, in-flight
|
|
37
|
-
counts, limits, completed/failed/rejected totals and cumulative durationMs. These
|
|
38
|
-
process-local counters reset at restart and are for trusted operator monitoring;
|
|
39
|
-
there is no public metrics endpoint/exporter yet. `readHealthy` and `writeHealthy`
|
|
40
|
-
are separate. Public runtime readiness uses `readHealthy` when available; management
|
|
41
|
-
operators must monitor writer health separately. A read-only pool has zero writers
|
|
42
|
-
and rejects mutations. Shutdown drains both groups and rejects new admission.
|
|
43
|
-
|
|
44
|
-
Do not multiply connection counts blindly across processes: N public replicas at
|
|
45
|
-
R readers use N×R connections, plus management readers/writers. Each connection
|
|
46
|
-
has its own worker and memory budget. Measure mixed load and lock contention;
|
|
47
|
-
adding readers can reduce performance on an already saturated disk.
|
|
48
|
-
|
|
49
|
-
SQLite WAL supports simultaneous readers and a single active writer across the
|
|
50
|
-
database. Multiple writer connections cannot create parallel write throughput.
|
|
51
|
-
All connections must access the same local database on one host; never mount it
|
|
52
|
-
across hosts over a network filesystem. See [SQLite WAL](https://www.sqlite.org/wal.html).
|
|
53
|
-
We require a Node build with SQLite 3.51.3+ or patched branches 3.50.7+/3.44.6+
|
|
54
|
-
to avoid the documented [WAL-reset concurrency bug](https://www.sqlite.org/wal.html#the_wal_reset_bug).
|
|
55
|
-
Live-link initialization checks this before opening files and verifies WAL mode.
|
|
56
|
-
Use `urlcode doctor` to inspect the bundled SQLite version; upgrade Node when
|
|
57
|
-
rejected. Static YAML projects do not require SQLite.
|
|
58
|
-
|
|
59
|
-
For multi-host scaling, a future server-database adapter must provide distinct
|
|
60
|
-
read/write credentials and pool budgets, connect/acquire/query deadlines,
|
|
61
|
-
transactional version checks, primary-read or explicit replica consistency,
|
|
62
|
-
replica-lag monitoring, migration coordination, backup/restore and failover drills.
|
|
63
|
-
These are adapter acceptance requirements, not implemented PostgreSQL support.
|
|
64
|
-
Keep writes on the primary and avoid automatic retries of ambiguous commits.
|
|
65
|
-
The existing operator adapter boundary remains available, but deploying a custom
|
|
66
|
-
adapter requires its own conformance/load/recovery evidence.
|
|
67
|
-
|
|
68
|
-
## Shutdown and management defaults
|
|
69
|
-
|
|
70
|
-
`links api` defaults to private address `127.0.0.1:3001`; public serving defaults
|
|
71
|
-
to port 3000. Endpoint method errors return 405 with an `Allow` header.
|
|
72
|
-
Store shutdown rejects new work, drains accepted operations within each connection and
|
|
73
|
-
then closes SQLite. Repeated `close()` calls share completion. Existing operation
|
|
74
|
-
deadlines still apply: a timeout can leave a mutation outcome unknown, so read
|
|
75
|
-
the record before retrying. Missing/invalid revision metadata rejects startup.
|
package/docs/links/setup.md
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# Dynamic links: Setup: requirements, YAML and the example
|
|
2
|
-
|
|
3
|
-
Part of [dynamic links](../DYNAMIC-LINKS.md), which indexes every page.
|
|
4
|
-
|
|
5
|
-
## Node build requirement
|
|
6
|
-
|
|
7
|
-
Live links need a Node build carrying the patched SQLite WAL fix: SQLite 3.51.3
|
|
8
|
-
or newer, 3.50.7 or 3.44.6. Node bundles SQLite, so this is a property of the
|
|
9
|
-
build, not something you can install separately, and some current releases on a
|
|
10
|
-
supported Node line ship an unpatched version. Run `urlcode doctor` and check
|
|
11
|
-
`liveLinks`; activation fails closed and names the detected version when the
|
|
12
|
-
build is unsuitable. Everything except live links works on any supported Node.
|
|
13
|
-
|
|
14
|
-
Available in URLCode 0.1.0. Define a stable route once; create, update and delete
|
|
15
|
-
short-code records while `serve` keeps running. No YAML rewrite, route snapshot
|
|
16
|
-
rebuild, Git commit or public-server restart is needed for record changes.
|
|
17
|
-
|
|
18
|
-
This first adapter uses optional SQLite storage on one host. Multiple processes
|
|
19
|
-
on that host can share it. No database is required for ordinary YAML-defined
|
|
20
|
-
routes. Network filesystems, multi-host replication and serverless ephemeral disks
|
|
21
|
-
are not supported by this adapter. SQLite WAL requires processes on the same
|
|
22
|
-
host; see [SQLite WAL](https://www.sqlite.org/wal.html).
|
|
23
|
-
|
|
24
|
-
## Behavior in YAML, data outside Git
|
|
25
|
-
|
|
26
|
-
```yaml
|
|
27
|
-
version: "1"
|
|
28
|
-
dynamicLinks: true
|
|
29
|
-
routes:
|
|
30
|
-
/r/{code}:
|
|
31
|
-
parameters:
|
|
32
|
-
- name: code
|
|
33
|
-
in: path
|
|
34
|
-
required: true
|
|
35
|
-
schema: {type: string, minLength: 1, maxLength: 128}
|
|
36
|
-
link:
|
|
37
|
-
collection: links
|
|
38
|
-
code: {from: path, name: code}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
`link` is a seventh primary handler, exclusive with `function`, `redirect`,
|
|
42
|
-
`respond`, `page`, `static` and `download`. Its `code` is a declared path-input
|
|
43
|
-
reference. `collection` is a logical name, not a filesystem path. GET and HEAD
|
|
44
|
-
are supported; normal route precedence, lifecycle and input validation apply.
|
|
45
|
-
An exact YAML route can intentionally shadow a stored code's URL.
|
|
46
|
-
|
|
47
|
-
The operator binds `links` to a database outside the project. YAML cannot choose
|
|
48
|
-
a database file or grant itself storage. The built-in public binding opens it
|
|
49
|
-
read-only. It performs an indexed database lookup for each request, with no
|
|
50
|
-
application cache or negative cache. Requests starting after an acknowledged
|
|
51
|
-
mutation can see it immediately; an already-running request can finish with an
|
|
52
|
-
older result. Browser/proxy caches remain outside that guarantee.
|
|
53
|
-
|
|
54
|
-
Missing or disabled record: 404. Expired record: 410. Unavailable/overloaded
|
|
55
|
-
store: 503. Invalid code syntax: 404 after route input validation. Redirects
|
|
56
|
-
default to 302 and no-store. Query strings are not forwarded. A record's URL is
|
|
57
|
-
literal HTTP(S), with no embedded credentials, control characters or interpolation.
|
|
58
|
-
It is a redirect, not a server-side fetch. The store does not verify destination
|
|
59
|
-
ownership, safety or availability; application abuse prevention remains necessary.
|
|
60
|
-
|
|
61
|
-
## Run the included example
|
|
62
|
-
|
|
63
|
-
From the runtime checkout, choose a private data directory **outside the app**.
|
|
64
|
-
Its parent directory must already exist. The following POSIX-shell example uses
|
|
65
|
-
an operator-created directory; on Windows use an absolute local drive path.
|
|
66
|
-
|
|
67
|
-
```sh
|
|
68
|
-
mkdir -p ../urlcode-data
|
|
69
|
-
URLCODE_DATA="$(cd ../urlcode-data && pwd)"
|
|
70
|
-
node src/cli.ts links init --store "$URLCODE_DATA/links.sqlite"
|
|
71
|
-
node src/cli.ts links create --store "$URLCODE_DATA/links.sqlite" \
|
|
72
|
-
--code demo --destination https://example.com/demo
|
|
73
|
-
node src/cli.ts serve --project examples/live-links \
|
|
74
|
-
--link-store "links=$URLCODE_DATA/links.sqlite" --port 3000
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Open `/r/demo`. In a second terminal, run another `links create` with an unused
|
|
78
|
-
code against the same absolute file; its URL works immediately. Omit `--code`
|
|
79
|
-
to generate a cryptographically random 16-character base64url code. Codes allow
|
|
80
|
-
1–128 letters, digits, underscores and hyphens; collection names begin with a
|
|
81
|
-
letter and contain at most 64 letters/digits/underscores/hyphens.
|
|
82
|
-
|
|
83
|
-
The CLI defaults to collection `links`; specify `--collection` to manage another.
|
|
84
|
-
Serving currently accepts one `--link-store collection=/absolute/file` binding;
|
|
85
|
-
embedded applications may supply multiple adapters. Commands do not copy records
|
|
86
|
-
into YAML or create route definitions automatically.
|
|
87
|
-
|
|
88
|
-
## Explicit project opt-in
|
|
89
|
-
|
|
90
|
-
Only the entry `urlcode.yaml` may set `dynamicLinks: true`. It defaults to false;
|
|
91
|
-
the starter writes `dynamicLinks: false` explicitly. Included route files cannot
|
|
92
|
-
set or override it. Any `link` handler, including a disabled route, or runtime
|
|
93
|
-
link-store binding requires the opt-in. This flag means live stored-link records,
|
|
94
|
-
not parameterized redirects, custom functions, middleware or development reload.
|
|
95
|
-
|
|
96
|
-
`validate`, `routes`, `audit` and `scaffold` reports expose `dynamicLinks` as a
|
|
97
|
-
boolean. Enabling it grants no storage access to guest code and starts no
|
|
98
|
-
management endpoint. The operator still supplies the external store binding;
|
|
99
|
-
management remains a separate authenticated service. Standalone `links` CRUD/API
|
|
100
|
-
commands operate the operator's store independently of this public-runtime flag.
|
|
101
|
-
|
|
102
|
-
Migration: existing live-link projects must add `dynamicLinks: true` to their
|
|
103
|
-
entry file. Refresh revision-pinned function policies for those projects using
|
|
104
|
-
the normal operator review flow; enabling the capability changes the approval
|
|
105
|
-
digest. Projects that omit it or explicitly set false retain their prior digest.
|
|
106
|
-
To disable, remove `link` declarations and serving-store bindings, then set false
|
|
107
|
-
and validate/redeploy. Editing the flag alone does not stop an already running
|
|
108
|
-
production process or management API. Invalid reloads retain the last-good state.
|
|
109
|
-
|
|
110
|
-
## Middleware, sandbox and tests
|
|
111
|
-
|
|
112
|
-
Middleware may wrap a successful link response; the usual native metadata/body
|
|
113
|
-
rules apply. Lookup/missing/disabled/expiry errors happen before middleware. The
|
|
114
|
-
handler does not make database objects available to guest code. Functions still
|
|
115
|
-
have no filesystem, SQL, fetch, storage broker or management token capability.
|
|
116
|
-
Link changes do not alter configuration/source digests or invalidate unrelated
|
|
117
|
-
function-binding grants. Changing YAML still does.
|
|
118
|
-
|
|
119
|
-
`routes` and `audit --expect-routes` count definitions, not stored records. Link
|
|
120
|
-
routes require explicit successful GET/HEAD fixtures; there is no assumed fixture
|
|
121
|
-
for live data. Seed a disposable test database, then pass `--link-store` to
|
|
122
|
-
validate/test/audit/benchmark. Do not run mutation tests against production.
|
|
123
|
-
|
|
124
|
-
```sh
|
|
125
|
-
node src/cli.ts test --project examples/live-links --link-store links=/absolute/test-links.sqlite
|
|
126
|
-
node src/cli.ts audit --project examples/live-links --link-store links=/absolute/test-links.sqlite --expect-routes 2
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
The example expects `demo -> https://example.com/demo` and an unused `not-created`
|
|
130
|
-
code. Tests cover create/update/delete visibility without reload, persistence,
|
|
131
|
-
concurrent conflicts, expiry/disabled semantics, scope, public/admin separation,
|
|
132
|
-
body/token boundaries, overload and acknowledged writes after abrupt writer exit.
|
|
133
|
-
Production durability, sustained load and recovery drills still require validation
|
|
134
|
-
on your actual storage. General application state, WebRTC sessions, user-account
|
|
135
|
-
APIs and arbitrary runtime code registration remain separate future work.
|
package/docs/yaml/links.md
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# YAML guide: Live short-link records
|
|
2
|
-
|
|
3
|
-
Snippets are entries under `routes:` unless stated otherwise; the [guide index](../YAML-GUIDE.md) lists every page.
|
|
4
|
-
|
|
5
|
-
## 15. Live short-link records
|
|
6
|
-
|
|
7
|
-
Set `dynamicLinks: true` in the entry `urlcode.yaml` before adding this route.
|
|
8
|
-
It defaults to false and cannot be enabled by an included file.
|
|
9
|
-
|
|
10
|
-
```yaml
|
|
11
|
-
/r/{code}:
|
|
12
|
-
parameters:
|
|
13
|
-
- name: code
|
|
14
|
-
in: path
|
|
15
|
-
required: true
|
|
16
|
-
schema: {type: string, minLength: 1, maxLength: 128}
|
|
17
|
-
link:
|
|
18
|
-
collection: links
|
|
19
|
-
code: {from: path, name: code}
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
The seventh handler resolves stored records without rebuilding YAML. It requires
|
|
23
|
-
an external operator store binding; the [live-link example](../../examples/live-links/README.md)
|
|
24
|
-
has separate setup and fixtures. See [dynamic links](../DYNAMIC-LINKS.md) for CLI/API
|
|
25
|
-
creation, optimistic updates, disabled/expired records, persistence and backups.
|
|
26
|
-
This is not a general database capability for sandboxed functions.
|
|
27
|
-
|
|
28
|
-
Live-link recipes require `dynamicLinks: true` in the entry `urlcode.yaml`. It is
|
|
29
|
-
false by default and cannot be set in included route files. Parameterized routes
|
|
30
|
-
and functions alone do not need it. See [dynamic-link opt-in](../DYNAMIC-LINKS.md#explicit-project-opt-in).
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Live links without route reloads
|
|
2
|
-
|
|
3
|
-
Follow [the dynamic-link guide](../../docs/DYNAMIC-LINKS.md) to create an external
|
|
4
|
-
SQLite store and seed `demo -> https://example.com/demo`. Then start this project
|
|
5
|
-
with `--link-store links=/absolute/path/links.sqlite`. Its fixtures expect that
|
|
6
|
-
seed and an unused `not-created` code; use a disposable test store, not production.
|
|
7
|
-
|
|
8
|
-
Create/update/delete records through the CLI or separate authenticated API while
|
|
9
|
-
the public server keeps serving. YAML, code, route counts and health version do
|
|
10
|
-
not change per link. This example deliberately requires explicit operator storage
|
|
11
|
-
binding; the default starter still runs without a database.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
id: live-links
|
|
2
|
-
description: Stored links served from an external SQLite store without a route reload, with dynamicLinks enabled in the entry file.
|
|
3
|
-
tags: [links, live, dynamic, sqlite, store, short-links, link, redirect]
|
|
4
|
-
complexity: intermediate
|
|
5
|
-
capabilities: [dynamicLinks, enabled, link, methods, parameters, respond]
|
|
6
|
-
targets: {self-hosted: compatible, aws: refused, vercel: refused, cloudflare: refused}
|
|
7
|
-
routes: 2
|
|
8
|
-
services:
|
|
9
|
-
- name: link store
|
|
10
|
-
description: An operator-owned SQLite store passed as --link-store, seeded with demo -> https://example.com/demo.
|
|
11
|
-
grants:
|
|
12
|
-
- kind: link-store
|
|
13
|
-
description: The store binding is an operator flag, never a project file.
|
|
14
|
-
files: [urlcode.yaml, tests/requests.json, README.md]
|
|
15
|
-
tests:
|
|
16
|
-
fixtures: tests/requests.json
|
|
17
|
-
commands:
|
|
18
|
-
- node src/cli.ts links init --store /absolute/links.sqlite
|
|
19
|
-
- node src/cli.ts test --project examples/live-links --link-store links=/absolute/links.sqlite
|
|
20
|
-
behavior:
|
|
21
|
-
- "/r/{code} answers the stored destination for a seeded code and 404 for one that was never created"
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{"path":"/r/demo","status":302,"expectHeaders":{"location":"https://example.com/demo","cache-control":"no-store"}},
|
|
3
|
-
{"path":"/r/demo","method":"HEAD","status":302,"expectBody":"","expectHeaders":{"location":"https://example.com/demo"}},
|
|
4
|
-
{"path":"/r/not-created","status":404},
|
|
5
|
-
{"path":"/r/demo","method":"POST","status":405,"expectHeaders":{"allow":"GET, HEAD"}}
|
|
6
|
-
]
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# yaml-language-server: $schema=https://raw.githubusercontent.com/jimhoyd-com/urlcode/669632fb4f188f293a0f622847f87ee019c0627f/schemas/urlcode.schema.json
|
|
2
|
-
version: "1"
|
|
3
|
-
dynamicLinks: true
|
|
4
|
-
routes:
|
|
5
|
-
/r/{code}:
|
|
6
|
-
parameters:
|
|
7
|
-
- name: code
|
|
8
|
-
in: path
|
|
9
|
-
required: true
|
|
10
|
-
schema: {type: string, minLength: 1, maxLength: 128}
|
|
11
|
-
link:
|
|
12
|
-
collection: links
|
|
13
|
-
code: {from: path, name: code}
|
|
14
|
-
/about:
|
|
15
|
-
respond:
|
|
16
|
-
text: Links are stored separately from this YAML.
|