ampless 0.2.0-alpha.8 → 1.0.0-alpha.10

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/index.d.ts CHANGED
@@ -4,7 +4,6 @@ type SiteSettingsEventType = 'site.settings.updated';
4
4
  type EventType = ContentEventType | MediaEventType | SiteSettingsEventType;
5
5
  /** Minimal projection of a Post item carried in events (no body, to keep payloads small). */
6
6
  interface ContentEventPayload {
7
- siteId: string;
8
7
  postId: string;
9
8
  slug: string;
10
9
  title: string;
@@ -13,18 +12,16 @@ interface ContentEventPayload {
13
12
  tags?: string[];
14
13
  }
15
14
  interface MediaEventPayload {
16
- siteId: string;
17
15
  mediaId: string;
18
16
  src: string;
19
17
  mimeType: string;
20
18
  }
21
19
  /**
22
- * Emitted whenever any setting under `siteconfig:{siteId}` in KvStore
23
- * is created, updated, or removed. Subscribers (built-in or user
24
- * plugins) can rebuild caches, theme assets, etc.
20
+ * Emitted whenever any setting under the `siteconfig:` PK in KvStore is
21
+ * created, updated, or removed. Subscribers (built-in or user plugins)
22
+ * can rebuild caches, theme assets, etc.
25
23
  */
26
24
  interface SiteSettingsEventPayload {
27
- siteId: string;
28
25
  }
29
26
  type EventPayloadOf<T extends EventType> = T extends ContentEventType ? ContentEventPayload : T extends MediaEventType ? MediaEventPayload : T extends SiteSettingsEventType ? SiteSettingsEventPayload : never;
30
27
  interface AmplessEvent<T extends EventType = EventType> {
@@ -89,13 +86,12 @@ type PluginEventHandler<T extends EventType = EventType> = (event: AmplessEvent<
89
86
  * (sandbox, tests) without touching plugin code.
90
87
  */
91
88
  interface PluginRuntimeContext {
92
- siteId: string;
93
89
  /** Read-only view of the cms.config site block (name, url, description). */
94
90
  site: Config['site'];
95
- /** Read all published posts for the site (used by sitemap/RSS). */
91
+ /** Read all published posts (used by sitemap/RSS). */
96
92
  listPublishedPosts(): Promise<Post[]>;
97
93
  /**
98
- * Persist a file under `public/plugins/{pluginName}/{key}` in the site's
94
+ * Persist a file under `public/plugins/{pluginName}/{key}` in the
99
95
  * S3 bucket. Returns the public URL.
100
96
  */
101
97
  writePublicAsset(key: string, body: string | Uint8Array, contentType: string): Promise<string>;
@@ -157,9 +153,9 @@ interface AmplessPlugin {
157
153
  siteMetadata?(site: Config['site']): PluginMetadata;
158
154
  /**
159
155
  * Dynamic OG image renderer. The dispatcher route (e.g.
160
- * `app/site/[siteId]/og/[slug]/route.ts`) reads this and feeds the
161
- * element into Next.js `ImageResponse`. Only one plugin should set this
162
- * — the route resolves the first plugin in `cms.config.plugins` that
156
+ * `app/og/[slug]/route.ts`) reads this and feeds the element into
157
+ * Next.js `ImageResponse`. Only one plugin should set this — the
158
+ * route resolves the first plugin in `cms.config.plugins` that
163
159
  * declares `ogImage`.
164
160
  */
165
161
  ogImage?: OgImageConfig;
@@ -169,9 +165,9 @@ declare function definePlugin(p: AmplessPlugin): AmplessPlugin;
169
165
  type ContentFormat = 'tiptap' | 'markdown' | 'html' | 'static';
170
166
  /**
171
167
  * Body shape for `format: 'static'` posts. The actual asset bytes
172
- * live under S3 at `public/static/<siteId>/<slug>/<files...>` — the
173
- * body here is the manifest describing which entrypoint to serve and
174
- * which files are part of the bundle.
168
+ * live under S3 at `public/static/<slug>/<files...>` — the body here
169
+ * is the manifest describing which entrypoint to serve and which files
170
+ * are part of the bundle.
175
171
  *
176
172
  * Stored as JSON in the `body` column (same encoding pattern as the
177
173
  * tiptap doc / html string / markdown string for the other formats).
@@ -192,6 +188,22 @@ interface StaticPostBody {
192
188
  uploadedAt: string;
193
189
  }
194
190
  type PostStatus = 'draft' | 'published';
191
+ /**
192
+ * Per-post cache strategy. Middleware computes the response's
193
+ * Cache-Control header from this value (plus `post.updatedAt` for the
194
+ * `auto` case and the project's `cms.config.cache.*` knobs).
195
+ *
196
+ * - `'auto'` (default): cooldown by edit time. Posts updated within
197
+ * the cooldown window (`cms.config.cache.cooldownMs`, default 1h)
198
+ * emit a no-store header so editors see fresh content immediately.
199
+ * Older posts emit a long s-maxage so the CDN serves them cheaply.
200
+ * - `'deep'`: always long-cache (`cms.config.cache.deepTtlSeconds`,
201
+ * default 1h). Use for posts whose content is fixed for the
202
+ * foreseeable future.
203
+ * - `'hot'`: always no-store. Use for posts whose content is rapidly
204
+ * evolving or computed per request.
205
+ */
206
+ type CacheStrategy = 'auto' | 'deep' | 'hot';
195
207
  /**
196
208
  * Free-form per-post metadata. The `metadata` JSON column carries
197
209
  * arbitrary key/value pairs; the runtime / themes / plugins each pick
@@ -200,8 +212,13 @@ type PostStatus = 'draft' | 'published';
200
212
  *
201
213
  * Well-known keys:
202
214
  * - `no_layout`: when true, the public page is served as bare HTML
203
- * (no theme chrome). The runtime's post dispatcher checks this
204
- * before rendering and redirects to the raw route handler.
215
+ * (no theme chrome). Middleware rewrites the request to the
216
+ * unified internal route handler (`/r/<slug>`) for such posts
217
+ * and renders the body verbatim — no Next.js root layout, no
218
+ * theme chrome.
219
+ * - `cache`: see `CacheStrategy`. Overrides the default 'auto'
220
+ * cache strategy for this post. Independent of `no_layout` —
221
+ * applies uniformly to themed, no_layout, and static posts.
205
222
  *
206
223
  * Additional keys are passed through unchanged — themes and plugins
207
224
  * are free to store their own per-post state here (e.g. SEO overrides,
@@ -209,11 +226,11 @@ type PostStatus = 'draft' | 'published';
209
226
  */
210
227
  interface PostMetadata {
211
228
  no_layout?: boolean;
229
+ cache?: CacheStrategy;
212
230
  [key: string]: unknown;
213
231
  }
214
232
  interface Post {
215
233
  postId: string;
216
- siteId: string;
217
234
  slug: string;
218
235
  title: string;
219
236
  excerpt?: string;
@@ -223,10 +240,18 @@ interface Post {
223
240
  publishedAt?: string;
224
241
  tags?: string[];
225
242
  metadata?: PostMetadata;
243
+ /**
244
+ * DynamoDB auto-managed timestamp (ISO 8601). Surfaced through the
245
+ * `PublicPost` projection so middleware can compute the
246
+ * `metadata.cache='auto'` cooldown without re-fetching the model
247
+ * row. Absent on optimistically-constructed posts (e.g. test
248
+ * fixtures); the cache strategy treats absent values as "very old"
249
+ * and emits a long s-maxage.
250
+ */
251
+ updatedAt?: string;
226
252
  }
227
253
  interface Page {
228
254
  pageId: string;
229
- siteId: string;
230
255
  slug: string;
231
256
  title: string;
232
257
  format: ContentFormat;
@@ -236,7 +261,6 @@ interface Page {
236
261
  }
237
262
  interface Media {
238
263
  mediaId: string;
239
- siteId: string;
240
264
  src: string;
241
265
  mimeType: string;
242
266
  size: number;
@@ -261,21 +285,6 @@ interface MediaProcessingDefaults {
261
285
  /** Use lossless WebP for PNG inputs (default true). */
262
286
  losslessForPng?: boolean;
263
287
  }
264
- /**
265
- * Per-site override. The top-level `Config.site` provides defaults that
266
- * fall through when these are unset. `domains` is required because it's
267
- * how the middleware maps incoming requests to a siteId.
268
- */
269
- interface SiteConfig {
270
- /** Hostnames this site responds to (subdomains, separate apex domains, both fine). */
271
- domains: string[];
272
- /** Override `Config.site.name` for this site. */
273
- name?: string;
274
- /** Override `Config.site.url` (canonical) for this site. */
275
- url?: string;
276
- /** Override `Config.site.description` for this site. */
277
- description?: string;
278
- }
279
288
  interface Config {
280
289
  site: {
281
290
  name: string;
@@ -304,16 +313,9 @@ interface Config {
304
313
  * UI locale for the admin app. The scaffolded project ships
305
314
  * `locales/<code>.json` dictionaries; defaults are `en` and `ja`.
306
315
  * Add a new language by dropping `locales/<code>.json` in and
307
- * updating the dictionary map in `lib/i18n.ts`. Per-site override is
308
- * possible via the `locale` site setting.
316
+ * updating the dictionary map in `lib/i18n.ts`.
309
317
  */
310
318
  locale?: string;
311
- /**
312
- * Multi-site configuration. When 2+ entries are declared, the runtime
313
- * switches to multi-site mode (host-based routing + Cache-Control:
314
- * private). When 0 or 1 entries, single-site mode is used.
315
- */
316
- sites?: Record<string, SiteConfig>;
317
319
  /**
318
320
  * Active plugins. Each entry is the result of a plugin factory call
319
321
  * (e.g. `seoPlugin({ ... })`) or a raw AmplessPlugin object. Strings are
@@ -321,6 +323,36 @@ interface Config {
321
323
  * ignored by the runtime.
322
324
  */
323
325
  plugins?: Array<AmplessPlugin | string>;
326
+ /**
327
+ * Cache strategy knobs read by the runtime's middleware when
328
+ * computing `Cache-Control` for post responses. Each field is
329
+ * optional — middleware applies the documented defaults when a
330
+ * field is absent.
331
+ */
332
+ cache?: CacheConfig;
333
+ }
334
+ /**
335
+ * Tunables for middleware-computed `Cache-Control`. See
336
+ * `PostMetadata.cache` / `CacheStrategy` for how the per-post override
337
+ * interacts with these defaults.
338
+ */
339
+ interface CacheConfig {
340
+ /**
341
+ * `cache: 'auto'` cooldown. Posts whose `updatedAt` is younger than
342
+ * this many milliseconds emit a no-store header so editors see
343
+ * fresh content immediately after a save. Default 3,600,000 (1h).
344
+ */
345
+ cooldownMs?: number;
346
+ /**
347
+ * `cache: 'auto'` post-cooldown TTL, in seconds. Applied as both
348
+ * `max-age` and `s-maxage` on the response. Default 300 (5 minutes).
349
+ */
350
+ freshTtlSeconds?: number;
351
+ /**
352
+ * `cache: 'deep'` TTL, in seconds. Applied as both `max-age` and
353
+ * `s-maxage`. Default 3600 (1 hour).
354
+ */
355
+ deepTtlSeconds?: number;
324
356
  }
325
357
  type Role = 'reader' | 'editor' | 'admin';
326
358
  interface AuthContext {
@@ -346,7 +378,6 @@ interface ContentTypeDefinition {
346
378
  declare function defineSchema<T extends Record<string, ContentTypeDefinition>>(schema: T): T;
347
379
 
348
380
  interface ListOptions {
349
- siteId?: string;
350
381
  limit?: number;
351
382
  status?: 'draft' | 'published' | 'all';
352
383
  }
@@ -355,85 +386,20 @@ type CreatePostInput = Omit<Post, 'postId'> & {
355
386
  };
356
387
  interface PostsProvider {
357
388
  list(opts?: ListOptions): Promise<Post[]>;
358
- get(slug: string, opts?: {
359
- siteId?: string;
360
- }): Promise<Post | null>;
361
- getById(postId: string, opts?: {
362
- siteId?: string;
363
- }): Promise<Post | null>;
389
+ get(slug: string): Promise<Post | null>;
390
+ getById(postId: string): Promise<Post | null>;
364
391
  create(data: CreatePostInput): Promise<Post>;
365
- update(postId: string, data: Partial<Post>, opts?: {
366
- siteId?: string;
367
- }): Promise<Post>;
368
- remove(postId: string, opts?: {
369
- siteId?: string;
370
- }): Promise<void>;
392
+ update(postId: string, data: Partial<Post>): Promise<Post>;
393
+ remove(postId: string): Promise<void>;
371
394
  }
372
395
  declare function setPostsProvider(p: PostsProvider): void;
373
396
  declare function hasPostsProvider(): boolean;
374
397
  declare function listPosts(opts?: ListOptions): Promise<Post[]>;
375
- declare function getPost(slug: string, opts?: {
376
- siteId?: string;
377
- }): Promise<Post | null>;
378
- declare function getPostById(postId: string, opts?: {
379
- siteId?: string;
380
- }): Promise<Post | null>;
398
+ declare function getPost(slug: string): Promise<Post | null>;
399
+ declare function getPostById(postId: string): Promise<Post | null>;
381
400
  declare function createPost(data: CreatePostInput): Promise<Post>;
382
- declare function updatePost(postId: string, data: Partial<Post>, opts?: {
383
- siteId?: string;
384
- }): Promise<Post>;
385
- declare function deletePost(postId: string, opts?: {
386
- siteId?: string;
387
- }): Promise<void>;
388
-
389
- /**
390
- * Single-site fallback identifier. Used when `cms.config.sites` is unset
391
- * or empty — keeps existing single-site code paths working without
392
- * special-casing.
393
- */
394
- declare const DEFAULT_SITE_ID = "default";
395
- /**
396
- * Resolve a hostname to a configured siteId.
397
- *
398
- * - Single-site mode (no `sites` defined / empty / exactly one entry):
399
- * returns that site's id regardless of host. The single site catches
400
- * every request. Matches `isMultiSite` (≥2 entries = multi).
401
- * - Multi-site mode (2+ entries): looks up the host in each site's
402
- * `domains` list. Returns `null` if the host is not registered
403
- * (caller should 404).
404
- *
405
- * The host comparison is case-insensitive; ports are not stripped here
406
- * — pass the bare hostname (e.g. `'site-a.example.com'`).
407
- */
408
- declare function resolveSiteId(host: string, config: Config): string | null;
409
- /**
410
- * Multi-site mode iff two or more sites are declared. A single declared
411
- * site is treated as single-site mode (the explicit declaration just lets
412
- * the operator name the site, but no host disambiguation is needed).
413
- */
414
- declare function isMultiSite(config: Config): boolean;
415
- /**
416
- * Site-effective name / url / description for a given siteId. Per-site
417
- * `sites.{id}.{name|url|description}` overrides the top-level `site.*`
418
- * defaults; otherwise falls through.
419
- */
420
- declare function siteFor(siteId: string, config: Config): {
421
- name: string;
422
- url: string;
423
- description?: string;
424
- };
425
- /**
426
- * Build the denormalized GSI key for `bySiteIdStatus`. All Post writes
427
- * (admin client, MCP tools) must set this so the public-read resolvers
428
- * can do a single Query without table-level filtering.
429
- */
430
- declare function composeSiteIdStatus(siteId: string, status: PostStatus): string;
431
- /**
432
- * Build the denormalized GSI key for `bySiteIdSlug`. The public
433
- * `getPublishedPost(slug)` resolver does an O(1) PK lookup against
434
- * this index, so every Post write must set it alongside the slug.
435
- */
436
- declare function composeSiteIdSlug(siteId: string, slug: string): string;
401
+ declare function updatePost(postId: string, data: Partial<Post>): Promise<Post>;
402
+ declare function deletePost(postId: string): Promise<void>;
437
403
 
438
404
  interface KvItem<T = unknown> {
439
405
  pk: string;
@@ -459,15 +425,15 @@ declare function hasKvStore(): boolean;
459
425
  * namespace (e.g. `mcp-tokens`).
460
426
  */
461
427
  declare function getKvStore(): KvStore;
462
- declare const SITE_CONFIG_PK: (siteId: string) => string;
463
- declare function getSiteSetting<T = unknown>(siteId: string, key: string): Promise<T | null>;
464
- declare function setSiteSetting(siteId: string, key: string, value: unknown): Promise<void>;
465
- declare function deleteSiteSetting(siteId: string, key: string): Promise<void>;
428
+ declare const SITE_CONFIG_PK = "siteconfig";
429
+ declare function getSiteSetting<T = unknown>(key: string): Promise<T | null>;
430
+ declare function setSiteSetting(key: string, value: unknown): Promise<void>;
431
+ declare function deleteSiteSetting(key: string): Promise<void>;
466
432
  /**
467
- * Fetch every setting for a site as a flat map (`{ 'site.name': 'My Blog', ... }`).
433
+ * Fetch every site setting as a flat map (`{ 'site.name': 'My Blog', ... }`).
468
434
  * Use `unflattenSettings` to convert to the nested shape if needed.
469
435
  */
470
- declare function listSiteSettings(siteId?: string): Promise<Record<string, unknown>>;
436
+ declare function listSiteSettings(): Promise<Record<string, unknown>>;
471
437
  declare function flattenSettings(obj: Record<string, unknown>, prefix?: string): Record<string, unknown>;
472
438
  declare function unflattenSettings(flat: Record<string, unknown>): Record<string, unknown>;
473
439
 
@@ -614,7 +580,7 @@ interface BundleExtractResult {
614
580
  * render a single list of problems before saving.
615
581
  */
616
582
  declare function validateBundle(files: ExtractedFile[]): ValidationIssue[];
617
- declare function bundlePrefix(siteId: string, slug: string): string;
583
+ declare function bundlePrefix(slug: string): string;
618
584
  /**
619
585
  * If every file shares the same top-level directory (e.g. macOS Finder
620
586
  * zipping wraps the contents in a `MyBundle/` folder), strip that
@@ -741,9 +707,7 @@ declare function defineTheme(m: ThemeManifest): ThemeManifest;
741
707
  */
742
708
  declare function resolveLocalized(value: LocalizedString | undefined, locale: string, fallback?: string): string;
743
709
  interface ThemeRouteContext<P = Record<string, string>> {
744
- params: Promise<P & {
745
- siteId: string;
746
- }>;
710
+ params: Promise<P>;
747
711
  }
748
712
  interface ThemeModule {
749
713
  /** Stable identifier — must match the directory name and the value
@@ -751,9 +715,10 @@ interface ThemeModule {
751
715
  name: string;
752
716
  manifest: ThemeManifest;
753
717
  /**
754
- * Server components rendered by the dispatcher routes under
755
- * `app/site/[siteId]/`. Each theme MUST provide Home; Post / Tag are
756
- * recommended but optional (dispatcher 404s when missing).
718
+ * Server components rendered by the dispatcher routes
719
+ * (`app/page.tsx`, `app/[slug]/page.tsx`, `app/tag/[tag]/page.tsx`).
720
+ * Each theme MUST provide Home; Post / Tag are recommended but
721
+ * optional (dispatcher 404s when missing).
757
722
  */
758
723
  components: {
759
724
  Home: (ctx: ThemeRouteContext) => Promise<unknown> | unknown;
@@ -783,11 +748,9 @@ interface ThemeModule {
783
748
  */
784
749
  routes?: {
785
750
  feed?: (ctx: {
786
- siteId: string;
787
751
  request: Request;
788
752
  }) => Promise<Response>;
789
753
  sitemap?: (ctx: {
790
- siteId: string;
791
754
  request: Request;
792
755
  }) => Promise<Response>;
793
756
  };
@@ -845,11 +808,11 @@ declare function isTagListUrl(url: string): {
845
808
  /**
846
809
  * Resolve effective values for every manifest field, merging stored
847
810
  * overrides on top of defaults. `stored` is the flat settings map keyed
848
- * by `theme.{key}` — typically the output of `listSiteSettings(siteId)`
811
+ * by `theme.{key}` — typically the output of `listSiteSettings()`
849
812
  * filtered to theme entries.
850
813
  */
851
814
  declare function resolveThemeValues(manifest: ThemeManifest, stored: Record<string, unknown>): Record<string, string>;
852
815
 
853
816
  declare const VERSION = "0.0.1";
854
817
 
855
- export { type AmplessEvent, type AmplessPlugin, type AuthContext, type BundleExtractResult, type Config, type ContentEventPayload, type ContentEventType, type ContentFormat, type ContentTypeDefinition, type CreatePostInput, DEFAULT_ENTRYPOINT, DEFAULT_SITE_ID, type DateFormat, type EventPayloadOf, type EventType, type ExtractedFile, type FieldDefinition, type FieldType, type ImageDisplay, type KvItem, type KvStore, type LinkListItem, type ListOptions, type LocalizedString, MAX_BUNDLE_BYTES, type Media, type MediaEventPayload, type MediaEventType, type MediaProcessingDefaults, type OgImageConfig, type OgImageFont, type OgImageRenderContext, type Page, type PluginEventHandler, type PluginMetadata, type PluginRuntimeContext, type Post, type PostMetadata, type PostStatus, type PostsProvider, type Role, SITE_CONFIG_PK, type SiteConfig, type SiteSettingsEventPayload, type SiteSettingsEventType, type StaticPostBody, type StreamEventName, TEXT_EXTENSIONS, type ThemeColorField, type ThemeField, type ThemeFieldType, type ThemeFontFamilyField, type ThemeImageField, type ThemeLengthField, type ThemeLinkListField, type ThemeManifest, type ThemeModule, type ThemeRouteContext, type ThemeSelectField, type ThemeTextField, type TrustLevel, VERSION, type ValidationIssue, bundlePrefix, composeSiteIdSlug, composeSiteIdStatus, createPost, decodeAwsJson, defineConfig, definePlugin, defineSchema, defineTheme, defineThemeModule, deletePost, deleteSiteSetting, detectContentEvents, encodeAwsJson, escapeXml, extractFirstImageUrl, findAbsolutePathRefs, flattenSettings, formatColorPair, formatDate, formatPublicAssetUrl, getKvStore, getPost, getPostById, getSiteSetting, hasKvStore, hasPostsProvider, isMultiSite, isTagListUrl, listPosts, listSiteSettings, mimeTypeFor, parseColorPair, parseLinkList, pickDefaultEntrypoint, resolveLocalized, resolveSiteId, resolveThemeValues, setKvStore, setPostsProvider, setSiteSetting, siteFor, stringifyLinkList, stripCommonPrefix, themeSettingKey, unflattenSettings, updatePost, validateBundle, validateBundlePath, validateThemeValue };
818
+ export { type AmplessEvent, type AmplessPlugin, type AuthContext, type BundleExtractResult, type CacheConfig, type CacheStrategy, type Config, type ContentEventPayload, type ContentEventType, type ContentFormat, type ContentTypeDefinition, type CreatePostInput, DEFAULT_ENTRYPOINT, type DateFormat, type EventPayloadOf, type EventType, type ExtractedFile, type FieldDefinition, type FieldType, type ImageDisplay, type KvItem, type KvStore, type LinkListItem, type ListOptions, type LocalizedString, MAX_BUNDLE_BYTES, type Media, type MediaEventPayload, type MediaEventType, type MediaProcessingDefaults, type OgImageConfig, type OgImageFont, type OgImageRenderContext, type Page, type PluginEventHandler, type PluginMetadata, type PluginRuntimeContext, type Post, type PostMetadata, type PostStatus, type PostsProvider, type Role, SITE_CONFIG_PK, type SiteSettingsEventPayload, type SiteSettingsEventType, type StaticPostBody, type StreamEventName, TEXT_EXTENSIONS, type ThemeColorField, type ThemeField, type ThemeFieldType, type ThemeFontFamilyField, type ThemeImageField, type ThemeLengthField, type ThemeLinkListField, type ThemeManifest, type ThemeModule, type ThemeRouteContext, type ThemeSelectField, type ThemeTextField, type TrustLevel, VERSION, type ValidationIssue, bundlePrefix, createPost, decodeAwsJson, defineConfig, definePlugin, defineSchema, defineTheme, defineThemeModule, deletePost, deleteSiteSetting, detectContentEvents, encodeAwsJson, escapeXml, extractFirstImageUrl, findAbsolutePathRefs, flattenSettings, formatColorPair, formatDate, formatPublicAssetUrl, getKvStore, getPost, getPostById, getSiteSetting, hasKvStore, hasPostsProvider, isTagListUrl, listPosts, listSiteSettings, mimeTypeFor, parseColorPair, parseLinkList, pickDefaultEntrypoint, resolveLocalized, resolveThemeValues, setKvStore, setPostsProvider, setSiteSetting, stringifyLinkList, stripCommonPrefix, themeSettingKey, unflattenSettings, updatePost, validateBundle, validateBundlePath, validateThemeValue };
package/dist/index.js CHANGED
@@ -12,7 +12,6 @@ function defineSchema(schema) {
12
12
  var DUMMY_POSTS = [
13
13
  {
14
14
  postId: "post-001",
15
- siteId: "default",
16
15
  slug: "hello-world",
17
16
  title: "Hello, ampless",
18
17
  excerpt: "Welcome to your new ampless-powered blog. This is the first post.",
@@ -24,7 +23,6 @@ var DUMMY_POSTS = [
24
23
  },
25
24
  {
26
25
  postId: "post-002",
27
- siteId: "default",
28
26
  slug: "about-ampless",
29
27
  title: "About ampless",
30
28
  excerpt: "Why ampless exists, and what makes it different from other CMS options.",
@@ -36,7 +34,6 @@ var DUMMY_POSTS = [
36
34
  },
37
35
  {
38
36
  postId: "post-003",
39
- siteId: "default",
40
37
  slug: "getting-started",
41
38
  title: "Getting started",
42
39
  excerpt: "How to set up your ampless site and deploy it to AWS.",
@@ -57,8 +54,8 @@ function hasPostsProvider() {
57
54
  return provider !== null;
58
55
  }
59
56
  function dummyList(opts = {}) {
60
- const { siteId = "default", limit, status = "published" } = opts;
61
- let posts = DUMMY_POSTS.filter((p) => p.siteId === siteId);
57
+ const { limit, status = "published" } = opts;
58
+ let posts = DUMMY_POSTS;
62
59
  if (status !== "all") posts = posts.filter((p) => p.status === status);
63
60
  return limit ? posts.slice(0, limit) : posts;
64
61
  }
@@ -66,60 +63,25 @@ async function listPosts(opts = {}) {
66
63
  if (provider) return provider.list(opts);
67
64
  return dummyList(opts);
68
65
  }
69
- async function getPost(slug, opts = {}) {
70
- if (provider) return provider.get(slug, opts);
71
- const { siteId = "default" } = opts;
72
- return DUMMY_POSTS.find((p) => p.siteId === siteId && p.slug === slug) ?? null;
66
+ async function getPost(slug) {
67
+ if (provider) return provider.get(slug);
68
+ return DUMMY_POSTS.find((p) => p.slug === slug) ?? null;
73
69
  }
74
- async function getPostById(postId, opts = {}) {
75
- if (provider) return provider.getById(postId, opts);
76
- const { siteId = "default" } = opts;
77
- return DUMMY_POSTS.find((p) => p.siteId === siteId && p.postId === postId) ?? null;
70
+ async function getPostById(postId) {
71
+ if (provider) return provider.getById(postId);
72
+ return DUMMY_POSTS.find((p) => p.postId === postId) ?? null;
78
73
  }
79
74
  async function createPost(data) {
80
75
  if (!provider) throw new Error("No posts provider configured. Call setPostsProvider() first.");
81
76
  return provider.create(data);
82
77
  }
83
- async function updatePost(postId, data, opts = {}) {
78
+ async function updatePost(postId, data) {
84
79
  if (!provider) throw new Error("No posts provider configured. Call setPostsProvider() first.");
85
- return provider.update(postId, data, opts);
80
+ return provider.update(postId, data);
86
81
  }
87
- async function deletePost(postId, opts = {}) {
82
+ async function deletePost(postId) {
88
83
  if (!provider) throw new Error("No posts provider configured. Call setPostsProvider() first.");
89
- return provider.remove(postId, opts);
90
- }
91
-
92
- // src/sites.ts
93
- var DEFAULT_SITE_ID = "default";
94
- function resolveSiteId(host, config) {
95
- const sites = config.sites;
96
- if (!sites || Object.keys(sites).length === 0) {
97
- return DEFAULT_SITE_ID;
98
- }
99
- const ids = Object.keys(sites);
100
- if (ids.length === 1) return ids[0];
101
- const lower = host.toLowerCase();
102
- for (const [id, site] of Object.entries(sites)) {
103
- if (site.domains.some((d) => d.toLowerCase() === lower)) return id;
104
- }
105
- return null;
106
- }
107
- function isMultiSite(config) {
108
- return !!config.sites && Object.keys(config.sites).length >= 2;
109
- }
110
- function siteFor(siteId, config) {
111
- const override = config.sites?.[siteId];
112
- return {
113
- name: override?.name ?? config.site.name,
114
- url: override?.url ?? config.site.url,
115
- description: override?.description ?? config.site.description
116
- };
117
- }
118
- function composeSiteIdStatus(siteId, status) {
119
- return `${siteId}#${status}`;
120
- }
121
- function composeSiteIdSlug(siteId, slug) {
122
- return `${siteId}#${slug}`;
84
+ return provider.remove(postId);
123
85
  }
124
86
 
125
87
  // src/kv.ts
@@ -139,18 +101,18 @@ function requireStore() {
139
101
  function getKvStore() {
140
102
  return requireStore();
141
103
  }
142
- var SITE_CONFIG_PK = (siteId) => `siteconfig:${siteId}`;
143
- async function getSiteSetting(siteId, key) {
144
- return requireStore().get(SITE_CONFIG_PK(siteId), key);
104
+ var SITE_CONFIG_PK = "siteconfig";
105
+ async function getSiteSetting(key) {
106
+ return requireStore().get(SITE_CONFIG_PK, key);
145
107
  }
146
- async function setSiteSetting(siteId, key, value) {
147
- return requireStore().put(SITE_CONFIG_PK(siteId), key, value);
108
+ async function setSiteSetting(key, value) {
109
+ return requireStore().put(SITE_CONFIG_PK, key, value);
148
110
  }
149
- async function deleteSiteSetting(siteId, key) {
150
- return requireStore().remove(SITE_CONFIG_PK(siteId), key);
111
+ async function deleteSiteSetting(key) {
112
+ return requireStore().remove(SITE_CONFIG_PK, key);
151
113
  }
152
- async function listSiteSettings(siteId = DEFAULT_SITE_ID) {
153
- const items = await requireStore().query(SITE_CONFIG_PK(siteId));
114
+ async function listSiteSettings() {
115
+ const items = await requireStore().query(SITE_CONFIG_PK);
154
116
  const out = {};
155
117
  for (const item of items) {
156
118
  out[item.sk] = item.value;
@@ -402,8 +364,8 @@ function validateBundle(files) {
402
364
  }
403
365
  return issues;
404
366
  }
405
- function bundlePrefix(siteId, slug) {
406
- return `public/static/${siteId}/${slug}/`;
367
+ function bundlePrefix(slug) {
368
+ return `public/static/${slug}/`;
407
369
  }
408
370
  function stripCommonPrefix(files) {
409
371
  if (files.length === 0) return files;
@@ -601,14 +563,11 @@ function defaultValueAsString(field) {
601
563
  var VERSION = "0.0.1";
602
564
  export {
603
565
  DEFAULT_ENTRYPOINT,
604
- DEFAULT_SITE_ID,
605
566
  MAX_BUNDLE_BYTES,
606
567
  SITE_CONFIG_PK,
607
568
  TEXT_EXTENSIONS,
608
569
  VERSION,
609
570
  bundlePrefix,
610
- composeSiteIdSlug,
611
- composeSiteIdStatus,
612
571
  createPost,
613
572
  decodeAwsJson,
614
573
  defineConfig,
@@ -633,7 +592,6 @@ export {
633
592
  getSiteSetting,
634
593
  hasKvStore,
635
594
  hasPostsProvider,
636
- isMultiSite,
637
595
  isTagListUrl,
638
596
  listPosts,
639
597
  listSiteSettings,
@@ -642,12 +600,10 @@ export {
642
600
  parseLinkList,
643
601
  pickDefaultEntrypoint,
644
602
  resolveLocalized,
645
- resolveSiteId,
646
603
  resolveThemeValues,
647
604
  setKvStore,
648
605
  setPostsProvider,
649
606
  setSiteSetting,
650
- siteFor,
651
607
  stringifyLinkList,
652
608
  stripCommonPrefix,
653
609
  themeSettingKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ampless",
3
- "version": "0.2.0-alpha.8",
3
+ "version": "1.0.0-alpha.10",
4
4
  "description": "Serverless CMS for AWS Amplify",
5
5
  "license": "MIT",
6
6
  "type": "module",