@capacms/sdk 1.0.0-next.0 → 1.0.0-next.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +450 -0
  2. package/README.md +1754 -156
  3. package/bin/capa-codegen.js +192 -5
  4. package/bin/capa.js +235 -0
  5. package/bin/graphql-project.js +142 -0
  6. package/bin/project-env.js +58 -0
  7. package/dist/client.d.ts +5 -0
  8. package/dist/client.js +17 -0
  9. package/dist/codegen.d.ts +55 -0
  10. package/dist/codegen.js +320 -39
  11. package/dist/config.d.ts +5 -36
  12. package/dist/config.js +47 -1
  13. package/dist/esm/image/index.d.ts +120 -0
  14. package/dist/esm/image/index.js +250 -0
  15. package/dist/esm/image/shared-params.generated.d.ts +190 -0
  16. package/dist/esm/image/shared-params.generated.js +461 -0
  17. package/dist/esm/nextjs/image-loader.d.ts +60 -0
  18. package/dist/esm/nextjs/image-loader.js +67 -0
  19. package/dist/esm/nextjs/overlay.d.ts +30 -0
  20. package/dist/esm/nextjs/overlay.js +75 -0
  21. package/dist/esm/overlay/index.d.ts +32 -0
  22. package/dist/esm/overlay/index.js +576 -0
  23. package/dist/esm/overlay/protocol.d.ts +187 -0
  24. package/dist/esm/overlay/protocol.js +240 -0
  25. package/dist/esm/package.json +4 -0
  26. package/dist/graphql-codegen.d.ts +117 -0
  27. package/dist/graphql-codegen.js +705 -0
  28. package/dist/http.js +1 -1
  29. package/dist/image/index.d.ts +120 -0
  30. package/dist/image/index.js +257 -0
  31. package/dist/image/shared-params.generated.d.ts +190 -0
  32. package/dist/image/shared-params.generated.js +471 -0
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.js +2 -1
  35. package/dist/next/attrs.d.ts +98 -0
  36. package/dist/next/attrs.js +125 -0
  37. package/dist/next/client.d.ts +176 -32
  38. package/dist/next/client.js +212 -90
  39. package/dist/next/entry-fields.d.ts +162 -0
  40. package/dist/next/entry-fields.js +2 -0
  41. package/dist/next/errors.d.ts +136 -0
  42. package/dist/next/errors.js +214 -0
  43. package/dist/next/field-names.d.ts +37 -0
  44. package/dist/next/field-names.js +145 -0
  45. package/dist/next/graphql/build.d.ts +27 -0
  46. package/dist/next/graphql/build.js +98 -0
  47. package/dist/next/graphql/documents.d.ts +67 -0
  48. package/dist/next/graphql/documents.js +35 -0
  49. package/dist/next/graphql/edit-mode.d.ts +16 -0
  50. package/dist/next/graphql/edit-mode.js +93 -0
  51. package/dist/next/graphql/filter-values.d.ts +34 -0
  52. package/dist/next/graphql/filter-values.js +96 -0
  53. package/dist/next/graphql/introspection.d.ts +89 -0
  54. package/dist/next/graphql/introspection.js +102 -0
  55. package/dist/next/graphql/plan.d.ts +115 -0
  56. package/dist/next/graphql/plan.js +531 -0
  57. package/dist/next/graphql/request.d.ts +228 -0
  58. package/dist/next/graphql/request.js +283 -0
  59. package/dist/next/graphql/rest.d.ts +66 -0
  60. package/dist/next/graphql/rest.js +502 -0
  61. package/dist/next/graphql/selection.d.ts +55 -0
  62. package/dist/next/graphql/selection.js +212 -0
  63. package/dist/next/graphql/sha256.d.ts +13 -0
  64. package/dist/next/graphql/sha256.js +86 -0
  65. package/dist/next/graphql/summary.d.ts +83 -0
  66. package/dist/next/graphql/summary.js +151 -0
  67. package/dist/next/graphql/tree-layout.d.ts +36 -0
  68. package/dist/next/graphql/tree-layout.js +20 -0
  69. package/dist/next/graphql/tree.d.ts +171 -0
  70. package/dist/next/graphql/tree.js +249 -0
  71. package/dist/next/graphql/typed.d.ts +261 -0
  72. package/dist/next/graphql/typed.js +146 -0
  73. package/dist/next/index.d.ts +30 -3
  74. package/dist/next/index.js +34 -1
  75. package/dist/next/inflate.d.ts +51 -0
  76. package/dist/next/inflate.js +243 -0
  77. package/dist/next/key-family.d.ts +31 -0
  78. package/dist/next/key-family.js +66 -0
  79. package/dist/next/select-types.d.ts +58 -5
  80. package/dist/next/system-keys.d.ts +27 -0
  81. package/dist/next/system-keys.js +42 -0
  82. package/dist/nextjs/image-loader.d.ts +60 -0
  83. package/dist/nextjs/image-loader.js +71 -0
  84. package/dist/nextjs/index.d.ts +484 -5
  85. package/dist/nextjs/index.js +704 -9
  86. package/dist/nextjs/overlay.d.ts +30 -0
  87. package/dist/nextjs/overlay.js +78 -0
  88. package/dist/overlay/index.d.ts +32 -0
  89. package/dist/overlay/index.js +596 -0
  90. package/dist/overlay/protocol.d.ts +187 -0
  91. package/dist/overlay/protocol.js +253 -0
  92. package/package.json +70 -15
@@ -0,0 +1,261 @@
1
+ /**
2
+ * typed.ts — the typed object builder behind `client.graphql.query()`.
3
+ *
4
+ * A selection is a plain object shaped like the response: `true` for a scalar,
5
+ * an object for anything with fields, and `args` beside the fields of a field
6
+ * that takes arguments.
7
+ *
8
+ * capa.graphql.query({
9
+ * articles: {
10
+ * args: { first: 5, sort: ["publishedAt_DESC"] },
11
+ * nodes: { title: true, author: { name: true } },
12
+ * },
13
+ * });
14
+ *
15
+ * The types come from `capa-codegen --graphql`, which writes the key's schema
16
+ * as TypeScript: pass its `CapaQuery` to `createClient<CapaQuery>()` and the
17
+ * selection is checked field by field (a misspelled field does not compile)
18
+ * while the result is typed from exactly what was selected.
19
+ *
20
+ * An alias reads a field again under another name, in the same request:
21
+ * `{ latest: { __aliasFor: "articles", args: { sort: ["publishedAt_DESC"] }, nodes: { title: true } } }`
22
+ * prints `latest: articles(sort: [publishedAt_DESC]) { ... }` and is typed as
23
+ * `articles` is, under `latest`. A scalar is aliased with `__aliasFor` alone:
24
+ * `{ headline: { __aliasFor: "title" } }`. `client.graphql.query` takes its
25
+ * selection as a `const` type parameter, so `__aliasFor` and every `sort`
26
+ * value keep their literal types inside an alias, which no field's type
27
+ * gives them there.
28
+ *
29
+ * Arguments are written inline as GraphQL literals. Every Capa argument is a
30
+ * scalar or an input object except `sort`, whose values are enum members, so
31
+ * `sort` is the one argument printed without quotes.
32
+ */
33
+ /**
34
+ * A field that takes arguments, as codegen writes it: `R` is what it returns
35
+ * and `A` the arguments it takes. Never a runtime value.
36
+ */
37
+ export interface CapaField<R, A> {
38
+ readonly __capaReturns: R;
39
+ readonly __capaArgs: A;
40
+ }
41
+ /**
42
+ * The key codegen writes each model type's `TreeLayout` under. A symbol, so it
43
+ * is never a field: a selection, a result and autocomplete see string keys only.
44
+ */
45
+ declare const treeLayout: unique symbol;
46
+ export type { treeLayout };
47
+ /**
48
+ * How `toTree` lays a model's entries out in REST's shape, from what only the
49
+ * schema's descriptions say: each field's namespace, which is its key under
50
+ * `fields` (`hero_image` is `hero-image`, `status_field` is `status`), and
51
+ * which fields GraphQL types as ids because the key cannot read their model.
52
+ * Never a runtime value.
53
+ */
54
+ export interface TreeLayout {
55
+ fields: {
56
+ [graphqlName: string]: string;
57
+ };
58
+ ids: string;
59
+ }
60
+ /** What a field returns, under its `CapaField` wrapper when it takes arguments. */
61
+ export type Returns<F> = F extends CapaField<infer R, unknown> ? R : F;
62
+ type ArgsOf<F> = F extends CapaField<unknown, infer A> ? A : never;
63
+ /**
64
+ * Whether `R` admits `null`. Without `strictNullChecks`, `null extends R` holds
65
+ * for every `R`, so the check also asks that `R` changes without `null`: a
66
+ * type that stays itself is not nullable. That keeps the recursion on
67
+ * `NonNullable<R>` finite in a project compiled with `strict: false`.
68
+ */
69
+ export type Nullable<R> = null extends R ? ([R] extends [NonNullable<R>] ? false : true) : false;
70
+ /** The object type under nullability and lists. */
71
+ export type Base<T> = NonNullable<T> extends ReadonlyArray<infer E> ? Base<E> : NonNullable<T>;
72
+ type IsLeaf<T> = unknown extends T ? true : [Base<T>] extends [string | number | boolean | bigint] ? true : false;
73
+ /**
74
+ * Arguments as a selection may write them: every list may be readonly, so a
75
+ * selection declared `as const` (which a selection kept in a variable for
76
+ * `toTree` needs, to keep its enum values) is accepted.
77
+ */
78
+ export type ArgsInput<A> = A extends ReadonlyArray<infer E> ? ReadonlyArray<ArgsInput<E>> : A extends object ? {
79
+ [K in keyof A]: ArgsInput<A[K]>;
80
+ } : A;
81
+ /**
82
+ * Where a field's `args` go: optional when every argument is, and required
83
+ * when one is (`article` needs its `id`), so a read the API would refuse for
84
+ * a missing argument does not compile.
85
+ */
86
+ type ArgsSlot<A> = {} extends ArgsInput<A> ? {
87
+ args?: ArgsInput<A>;
88
+ } : {
89
+ args: ArgsInput<A>;
90
+ };
91
+ /**
92
+ * A scalar is selected with `true`. `boolean` is accepted too, because an
93
+ * object literal held in a variable widens `true` to `boolean`; such a field
94
+ * is typed as possibly absent, and `false` selects nothing.
95
+ */
96
+ type FieldSelection<F> = IsLeaf<Returns<F>> extends true ? boolean : [ArgsOf<F>] extends [never] ? Selection<Base<Returns<F>>> : Selection<Base<Returns<F>>> & ArgsSlot<ArgsOf<F>>;
97
+ /**
98
+ * What may be selected from an object type `T`: each of its fields, and any
99
+ * other key as an alias of one, which `ExactSelection` checks as the field it
100
+ * names. The index signature lets a level hold aliases only: an object type
101
+ * whose keys are all optional accepts no object that shares none of them.
102
+ */
103
+ export type Selection<T> = {
104
+ [K in Extract<keyof T, string>]?: FieldSelection<T[K]>;
105
+ } & {
106
+ readonly [alias: string]: unknown;
107
+ };
108
+ /** The key that makes a selection an alias of another field. */
109
+ export type AliasKey = "__aliasFor";
110
+ /** The field an alias selection `V` reads: its `__aliasFor`, or `never` when `V` is no alias. */
111
+ export type AliasFor<V> = V extends {
112
+ readonly __aliasFor: infer F;
113
+ } ? Extract<F, string> : never;
114
+ /** The keys of selection `S` that alias a field of `T`, rather than name one. */
115
+ export type AliasKeys<S, T> = {
116
+ [K in keyof S]-?: K extends keyof T ? never : [AliasFor<S[K]>] extends [never] ? never : AliasFor<S[K]> extends keyof T ? K : never;
117
+ }[keyof S];
118
+ /** The selection an alias stands for: `true` for a scalar, else its own fields and `args`. */
119
+ type AliasedSelection<T, V> = IsLeaf<Returns<T[Extract<AliasFor<V>, keyof T>]>> extends true ? true : V;
120
+ export type FieldResult<R, S> = S extends true ? R : Nullable<R> extends true ? FieldResult<NonNullable<R>, S> | null : R extends ReadonlyArray<infer E> ? Array<FieldResult<E, S>> : SelectionResult<R, S>;
121
+ /** One object type from an intersection, so a result reads as the object it is. */
122
+ export type Flatten<T> = {
123
+ [K in keyof T]: T[K];
124
+ };
125
+ /**
126
+ * The response for selection `S` on object type `T`: only the fields
127
+ * selected. A field selected with `true` or a sub-selection is always there,
128
+ * one selected with a `boolean` may be absent, one selected with `false` is not.
129
+ */
130
+ export type SelectionResult<T, S> = Flatten<{
131
+ [K in Extract<keyof S, keyof T> as [S[K]] extends [false | undefined] ? never : boolean extends S[K] ? never : K]: FieldResult<Returns<T[K]>, S[K]>;
132
+ } & {
133
+ [K in Extract<keyof S, keyof T> as boolean extends S[K] ? K : never]?: FieldResult<Returns<T[K]>, true>;
134
+ } & {
135
+ [K in AliasKeys<S, T>]: FieldResult<Returns<T[Extract<AliasFor<S[K]>, keyof T>]>, AliasedSelection<T, S[K]>>;
136
+ }>;
137
+ /**
138
+ * What a key the schema does not take is checked against. Nothing satisfies
139
+ * it, and the compiler prints its message, which names the key and where it
140
+ * was written: `Type 'true' is not assignable to type 'true &
141
+ * SelectionError<"titel is not a field of articles.nodes">'`. A `never`, or a
142
+ * message as a string literal, which intersects with `true` to `never`,
143
+ * would print as `never` and name neither.
144
+ */
145
+ export interface SelectionError<Message extends string> {
146
+ readonly __capaSelectionError: Message;
147
+ }
148
+ /**
149
+ * Where a key sits in a selection, as the compiler names it in a refusal:
150
+ * `articles.nodes`, from `P`, the path of the level holding `K`.
151
+ */
152
+ type PathTo<P extends string, K extends string> = P extends "" ? K : `${P}.${K}`;
153
+ /** The level a path names, for a refusal: the path, or `Query` at the root. */
154
+ type LevelName<P extends string> = P extends "" ? "Query" : P;
155
+ /**
156
+ * An argument value `S` checked against the input type `Shape`: every key an
157
+ * input object does not declare becomes a `SelectionError` naming it and where
158
+ * it was written (`"frist is not accepted in articles.args"`), through lists and
159
+ * nested inputs (`and`, `or`, `not`, a relation filter's hop), so a
160
+ * misspelled filter field or operator fails to compile even beside a valid
161
+ * one, and the compiler's error says which.
162
+ */
163
+ type ExactInput<S, Shape, P extends string> = S extends ReadonlyArray<infer E> ? Shape extends ReadonlyArray<infer ShapeElement> ? ReadonlyArray<ExactInput<E, NonNullable<ShapeElement>, P>> : S : S extends object ? {
164
+ [K in keyof S]: K extends keyof Shape ? ExactInput<S[K], NonNullable<Shape[K]>, PathTo<P, K & string>> : SelectionError<`${K & string} is not accepted in ${P}`>;
165
+ } : S;
166
+ /**
167
+ * Selection `S` checked against object type `T`: every key that is neither a
168
+ * field of `T` nor an alias of one becomes a `SelectionError` naming it and
169
+ * the level it was written at (`"titel is not a field of articles.nodes"`), at
170
+ * every level, and so does an argument the field does not declare. A
171
+ * misspelling then fails to compile, instead of being accepted as an extra
172
+ * property, with an error that names it.
173
+ */
174
+ export type Exact<S, T> = S extends object ? ExactLevel<S, T, never, ""> : S;
175
+ /**
176
+ * One level of a selection, at path `P`: the fields of `T`, aliases of them,
177
+ * and `args` when the field takes arguments `A`.
178
+ */
179
+ type ExactLevel<S, T, A, P extends string> = {
180
+ [K in keyof S]: K extends "args" ? [A] extends [never] ? SelectionError<`${LevelName<P>} takes no arguments`> : ExactInput<S[K], ArgsInput<A>, PathTo<P, "args">> : K extends Extract<keyof T, string> ? ExactField<S[K], T[K], PathTo<P, K>> : ExactAlias<S[K], T, P, K & string>;
181
+ };
182
+ /** The selection of field `F` at path `P`: `true` for a scalar, its fields and `args` otherwise. */
183
+ type ExactField<V, F, P extends string> = V extends object ? ExactLevel<V, Base<Returns<F>>, ArgsOf<F>, P> : V;
184
+ /**
185
+ * Key `K` at path `P` checked as an alias: as the field it names, its required
186
+ * arguments and their types included, or a `SelectionError` when it names no
187
+ * field of `T`, or is no alias and no field at all.
188
+ */
189
+ type ExactAlias<V, T, P extends string, K extends string> = [AliasFor<V>] extends [never] ? SelectionError<`${K} is not a field of ${LevelName<P>}`> : AliasFor<V> extends Extract<keyof T, string> ? ExactField<Omit<V, AliasKey>, T[AliasFor<V>], PathTo<P, K>> & {
190
+ readonly __aliasFor: AliasFor<V>;
191
+ } & AliasShape<FieldSelection<T[AliasFor<V>]>> : SelectionError<`${AliasFor<V>} is not a field of ${LevelName<P>}`>;
192
+ /** What an alias of a field selected as `F` must also be: nothing more for a scalar, the field's own selection otherwise. */
193
+ type AliasShape<F> = [F] extends [boolean] ? unknown : F;
194
+ /**
195
+ * Stands in for the schema when a client was created without codegen types:
196
+ * any selection is accepted and the result is untyped.
197
+ */
198
+ export interface UntypedQuery {
199
+ readonly __capaUntyped: true;
200
+ }
201
+ type AnySelection = {
202
+ [field: string]: boolean | AnySelection | Record<string, unknown>;
203
+ };
204
+ declare const runtimeSelection: unique symbol;
205
+ /**
206
+ * A selection built at run time from a REST read (`selectToSelection`): its
207
+ * fields are known only once it runs, so any client runs it, untyped, and
208
+ * `toTree` reads it with any schema. A selection written in code is never one,
209
+ * so it is still checked field by field.
210
+ */
211
+ export interface RuntimeSelection {
212
+ readonly [runtimeSelection]: true;
213
+ readonly [rootField: string]: Readonly<Record<string, unknown>>;
214
+ }
215
+ /** Whether `Q` carries no schema: a client created without codegen types, or a schema summary read without them. */
216
+ export type IsUntyped<Q> = unknown extends Q ? true : [Q] extends [UntypedQuery] ? true : false;
217
+ /** The selection accepted by a client typed with `Q`: its schema's fields, or a selection built at run time. */
218
+ export type QuerySelection<Q> = (IsUntyped<Q> extends true ? AnySelection : Selection<Q>) | RuntimeSelection;
219
+ /** `S` checked against `Q`: an unknown field becomes a `SelectionError` naming it. Untyped clients, and a selection built at run time, take it as it is. */
220
+ export type ExactSelection<S, Q> = S extends RuntimeSelection ? S : IsUntyped<Q> extends true ? S : Exact<S, Q>;
221
+ /** The data returned for selection `S` by a client typed with `Q`; untyped for a selection built at run time. */
222
+ export type QueryResult<Q, S> = S extends RuntimeSelection ? Record<string, unknown> : IsUntyped<Q> extends true ? Record<string, unknown> : SelectionResult<Q, S>;
223
+ /** The schema field root key `K` of selection `S` reads: `K` itself, or the field an alias names. */
224
+ type RootFieldOf<Q, S, K extends keyof S> = K extends keyof Q ? K : Extract<AliasFor<S[K]>, keyof Q>;
225
+ /** Whether a root field returns a connection (a list root), whose entries are its `nodes` or `edges`. */
226
+ type IsConnection<T> = T extends {
227
+ nodes: unknown;
228
+ pageInfo: unknown;
229
+ } ? true : false;
230
+ /** One entry of root data `R`: an item of its `nodes` (or an `edges` node) for a list root, `R` itself for a single root. */
231
+ type EntryOfRoot<R, Connection> = Connection extends true ? R extends {
232
+ nodes: ReadonlyArray<infer N>;
233
+ } ? N : R extends {
234
+ edges: ReadonlyArray<{
235
+ node: infer N;
236
+ }>;
237
+ } ? NonNullable<N> : never : R;
238
+ /**
239
+ * One entry that root field `K` of selection `S` reads, as a client typed
240
+ * with `Q` returns it: a node of a list root (`articles`), or the entry of a
241
+ * single root (`article`). A component that renders one entry takes it as its
242
+ * props type, so the component and the query cannot drift:
243
+ *
244
+ * const teasers = { articles: { args: { first: 5 }, nodes: { id: true, title: true } } } as const;
245
+ * type Teaser = NodeOf<CapaQuery, typeof teasers, "articles">; // { id: string; title: string | null }
246
+ *
247
+ * `K` may be an alias. `unknown` for an untyped client.
248
+ */
249
+ export type NodeOf<Q, S, K extends keyof S> = IsUntyped<Q> extends true ? unknown : EntryOfRoot<NonNullable<QueryResult<Q, S>[K & keyof QueryResult<Q, S>]>, IsConnection<Base<Returns<Q[RootFieldOf<Q, S, K>]>>>>;
250
+ /**
251
+ * The field a selection reads when it is an alias (`{ __aliasFor: "articles" }`),
252
+ * or undefined when it is none.
253
+ */
254
+ export declare function aliasedField(selection: unknown): string | undefined;
255
+ /** The keys a selection level selects: not `args`, `__aliasFor` or `__typename`, and not `false`. */
256
+ export declare function selectedKeys(selection: Readonly<Record<string, unknown>>): string[];
257
+ /**
258
+ * The GraphQL document for a builder selection. Pure, exported so the text a
259
+ * selection sends can be logged, persisted or tested.
260
+ */
261
+ export declare function selectionToDocument(selection: unknown, operationName?: string): string;
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ /**
3
+ * typed.ts — the typed object builder behind `client.graphql.query()`.
4
+ *
5
+ * A selection is a plain object shaped like the response: `true` for a scalar,
6
+ * an object for anything with fields, and `args` beside the fields of a field
7
+ * that takes arguments.
8
+ *
9
+ * capa.graphql.query({
10
+ * articles: {
11
+ * args: { first: 5, sort: ["publishedAt_DESC"] },
12
+ * nodes: { title: true, author: { name: true } },
13
+ * },
14
+ * });
15
+ *
16
+ * The types come from `capa-codegen --graphql`, which writes the key's schema
17
+ * as TypeScript: pass its `CapaQuery` to `createClient<CapaQuery>()` and the
18
+ * selection is checked field by field (a misspelled field does not compile)
19
+ * while the result is typed from exactly what was selected.
20
+ *
21
+ * An alias reads a field again under another name, in the same request:
22
+ * `{ latest: { __aliasFor: "articles", args: { sort: ["publishedAt_DESC"] }, nodes: { title: true } } }`
23
+ * prints `latest: articles(sort: [publishedAt_DESC]) { ... }` and is typed as
24
+ * `articles` is, under `latest`. A scalar is aliased with `__aliasFor` alone:
25
+ * `{ headline: { __aliasFor: "title" } }`. `client.graphql.query` takes its
26
+ * selection as a `const` type parameter, so `__aliasFor` and every `sort`
27
+ * value keep their literal types inside an alias, which no field's type
28
+ * gives them there.
29
+ *
30
+ * Arguments are written inline as GraphQL literals. Every Capa argument is a
31
+ * scalar or an input object except `sort`, whose values are enum members, so
32
+ * `sort` is the one argument printed without quotes.
33
+ */
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.aliasedField = aliasedField;
36
+ exports.selectedKeys = selectedKeys;
37
+ exports.selectionToDocument = selectionToDocument;
38
+ const NAME = /^[_A-Za-z][_0-9A-Za-z]*$/;
39
+ function checkName(name, where) {
40
+ if (!NAME.test(name))
41
+ throw new TypeError(`@capacms/sdk/next: ${JSON.stringify(name)} is not a GraphQL name (${where}).`);
42
+ return name;
43
+ }
44
+ function literal(value, enumValues) {
45
+ if (value === null)
46
+ return "null";
47
+ if (Array.isArray(value))
48
+ return `[${value.map((v) => literal(v, enumValues)).join(", ")}]`;
49
+ switch (typeof value) {
50
+ case "string":
51
+ return enumValues ? checkName(value, "sort value") : JSON.stringify(value);
52
+ case "number":
53
+ if (!Number.isFinite(value))
54
+ throw new TypeError("@capacms/sdk/next: an argument number must be finite.");
55
+ return String(value);
56
+ case "boolean":
57
+ return String(value);
58
+ case "object": {
59
+ // A date goes as the ISO text the DateTime scalar reads; any other
60
+ // object that is not plain would print as its enumerable keys, `{}`.
61
+ if (value instanceof Date) {
62
+ if (Number.isNaN(value.getTime()))
63
+ throw new TypeError("@capacms/sdk/next: an argument date is not a valid date.");
64
+ return JSON.stringify(value.toISOString());
65
+ }
66
+ const prototype = Object.getPrototypeOf(value);
67
+ if (prototype !== Object.prototype && prototype !== null) {
68
+ throw new TypeError(`@capacms/sdk/next: an argument cannot be a ${prototype?.constructor?.name ?? "class instance"}; ` +
69
+ "write a plain object, a list, text, a number, true, false or null.");
70
+ }
71
+ const fields = Object.entries(value)
72
+ .filter(([, inner]) => inner !== undefined)
73
+ .map(([key, inner]) => `${checkName(key, "argument field")}: ${literal(inner, false)}`);
74
+ return `{${fields.join(", ")}}`;
75
+ }
76
+ default:
77
+ throw new TypeError(`@capacms/sdk/next: an argument cannot be ${typeof value}.`);
78
+ }
79
+ }
80
+ function printArgs(args) {
81
+ if (args === undefined)
82
+ return "";
83
+ if (!args || typeof args !== "object" || Array.isArray(args)) {
84
+ throw new TypeError("@capacms/sdk/next: args must be an object.");
85
+ }
86
+ const parts = Object.entries(args)
87
+ .filter(([, value]) => value !== undefined)
88
+ .map(([name, value]) => `${checkName(name, "argument")}: ${literal(value, name === "sort")}`);
89
+ return parts.length ? `(${parts.join(", ")})` : "";
90
+ }
91
+ /** The key that makes a selection an alias of another field. */
92
+ const ALIAS_KEY = "__aliasFor";
93
+ /**
94
+ * The field a selection reads when it is an alias (`{ __aliasFor: "articles" }`),
95
+ * or undefined when it is none.
96
+ */
97
+ function aliasedField(selection) {
98
+ if (!selection || typeof selection !== "object" || !(ALIAS_KEY in selection))
99
+ return undefined;
100
+ const field = selection[ALIAS_KEY];
101
+ if (typeof field !== "string")
102
+ throw new TypeError(`@capacms/sdk/next: ${ALIAS_KEY} names the field an alias reads, as text.`);
103
+ return checkName(field, "aliased field");
104
+ }
105
+ /** The keys a selection level selects: not `args`, `__aliasFor` or `__typename`, and not `false`. */
106
+ function selectedKeys(selection) {
107
+ return Object.keys(selection).filter((key) => key !== "args" && key !== ALIAS_KEY && key !== "__typename" && selection[key] !== false && selection[key] !== undefined);
108
+ }
109
+ function printSelection(selection, depth) {
110
+ if (!selection || typeof selection !== "object" || Array.isArray(selection)) {
111
+ throw new TypeError("@capacms/sdk/next: a selection must be an object of fields.");
112
+ }
113
+ const pad = " ".repeat(depth);
114
+ const lines = [];
115
+ for (const [name, value] of Object.entries(selection)) {
116
+ if (name === "args" || name === ALIAS_KEY || value === undefined || value === false)
117
+ continue;
118
+ checkName(name, "field");
119
+ if (value === true) {
120
+ lines.push(`${pad}${name}`);
121
+ continue;
122
+ }
123
+ const field = aliasedField(value);
124
+ const head = `${pad}${field === undefined ? name : `${name}: ${field}`}${printArgs(value.args)}`;
125
+ const inner = printSelection(value, depth + 1);
126
+ // An alias of a scalar selects nothing below it.
127
+ if (inner.length === 0 && field !== undefined)
128
+ lines.push(head);
129
+ else if (inner.length === 0)
130
+ throw new TypeError(`@capacms/sdk/next: ${name} selects no fields.`);
131
+ else
132
+ lines.push(`${head} {`, ...inner, `${pad}}`);
133
+ }
134
+ return lines;
135
+ }
136
+ /**
137
+ * The GraphQL document for a builder selection. Pure, exported so the text a
138
+ * selection sends can be logged, persisted or tested.
139
+ */
140
+ function selectionToDocument(selection, operationName) {
141
+ const name = operationName === undefined ? "" : ` ${checkName(operationName, "operation name")}`;
142
+ const body = printSelection(selection, 1);
143
+ if (body.length === 0)
144
+ throw new TypeError("@capacms/sdk/next: a query must select at least one field.");
145
+ return [`query${name} {`, ...body, "}"].join("\n");
146
+ }
@@ -1,3 +1,30 @@
1
- export { CapaError, createClient, isCapaError, resolveNextConfig, serializeSelect, } from "./client";
2
- export type { CallOptions, CapaNextClient, CapaNextConfig, EntriesResource, Entry, Filter, FilterOperator, FilterScalar, FilterValue, GetOptions, ListOptions, Page, PageDetail, PageInfo, PageSummary, PagesListOptions, PagesResource, PreviewClaim, ResponseMeta, Single, } from "./client";
3
- export type { CapaRelation, CapaRelationList, RelationSelectOptions, Select, SelectItem, SelectSort, } from "./select-types";
1
+ export { CapaError, createClient, isCapaError, LAYOUT_PAGE, resolveNextConfig, serializeSelect, } from "./client";
2
+ export { CAPA_EDIT, capaAttrs, fieldAttrs, isEditEntry, markEditEntries, markGraphQLEntries } from "./attrs";
3
+ export { inflate } from "./inflate";
4
+ export { isCapaGraphQLError } from "./errors";
5
+ export type { CapaGraphQLError, GraphQLErrorItem } from "./errors";
6
+ export { INTROSPECTION_QUERY } from "./graphql/introspection";
7
+ export type { CapaIntrospection } from "./graphql/introspection";
8
+ export { PERSISTED_QUERY_NOT_FOUND } from "./graphql/request";
9
+ export { gql } from "./graphql/documents";
10
+ export type { CapaDocumentResult, CapaDocuments, CapaDocumentVariables, NotARecordedDocument, RunCapaCodegen } from "./graphql/documents";
11
+ export type { CapaGraphQLCost, CapaGraphQLExtensions, GraphQLCallOptions, GraphQLDeprecation, GraphQLQueryCost, GraphQLResult, TypedDocument, VariablesThenOptions, } from "./graphql/request";
12
+ export { summarizeIntrospection } from "./graphql/summary";
13
+ export type { GraphQLFieldKind, GraphQLFieldSummary, GraphQLModelSummary, GraphQLSchemaSummary, GraphQLSystemFilterSummary, } from "./graphql/summary";
14
+ export { CapaBuildError } from "./graphql/plan";
15
+ export type { GraphQLFieldSpec, GraphQLFieldSpecSort, GraphQLQuerySpec } from "./graphql/plan";
16
+ export { buildGraphQLQuery } from "./graphql/build";
17
+ export type { BuiltGraphQLQuery } from "./graphql/build";
18
+ export { selectToGraphQL } from "./graphql/rest";
19
+ export type { RestReadOptions, RestRequest } from "./graphql/rest";
20
+ export { graphqlToSelect, selectToSelection } from "./graphql/selection";
21
+ export { toTree } from "./graphql/tree";
22
+ export type { TreeData, TreeEntry, TreeRoot, TreeSelection } from "./graphql/tree";
23
+ export type { CapaTreeLayout, TreeLayoutField, TreeLayoutModel } from "./graphql/tree-layout";
24
+ export { selectionToDocument } from "./graphql/typed";
25
+ export type { ArgsInput, CapaField, Exact, ExactSelection, NodeOf, QueryResult, QuerySelection, RuntimeSelection, Selection, SelectionError, SelectionResult, TreeLayout, treeLayout, UntypedQuery, } from "./graphql/typed";
26
+ export type { FlatResponse, Inflated } from "./inflate";
27
+ export type { EntryFields, EntryMedia, EntryReference, FlatFields, IncludedFields, MissingEntry, RelationItems, } from "./entry-fields";
28
+ export type { CapaAttrs, FieldAttrs, TaggableField } from "./attrs";
29
+ export type { BuilderCallOptions, CallOptions, CapaNextClient, CapaNextConfig, EntriesResource, Entry, GraphQLClient, Filter, FilterOperator, FlatGetOptions, FlatListOptions, FlatPage, FlatSingle, Included, FilterScalar, FilterValue, GetOptions, ListOptions, Page, PageDetail, PageInfo, PageSummary, PagesListOptions, PagesResource, PreviewClaim, ResponseMeta, ResponseShape, Single, } from "./client";
30
+ export type { ExpandedTargets, CapaRelation, CapaRelationList, RelationSelectOptions, Select, SelectItem, SelectSort, SortableSystemKey, SystemKey, } from "./select-types";
@@ -1,9 +1,42 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serializeSelect = exports.resolveNextConfig = exports.isCapaError = exports.createClient = exports.CapaError = void 0;
3
+ exports.selectionToDocument = exports.toTree = exports.selectToSelection = exports.graphqlToSelect = exports.selectToGraphQL = exports.buildGraphQLQuery = exports.CapaBuildError = exports.summarizeIntrospection = exports.gql = exports.PERSISTED_QUERY_NOT_FOUND = exports.INTROSPECTION_QUERY = exports.isCapaGraphQLError = exports.inflate = exports.markGraphQLEntries = exports.markEditEntries = exports.isEditEntry = exports.fieldAttrs = exports.capaAttrs = exports.CAPA_EDIT = exports.serializeSelect = exports.resolveNextConfig = exports.LAYOUT_PAGE = exports.isCapaError = exports.createClient = exports.CapaError = void 0;
4
4
  var client_1 = require("./client");
5
5
  Object.defineProperty(exports, "CapaError", { enumerable: true, get: function () { return client_1.CapaError; } });
6
6
  Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return client_1.createClient; } });
7
7
  Object.defineProperty(exports, "isCapaError", { enumerable: true, get: function () { return client_1.isCapaError; } });
8
+ Object.defineProperty(exports, "LAYOUT_PAGE", { enumerable: true, get: function () { return client_1.LAYOUT_PAGE; } });
8
9
  Object.defineProperty(exports, "resolveNextConfig", { enumerable: true, get: function () { return client_1.resolveNextConfig; } });
9
10
  Object.defineProperty(exports, "serializeSelect", { enumerable: true, get: function () { return client_1.serializeSelect; } });
11
+ var attrs_1 = require("./attrs");
12
+ Object.defineProperty(exports, "CAPA_EDIT", { enumerable: true, get: function () { return attrs_1.CAPA_EDIT; } });
13
+ Object.defineProperty(exports, "capaAttrs", { enumerable: true, get: function () { return attrs_1.capaAttrs; } });
14
+ Object.defineProperty(exports, "fieldAttrs", { enumerable: true, get: function () { return attrs_1.fieldAttrs; } });
15
+ Object.defineProperty(exports, "isEditEntry", { enumerable: true, get: function () { return attrs_1.isEditEntry; } });
16
+ Object.defineProperty(exports, "markEditEntries", { enumerable: true, get: function () { return attrs_1.markEditEntries; } });
17
+ Object.defineProperty(exports, "markGraphQLEntries", { enumerable: true, get: function () { return attrs_1.markGraphQLEntries; } });
18
+ var inflate_1 = require("./inflate");
19
+ Object.defineProperty(exports, "inflate", { enumerable: true, get: function () { return inflate_1.inflate; } });
20
+ var errors_1 = require("./errors");
21
+ Object.defineProperty(exports, "isCapaGraphQLError", { enumerable: true, get: function () { return errors_1.isCapaGraphQLError; } });
22
+ var introspection_1 = require("./graphql/introspection");
23
+ Object.defineProperty(exports, "INTROSPECTION_QUERY", { enumerable: true, get: function () { return introspection_1.INTROSPECTION_QUERY; } });
24
+ var request_1 = require("./graphql/request");
25
+ Object.defineProperty(exports, "PERSISTED_QUERY_NOT_FOUND", { enumerable: true, get: function () { return request_1.PERSISTED_QUERY_NOT_FOUND; } });
26
+ var documents_1 = require("./graphql/documents");
27
+ Object.defineProperty(exports, "gql", { enumerable: true, get: function () { return documents_1.gql; } });
28
+ var summary_1 = require("./graphql/summary");
29
+ Object.defineProperty(exports, "summarizeIntrospection", { enumerable: true, get: function () { return summary_1.summarizeIntrospection; } });
30
+ var plan_1 = require("./graphql/plan");
31
+ Object.defineProperty(exports, "CapaBuildError", { enumerable: true, get: function () { return plan_1.CapaBuildError; } });
32
+ var build_1 = require("./graphql/build");
33
+ Object.defineProperty(exports, "buildGraphQLQuery", { enumerable: true, get: function () { return build_1.buildGraphQLQuery; } });
34
+ var rest_1 = require("./graphql/rest");
35
+ Object.defineProperty(exports, "selectToGraphQL", { enumerable: true, get: function () { return rest_1.selectToGraphQL; } });
36
+ var selection_1 = require("./graphql/selection");
37
+ Object.defineProperty(exports, "graphqlToSelect", { enumerable: true, get: function () { return selection_1.graphqlToSelect; } });
38
+ Object.defineProperty(exports, "selectToSelection", { enumerable: true, get: function () { return selection_1.selectToSelection; } });
39
+ var tree_1 = require("./graphql/tree");
40
+ Object.defineProperty(exports, "toTree", { enumerable: true, get: function () { return tree_1.toTree; } });
41
+ var typed_1 = require("./graphql/typed");
42
+ Object.defineProperty(exports, "selectionToDocument", { enumerable: true, get: function () { return typed_1.selectionToDocument; } });
@@ -0,0 +1,51 @@
1
+ import type { Entry } from "./client";
2
+ import type { EntryFields, FlatRead, flatRead } from "./entry-fields";
3
+ /** The flat body, or an SDK result wrapping one. */
4
+ export interface FlatResponse {
5
+ data: unknown;
6
+ included: Record<string, Record<string, unknown>>;
7
+ /** The select the request sent, when the SDK made it. */
8
+ select?: string;
9
+ }
10
+ /**
11
+ * One level of a select: `*` or not, and the names it wrote, in order, each
12
+ * read back from its quotes. A quoted name is always a field (`"tags"`),
13
+ * never a system key, and is marked `quoted`.
14
+ */
15
+ interface Level {
16
+ star: boolean;
17
+ items: Array<{
18
+ name: string;
19
+ expand: Level | null;
20
+ quoted?: true;
21
+ }>;
22
+ }
23
+ /**
24
+ * The select grammar, read only as far as `inflate` needs it: names, bare or
25
+ * quoted (`"price.usd"`, spec 17 amendment 121), nesting and `*`. Modifiers
26
+ * (`limit:`, `sort:`, `after:`) decide which rows the API returned, which the
27
+ * response already reflects, so they are skipped. The API validated the
28
+ * select before answering, so this parser trusts its shape and throws a
29
+ * `TypeError` only on text it cannot split at all.
30
+ */
31
+ export declare function parseSelectLevels(select: string): Level;
32
+ /**
33
+ * What `inflate` returns for `R`: `R` without `included` and `select`. For a
34
+ * flat read of this SDK, `data` is typed as the tree read of the same model
35
+ * and select returns it (`EntryFields`).
36
+ */
37
+ export type Inflated<R> = typeof flatRead extends keyof R ? R extends FlatRead<infer T, infer S> ? Omit<R, "included" | "select" | "data" | typeof flatRead> & {
38
+ data: R extends {
39
+ data: ReadonlyArray<unknown>;
40
+ } ? Array<Entry<EntryFields<T, S>>> : Entry<EntryFields<T, S>>;
41
+ } : Omit<R, "included" | "select"> : Omit<R, "included" | "select">;
42
+ /**
43
+ * The tree shape of a flat response: `data` with every expansion nested back
44
+ * in, `included` and `select` removed, everything else (`page`, `meta`,
45
+ * `cacheTags`) carried over as it was.
46
+ *
47
+ * `select` is what the request sent; it defaults to `response.select`, which
48
+ * an SDK flat read fills in. A request with no select expanded nothing.
49
+ */
50
+ export declare function inflate<R extends FlatResponse>(response: R, select?: string): Inflated<R>;
51
+ export {};