ampless 1.0.0-alpha.18 → 1.0.0-alpha.19
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 +14 -3
- package/dist/index.js +17 -0
- package/docs/plugin-author-guide.ja.md +23 -1
- package/docs/plugin-author-guide.md +33 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -283,9 +283,11 @@ type TrustLevel = 'untrusted' | 'trusted' | 'privileged';
|
|
|
283
283
|
* declaration-vs-implementation reconciliation warnings and (in later
|
|
284
284
|
* phases) for `allowCapabilities` gating in `cms.config.ts`.
|
|
285
285
|
*
|
|
286
|
-
*
|
|
286
|
+
* Active capabilities:
|
|
287
287
|
* - `publicHead` / `publicBody`: descriptor-based head/body injection.
|
|
288
288
|
* - `metadata` / `eventHooks`: name-only declaration for existing surfaces.
|
|
289
|
+
* - `adminSettings`: admin-managed public settings manifest.
|
|
290
|
+
* - `writePublicAsset`: trusted hook context can write namespaced public assets.
|
|
289
291
|
*
|
|
290
292
|
* Reserved capabilities are accepted by the type so that plugins can
|
|
291
293
|
* declare future intent, but the runtime does nothing with them yet —
|
|
@@ -293,7 +295,7 @@ type TrustLevel = 'untrusted' | 'trusted' | 'privileged';
|
|
|
293
295
|
* capability today is harmless, but the runtime won't expose any new
|
|
294
296
|
* surface for it until the matching phase ships.
|
|
295
297
|
*/
|
|
296
|
-
type PluginCapability = 'publicHead' | 'publicBody' | 'metadata' | 'eventHooks' | 'adminSettings' | '
|
|
298
|
+
type PluginCapability = 'publicHead' | 'publicBody' | 'metadata' | 'eventHooks' | 'adminSettings' | 'writePublicAsset' | 'schema' | 'contentFields' | 'adminPage' | 'serverRoute' | 'secretSettings' | 'network' | 'scheduler' | 'storageWrite' | 'privilegedSystem';
|
|
297
299
|
/**
|
|
298
300
|
* Loading strategy for `script` / `inlineScript` descriptors.
|
|
299
301
|
*
|
|
@@ -1026,6 +1028,15 @@ declare function decodeAwsJson(value: unknown): unknown;
|
|
|
1026
1028
|
*/
|
|
1027
1029
|
declare function formatPublicAssetUrl(bucket: string, region: string, key: string): string;
|
|
1028
1030
|
|
|
1031
|
+
/**
|
|
1032
|
+
* Validate the user-supplied key for ctx.writePublicAsset.
|
|
1033
|
+
*
|
|
1034
|
+
* The trusted Lambda still has a processor-wide S3 grant, so path safety is
|
|
1035
|
+
* enforced at the runtime context boundary before the key is joined under the
|
|
1036
|
+
* plugin namespace.
|
|
1037
|
+
*/
|
|
1038
|
+
declare function validatePublicAssetKey(key: string): string | null;
|
|
1039
|
+
|
|
1029
1040
|
declare const PLUGIN_KEY_PATTERN: RegExp;
|
|
1030
1041
|
declare function isValidPluginKey(key: string): boolean;
|
|
1031
1042
|
/**
|
|
@@ -1178,4 +1189,4 @@ declare function pickDefaultEntrypoint(files: readonly {
|
|
|
1178
1189
|
|
|
1179
1190
|
declare const VERSION = "0.0.1";
|
|
1180
1191
|
|
|
1181
|
-
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 MediaMetadata, type MediaProcessingDefaults, type OgImageConfig, type OgImageFont, type OgImageRenderContext, PLUGIN_KEY_PATTERN, type Page, type PluginBooleanField, type PluginCapability, type PluginCodeField, type PluginEventHandler, type PluginJsonField, type PluginMetadata, type PluginNumberField, type PluginPublicRenderContext, type PluginRuntimeContext, type PluginSelectField, type PluginSettingField, type PluginSettingsManifest, type PluginTextField, type PluginTextareaField, type PluginUrlField, type Post, type PostIndexEventPayload, type PostIndexEventType, type PostMetadata, type PostStatus, type PostsProvider, type PublicBodyDescriptor, type PublicHeadDescriptor, type Role, SITE_CONFIG_PK, type ScriptStrategy, type SiteSettingsEventPayload, type SiteSettingsEventType, type StaticPostBody, type StaticPostFileMeta, 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, isValidPluginKey, listPosts, listSiteSettings, mimeTypeFor, parseColorPair, parseLinkList, pickDefaultEntrypoint, resolveLocalized, resolvePluginSettings, resolveThemeValues, setKvStore, setPostsProvider, setSiteSetting, stringifyLinkList, stripCommonPrefix, themeSettingKey, unflattenSettings, updatePost, validateBundle, validateBundlePath, validatePluginSettingValue, validateThemeValue };
|
|
1192
|
+
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 MediaMetadata, type MediaProcessingDefaults, type OgImageConfig, type OgImageFont, type OgImageRenderContext, PLUGIN_KEY_PATTERN, type Page, type PluginBooleanField, type PluginCapability, type PluginCodeField, type PluginEventHandler, type PluginJsonField, type PluginMetadata, type PluginNumberField, type PluginPublicRenderContext, type PluginRuntimeContext, type PluginSelectField, type PluginSettingField, type PluginSettingsManifest, type PluginTextField, type PluginTextareaField, type PluginUrlField, type Post, type PostIndexEventPayload, type PostIndexEventType, type PostMetadata, type PostStatus, type PostsProvider, type PublicBodyDescriptor, type PublicHeadDescriptor, type Role, SITE_CONFIG_PK, type ScriptStrategy, type SiteSettingsEventPayload, type SiteSettingsEventType, type StaticPostBody, type StaticPostFileMeta, 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, isValidPluginKey, listPosts, listSiteSettings, mimeTypeFor, parseColorPair, parseLinkList, pickDefaultEntrypoint, resolveLocalized, resolvePluginSettings, resolveThemeValues, setKvStore, setPostsProvider, setSiteSetting, stringifyLinkList, stripCommonPrefix, themeSettingKey, unflattenSettings, updatePost, validateBundle, validateBundlePath, validatePluginSettingValue, validatePublicAssetKey, validateThemeValue };
|
package/dist/index.js
CHANGED
|
@@ -215,6 +215,22 @@ function definePlugin(p) {
|
|
|
215
215
|
return p;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
// src/plugin-asset-key.ts
|
|
219
|
+
function validatePublicAssetKey(key) {
|
|
220
|
+
if (key.length === 0) return "key must not be empty";
|
|
221
|
+
if (key.length > 256) return "key must be 256 characters or less";
|
|
222
|
+
if (key.startsWith("/")) return 'key must be relative and must not start with "/"';
|
|
223
|
+
if (key.includes("\\")) return "key must not contain backslashes";
|
|
224
|
+
if (/[\u0000-\u001f\u007f]/.test(key)) {
|
|
225
|
+
return "key must not contain control characters";
|
|
226
|
+
}
|
|
227
|
+
const segments = key.split("/");
|
|
228
|
+
if (segments.some((segment) => segment === "." || segment === "..")) {
|
|
229
|
+
return 'key must not contain "." or ".." path segments';
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
218
234
|
// src/plugin-settings.ts
|
|
219
235
|
var PLUGIN_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
220
236
|
function isValidPluginKey(key) {
|
|
@@ -721,5 +737,6 @@ export {
|
|
|
721
737
|
validateBundle,
|
|
722
738
|
validateBundlePath,
|
|
723
739
|
validatePluginSettingValue,
|
|
740
|
+
validatePublicAssetKey,
|
|
724
741
|
validateThemeValue
|
|
725
742
|
};
|
|
@@ -139,7 +139,7 @@ analyticsGa4Plugin({ instanceId: 'product' })
|
|
|
139
139
|
| 階層 | IAM | 用途 |
|
|
140
140
|
|---|---|---|
|
|
141
141
|
| `untrusted` | なし (SQS consume のみ) | head/body descriptor、webhook 配送、コンテンツ変換 |
|
|
142
|
-
| `trusted` | 投稿読み出し、`public/plugins/<name>/...` への書き込み | RSS フィード、sitemap、計算済み JSON インデックス |
|
|
142
|
+
| `trusted` | 投稿読み出し、`public/plugins/<instanceId ?? name>/...` への書き込み | RSS フィード、sitemap、計算済み JSON インデックス |
|
|
143
143
|
| `privileged` | 予約 | 将来: SES、secret、private S3 |
|
|
144
144
|
|
|
145
145
|
決め方の目安:
|
|
@@ -273,6 +273,26 @@ hooks: {
|
|
|
273
273
|
}
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
+
### `writePublicAsset`
|
|
277
|
+
|
|
278
|
+
公開生成ファイルを書き出す trusted plugin は capability を宣言してください:
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
capabilities: ['eventHooks', 'writePublicAsset']
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
同じ plugin が `metadata()` または `siteMetadata()` も実装する場合は、`metadata` も宣言します。この capability 名は両方の metadata 関数をまとめて表し、別個の `siteMetadata` capability はありません。
|
|
285
|
+
|
|
286
|
+
trusted processor は次の場所に書き込みます:
|
|
287
|
+
|
|
288
|
+
```txt
|
|
289
|
+
public/plugins/<instanceId ?? name>/<key>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
`key` は相対 asset key である必要があります。空文字、絶対パス、`.` / `..` path segment、backslash、制御文字、256 文字超の key は S3 呼び出し前に拒否されます。`indexes/posts.json` のような nested path は許可されます。戻り値は書き込まれた object の public URL です。
|
|
293
|
+
|
|
294
|
+
移行期間中、`capabilities` フィールドが無い plugin はそのまま動きます。`capabilities` を宣言しているのに `writePublicAsset` を省いた plugin は、実際に `ctx.writePublicAsset()` を呼んだ時に 1 回だけ warn します。
|
|
295
|
+
|
|
276
296
|
### ベストプラクティス
|
|
277
297
|
|
|
278
298
|
- **冪等にする**。SQS は at-least-once 配送 — 同じイベントが 2 回 fire する可能性があります。同じ入力で同じ出力 (決定論的なフィード等) を生成するようにしてください
|
|
@@ -467,6 +487,8 @@ it('admin が空文字保存した場合は空配列', () => {
|
|
|
467
487
|
参考実装:
|
|
468
488
|
|
|
469
489
|
- [`packages/plugin-analytics-ga4`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-analytics-ga4) — descriptor ベース、Phase 2 settings
|
|
490
|
+
- [`packages/plugin-gtm`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-gtm) — `publicHead`(ローダーインラインスクリプト)+ `publicBodyEnd`(`<noscript>` iframe フォールバック)を両方使用、コンテナ ID は admin 編集可能
|
|
491
|
+
- [`packages/plugin-plausible`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-plausible) — `data-*` attrs 付きの単一 `<script>` descriptor、`required` な URL field(self-hosted Plausible 上書き対応)
|
|
470
492
|
- [`packages/plugin-rss`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-rss) — trusted、非同期 hooks + `writePublicAsset`
|
|
471
493
|
- [`packages/plugin-seo`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-seo) — `metadata()` + `siteMetadata()`
|
|
472
494
|
- [`packages/plugin-webhook`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-webhook) — untrusted hook + 外向き HTTP
|
|
@@ -168,7 +168,7 @@ touch IAM):
|
|
|
168
168
|
| Tier | IAM | Used by |
|
|
169
169
|
|---|---|---|
|
|
170
170
|
| `untrusted` | none (SQS consume only) | head/body descriptors, webhook delivery, content transforms |
|
|
171
|
-
| `trusted` | read posts, write `public/plugins/<name>/...` | RSS feed, sitemap, computed JSON indexes |
|
|
171
|
+
| `trusted` | read posts, write `public/plugins/<instanceId ?? name>/...` | RSS feed, sitemap, computed JSON indexes |
|
|
172
172
|
| `privileged` | reserved | future: SES, secrets, private S3 |
|
|
173
173
|
|
|
174
174
|
Rule of thumb:
|
|
@@ -332,6 +332,36 @@ hooks: {
|
|
|
332
332
|
}
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
+
### `writePublicAsset`
|
|
336
|
+
|
|
337
|
+
Trusted plugins that write public generated files should declare the
|
|
338
|
+
capability:
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
capabilities: ['eventHooks', 'writePublicAsset']
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
If the same plugin implements `metadata()` or `siteMetadata()`, also
|
|
345
|
+
declare `metadata`. That capability name covers both metadata
|
|
346
|
+
functions; there is no separate `siteMetadata` capability.
|
|
347
|
+
|
|
348
|
+
The trusted processor writes under:
|
|
349
|
+
|
|
350
|
+
```txt
|
|
351
|
+
public/plugins/<instanceId ?? name>/<key>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
`key` must be a relative asset key. Empty strings, absolute paths,
|
|
355
|
+
`.` / `..` path segments, backslashes, control characters, and keys
|
|
356
|
+
over 256 characters are rejected before S3 is called. Nested paths
|
|
357
|
+
such as `indexes/posts.json` are allowed. The return value is the
|
|
358
|
+
public URL for the written object.
|
|
359
|
+
|
|
360
|
+
During the migration period, plugins with no `capabilities` field
|
|
361
|
+
keep working. Plugins that do declare `capabilities` but omit
|
|
362
|
+
`writePublicAsset` warn once when they actually call
|
|
363
|
+
`ctx.writePublicAsset()`.
|
|
364
|
+
|
|
335
365
|
### Best practices
|
|
336
366
|
|
|
337
367
|
- **Be idempotent.** SQS delivery is at-least-once: the same event
|
|
@@ -575,6 +605,8 @@ a normal npm package:
|
|
|
575
605
|
Worked examples to crib from:
|
|
576
606
|
|
|
577
607
|
- [`packages/plugin-analytics-ga4`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-analytics-ga4) — descriptor-based, Phase 2 settings.
|
|
608
|
+
- [`packages/plugin-gtm`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-gtm) — uses both `publicHead` (loader inline script) and `publicBodyEnd` (`<noscript>` iframe fallback) with the container ID admin-edited.
|
|
609
|
+
- [`packages/plugin-plausible`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-plausible) — single `<script>` descriptor with `data-*` attrs and a required URL field (self-hosted Plausible override).
|
|
578
610
|
- [`packages/plugin-rss`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-rss) — trusted, async event hooks + `writePublicAsset`.
|
|
579
611
|
- [`packages/plugin-seo`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-seo) — `metadata()` + `siteMetadata()`.
|
|
580
612
|
- [`packages/plugin-webhook`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-webhook) — untrusted hook with outbound HTTP.
|