Restore approved state (tree of 4effcc7 "Added LICENSE")

Roll the working tree back to the last approved shape, before the post-LICENSE span that false-greened the AFI parity matrix with symbol-presence probes and smuggled an unauthorized SQLAlchemy dependency into FastAPI's Shapes binding.

Forward commit, not a history rewrite — the six commits since 4effcc7 stay in the log as the record of what happened.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 14:59:53 -04:00
parent adcc027894
commit ae684a36cb
126 changed files with 1711 additions and 13265 deletions

View File

@@ -13,7 +13,7 @@
* }
*/
import { ReactContext, type ClientOptions, type RegistryEntry, type ParamDef, type AuthRequirement, type AffectsTarget } from './types'
import { ReactContext, type ClientOptions, type RegistryEntry, type ParamDef } from './types'
import { register } from './registry'
function resolveContext(ctx: ReactContext | string | undefined): string | undefined {
@@ -21,25 +21,6 @@ function resolveContext(ctx: ReactContext | string | undefined): string | undefi
return ctx
}
function normalizeMerge(merge: ClientOptions['merge']): string[] | undefined {
if (!merge) return undefined
const items = Array.isArray(merge) ? merge : [merge]
return items.map((m: AffectsTarget) => (m instanceof ReactContext ? m.name : m))
}
/**
* Normalize the public auth option into the stored requirement.
* Mirrors Python: undefined→undefined, true→'required', callable→callable,
* 'staff'/'superuser' pass through, anything else throws at decoration time.
*/
function normalizeAuth(auth: ClientOptions['auth']): AuthRequirement | undefined {
if (auth === undefined) return undefined
if (auth === true) return 'required'
if (typeof auth === 'function') return auth
if (auth === 'staff' || auth === 'superuser') return auth
throw new Error(`Invalid auth value ${JSON.stringify(auth)}`)
}
function normalizeAffects(
affects: ClientOptions['affects'],
): RegistryEntry['affects'] | undefined {
@@ -71,36 +52,6 @@ function extractParams(fn: Function): ParamDef[] {
})
}
function buildEntry(options: ClientOptions, name: string, fn: Function): RegistryEntry {
const context = resolveContext(options.context)
const affects = normalizeAffects(options.affects)
if (context && affects) {
throw new Error('context and affects are mutually exclusive')
}
return {
name,
fn: fn as any,
context,
affects,
merge: normalizeMerge(options.merge),
params: extractParams(fn),
private: options.private ?? false,
viewPath: false,
route: options.route,
methods: options.methods,
auth: normalizeAuth(options.auth),
websocket: options.websocket,
rev: options.rev,
cache: options.cache,
ir: options.ir,
form: options.form,
formName: options.formName,
formRole: options.formRole,
}
}
/**
* Function wrapper — registers a standalone function.
*
@@ -121,19 +72,69 @@ export function client<T extends (...args: any[]) => Promise<any>>(
*/
export function client(options: ClientOptions): MethodDecorator
export function client(optionsOrFn: ClientOptions, fn?: Function): any {
export function client(optionsOrFn: ClientOptions | ClientOptions, fn?: Function): any {
// Function wrapper form: client(options, fn)
if (fn && typeof fn === 'function') {
const options = optionsOrFn as ClientOptions
const context = resolveContext(options.context)
const affects = normalizeAffects(options.affects)
if (context && affects) {
throw new Error('context and affects are mutually exclusive')
}
const name = fn.name || 'anonymous'
register(buildEntry(options, name, fn))
const params = extractParams(fn)
const isView = false // Determined at call time for function wrappers
const entry: RegistryEntry = {
name,
fn: fn as any,
context,
affects,
params,
private: options.private ?? false,
viewPath: isView,
route: options.route,
methods: options.methods,
auth: options.auth,
rev: options.rev,
cache: options.cache,
}
register(entry)
return fn
}
// Decorator form: @client(options)
const options = optionsOrFn as ClientOptions
return function (_target: any, propertyKey: string, descriptor: PropertyDescriptor) {
register(buildEntry(options, propertyKey, descriptor.value))
const originalMethod = descriptor.value
const context = resolveContext(options.context)
const affects = normalizeAffects(options.affects)
if (context && affects) {
throw new Error('context and affects are mutually exclusive')
}
const params = extractParams(originalMethod)
const entry: RegistryEntry = {
name: propertyKey,
fn: originalMethod,
context,
affects,
params,
private: options.private ?? false,
viewPath: false,
route: options.route,
methods: options.methods,
auth: options.auth,
rev: options.rev,
cache: options.cache,
}
register(entry)
return descriptor
}
}