@myna-sh/cli 0.1.2 → 0.1.4

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/dsl.d.ts ADDED
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Canonical schema representation (SPEC 6.2 / 7).
3
+ *
4
+ * These are the normalized, serializable shapes stored as `schema_json`. Field
5
+ * order is significant and preserved as an array; object *keys* are sorted only
6
+ * during canonical stringification for a stable hash.
7
+ */
8
+ type FieldType = "text" | "number" | "boolean" | "date" | "datetime" | "markdown" | "json" | "asset" | "reference" | "list" | "object" | "slug";
9
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
10
+ [key: string]: JsonValue;
11
+ };
12
+ /** UI metadata carried on every field (non-semantic, does not affect validation). */
13
+ interface FieldUi {
14
+ widget?: string;
15
+ placeholder?: string;
16
+ helpText?: string;
17
+ group?: string;
18
+ hidden?: boolean;
19
+ }
20
+ interface FieldBase {
21
+ key: string;
22
+ type: FieldType;
23
+ label: string;
24
+ description?: string;
25
+ required: boolean;
26
+ ui?: FieldUi;
27
+ }
28
+ interface TextField extends FieldBase {
29
+ type: "text";
30
+ multiline: boolean;
31
+ minLength?: number;
32
+ maxLength?: number;
33
+ pattern?: string;
34
+ enum?: string[];
35
+ default?: string;
36
+ }
37
+ interface NumberField extends FieldBase {
38
+ type: "number";
39
+ integer: boolean;
40
+ min?: number;
41
+ max?: number;
42
+ default?: number;
43
+ }
44
+ interface BooleanField extends FieldBase {
45
+ type: "boolean";
46
+ default?: boolean;
47
+ }
48
+ interface DateField extends FieldBase {
49
+ type: "date" | "datetime";
50
+ min?: string;
51
+ max?: string;
52
+ default?: string;
53
+ }
54
+ interface MarkdownField extends FieldBase {
55
+ type: "markdown";
56
+ minLength?: number;
57
+ maxLength?: number;
58
+ default?: string;
59
+ }
60
+ interface JsonField extends FieldBase {
61
+ type: "json";
62
+ default?: JsonValue;
63
+ }
64
+ interface AssetField extends FieldBase {
65
+ type: "asset";
66
+ /** Allowed MIME families, e.g. `image/*`, `application/pdf`. */
67
+ allowed: string[];
68
+ multiple: boolean;
69
+ }
70
+ interface ReferenceField extends FieldBase {
71
+ type: "reference";
72
+ /** Target collection key. */
73
+ target: string;
74
+ multiple: boolean;
75
+ }
76
+ interface SlugField extends FieldBase {
77
+ type: "slug";
78
+ /** Source field key to derive the slug from. */
79
+ from?: string;
80
+ }
81
+ type PrimitiveItem = {
82
+ kind: "text";
83
+ minLength?: number;
84
+ maxLength?: number;
85
+ pattern?: string;
86
+ enum?: string[];
87
+ } | {
88
+ kind: "number";
89
+ integer?: boolean;
90
+ min?: number;
91
+ max?: number;
92
+ } | {
93
+ kind: "boolean";
94
+ } | {
95
+ kind: "date" | "datetime";
96
+ min?: string;
97
+ max?: string;
98
+ } | {
99
+ kind: "markdown";
100
+ minLength?: number;
101
+ maxLength?: number;
102
+ } | {
103
+ kind: "json";
104
+ };
105
+ type ListItem = PrimitiveItem | {
106
+ kind: "reference";
107
+ target: string;
108
+ } | {
109
+ kind: "asset";
110
+ allowed: string[];
111
+ } | {
112
+ kind: "object";
113
+ fields: FieldDef[];
114
+ };
115
+ interface ListField extends FieldBase {
116
+ type: "list";
117
+ item: ListItem;
118
+ minItems?: number;
119
+ maxItems?: number;
120
+ }
121
+ interface ObjectField extends FieldBase {
122
+ type: "object";
123
+ fields: FieldDef[];
124
+ }
125
+ type FieldDef = TextField | NumberField | BooleanField | DateField | MarkdownField | JsonField | AssetField | ReferenceField | SlugField | ListField | ObjectField;
126
+ type CollectionKind = "collection" | "singleton";
127
+ type Visibility = "public" | "private";
128
+ interface SlugConfig {
129
+ from: string;
130
+ required: boolean;
131
+ }
132
+ /** Canonical collection schema (one `collection_versions.schema_json`). */
133
+ interface CollectionSchema {
134
+ name: string;
135
+ label: string;
136
+ kind: CollectionKind;
137
+ visibility: Visibility;
138
+ titleField: string | null;
139
+ slug: SlugConfig | null;
140
+ path: string | null;
141
+ fields: FieldDef[];
142
+ }
143
+ /** Maximum object/list nesting depth (SPEC 6.2). */
144
+ declare const MAX_NESTING_DEPTH = 4;
145
+
146
+ /** A field definition before its `key` is assigned by `collection()`. */
147
+ type FieldInput = DistributiveOmit<FieldDef, "key">;
148
+ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
149
+ interface CommonOptions {
150
+ label?: string;
151
+ description?: string;
152
+ required?: boolean;
153
+ ui?: FieldUi;
154
+ }
155
+ interface TextOptions extends CommonOptions {
156
+ multiline?: boolean;
157
+ minLength?: number;
158
+ maxLength?: number;
159
+ pattern?: string;
160
+ enum?: string[];
161
+ default?: string;
162
+ }
163
+ interface NumberOptions extends CommonOptions {
164
+ integer?: boolean;
165
+ min?: number;
166
+ max?: number;
167
+ default?: number;
168
+ }
169
+ interface BooleanOptions extends CommonOptions {
170
+ default?: boolean;
171
+ }
172
+ interface DateOptions extends CommonOptions {
173
+ min?: string;
174
+ max?: string;
175
+ default?: string;
176
+ }
177
+ interface MarkdownOptions extends CommonOptions {
178
+ minLength?: number;
179
+ maxLength?: number;
180
+ default?: string;
181
+ }
182
+ interface JsonOptions extends CommonOptions {
183
+ default?: JsonValue;
184
+ }
185
+ interface AssetOptions extends CommonOptions {
186
+ allowed?: string[];
187
+ multiple?: boolean;
188
+ }
189
+ interface ReferenceOptions extends CommonOptions {
190
+ to: string;
191
+ multiple?: boolean;
192
+ }
193
+ interface SlugOptions extends CommonOptions {
194
+ from?: string;
195
+ }
196
+ interface ListOptions extends CommonOptions {
197
+ of: ListItem;
198
+ minItems?: number;
199
+ maxItems?: number;
200
+ }
201
+ interface ObjectOptions extends CommonOptions {
202
+ fields: Record<string, FieldInput>;
203
+ }
204
+ declare const field: {
205
+ readonly text: (o?: TextOptions) => Omit<TextField, "key">;
206
+ readonly number: (o?: NumberOptions) => Omit<NumberField, "key">;
207
+ readonly boolean: (o?: BooleanOptions) => Omit<BooleanField, "key">;
208
+ readonly date: (o?: DateOptions) => Omit<DateField, "key">;
209
+ readonly datetime: (o?: DateOptions) => Omit<DateField, "key">;
210
+ readonly markdown: (o?: MarkdownOptions) => Omit<MarkdownField, "key">;
211
+ readonly json: (o?: JsonOptions) => Omit<JsonField, "key">;
212
+ readonly asset: (o?: AssetOptions) => Omit<AssetField, "key">;
213
+ readonly reference: (o: ReferenceOptions) => Omit<ReferenceField, "key">;
214
+ readonly slug: (o?: SlugOptions) => Omit<SlugField, "key">;
215
+ readonly list: (o: ListOptions) => Omit<ListField, "key">;
216
+ readonly object: (o: ObjectOptions) => Omit<ObjectField, "key">;
217
+ };
218
+ /** Item builders for `field.list({ of: item.<type>() })`. */
219
+ declare const item: {
220
+ readonly text: (o?: {
221
+ minLength?: number;
222
+ maxLength?: number;
223
+ pattern?: string;
224
+ enum?: string[];
225
+ }) => ListItem;
226
+ readonly number: (o?: {
227
+ integer?: boolean;
228
+ min?: number;
229
+ max?: number;
230
+ }) => ListItem;
231
+ readonly boolean: () => ListItem;
232
+ readonly date: (o?: {
233
+ min?: string;
234
+ max?: string;
235
+ }) => ListItem;
236
+ readonly datetime: (o?: {
237
+ min?: string;
238
+ max?: string;
239
+ }) => ListItem;
240
+ readonly markdown: (o?: {
241
+ minLength?: number;
242
+ maxLength?: number;
243
+ }) => ListItem;
244
+ readonly json: () => ListItem;
245
+ readonly reference: (o: {
246
+ to: string;
247
+ }) => ListItem;
248
+ readonly asset: (o?: {
249
+ allowed?: string[];
250
+ }) => ListItem;
251
+ readonly object: (o: {
252
+ fields: Record<string, FieldInput>;
253
+ }) => ListItem;
254
+ };
255
+ /** Turn a `{ key: FieldInput }` map into an ordered array of `FieldDef`. */
256
+ declare function assignKeys(fields: Record<string, FieldInput>): FieldDef[];
257
+
258
+ interface CollectionInput {
259
+ /** Immutable collection key, e.g. `posts`. */
260
+ name: string;
261
+ label?: string;
262
+ kind?: CollectionKind;
263
+ /** Visibility defaults to `private` and must be explicitly declared `public`. */
264
+ visibility?: Visibility;
265
+ titleField?: string;
266
+ /** Path template such as `/blog/{slug}`. */
267
+ path?: string;
268
+ fields: Record<string, FieldInput>;
269
+ }
270
+ /**
271
+ * Author a collection schema. Returns the canonical `CollectionSchema` with an
272
+ * ordered fields array. Defaults: `kind=collection`, `visibility=private`.
273
+ */
274
+ declare function collection(input: CollectionInput): CollectionSchema;
275
+
276
+ export { type AssetField, type AssetOptions, type BooleanField, type BooleanOptions, type CollectionInput, type CollectionKind, type CollectionSchema, type DateField, type DateOptions, type FieldDef, type FieldInput, type FieldType, type FieldUi, type JsonField, type JsonOptions, type JsonValue, type ListField, type ListItem, type ListOptions, MAX_NESTING_DEPTH, type MarkdownField, type MarkdownOptions, type NumberField, type NumberOptions, type ObjectField, type ObjectOptions, type PrimitiveItem, type ReferenceField, type ReferenceOptions, type SlugConfig, type SlugField, type SlugOptions, type TextField, type TextOptions, type Visibility, assignKeys, collection, field, item };
package/dist/dsl.js ADDED
@@ -0,0 +1,189 @@
1
+ // ../schema/src/types.ts
2
+ var MAX_NESTING_DEPTH = 4;
3
+
4
+ // ../schema/src/fields.ts
5
+ function common(o) {
6
+ const base = {
7
+ required: o.required ?? false
8
+ };
9
+ if (o.label !== void 0) base.label = o.label;
10
+ if (o.description !== void 0) base.description = o.description;
11
+ if (o.ui !== void 0) base.ui = o.ui;
12
+ return base;
13
+ }
14
+ function defined(obj) {
15
+ for (const key of Object.keys(obj)) {
16
+ if (obj[key] === void 0) delete obj[key];
17
+ }
18
+ return obj;
19
+ }
20
+ var field = {
21
+ text(o = {}) {
22
+ return defined({
23
+ type: "text",
24
+ ...common(o),
25
+ multiline: o.multiline ?? false,
26
+ minLength: o.minLength,
27
+ maxLength: o.maxLength,
28
+ pattern: o.pattern,
29
+ enum: o.enum,
30
+ default: o.default
31
+ });
32
+ },
33
+ number(o = {}) {
34
+ return defined({
35
+ type: "number",
36
+ ...common(o),
37
+ integer: o.integer ?? false,
38
+ min: o.min,
39
+ max: o.max,
40
+ default: o.default
41
+ });
42
+ },
43
+ boolean(o = {}) {
44
+ return defined({
45
+ type: "boolean",
46
+ ...common(o),
47
+ default: o.default
48
+ });
49
+ },
50
+ date(o = {}) {
51
+ return defined({
52
+ type: "date",
53
+ ...common(o),
54
+ min: o.min,
55
+ max: o.max,
56
+ default: o.default
57
+ });
58
+ },
59
+ datetime(o = {}) {
60
+ return defined({
61
+ type: "datetime",
62
+ ...common(o),
63
+ min: o.min,
64
+ max: o.max,
65
+ default: o.default
66
+ });
67
+ },
68
+ markdown(o = {}) {
69
+ return defined({
70
+ type: "markdown",
71
+ ...common(o),
72
+ minLength: o.minLength,
73
+ maxLength: o.maxLength,
74
+ default: o.default
75
+ });
76
+ },
77
+ json(o = {}) {
78
+ return defined({
79
+ type: "json",
80
+ ...common(o),
81
+ default: o.default
82
+ });
83
+ },
84
+ asset(o = {}) {
85
+ return defined({
86
+ type: "asset",
87
+ ...common(o),
88
+ allowed: o.allowed ?? ["*/*"],
89
+ multiple: o.multiple ?? false
90
+ });
91
+ },
92
+ reference(o) {
93
+ return defined({
94
+ type: "reference",
95
+ ...common(o),
96
+ target: o.to,
97
+ multiple: o.multiple ?? false
98
+ });
99
+ },
100
+ slug(o = {}) {
101
+ return defined({
102
+ type: "slug",
103
+ ...common(o),
104
+ from: o.from
105
+ });
106
+ },
107
+ list(o) {
108
+ return defined({
109
+ type: "list",
110
+ ...common(o),
111
+ item: o.of,
112
+ minItems: o.minItems,
113
+ maxItems: o.maxItems
114
+ });
115
+ },
116
+ object(o) {
117
+ return defined({
118
+ type: "object",
119
+ ...common(o),
120
+ fields: assignKeys(o.fields)
121
+ });
122
+ }
123
+ };
124
+ var item = {
125
+ text(o = {}) {
126
+ return defined({ kind: "text", ...o });
127
+ },
128
+ number(o = {}) {
129
+ return defined({ kind: "number", ...o });
130
+ },
131
+ boolean() {
132
+ return { kind: "boolean" };
133
+ },
134
+ date(o = {}) {
135
+ return defined({ kind: "date", ...o });
136
+ },
137
+ datetime(o = {}) {
138
+ return defined({ kind: "datetime", ...o });
139
+ },
140
+ markdown(o = {}) {
141
+ return defined({ kind: "markdown", ...o });
142
+ },
143
+ json() {
144
+ return { kind: "json" };
145
+ },
146
+ reference(o) {
147
+ return { kind: "reference", target: o.to };
148
+ },
149
+ asset(o = {}) {
150
+ return { kind: "asset", allowed: o.allowed ?? ["*/*"] };
151
+ },
152
+ object(o) {
153
+ return { kind: "object", fields: assignKeys(o.fields) };
154
+ }
155
+ };
156
+ function assignKeys(fields) {
157
+ return Object.entries(fields).map(([key, def]) => ({ key, ...def }));
158
+ }
159
+
160
+ // ../schema/src/collection.ts
161
+ function collection(input) {
162
+ const fields = assignKeys(input.fields);
163
+ const slugField = fields.find((f) => f.type === "slug");
164
+ let slug = null;
165
+ if (slugField && slugField.type === "slug") {
166
+ slug = {
167
+ from: slugField.from ?? input.titleField ?? slugField.key,
168
+ required: slugField.required
169
+ };
170
+ }
171
+ return {
172
+ name: input.name,
173
+ label: input.label ?? input.name,
174
+ kind: input.kind ?? "collection",
175
+ visibility: input.visibility ?? "private",
176
+ titleField: input.titleField ?? null,
177
+ slug,
178
+ path: input.path ?? null,
179
+ fields
180
+ };
181
+ }
182
+ export {
183
+ MAX_NESTING_DEPTH,
184
+ assignKeys,
185
+ collection,
186
+ field,
187
+ item
188
+ };
189
+ //# sourceMappingURL=dsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../schema/src/types.ts","../../schema/src/fields.ts","../../schema/src/collection.ts"],"sourcesContent":["/**\n * Canonical schema representation (SPEC 6.2 / 7).\n *\n * These are the normalized, serializable shapes stored as `schema_json`. Field\n * order is significant and preserved as an array; object *keys* are sorted only\n * during canonical stringification for a stable hash.\n */\n\nexport type FieldType =\n | \"text\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"datetime\"\n | \"markdown\"\n | \"json\"\n | \"asset\"\n | \"reference\"\n | \"list\"\n | \"object\"\n | \"slug\";\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/** UI metadata carried on every field (non-semantic, does not affect validation). */\nexport interface FieldUi {\n widget?: string;\n placeholder?: string;\n helpText?: string;\n group?: string;\n hidden?: boolean;\n}\n\ninterface FieldBase {\n key: string;\n type: FieldType;\n label: string;\n description?: string;\n required: boolean;\n ui?: FieldUi;\n}\n\nexport interface TextField extends FieldBase {\n type: \"text\";\n multiline: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n enum?: string[];\n default?: string;\n}\n\nexport interface NumberField extends FieldBase {\n type: \"number\";\n integer: boolean;\n min?: number;\n max?: number;\n default?: number;\n}\n\nexport interface BooleanField extends FieldBase {\n type: \"boolean\";\n default?: boolean;\n}\n\nexport interface DateField extends FieldBase {\n type: \"date\" | \"datetime\";\n min?: string;\n max?: string;\n default?: string;\n}\n\nexport interface MarkdownField extends FieldBase {\n type: \"markdown\";\n minLength?: number;\n maxLength?: number;\n default?: string;\n}\n\nexport interface JsonField extends FieldBase {\n type: \"json\";\n default?: JsonValue;\n}\n\nexport interface AssetField extends FieldBase {\n type: \"asset\";\n /** Allowed MIME families, e.g. `image/*`, `application/pdf`. */\n allowed: string[];\n multiple: boolean;\n}\n\nexport interface ReferenceField extends FieldBase {\n type: \"reference\";\n /** Target collection key. */\n target: string;\n multiple: boolean;\n}\n\nexport interface SlugField extends FieldBase {\n type: \"slug\";\n /** Source field key to derive the slug from. */\n from?: string;\n}\n\nexport type PrimitiveItem =\n | { kind: \"text\"; minLength?: number; maxLength?: number; pattern?: string; enum?: string[] }\n | { kind: \"number\"; integer?: boolean; min?: number; max?: number }\n | { kind: \"boolean\" }\n | { kind: \"date\" | \"datetime\"; min?: string; max?: string }\n | { kind: \"markdown\"; minLength?: number; maxLength?: number }\n | { kind: \"json\" };\n\nexport type ListItem =\n | PrimitiveItem\n | { kind: \"reference\"; target: string }\n | { kind: \"asset\"; allowed: string[] }\n | { kind: \"object\"; fields: FieldDef[] };\n\nexport interface ListField extends FieldBase {\n type: \"list\";\n item: ListItem;\n minItems?: number;\n maxItems?: number;\n}\n\nexport interface ObjectField extends FieldBase {\n type: \"object\";\n fields: FieldDef[];\n}\n\nexport type FieldDef =\n | TextField\n | NumberField\n | BooleanField\n | DateField\n | MarkdownField\n | JsonField\n | AssetField\n | ReferenceField\n | SlugField\n | ListField\n | ObjectField;\n\nexport type CollectionKind = \"collection\" | \"singleton\";\nexport type Visibility = \"public\" | \"private\";\n\nexport interface SlugConfig {\n from: string;\n required: boolean;\n}\n\n/** Canonical collection schema (one `collection_versions.schema_json`). */\nexport interface CollectionSchema {\n name: string;\n label: string;\n kind: CollectionKind;\n visibility: Visibility;\n titleField: string | null;\n slug: SlugConfig | null;\n path: string | null;\n fields: FieldDef[];\n}\n\n/** Maximum object/list nesting depth (SPEC 6.2). */\nexport const MAX_NESTING_DEPTH = 4;\n","import type {\n AssetField,\n BooleanField,\n DateField,\n FieldDef,\n FieldUi,\n JsonField,\n JsonValue,\n ListField,\n ListItem,\n MarkdownField,\n NumberField,\n ObjectField,\n ReferenceField,\n SlugField,\n TextField,\n} from \"./types.js\";\n\n/** A field definition before its `key` is assigned by `collection()`. */\nexport type FieldInput = DistributiveOmit<FieldDef, \"key\">;\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\ninterface CommonOptions {\n label?: string;\n description?: string;\n required?: boolean;\n ui?: FieldUi;\n}\n\nfunction common(o: CommonOptions): { label?: string; description?: string; required: boolean; ui?: FieldUi } {\n const base: { label?: string; description?: string; required: boolean; ui?: FieldUi } = {\n required: o.required ?? false,\n };\n if (o.label !== undefined) base.label = o.label;\n if (o.description !== undefined) base.description = o.description;\n if (o.ui !== undefined) base.ui = o.ui;\n return base;\n}\n\nexport interface TextOptions extends CommonOptions {\n multiline?: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n enum?: string[];\n default?: string;\n}\nexport interface NumberOptions extends CommonOptions {\n integer?: boolean;\n min?: number;\n max?: number;\n default?: number;\n}\nexport interface BooleanOptions extends CommonOptions {\n default?: boolean;\n}\nexport interface DateOptions extends CommonOptions {\n min?: string;\n max?: string;\n default?: string;\n}\nexport interface MarkdownOptions extends CommonOptions {\n minLength?: number;\n maxLength?: number;\n default?: string;\n}\nexport interface JsonOptions extends CommonOptions {\n default?: JsonValue;\n}\nexport interface AssetOptions extends CommonOptions {\n allowed?: string[];\n multiple?: boolean;\n}\nexport interface ReferenceOptions extends CommonOptions {\n to: string;\n multiple?: boolean;\n}\nexport interface SlugOptions extends CommonOptions {\n from?: string;\n}\nexport interface ListOptions extends CommonOptions {\n of: ListItem;\n minItems?: number;\n maxItems?: number;\n}\nexport interface ObjectOptions extends CommonOptions {\n fields: Record<string, FieldInput>;\n}\n\nfunction defined<T extends Record<string, unknown>>(obj: T): T {\n for (const key of Object.keys(obj)) {\n if (obj[key] === undefined) delete obj[key];\n }\n return obj;\n}\n\nexport const field = {\n text(o: TextOptions = {}): Omit<TextField, \"key\"> {\n return defined({\n type: \"text\",\n ...common(o),\n multiline: o.multiline ?? false,\n minLength: o.minLength,\n maxLength: o.maxLength,\n pattern: o.pattern,\n enum: o.enum,\n default: o.default,\n }) as Omit<TextField, \"key\">;\n },\n\n number(o: NumberOptions = {}): Omit<NumberField, \"key\"> {\n return defined({\n type: \"number\",\n ...common(o),\n integer: o.integer ?? false,\n min: o.min,\n max: o.max,\n default: o.default,\n }) as Omit<NumberField, \"key\">;\n },\n\n boolean(o: BooleanOptions = {}): Omit<BooleanField, \"key\"> {\n return defined({\n type: \"boolean\",\n ...common(o),\n default: o.default,\n }) as Omit<BooleanField, \"key\">;\n },\n\n date(o: DateOptions = {}): Omit<DateField, \"key\"> {\n return defined({\n type: \"date\",\n ...common(o),\n min: o.min,\n max: o.max,\n default: o.default,\n }) as Omit<DateField, \"key\">;\n },\n\n datetime(o: DateOptions = {}): Omit<DateField, \"key\"> {\n return defined({\n type: \"datetime\",\n ...common(o),\n min: o.min,\n max: o.max,\n default: o.default,\n }) as Omit<DateField, \"key\">;\n },\n\n markdown(o: MarkdownOptions = {}): Omit<MarkdownField, \"key\"> {\n return defined({\n type: \"markdown\",\n ...common(o),\n minLength: o.minLength,\n maxLength: o.maxLength,\n default: o.default,\n }) as Omit<MarkdownField, \"key\">;\n },\n\n json(o: JsonOptions = {}): Omit<JsonField, \"key\"> {\n return defined({\n type: \"json\",\n ...common(o),\n default: o.default,\n }) as Omit<JsonField, \"key\">;\n },\n\n asset(o: AssetOptions = {}): Omit<AssetField, \"key\"> {\n return defined({\n type: \"asset\",\n ...common(o),\n allowed: o.allowed ?? [\"*/*\"],\n multiple: o.multiple ?? false,\n }) as Omit<AssetField, \"key\">;\n },\n\n reference(o: ReferenceOptions): Omit<ReferenceField, \"key\"> {\n return defined({\n type: \"reference\",\n ...common(o),\n target: o.to,\n multiple: o.multiple ?? false,\n }) as Omit<ReferenceField, \"key\">;\n },\n\n slug(o: SlugOptions = {}): Omit<SlugField, \"key\"> {\n return defined({\n type: \"slug\",\n ...common(o),\n from: o.from,\n }) as Omit<SlugField, \"key\">;\n },\n\n list(o: ListOptions): Omit<ListField, \"key\"> {\n return defined({\n type: \"list\",\n ...common(o),\n item: o.of,\n minItems: o.minItems,\n maxItems: o.maxItems,\n }) as Omit<ListField, \"key\">;\n },\n\n object(o: ObjectOptions): Omit<ObjectField, \"key\"> {\n return defined({\n type: \"object\",\n ...common(o),\n fields: assignKeys(o.fields),\n }) as Omit<ObjectField, \"key\">;\n },\n} as const;\n\n/** Item builders for `field.list({ of: item.<type>() })`. */\nexport const item = {\n text(o: { minLength?: number; maxLength?: number; pattern?: string; enum?: string[] } = {}): ListItem {\n return defined({ kind: \"text\", ...o }) as ListItem;\n },\n number(o: { integer?: boolean; min?: number; max?: number } = {}): ListItem {\n return defined({ kind: \"number\", ...o }) as ListItem;\n },\n boolean(): ListItem {\n return { kind: \"boolean\" };\n },\n date(o: { min?: string; max?: string } = {}): ListItem {\n return defined({ kind: \"date\", ...o }) as ListItem;\n },\n datetime(o: { min?: string; max?: string } = {}): ListItem {\n return defined({ kind: \"datetime\", ...o }) as ListItem;\n },\n markdown(o: { minLength?: number; maxLength?: number } = {}): ListItem {\n return defined({ kind: \"markdown\", ...o }) as ListItem;\n },\n json(): ListItem {\n return { kind: \"json\" };\n },\n reference(o: { to: string }): ListItem {\n return { kind: \"reference\", target: o.to };\n },\n asset(o: { allowed?: string[] } = {}): ListItem {\n return { kind: \"asset\", allowed: o.allowed ?? [\"*/*\"] };\n },\n object(o: { fields: Record<string, FieldInput> }): ListItem {\n return { kind: \"object\", fields: assignKeys(o.fields) };\n },\n} as const;\n\n/** Turn a `{ key: FieldInput }` map into an ordered array of `FieldDef`. */\nexport function assignKeys(fields: Record<string, FieldInput>): FieldDef[] {\n return Object.entries(fields).map(([key, def]) => ({ key, ...def }) as FieldDef);\n}\n","import { assignKeys, type FieldInput } from \"./fields.js\";\nimport type { CollectionKind, CollectionSchema, SlugConfig, Visibility } from \"./types.js\";\n\nexport interface CollectionInput {\n /** Immutable collection key, e.g. `posts`. */\n name: string;\n label?: string;\n kind?: CollectionKind;\n /** Visibility defaults to `private` and must be explicitly declared `public`. */\n visibility?: Visibility;\n titleField?: string;\n /** Path template such as `/blog/{slug}`. */\n path?: string;\n fields: Record<string, FieldInput>;\n}\n\n/**\n * Author a collection schema. Returns the canonical `CollectionSchema` with an\n * ordered fields array. Defaults: `kind=collection`, `visibility=private`.\n */\nexport function collection(input: CollectionInput): CollectionSchema {\n const fields = assignKeys(input.fields);\n const slugField = fields.find((f) => f.type === \"slug\");\n\n let slug: SlugConfig | null = null;\n if (slugField && slugField.type === \"slug\") {\n slug = {\n from: slugField.from ?? input.titleField ?? slugField.key,\n required: slugField.required,\n };\n }\n\n return {\n name: input.name,\n label: input.label ?? input.name,\n kind: input.kind ?? \"collection\",\n visibility: input.visibility ?? \"private\",\n titleField: input.titleField ?? null,\n slug,\n path: input.path ?? null,\n fields,\n };\n}\n"],"mappings":"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","names":[]}
package/dist/main.js CHANGED
@@ -945,9 +945,14 @@ function registerAuth(program) {
945
945
  handle(async (ctx) => {
946
946
  const token = ctx.token ?? loadToken(ctx.apiUrl);
947
947
  if (!token) throw new CliError("Not authenticated. Run `myna login`.");
948
- const account = await fetch(`${ctx.apiUrl}/v1/account`, {
948
+ const identityResponse = await fetch(`${ctx.apiUrl}/v1/auth/whoami`, {
949
949
  headers: { authorization: `Bearer ${token}`, accept: "application/json" }
950
- }).then(async (r) => r.ok ? (await r.json()).data.user : void 0).catch(() => void 0);
950
+ });
951
+ const identityBody = await identityResponse.json().catch(() => ({}));
952
+ if (!identityResponse.ok || !identityBody.data) {
953
+ throw new CliError(identityBody.detail ?? "Stored credential is invalid. Run `myna login` again.");
954
+ }
955
+ const identity = identityBody.data;
951
956
  let organization;
952
957
  if (ctx.organization) {
953
958
  organization = await ctx.management().organizations.get(ctx.organization).then((o) => ({ name: o.name, role: o.role, slug: o.slug })).catch((e) => {
@@ -955,12 +960,12 @@ function registerAuth(program) {
955
960
  throw e;
956
961
  });
957
962
  }
958
- emit({ apiUrl: ctx.apiUrl, authenticated: true, account: account ?? null, organization: organization ?? null }, () => {
963
+ emit({ apiUrl: ctx.apiUrl, authenticated: true, identity, organization: organization ?? null }, () => {
959
964
  const pairs = [["API", ctx.apiUrl], ["Authenticated", "yes"]];
960
- if (account && typeof account === "object" && "username" in account) {
961
- pairs.push(["User", String(account.username)]);
965
+ if (identity.credential === "user") {
966
+ pairs.push(["User", identity.user?.username ?? "(unknown)"]);
962
967
  } else {
963
- pairs.push(["Credential", "API token"]);
968
+ pairs.push(["Credential", identity.credential === "api_key" ? "API key" : "Preview token"]);
964
969
  }
965
970
  if (organization) pairs.push(["Organization", `${organization.name} (${organization.role})`]);
966
971
  keyValues(pairs);
@@ -972,7 +977,7 @@ function registerAuth(program) {
972
977
  // src/commands/workspace.ts
973
978
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
974
979
  import { join as join2 } from "path";
975
- var EXAMPLE_SCHEMA = `import { collection, field } from "@myna-sh/schema";
980
+ var EXAMPLE_SCHEMA = `import { collection, field } from "@myna-sh/sdk/schema";
976
981
 
977
982
  /**
978
983
  * Example collection. Edit freely, then run:
@@ -1103,6 +1108,7 @@ import { join as join4 } from "path";
1103
1108
  // src/schema-loader.ts
1104
1109
  import { existsSync as existsSync3, readdirSync, statSync } from "fs";
1105
1110
  import { join as join3, resolve as resolve2 } from "path";
1111
+ import { fileURLToPath } from "url";
1106
1112
  import { build } from "esbuild";
1107
1113
 
1108
1114
  // ../schema/dist/canonical.js
@@ -1130,6 +1136,18 @@ function toCanonical(schema) {
1130
1136
 
1131
1137
  // src/schema-loader.ts
1132
1138
  var DEFAULT_SCHEMA_DIR = "myna";
1139
+ function dslAliasPlugin() {
1140
+ let dslPath = fileURLToPath(new URL("./dsl.js", import.meta.url));
1141
+ if (!existsSync3(dslPath)) dslPath = dslPath.replace(/\.js$/, ".ts");
1142
+ return {
1143
+ name: "myna-dsl-alias",
1144
+ setup(builder) {
1145
+ builder.onResolve({ filter: /^@myna-sh\/(schema|sdk\/schema)$/ }, () => ({
1146
+ path: dslPath
1147
+ }));
1148
+ }
1149
+ };
1150
+ }
1133
1151
  function looksLikeCollection(value) {
1134
1152
  return typeof value === "object" && value !== null && typeof value.name === "string" && Array.isArray(value.fields);
1135
1153
  }
@@ -1176,7 +1194,8 @@ async function loadLocalSchemas(schemaDir = DEFAULT_SCHEMA_DIR) {
1176
1194
  platform: "node",
1177
1195
  target: "node20",
1178
1196
  logLevel: "silent",
1179
- absWorkingDir: process.cwd()
1197
+ absWorkingDir: process.cwd(),
1198
+ plugins: [dslAliasPlugin()]
1180
1199
  }).catch((error) => {
1181
1200
  throw new CliError(`Failed to compile ${file}: ${error instanceof Error ? error.message : String(error)}`);
1182
1201
  });
@@ -1214,7 +1233,7 @@ function schemaToDsl(schema) {
1214
1233
  if (schema.path) opts.push(`path: ${str(schema.path)}`);
1215
1234
  const fieldLines = schema.fields.map((f) => ` ${ident(f.key)}: ${emitField(f)},`).join("\n");
1216
1235
  return [
1217
- `import { collection, field, item } from "@myna-sh/schema";`,
1236
+ `import { collection, field, item } from "@myna-sh/sdk/schema";`,
1218
1237
  ``,
1219
1238
  `export const ${varName(schema.name)} = collection({`,
1220
1239
  ` ${opts.join(",\n ")},`,
@@ -1874,6 +1893,38 @@ function registerProjects(program) {
1874
1893
  );
1875
1894
  })
1876
1895
  );
1896
+ projects.command("update").description("Update project settings").argument("[project]", "project id or slug").option("--name <name>", "project name").option("--timezone <timezone>", "IANA timezone").option("--public-api <state>", "public API state (on|off)").option("--default-preview-template <template>", "default preview URL template").option("--clear-default-preview-template", "remove the default preview URL template").option("--origins <urls>", "comma-separated allowed origins").option("--clear-origins", "remove all allowed origins").action(
1897
+ handle(async (ctx, args, opts) => {
1898
+ const ref = args[0] ?? ctx.requireProject();
1899
+ const patch = {};
1900
+ if (opts.name !== void 0) patch.name = opts.name;
1901
+ if (opts.timezone !== void 0) patch.timezone = opts.timezone;
1902
+ if (opts.publicApi !== void 0) {
1903
+ const state = String(opts.publicApi).toLowerCase();
1904
+ if (!["on", "off", "true", "false"].includes(state)) {
1905
+ throw new UsageError("--public-api must be on or off.");
1906
+ }
1907
+ patch.publicApiEnabled = state === "on" || state === "true";
1908
+ }
1909
+ if (opts.defaultPreviewTemplate !== void 0 && opts.clearDefaultPreviewTemplate) {
1910
+ throw new UsageError("Use either --default-preview-template or --clear-default-preview-template, not both.");
1911
+ }
1912
+ if (opts.defaultPreviewTemplate !== void 0) {
1913
+ patch.defaultPreviewTemplate = opts.defaultPreviewTemplate;
1914
+ }
1915
+ if (opts.clearDefaultPreviewTemplate) patch.defaultPreviewTemplate = null;
1916
+ if (opts.origins !== void 0 && opts.clearOrigins) {
1917
+ throw new UsageError("Use either --origins or --clear-origins, not both.");
1918
+ }
1919
+ if (opts.origins !== void 0) patch.origins = csv(opts.origins);
1920
+ if (opts.clearOrigins) patch.origins = [];
1921
+ if (Object.keys(patch).length === 0) {
1922
+ throw new UsageError("Specify at least one project setting to update.");
1923
+ }
1924
+ const project = await ctx.management().projects.update(ref, patch);
1925
+ emit(project, () => diag(`Updated ${project.slug}.`));
1926
+ })
1927
+ );
1877
1928
  projects.command("archive").description("Archive a project").argument("[project]", "project id or slug").action(
1878
1929
  handle(async (ctx, args) => {
1879
1930
  const ref = args[0] ?? ctx.requireProject();
@@ -2116,7 +2167,7 @@ function registerBilling(program) {
2116
2167
  }
2117
2168
 
2118
2169
  // src/main.ts
2119
- var VERSION = "0.1.2";
2170
+ var VERSION = "0.1.4";
2120
2171
  var GLOBAL_VALUE_FLAGS = /* @__PURE__ */ new Set(["--project", "--organization", "--token", "--api-url"]);
2121
2172
  var GLOBAL_BOOL_FLAGS = /* @__PURE__ */ new Set(["--json", "--no-interactive", "--interactive"]);
2122
2173
  function normalizeGlobals(argv) {