@ryusenkei/maezae 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +2 -0
  2. package/dist/analytics.d.ts +1 -0
  3. package/dist/analytics.js +33 -0
  4. package/dist/body.d.ts +1 -24
  5. package/dist/body.js +1 -333
  6. package/dist/declared-9_jI3JXH.js +336 -0
  7. package/dist/delivery.d.ts +1 -211
  8. package/dist/integrations.d.ts +1 -72
  9. package/dist/integrations.js +12 -2
  10. package/dist/model.d.ts +1 -82
  11. package/dist/model.js +339 -1
  12. package/dist/preview.d.ts +1 -2
  13. package/dist/preview.js +1 -1
  14. package/dist/{src-CA_67dWy.js → src-Baj-EC2G.js} +105 -3
  15. package/dist/trace.d.ts +1 -0
  16. package/dist/trace.js +1 -0
  17. package/dist/types/access/src/index.d.ts +5 -0
  18. package/dist/types/access/src/jwt.d.ts +42 -0
  19. package/dist/types/access/src/oidc.d.ts +47 -0
  20. package/dist/types/access/src/signed.d.ts +47 -0
  21. package/dist/types/access/src/span.d.ts +23 -0
  22. package/dist/types/access/src/traceparent.d.ts +21 -0
  23. package/dist/types/analytics/src/day.d.ts +2 -0
  24. package/dist/types/analytics/src/index.d.ts +4 -0
  25. package/dist/types/analytics/src/record.d.ts +22 -0
  26. package/dist/types/analytics/src/schedule.d.ts +2 -0
  27. package/dist/types/analytics/src/source.d.ts +33 -0
  28. package/dist/types/analytics/src/store.d.ts +24 -0
  29. package/dist/types/body/src/components.d.ts +25 -0
  30. package/dist/types/body/src/declared.d.ts +34 -0
  31. package/dist/types/body/src/derive.d.ts +13 -0
  32. package/dist/types/body/src/description.d.ts +8 -0
  33. package/dist/types/body/src/href.d.ts +4 -0
  34. package/dist/types/body/src/index.d.ts +11 -0
  35. package/dist/types/body/src/library.d.ts +94 -0
  36. package/dist/types/body/src/markdown.d.ts +14 -0
  37. package/dist/types/body/src/normalize.d.ts +7 -0
  38. package/dist/types/body/src/profile.d.ts +48 -0
  39. package/dist/types/body/src/schema.d.ts +6 -0
  40. package/dist/types/body/src/standard.d.ts +20 -0
  41. package/dist/types/body/src/types.d.ts +91 -0
  42. package/dist/types/cms-contract/src/apiKeys.d.ts +13 -0
  43. package/dist/types/cms-contract/src/assets.d.ts +10 -0
  44. package/dist/types/cms-contract/src/builtins.d.ts +17 -0
  45. package/dist/types/cms-contract/src/embeds.d.ts +56 -0
  46. package/dist/types/cms-contract/src/errorLabels.d.ts +22 -0
  47. package/dist/types/cms-contract/src/errors.d.ts +97 -0
  48. package/dist/types/cms-contract/src/extensions.d.ts +75 -0
  49. package/dist/types/cms-contract/src/fieldRules.d.ts +37 -0
  50. package/dist/types/cms-contract/src/functions.d.ts +71 -0
  51. package/dist/types/cms-contract/src/index.d.ts +19 -0
  52. package/dist/types/cms-contract/src/labels.d.ts +6 -0
  53. package/dist/types/cms-contract/src/modules.d.ts +144 -0
  54. package/dist/types/cms-contract/src/paths.d.ts +6 -0
  55. package/dist/types/cms-contract/src/pending.d.ts +4 -0
  56. package/dist/types/cms-contract/src/permissions.d.ts +69 -0
  57. package/dist/types/cms-contract/src/roles.d.ts +35 -0
  58. package/dist/types/cms-contract/src/settings.d.ts +19 -0
  59. package/dist/types/cms-contract/src/transfer.d.ts +48 -0
  60. package/dist/types/cms-contract/src/views.d.ts +21 -0
  61. package/dist/types/cms-contract/src/webhooks.d.ts +45 -0
  62. package/dist/types/delivery-client/src/client.d.ts +63 -0
  63. package/dist/types/delivery-client/src/index.d.ts +5 -0
  64. package/dist/types/delivery-client/src/media.d.ts +12 -0
  65. package/dist/types/delivery-client/src/query.d.ts +68 -0
  66. package/dist/types/delivery-client/src/schema.d.ts +19 -0
  67. package/dist/types/delivery-client/src/values.d.ts +63 -0
  68. package/dist/types/model/src/asset.d.ts +89 -0
  69. package/dist/types/model/src/capabilities.d.ts +20 -0
  70. package/dist/types/model/src/changes.d.ts +23 -0
  71. package/dist/types/model/src/check.d.ts +10 -0
  72. package/dist/types/model/src/image.d.ts +38 -0
  73. package/dist/types/model/src/index.d.ts +14 -0
  74. package/dist/types/model/src/input.d.ts +26 -0
  75. package/dist/types/model/src/media.d.ts +5 -0
  76. package/dist/types/model/src/model.d.ts +194 -0
  77. package/dist/types/model/src/page.d.ts +47 -0
  78. package/dist/types/model/src/rules.d.ts +15 -0
  79. package/dist/types/model/src/schema.d.ts +3 -0
  80. package/dist/types/model/src/screens.d.ts +72 -0
  81. package/dist/types/model/src/time.d.ts +25 -0
  82. package/dist/types/model/src/values.d.ts +24 -0
  83. package/dist/types/sdk/src/analytics.d.ts +2 -0
  84. package/dist/types/sdk/src/body.d.ts +2 -0
  85. package/dist/types/sdk/src/defaults.d.ts +5 -0
  86. package/dist/types/sdk/src/delivery.d.ts +2 -0
  87. package/dist/types/sdk/src/integrations.d.ts +4 -0
  88. package/dist/types/sdk/src/model.d.ts +5 -0
  89. package/dist/types/sdk/src/preview.d.ts +2 -0
  90. package/dist/types/sdk/src/trace.d.ts +2 -0
  91. package/package.json +10 -2
  92. package/dist/index-C8duwjns.d.ts +0 -157
  93. package/dist/index-CLDe_wBc.d.ts +0 -340
  94. package/dist/signed-B_58gV21.d.ts +0 -44
package/dist/model.d.ts CHANGED
@@ -1,82 +1 @@
1
- import { A as pagePathOf, C as ContentType, D as typeOf, O as PageDef, S as ContentModel, T as FieldDef, _ as Hotspot, a as IMAGE_TYPE, b as mediaSchema, c as coverPosition, d as croppedHotspot, f as objectPosition, g as Crop, h as AssetRef, i as isDateOnly, j as publicPathOf, k as PageEntry, l as coverStart, m as Asset, n as DateString, o as VIDEO_TYPE, p as stillOf, r as createClock, s as CropRect, t as Clock, u as cropRect, v as LocalImage, y as Media } from "./index-CLDe_wBc.js";
2
- /** メニューのグループ(collapsed は既定で折りたたむ) */
3
- type MenuGroup = Readonly<{
4
- id: string;
5
- label: string;
6
- collapsed?: boolean;
7
- items: readonly string[];
8
- }>;
9
- /** メニューの1段(項目の id かグループ) */
10
- type MenuEntry = string | MenuGroup;
11
- /** 編集画面のセクション(label が空は見出しなし、collapsed は既定で折りたたむ) */
12
- type EditorSection = Readonly<{
13
- id: string;
14
- label: string;
15
- collapsed?: boolean;
16
- items: readonly string[];
17
- }>;
18
- /** コンテンツタイプの編集画面の配置(hidden は配置しない項目) */
19
- type EditorLayout = Readonly<{
20
- sections: readonly EditorSection[];
21
- hidden?: readonly string[];
22
- }>;
23
- /** 画面の設定(editors・columns のキーはコンテンツタイプの id) */
24
- type ScreenSettings = Readonly<{
25
- menu: readonly MenuEntry[];
26
- editors: Readonly<Record<string, EditorLayout>>;
27
- columns: Readonly<Record<string, readonly string[]>>;
28
- }>;
29
- /** 操作 */
30
- declare const ACTIONS: readonly ["read", "create", "update", "publish", "delete"];
31
- /** 操作 */
32
- type Action = (typeof ACTIONS)[number];
33
- /** 段階 */
34
- declare const LEVELS: readonly ["all", "own", "approval", "none"];
35
- /** 段階 */
36
- type Level = (typeof LEVELS)[number];
37
- /** 権限の表(キーは対象の id、'*' は表にない対象の既定、操作がなければ不可) */
38
- type Permissions = Readonly<Record<string, Readonly<Partial<Record<Action, Level>>>>>;
39
- /** ビューで許可できる一括操作(assign: 担当者の割り当て、publish: 公開) */
40
- declare const VIEW_ACTIONS: readonly ["assign", "publish"];
41
- /** ビューで許可できる一括操作 */
42
- type ViewAction = (typeof VIEW_ACTIONS)[number];
43
- /** ビューの内容(filters は列の id ごとの絞り込みの値、query は検索の文、columns は表示する列、editable は一覧で編集する列) */
44
- type ViewDefinition = Readonly<{
45
- filters: Readonly<Record<string, string>>;
46
- query: string;
47
- columns: readonly string[];
48
- editable: readonly string[];
49
- actions: readonly ViewAction[];
50
- }>;
51
- /** スキーマと設定の形式の名前 */
52
- export declare const CONFIG_FORMAT = "cms-config";
53
- /** スキーマと設定(schema はコンテンツスキーマ ContentModel・screens は画面設定 ScreenSettings の形、roles は管理者以外、views はチームのビュー) */
54
- type ConfigBundle = Readonly<{
55
- format: typeof CONFIG_FORMAT;
56
- version: 1;
57
- exported_at: string;
58
- schema: unknown;
59
- screens: unknown;
60
- roles: readonly Readonly<{
61
- id: string;
62
- label: string;
63
- permissions: Permissions;
64
- }>[];
65
- views: readonly Readonly<{
66
- id: string;
67
- type: string;
68
- label: string;
69
- definition: ViewDefinition;
70
- roles: readonly string[];
71
- }>[];
72
- extensions: readonly Readonly<{
73
- id: string;
74
- enabled: boolean;
75
- settings: Readonly<Record<string, unknown>>;
76
- }>[];
77
- }>;
78
- /** 中立の既定のスキーマ(新しい媒体の作成で適用する型: post・author・tag・image・video、設定の移入の土台) */
79
- export declare const DEFAULT_SCHEMA: ContentModel;
80
- /** 既定の画面設定(新しい媒体の作成で適用する中立の値、移入する screens の土台) */
81
- export declare const DEFAULT_SCREENS: ScreenSettings;
82
- export { type Asset, type AssetRef, type Clock, type ConfigBundle, type ContentModel, type ContentType, type Crop, type CropRect, type DateString, type FieldDef, type Hotspot, IMAGE_TYPE, type LocalImage, type Media, type PageDef, type PageEntry, type ScreenSettings, VIDEO_TYPE, coverPosition, coverStart, createClock, cropRect, croppedHotspot, isDateOnly, mediaSchema, objectPosition, pagePathOf, publicPathOf, stillOf, typeOf };
1
+ export * from './types/sdk/src/model.js';
package/dist/model.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { a as coverPosition, c as croppedHotspot, d as createClock, f as isDateOnly, i as typeOf, l as objectPosition, n as publicPathOf, o as coverStart, s as cropRect, t as pagePathOf, u as stillOf } from "./page-UEKb7_gu.js";
2
+ import { i as CORE_COMPONENTS, t as declaredComponentsSchema } from "./declared-9_jI3JXH.js";
2
3
  import "./src-BrLwIWaT.js";
3
4
  import { z } from "zod";
4
5
  // ../model/src/asset.ts
@@ -96,6 +97,343 @@ const VIDEO_TYPE = {
96
97
  ],
97
98
  fields: []
98
99
  };
100
+ // ../model/src/capabilities.ts
101
+ const NONE = {
102
+ editorial: false,
103
+ derived: false,
104
+ sources: false,
105
+ shared: false
106
+ };
107
+ const CORE_TABLES = {
108
+ articles: {
109
+ ...NONE,
110
+ editorial: true,
111
+ derived: true,
112
+ sources: true
113
+ },
114
+ sources: {
115
+ ...NONE,
116
+ shared: true
117
+ }
118
+ };
119
+ /** 表の性質(コアの表にない表はすべてなし) */
120
+ const tableTraitsOf = (table) => table && Object.hasOwn(CORE_TABLES, table) ? CORE_TABLES[table] : NONE;
121
+ // ../model/src/schema.ts
122
+ const key = z.string().regex(/^[a-z][a-z0-9_]*$/, "id は英小文字で始まり、英小文字・数字・アンダーラインだけ");
123
+ const fieldKey = z.string().regex(/^[a-z][a-zA-Z0-9_-]*$/, "key は英小文字で始まり、英字・数字・アンダーライン・ハイフンだけ");
124
+ const condition = z.object({
125
+ key: fieldKey,
126
+ in: z.array(z.string().min(1)).min(1)
127
+ });
128
+ const base = {
129
+ key: fieldKey,
130
+ label: z.string().min(1),
131
+ description: z.string().optional(),
132
+ required: z.union([
133
+ z.literal("save"),
134
+ z.literal("submit"),
135
+ z.literal("page"),
136
+ z.literal(false)
137
+ ]).optional(),
138
+ when: condition.optional(),
139
+ private: z.boolean().optional(),
140
+ adminOnly: z.boolean().optional(),
141
+ pendingUntil: fieldKey.optional()
142
+ };
143
+ const frame = z.object({
144
+ when: condition.optional(),
145
+ ratio: z.string().min(1),
146
+ size: z.object({
147
+ width: z.number().int().positive(),
148
+ height: z.number().int().positive()
149
+ }),
150
+ label: z.string().min(1)
151
+ });
152
+ const pageRule = z.union([
153
+ z.object({
154
+ key: z.string().min(1),
155
+ in: z.array(z.string())
156
+ }),
157
+ z.object({
158
+ key: z.string().min(1),
159
+ notIn: z.array(z.string())
160
+ }),
161
+ z.object({
162
+ key: z.string().min(1),
163
+ truthy: z.literal(true)
164
+ }),
165
+ z.object({
166
+ key: z.string().min(1),
167
+ notFuture: z.literal(true)
168
+ })
169
+ ]);
170
+ const page = z.object({
171
+ when: condition.optional(),
172
+ path: z.string().startsWith("/", "ページの雛形は / で始まる"),
173
+ public: z.array(pageRule).optional()
174
+ });
175
+ const field = z.lazy(() => fieldUnion);
176
+ const counts = {
177
+ minItems: z.number().int().nonnegative().optional(),
178
+ maxItems: z.number().int().positive().optional()
179
+ };
180
+ const regex = z.string().refine((p) => {
181
+ try {
182
+ new RegExp(p, "u");
183
+ return true;
184
+ } catch {
185
+ return false;
186
+ }
187
+ }, "形式の正規表現が不正");
188
+ const fieldUnion = z.discriminatedUnion("type", [
189
+ z.object({
190
+ ...base,
191
+ ...counts,
192
+ type: z.enum(["text", "textarea"]),
193
+ maxLength: z.number().int().positive().optional(),
194
+ minLength: z.number().int().positive().optional(),
195
+ pattern: regex.optional(),
196
+ guideLength: z.number().int().positive().optional(),
197
+ multiple: z.boolean().optional()
198
+ }),
199
+ z.object({
200
+ ...base,
201
+ type: z.literal("number"),
202
+ min: z.number().optional(),
203
+ max: z.number().optional()
204
+ }),
205
+ z.object({
206
+ ...base,
207
+ type: z.literal("checkbox")
208
+ }),
209
+ z.object({
210
+ ...base,
211
+ type: z.enum(["date", "datetime"])
212
+ }),
213
+ z.object({
214
+ ...base,
215
+ ...counts,
216
+ type: z.literal("select"),
217
+ options: z.array(z.object({
218
+ value: z.string().min(1),
219
+ label: z.string().min(1),
220
+ tone: z.enum([
221
+ "positive",
222
+ "caution",
223
+ "neutral"
224
+ ]).optional(),
225
+ restricted: z.boolean().optional()
226
+ })).min(1),
227
+ initial: z.string().optional(),
228
+ multiple: z.boolean().optional(),
229
+ derive: z.object({
230
+ from: fieldKey,
231
+ map: z.record(z.string(), z.string()),
232
+ otherwise: z.string()
233
+ }).optional(),
234
+ fixedBy: z.object({
235
+ ref: fieldKey,
236
+ key: fieldKey,
237
+ map: z.record(z.string(), z.string())
238
+ }).optional()
239
+ }).refine((f) => f.initial === void 0 || f.options.some((o) => o.value === f.initial), {
240
+ message: "初期値が選択肢にない",
241
+ path: ["initial"]
242
+ }).refine((f) => !f.derive || [...Object.values(f.derive.map), f.derive.otherwise].every((v) => f.options.some((o) => o.value === v)), {
243
+ message: "決まる値が選択肢にない",
244
+ path: ["derive"]
245
+ }).refine((f) => !f.fixedBy || Object.values(f.fixedBy.map).every((v) => f.options.some((o) => o.value === v)), {
246
+ message: "固定する値が選択肢にない",
247
+ path: ["fixedBy"]
248
+ }),
249
+ z.object({
250
+ ...base,
251
+ ...counts,
252
+ type: z.literal("reference"),
253
+ to: z.string().min(1),
254
+ multiple: z.boolean().optional(),
255
+ where: z.record(z.string(), z.string()).optional(),
256
+ requests: z.boolean().optional(),
257
+ emptyLabel: z.string().min(1).optional(),
258
+ unique: z.boolean().optional(),
259
+ published: z.boolean().optional(),
260
+ linkedBy: fieldKey.optional()
261
+ }),
262
+ z.object({
263
+ ...base,
264
+ ...counts,
265
+ type: z.literal("media"),
266
+ accept: z.array(z.enum(["image", "video"])).optional(),
267
+ multiple: z.boolean().optional(),
268
+ frames: z.array(frame).optional()
269
+ }),
270
+ z.object({
271
+ ...base,
272
+ type: z.literal("body"),
273
+ profile: z.object({
274
+ headings: z.array(z.number()),
275
+ marks: z.array(z.string()),
276
+ components: z.array(z.string())
277
+ }).passthrough()
278
+ }),
279
+ z.object({
280
+ ...base,
281
+ ...counts,
282
+ type: z.literal("group"),
283
+ fields: z.array(field),
284
+ multiple: z.boolean().optional()
285
+ })
286
+ ]);
287
+ /** 条件が一覧にある選択肢の項目と値を指すか */
288
+ const conditionValid = (when, fields) => {
289
+ const target = when && fields.find((g) => g.key === when.key && g.type === "select");
290
+ return !when || target !== void 0 && when.in.every((v) => target.options.some((o) => o.value === v));
291
+ };
292
+ /** 条件が同じ階層の選択肢の項目と値を指すか(まとまりの中も) */
293
+ const conditionsValid = (fields) => fields.every((f) => conditionValid(f.when, fields) && (!f.derive || fields.some((g) => g.key === f.derive.from && g.type === "select")) && (!f.fixedBy || fields.some((g) => g.key === f.fixedBy.ref && g.type === "reference" && !g.multiple)) && (f.frames ?? []).every((fr) => conditionValid(fr.when, fields)) && conditionsValid(f.fields ?? []));
294
+ /** まとまりの中で決まる値・参照先で固定を持つ項目の key(宣言の適用 rules.ts が最上位の項目だけのため) */
295
+ const nestedRules = (fields) => fields.flatMap((f) => (f.fields ?? []).flatMap((c) => [...c.derive || c.fixedBy ? [`${f.key}.${c.key}`] : [], ...nestedRules([c]).map((k) => `${f.key}.${k}`)]));
296
+ /**
297
+ * システムの値と同じ名前で、項目の key に使用できない名前(API・配信が項目の値を上書きするため)
298
+ * - すべての型: 行の ID・作成と更新の日時・作成者、管理画面の一覧で参照する行の数 uses
299
+ * - 公開の管理がある型と、コアの表を持つ型の追加の項目: 編集の機能の列
300
+ * - 本文から作成する列を持つ表の型: excerpt・read_min・links
301
+ * - 対象外: API・配信の値に出ない列 type、導入先の設定で決まるアカウントの email・account_role
302
+ */
303
+ const RESERVED = [
304
+ "id",
305
+ "created_at",
306
+ "created_by",
307
+ "updated_at",
308
+ "uses"
309
+ ];
310
+ const RESERVED_EDITORIAL = [
311
+ "status",
312
+ "published_at",
313
+ "visibility",
314
+ "version",
315
+ "review_note",
316
+ "assignee"
317
+ ];
318
+ const RESERVED_DERIVED = [
319
+ "excerpt",
320
+ "read_min",
321
+ "links"
322
+ ];
323
+ /** 予約の名前と同じ最上位の key(コアの項目は表の列そのものなので、編集の機能の列は対象外) */
324
+ function reservedKeysOf(t) {
325
+ const derived = tableTraitsOf(t.table).derived ? RESERVED_DERIVED : [];
326
+ const editorial = (t.publishing ?? "none") !== "none" || t.table ? RESERVED_EDITORIAL : [];
327
+ const core = t.core ?? [];
328
+ const extra = [...t.fields.map((f) => f.key), ...(t.counts ?? []).map((c) => c.key)];
329
+ return [...core.map((f) => f.key).filter((k) => [...RESERVED, ...derived].includes(k)), ...extra.filter((k) => [
330
+ ...RESERVED,
331
+ ...derived,
332
+ ...editorial
333
+ ].includes(k))];
334
+ }
335
+ /** 本文の項目が使用する部品の名前(まとまりの中も、key は項目の key) */
336
+ const bodyComponents = (fields) => fields.flatMap((f) => f.type === "body" ? f.profile.components.map((name) => ({
337
+ key: f.key,
338
+ name
339
+ })) : bodyComponents(f.fields ?? []));
340
+ /** 参照の項目の参照先(まとまりの中も) */
341
+ const referenceTargets = (fields) => fields.flatMap((f) => f.type === "reference" ? [f.to] : referenceTargets(f.fields ?? []));
342
+ const contentType = z.object({
343
+ id: key,
344
+ label: z.string().min(1),
345
+ description: z.string().optional(),
346
+ format: z.enum(["list", "object"]).optional(),
347
+ publishing: z.enum([
348
+ "none",
349
+ "draft",
350
+ "review"
351
+ ]).optional(),
352
+ table: key.optional(),
353
+ core: z.array(field).optional(),
354
+ fields: z.array(field),
355
+ pages: z.array(page).optional(),
356
+ counts: z.array(z.object({
357
+ key: fieldKey,
358
+ from: key,
359
+ field: fieldKey
360
+ })).optional(),
361
+ og: z.string().startsWith("/", "OG 画像の雛形は / で始まる").optional(),
362
+ idInput: z.boolean().optional()
363
+ }).refine((t) => t.format !== "object" || !t.core?.length, { message: "オブジェクト形式の型はコアの項目なし" }).refine((t) => new Set([...t.core ?? [], ...t.fields].map((f) => f.key)).size === (t.core?.length ?? 0) + t.fields.length, { message: "項目の key が重複(コアの項目を含む)" }).refine((t) => conditionsValid([...t.core ?? [], ...t.fields]), { message: "項目の条件が同じ階層の選択肢の項目と値を指していない" }).refine((t) => (t.pages ?? []).every((p) => conditionValid(p.when, [...t.core ?? [], ...t.fields])), { message: "ページの条件が型の選択肢の項目と値を指していない" }).superRefine((t, ctx) => {
364
+ for (const k of reservedKeysOf(t)) ctx.addIssue({
365
+ code: "custom",
366
+ message: `型 ${t.id} の key ${k} はシステムの値と同じ名前(別の key に)`
367
+ });
368
+ for (const k of nestedRules([...t.core ?? [], ...t.fields])) ctx.addIssue({
369
+ code: "custom",
370
+ message: `型 ${t.id} の項目 ${k}: まとまりの中の項目は決まる値 derive・参照先で固定 fixedBy なし`
371
+ });
372
+ });
373
+ const modelSchema = z.object({
374
+ components: declaredComponentsSchema.optional(),
375
+ types: z.array(contentType).refine((ts) => new Set(ts.map((t) => t.id)).size === ts.length, { message: "型の id が重複" }).superRefine((ts, ctx) => {
376
+ const ids = new Set(ts.map((t) => t.id));
377
+ for (const t of ts) for (const to of referenceTargets([...t.core ?? [], ...t.fields])) if (!ids.has(to)) ctx.addIssue({
378
+ code: "custom",
379
+ message: `型 ${t.id} の参照先 ${to} がスキーマにない`
380
+ });
381
+ for (const t of ts) {
382
+ const keys = new Set([...t.core ?? [], ...t.fields].map((f) => f.key));
383
+ for (const c of t.counts ?? []) {
384
+ const from = ts.find((x) => x.id === c.from);
385
+ const ref = from && [...from.core ?? [], ...from.fields].find((f) => f.key === c.field);
386
+ if (ref?.type !== "reference" || ref.to !== t.id) ctx.addIssue({
387
+ code: "custom",
388
+ message: `型 ${t.id} の被参照の件数 ${c.key}: 型 ${c.from} の参照の項目 ${c.field} がこの型を指していない`
389
+ });
390
+ if (keys.has(c.key)) ctx.addIssue({
391
+ code: "custom",
392
+ message: `型 ${t.id} の被参照の件数 ${c.key} が項目の key と重複`
393
+ });
394
+ }
395
+ }
396
+ })
397
+ }).superRefine((m, ctx) => {
398
+ const known = /* @__PURE__ */ new Set([...CORE_COMPONENTS.map((c) => c.name), ...(m.components ?? []).map((c) => c.name)]);
399
+ for (const t of m.types) for (const { key, name } of bodyComponents([...t.core ?? [], ...t.fields])) if (!known.has(name)) ctx.addIssue({
400
+ code: "custom",
401
+ message: `型 ${t.id} の本文の項目 ${key} の部品 ${name} がコアの部品にも宣言 components にもない`
402
+ });
403
+ });
404
+ /** コンテンツスキーマの JSON を検査して返却(形が合わなければ例外、理由は zod の issues) */
405
+ const parseModel = (json) => modelSchema.parse(json);
406
+ // ../model/src/screens.ts
407
+ /** メニューにある全項目の id(グループの中も、上から順) */
408
+ const menuItemsOf = (menu) => menu.flatMap((e) => typeof e === "string" ? [e] : e.items);
409
+ /** 編集画面に配置した項目の id(セクションの順) */
410
+ const placedItemsOf = (layout) => layout.sections.flatMap((s) => s.items);
411
+ const id = z.string().regex(/^[a-z][a-z0-9_:-]*$/, "id は英小文字で始まり、英小文字・数字・アンダーライン・コロン・ハイフンだけ");
412
+ const item = z.string().min(1);
413
+ const unique = (values) => new Set(values).size === values.length;
414
+ const group = z.object({
415
+ id,
416
+ label: z.string().trim().min(1),
417
+ collapsed: z.boolean().optional(),
418
+ items: z.array(item)
419
+ });
420
+ const section = z.object({
421
+ id,
422
+ label: z.string().trim(),
423
+ collapsed: z.boolean().optional(),
424
+ items: z.array(item)
425
+ });
426
+ const layout = z.object({
427
+ sections: z.array(section),
428
+ hidden: z.array(item).optional()
429
+ }).refine((l) => unique(l.sections.map((s) => s.id)), { message: "セクションの id が重複" }).refine((l) => unique([...placedItemsOf(l), ...l.hidden ?? []]), { message: "同じ項目を2か所に配置" });
430
+ const screensSchema = z.object({
431
+ menu: z.array(z.union([item, group])).refine((m) => unique(m.flatMap((e) => typeof e === "string" ? [] : [e.id])), { message: "メニューのグループの id が重複" }).refine((m) => unique(menuItemsOf(m)), { message: "メニューに同じ項目が2つ" }),
432
+ editors: z.record(z.string(), layout).default({}),
433
+ columns: z.record(z.string(), z.array(item).refine(unique, { message: "一覧に同じ列が2つ" })).default({})
434
+ });
435
+ /** 画面の設定の JSON を検査(形の誤りは ZodError) */
436
+ const parseScreens = (json) => screensSchema.parse(json);
99
437
  // ../cms-contract/src/transfer.ts
100
438
  /** スキーマと設定の形式の名前 */
101
439
  const CONFIG_FORMAT = "cms-config";
@@ -366,4 +704,4 @@ const DEFAULT_SCREENS = {
366
704
  "updated_at"
367
705
  ] }
368
706
  };
369
- export { CONFIG_FORMAT, DEFAULT_SCHEMA, DEFAULT_SCREENS, IMAGE_TYPE, VIDEO_TYPE, coverPosition, coverStart, createClock, cropRect, croppedHotspot, isDateOnly, mediaSchema, objectPosition, pagePathOf, publicPathOf, stillOf, typeOf };
707
+ export { CONFIG_FORMAT, DEFAULT_SCHEMA, DEFAULT_SCREENS, IMAGE_TYPE, VIDEO_TYPE, coverPosition, coverStart, createClock, cropRect, croppedHotspot, isDateOnly, mediaSchema, objectPosition, pagePathOf, parseModel, parseScreens, publicPathOf, stillOf, typeOf };
package/dist/preview.d.ts CHANGED
@@ -1,2 +1 @@
1
- import { a as signedHeaders, i as signParts, n as SignedParts, o as verifyParts, r as VerifyRequestOptions, s as verifyRequest, t as SIGNED_HEADERS } from "./signed-B_58gV21.js";
2
- export { SIGNED_HEADERS, type SignedParts, type VerifyRequestOptions, signParts, signedHeaders, verifyParts, verifyRequest };
1
+ export * from './types/sdk/src/preview.js';
package/dist/preview.js CHANGED
@@ -1 +1 @@
1
- export { t as SIGNED_HEADERS, n as signParts, r as signedHeaders, i as verifyParts, a as verifyRequest } from "./src-CA_67dWy.js";
1
+ export { i as SIGNED_HEADERS, o as signParts, s as signedHeaders, c as verifyParts, l as verifyRequest } from "./src-Baj-EC2G.js";
@@ -98,6 +98,108 @@ async function verifyRequest(secret, request, { header, subjectHeader, now }) {
98
98
  subject: subjectHeader ? request.headers.get(subjectHeader) : null
99
99
  }, now === void 0 ? {} : { now });
100
100
  }
101
- "0".repeat(32);
102
- "0".repeat(16);
103
- export { verifyRequest as a, verifyParts as i, signParts as n, signedHeaders as r, SIGNED_HEADERS as t };
101
+ /** 封印した値(署名の不一致・期限切れ・形の誤りは null) */
102
+ async function openValue(secret, token, now = Date.now()) {
103
+ const [body, sig] = token?.split(".") ?? [];
104
+ if (!secret || !body || !sig) return null;
105
+ try {
106
+ if (!await crypto.subtle.verify("HMAC", await hmacKey(secret), decodeBase64Url(sig), enc.encode(body))) return null;
107
+ const { v, exp } = JSON.parse(new TextDecoder().decode(decodeBase64Url(body)));
108
+ return typeof exp === "number" && exp * 1e3 > now ? v : null;
109
+ } catch {
110
+ return null;
111
+ }
112
+ }
113
+ // ../access/src/traceparent.ts
114
+ /** traceparent のヘッダーの名前 */
115
+ const TRACEPARENT_HEADER = "traceparent";
116
+ const PATTERN = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
117
+ const ZERO_TRACE = "0".repeat(32);
118
+ const ZERO_SPAN = "0".repeat(16);
119
+ /** 受け取った traceparent の解釈(なし・形の違反は null) */
120
+ function parseTraceparent(value) {
121
+ const m = value ? PATTERN.exec(value.trim()) : null;
122
+ if (!m) return null;
123
+ const [, version, traceId, spanId, flags, rest] = m;
124
+ if (version === "ff" || version === "00" && rest !== void 0) return null;
125
+ if (traceId === ZERO_TRACE || spanId === ZERO_SPAN) return null;
126
+ return {
127
+ traceId,
128
+ spanId,
129
+ sampled: (parseInt(flags, 16) & 1) === 1
130
+ };
131
+ }
132
+ /** traceparent の値(版は00) */
133
+ const formatTraceparent = (ctx) => `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
134
+ function randomHexId(bytes) {
135
+ const values = crypto.getRandomValues(new Uint8Array(bytes));
136
+ let hex = "";
137
+ for (const b of values) hex += b.toString(16).padStart(2, "0");
138
+ return hex;
139
+ }
140
+ /** 新しいトレースの ID(32桁) */
141
+ const newTraceId = () => randomHexId(16);
142
+ /** 新しい区間の ID(16桁) */
143
+ const newSpanId = () => randomHexId(8);
144
+ // ../access/src/span.ts
145
+ /** 記録の割合(0〜1、なし・範囲の外・数でない値は1) */
146
+ const sampleRateOf = (value) => {
147
+ const rate = value === void 0 || value.trim() === "" ? NaN : Number(value);
148
+ return rate >= 0 && rate <= 1 ? rate : 1;
149
+ };
150
+ /** エントリポイントの区間の開始(受け取った traceparent の子か、新しいトレースの根) */
151
+ function startEdgeSpan({ name, request, sampleRate = 1, write = (line) => console.info(line) }) {
152
+ const parent = parseTraceparent(request.headers.get(TRACEPARENT_HEADER));
153
+ const context = {
154
+ traceId: parent?.traceId ?? newTraceId(),
155
+ spanId: newSpanId(),
156
+ sampled: parent ? parent.sampled : Math.random() < sampleRate
157
+ };
158
+ const attributes = {
159
+ method: request.method,
160
+ path: new URL(request.url).pathname
161
+ };
162
+ const started = performance.now();
163
+ let ended = false;
164
+ return {
165
+ context,
166
+ traceparent: formatTraceparent(context),
167
+ end(result) {
168
+ if (ended) return;
169
+ ended = true;
170
+ if (!context.sampled) return;
171
+ const status = result === "error" || result >= 500 ? "error" : "ok";
172
+ const durationMs = Math.round((performance.now() - started) * 10) / 10;
173
+ const span = {
174
+ traceId: context.traceId,
175
+ spanId: context.spanId,
176
+ parentSpanId: parent?.spanId ?? null,
177
+ name,
178
+ durationMs,
179
+ status,
180
+ attributes: {
181
+ ...attributes,
182
+ ...result !== "error" && { status: result }
183
+ }
184
+ };
185
+ write(JSON.stringify({
186
+ level: "info",
187
+ msg: "span",
188
+ ...span
189
+ }));
190
+ }
191
+ };
192
+ }
193
+ /** 処理をエントリポイントの区間で包む(応答のステータスか例外で終了、例外は再送出) */
194
+ async function withEdgeSpan(options, handle) {
195
+ const span = startEdgeSpan(options);
196
+ try {
197
+ const res = await handle(span);
198
+ span.end(res.status);
199
+ return res;
200
+ } catch (e) {
201
+ span.end("error");
202
+ throw e;
203
+ }
204
+ }
205
+ export { openValue as a, verifyParts as c, SIGNED_HEADERS as i, verifyRequest as l, withEdgeSpan as n, signParts as o, TRACEPARENT_HEADER as r, signedHeaders as s, sampleRateOf as t };
@@ -0,0 +1 @@
1
+ export * from './types/sdk/src/trace.js';
package/dist/trace.js ADDED
@@ -0,0 +1 @@
1
+ export { r as TRACEPARENT_HEADER, t as sampleRateOf, n as withEdgeSpan } from "./src-Baj-EC2G.js";
@@ -0,0 +1,5 @@
1
+ export { accessJwtOptions, type FetchCerts, type JwtClaims, type JwtOptions, verifyAccessJwt, verifyJwt } from './jwt.js';
2
+ export { emailOfClaims, type LoginAuth, oidcLogin, type OidcLoginOptions, tokenAuth, type TokenAuthOptions } from './oidc.js';
3
+ export { type EdgeSpan, type EdgeSpanOptions, type EdgeSpanStatus, sampleRateOf, startEdgeSpan, withEdgeSpan } from './span.js';
4
+ export { openValue, sealValue, SIGNED_HEADERS, signedHeaders, signParts, type SignedParts, verifyParts, verifyRequest, type VerifyRequestOptions } from './signed.js';
5
+ export { childTraceContext, formatTraceparent, newSpanId, newTraceId, parseTraceparent, type TraceContext, TRACEPARENT_HEADER } from './traceparent.js';
@@ -0,0 +1,42 @@
1
+ type Jwk = JsonWebKey & {
2
+ kid?: string;
3
+ };
4
+ /** 公開鍵の一覧の取得(引数は JWKS の URL、refresh は保持した値を使用せずに再取得、テストで差し替え) */
5
+ export type FetchCerts = (jwksUrl: string, refresh?: boolean) => Promise<{
6
+ keys: Jwk[];
7
+ }>;
8
+ /** JWT のクレーム(検証を通った値) */
9
+ export type JwtClaims = Readonly<Record<string, unknown>>;
10
+ /** JWT の検証の設定 */
11
+ export type JwtOptions = Readonly<{
12
+ /** 発行元(iss と完全に一致) */
13
+ issuer: string;
14
+ /** 宛先(aud のどれかと一致、一覧はどれか1つと一致) */
15
+ audience: string | readonly string[];
16
+ /** 公開鍵の一覧の URL */
17
+ jwksUrl: string;
18
+ now?: number;
19
+ certs?: FetchCerts;
20
+ }>;
21
+ /** 公開鍵の一覧を保持する取得(取得の失敗は保持しない) */
22
+ export declare function cachedCerts(fetcher: FetchCerts, clock?: () => number): FetchCerts;
23
+ /** base64url の復号 */
24
+ export declare const decodeBase64Url: (s: string) => Uint8Array<ArrayBuffer>;
25
+ /** 検証を通った JWT のクレーム(署名・発行元・宛先・期限のどれかが違えば null) */
26
+ export declare function verifyJwt(token: string, { issuer, audience, jwksUrl, now, certs }: JwtOptions): Promise<JwtClaims | null>;
27
+ /**
28
+ * Cloudflare Access の JWT を検証する設定(teamDomain は <チーム>.cloudflareaccess.com、aud はアプリの AUD)
29
+ * - aud: カンマ区切りで複数のアプリ(ホスト名ごとにアプリが分かれる管理画面、どのアプリを通すかは Access がホスト名で判定)
30
+ */
31
+ export declare const accessJwtOptions: ({ teamDomain, aud }: Readonly<{
32
+ teamDomain: string;
33
+ aud: string;
34
+ }>) => Pick<JwtOptions, "issuer" | "audience" | "jwksUrl">;
35
+ /** Access の検証を通ったログインのメールアドレス、サービストークンは service:<クライアントの ID>(通らなければ null) */
36
+ export declare function verifyAccessJwt(token: string, { teamDomain, aud, now, certs }: {
37
+ teamDomain: string;
38
+ aud: string;
39
+ now?: number;
40
+ certs?: FetchCerts;
41
+ }): Promise<string | null>;
42
+ export {};
@@ -0,0 +1,47 @@
1
+ import { type FetchCerts, type JwtClaims, type JwtOptions } from './jwt.js';
2
+ /** ログイン(Auth のポートと同じ形) */
3
+ export type LoginAuth = {
4
+ emailOf(request: Request): Promise<string | null>;
5
+ /** ログインの入り口の応答(対象外のパスは null) */
6
+ handle?(request: Request): Promise<Response | null>;
7
+ /** ログアウトの応答 */
8
+ logout?(request: Request): Promise<Response>;
9
+ };
10
+ /** クレームのメールアドレス(なし・未検証は null、小文字に統一) */
11
+ export declare function emailOfClaims(claims: JwtClaims | null, claim?: string): string | null;
12
+ /** ヘッダーの JWT で判定するログインの設定 */
13
+ export type TokenAuthOptions = Readonly<{
14
+ issuer: string;
15
+ audience: JwtOptions['audience'];
16
+ /** 公開鍵の一覧の URL(なしは発行元の OIDC の設定から) */
17
+ jwksUrl?: string;
18
+ /** JWT のヘッダー(既定 authorization、authorization は Bearer を除外) */
19
+ header?: string;
20
+ /** メールアドレスのクレーム(既定 email) */
21
+ emailClaim?: string;
22
+ certs?: FetchCerts;
23
+ fetch?: typeof fetch;
24
+ }>;
25
+ /** ヘッダーの JWT を検証するログイン */
26
+ export declare function tokenAuth({ issuer, audience, jwksUrl, header, emailClaim, certs, fetch: fetcher }: TokenAuthOptions): LoginAuth;
27
+ /** アプリ自身が行う OIDC のログインの設定 */
28
+ export type OidcLoginOptions = Readonly<{
29
+ issuer: string;
30
+ clientId: string;
31
+ /** クライアントの秘密の値(公開のクライアントは なし、PKCE だけ) */
32
+ clientSecret?: string;
33
+ /** Cookie の署名の鍵 */
34
+ secret: string;
35
+ /** 入り口のパスの頭(既定 /auth) */
36
+ basePath?: string;
37
+ /** 要求するスコープ(既定 openid email) */
38
+ scope?: string;
39
+ /** セッションの秒数(既定は8時間) */
40
+ sessionTtlSec?: number;
41
+ certs?: FetchCerts;
42
+ fetch?: typeof fetch;
43
+ }>;
44
+ /** 同じオリジンの戻り先(外のオリジンへの転送を防ぐ) */
45
+ export declare const safeNext: (next: string | null) => string;
46
+ /** アプリ自身の OIDC のログイン(認可コードのフローと署名つきの Cookie のセッション) */
47
+ export declare function oidcLogin({ issuer, clientId, clientSecret, secret, basePath, scope, sessionTtlSec, certs, fetch: fetcher }: OidcLoginOptions): LoginAuth;