social components inlay-proto.up.railway.app/
atproto components sdui

always validate

+9 -23
+2 -3
packages/@inlay/render/README.md
··· 88 88 89 89 if (isValidElement(node)) { 90 90 const { resolved, node: out, context: outCtx } = await render( 91 - node, ctx, { resolver, validate: false } 91 + node, ctx, { resolver } 92 92 ); 93 93 if (resolved && isValidElement(out)) { 94 94 const Primitive = primitives[out.type]; ··· 168 168 **Render options:** 169 169 - `resolver: Resolver` — I/O callbacks (required) 170 170 - `maxDepth?: number` — nesting limit (default 30) 171 - - `validate?: boolean` — prop validation (default true) 172 171 173 172 ### Types 174 173 175 174 - **`Resolver`** — `{ fetchRecord, xrpc, resolveLexicon }` 176 175 - **`RenderContext`** — `{ imports, component?, componentUri?, depth?, scope?, stack? }` 177 176 - **`RenderResult`** — `{ resolved, node, context, cache? }` 178 - - **`RenderOptions`** — `{ resolver, maxDepth?, validate? }` 177 + - **`RenderOptions`** — `{ resolver, maxDepth? }` 179 178 - **`ComponentRecord`** — re-exported from generated lexicon defs 180 179 - **`CachePolicy`** — re-exported from generated lexicon defs
+4 -16
packages/@inlay/render/src/index.ts
··· 48 48 export type RenderOptions = { 49 49 resolver: Resolver; 50 50 maxDepth?: number; 51 - validate?: boolean; 52 51 }; 53 52 54 53 /** ··· 121 120 const ctx = slotContexts.get(element) ?? context; 122 121 const depth = ctx.depth ?? 0; 123 122 const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH; 124 - const validate = options.validate ?? true; 125 123 126 124 let errorStack = ctx.stack; 127 125 ··· 148 146 ctx.componentUri, 149 147 element, 150 148 props, 151 - ctx, 152 - validate 149 + ctx 153 150 ); 154 151 } 155 152 ··· 192 189 componentUri, 193 190 element, 194 191 props, 195 - ctx, 196 - validate 192 + ctx 197 193 ); 198 194 } catch (e) { 199 195 if (e instanceof MissingError) throw e; ··· 270 266 componentUri: string | undefined, 271 267 element: Element, 272 268 props: Record<string, unknown>, 273 - ctx: RenderContext, 274 - validate: boolean 269 + ctx: RenderContext 275 270 ): Promise<RenderResult> { 276 271 const depth = ctx.depth ?? 0; 277 272 const type = element.type; ··· 281 276 resolvedProps = expandBareDid(resolvedProps, component.view); 282 277 } 283 278 284 - if (validate) { 285 - resolvedProps = await validateProps( 286 - type, 287 - resolvedProps, 288 - component, 289 - resolver 290 - ); 291 - } 279 + resolvedProps = await validateProps(type, resolvedProps, component, resolver); 292 280 293 281 // Primitive: no body, return element with resolved props 294 282 if (!component.body) {
+3 -4
packages/@inlay/render/test/render.test.ts
··· 2919 2919 assert.deepEqual(output, h("span", { value: "Alice" })); 2920 2920 }); 2921 2921 2922 - it("does not expand DID when viewRecord has no rkey", async () => { 2922 + it("rejects bare DID when viewRecord has no rkey", async () => { 2923 2923 const post = "test.app.Post" as const; 2924 2924 const postComponent: ComponentRecord = { 2925 2925 $type: "at.inlay.component", ··· 2927 2927 body: { 2928 2928 $type: "at.inlay.component#bodyTemplate", 2929 2929 node: serializeTree( 2930 - // Bind to uri — shows exactly what the component received 2931 2930 $(Text, { value: $(Binding, { path: ["props", "uri"] }) }) 2932 2931 ), 2933 2932 }, ··· 2948 2947 2949 2948 const output = await renderToCompletion( 2950 2949 $(post, { uri: "did:plc:alice" }), 2951 - { resolver, validate: false }, 2950 + { resolver }, 2952 2951 createContext(postComponent) 2953 2952 ); 2954 2953 2955 - assert.deepEqual(output, h("span", { value: "did:plc:alice" })); 2954 + assert.equal((output as any).tag, "error"); 2956 2955 }); 2957 2956 }); 2958 2957