API — Operações & I/O — JavaScript / TypeScript
Índice
- Operações de Array
- JSON Patch
- Validação de Schema
- Segurança
- I/O & Carregamento de Arquivos
- Log de Auditoria
- Integrações de Framework
Operações de Array
Todas as operações de array são imutáveis — retornam uma nova instância do accessor.
Import: Estes são métodos de instância em qualquer accessor.
push(path: string, ...items: unknown[]): AbstractAccessor
Adiciona itens ao final do array no caminho dado.
const updated = accessor.push("tags", "new-tag");pop(path: string): AbstractAccessor
Remove o último item do array no caminho dado.
shift(path: string): AbstractAccessor
Remove o primeiro item do array no caminho dado.
unshift(path: string, ...items: unknown[]): AbstractAccessor
Adiciona itens ao início do array no caminho dado.
insert(path: string, index: number, ...items: unknown[]): AbstractAccessor
Insere itens no índice dado no array no caminho dado.
const updated = accessor.insert("items", 2, { id: 99 });filterAt(path: string, predicate: (item, index) => boolean): AbstractAccessor
Filtra o array no caminho dado usando uma função predicado.
const active = accessor.filterAt("users", (u) => u.active === true);mapAt(path: string, transform: (item, index) => unknown): AbstractAccessor
Transforma cada item no array no caminho dado.
sortAt(path: string, key?: string, direction?: 'asc' | 'desc'): AbstractAccessor
Ordena o array no caminho dado. Para arrays de objetos, passe key para ordenar por um campo específico.
const sorted = accessor.sortAt("items", "price", "desc");unique(path: string, key?: string): AbstractAccessor
Remove duplicatas do array no caminho dado. Para objetos, passe key para deduplicar por um campo específico.
flatten(path: string, depth?: number): AbstractAccessor
Achata arrays aninhados no caminho dado. Profundidade padrão é 1.
first(path: string, defaultValue?: unknown): unknown
Retorna o primeiro elemento do array no caminho dado.
accessor.first("items"); // primeiro item
accessor.first("items", null); // null se vaziolast(path: string, defaultValue?: unknown): unknown
Retorna o último elemento do array no caminho dado.
nth(path: string, index: number, defaultValue?: unknown): unknown
Retorna o elemento no índice dado. Suporta índices negativos.
accessor.nth("items", -1); // último itemJSON Patch
Import: import { diff, applyPatch } from '@safe-access-inline/safe-access-inline'
diff(a: Record<string, unknown>, b: Record<string, unknown>): JsonPatchOp[]
Calcula um JSON Patch RFC 6902 entre dois objetos.
const patches = diff(original, modified);
// [{ op: 'replace', path: '/name', value: 'New' }, ...]applyPatch(data: Record<string, unknown>, ops: JsonPatchOp[]): Record<string, unknown>
Aplica um JSON Patch a um objeto. Retorna um novo objeto (não muta o input).
const result = applyPatch(data, patches);Métodos de Instância
Accessors também expõem estes como métodos de instância:
const patches = accessorA.diff(accessorB);
const patched = accessor.applyPatch(patches);JsonPatchOp
type JsonPatchOp = {
op: "add" | "remove" | "replace" | "move" | "copy" | "test";
path: string;
value?: unknown;
from?: string;
};Validação de Schema
Import: import { SchemaRegistry, SchemaValidationError } from '@safe-access-inline/safe-access-inline'
SchemaRegistry.setDefaultAdapter(adapter: SchemaAdapterInterface): void
Define um adapter de schema global padrão usado por accessor.validate() quando nenhum adapter é passado.
SchemaRegistry.getDefaultAdapter(): SchemaAdapterInterface | null
Retorna o adapter padrão atual, ou null.
SchemaRegistry.clearDefaultAdapter(): void
Limpa o adapter padrão.
SchemaAdapterInterface
interface SchemaAdapterInterface<TSchema = unknown> {
validate(
data: Record<string, unknown>,
schema: TSchema,
): SchemaValidationResult;
}
interface SchemaValidationResult {
valid: boolean;
errors: SchemaValidationIssue[];
}
interface SchemaValidationIssue {
path: string;
message: string;
}Segurança
SecurityPolicy
Import: import { mergePolicy, defaultPolicy } from '@safe-access-inline/safe-access-inline'
Uma configuração de segurança unificada que agrega todas as opções de segurança.
import type { SecurityPolicy } from "@safe-access-inline/safe-access-inline";
const policy = mergePolicy(defaultPolicy(), {
maxDepth: 256,
allowedDirs: ["/etc/config"],
url: { allowPrivateIps: false, allowedHosts: ["api.example.com"] },
maskPatterns: ["password", "secret"],
});
const accessor = SafeAccess.withPolicy(data, policy);
const fileAccessor = await SafeAccess.fromFileWithPolicy(
"/etc/config/app.json",
policy,
);
const urlAccessor = await SafeAccess.fromUrlWithPolicy(
"https://api.example.com/config",
policy,
);Interface SecurityPolicy
interface SecurityPolicy {
maxDepth?: number;
maxPayloadBytes?: number;
maxKeys?: number;
allowedDirs?: string[];
url?: UrlPolicy;
csvMode?: "none" | "prefix" | "strip" | "error";
maskPatterns?: MaskPattern[];
}
interface UrlPolicy {
allowPrivateIps?: boolean;
allowedHosts?: string[];
allowedPorts?: number[];
}mergePolicy(base, overrides?): SecurityPolicy
Mescla duas policies. Overrides têm prioridade.
defaultPolicy(): SecurityPolicy
Retorna a policy padrão (maxDepth=512, maxPayloadBytes=10MB, maxKeys=10000).
SecurityOptions
Import: import { assertPayloadSize, assertMaxKeys, assertMaxDepth } from '@safe-access-inline/safe-access-inline'
Funções de asserção de baixo nível usadas internamente por todos os parsers de formato:
assertPayloadSize(input: string, maxBytes?: number): voidassertMaxKeys(data: Record<string, unknown>, maxKeys?: number): voidassertMaxDepth(currentDepth: number, maxDepth?: number): void
Mascaramento de Dados
Import: import { mask } from '@safe-access-inline/safe-access-inline'
mask(data, patterns?): Record<string, unknown>
Mascara recursivamente valores sensíveis. Auto-detecta chaves sensíveis comuns (password, secret, token, etc.). Suporta padrões wildcard com *.
const safe = mask(data, ["api_*", "credentials"]);
// { password: '[REDACTED]', api_key: '[REDACTED]', name: 'Ana' }Sanitização CSV
Import: import { sanitizeCsvCell, sanitizeCsvRow } from '@safe-access-inline/safe-access-inline'
Protege contra injeção de fórmulas CSV.
sanitizeCsvCell(cell: string, mode?: CsvSanitizeMode): stringsanitizeCsvRow(row: string[], mode?: CsvSanitizeMode): string[]
Modos: 'prefix' (prefixa com '), 'strip' (remove todos os caracteres de prefixo de injeção CSV: =, +, -, @, \t, \r, \n conforme orientação OWASP CSV Injection), 'error' (lança erro), 'none' (passthrough).
Deep Freeze
Import: import { deepFreeze } from '@safe-access-inline/safe-access-inline'
deepFreeze<T extends object>(obj: T): Readonly<T>
Congela recursivamente um objeto. Útil para tornar configurações imutáveis em tempo de execução.
IP Range Checker
Import: import { assertSafeUrl, isPrivateIp } from '@safe-access-inline/safe-access-inline'
assertSafeUrl(url: string, options?): void— LançaSecurityErrorse a URL aponta para um IP privado (proteção contra SSRF).isPrivateIp(ip: string): boolean— Retornatruepara IPs privados/loopback.
I/O & Carregamento de Arquivos
Carregamento de Arquivos
// Síncrono
const accessor = SafeAccess.fromFileSync("./config.json");
const accessor = SafeAccess.fromFileSync("./config.yaml", {
format: "yaml",
allowedDirs: ["/etc/config"],
});
// Assíncrono
const accessor = await SafeAccess.fromFile("./config.json");Carregamento via URL
const accessor = await SafeAccess.fromUrl(
"https://api.example.com/config.json",
{
allowPrivateIps: false,
allowedHosts: ["api.example.com"],
allowedPorts: [443],
},
);Configuração em Camadas
Mescla múltiplas fontes de configuração (última vence):
const config = SafeAccess.layer([defaults, overrides, local]);
const config = await SafeAccess.layerFiles([
"./defaults.yaml",
"./overrides.json",
]);File Watcher
const stop = SafeAccess.watchFile("./config.yaml", (accessor) => {
console.log("Config changed:", accessor.get("app.name"));
});
// Depois: parar de observar
stop();Log de Auditoria
Import: import { onAudit, clearAuditListeners } from '@safe-access-inline/safe-access-inline'
Inscreva-se em eventos de segurança e operações de dados.
const unsubscribe = SafeAccess.onAudit((event) => {
console.log(`[${event.type}]`, event.detail);
});
// Tipos de evento: 'file.read', 'url.fetch', 'security.violation', 'security.deprecation',
// 'data.mask', 'file.watch', 'data.freeze', 'schema.validate'
// Limpeza
SafeAccess.clearAuditListeners();
unsubscribe(); // ou cancelar inscrição individualmenteAuditEvent
interface AuditEvent {
type: AuditEventType;
timestamp: number;
detail: Record<string, unknown>;
}
type AuditEventType =
| "file.read"
| "file.watch"
| "url.fetch"
| "security.violation"
| "security.deprecation"
| "data.mask"
| "data.freeze"
| "schema.validate";Integrações de Framework
NestJS
Import: import { SafeAccessModule, SafeAccessService, SAFE_ACCESS, createSafeAccessProvider, createSafeAccessServiceProvider } from '@safe-access-inline/safe-access-inline'
// Opção 1: Registro de módulo
@Module({
imports: [
SafeAccessModule.register({
filePath: "./config.yaml",
}),
],
})
export class AppModule {}
// Opção 2: Provider customizado
@Module({
providers: [
createSafeAccessProvider({
layerPaths: ["./defaults.yaml", "./overrides.json"],
}),
],
exports: [SAFE_ACCESS],
})
export class ConfigModule {}
// Injetar em serviços
@Injectable()
class MyService {
constructor(@Inject(SAFE_ACCESS) private config: AbstractAccessor) {}
}createSafeAccessProvider(options: SafeAccessModuleOptions)
Retorna uma definição de provider NestJS que resolve um AbstractAccessor sob o token de injeção SAFE_ACCESS. Use quando quiser injetar o accessor diretamente.
createSafeAccessServiceProvider(options: SafeAccessModuleOptions)
Retorna uma definição de provider NestJS que resolve uma instância de SafeAccessService, que envolve o accessor e pode ser injetada por tipo.
@Module({
providers: [createSafeAccessServiceProvider({ filePath: "./config.yaml" })],
exports: [SafeAccessService],
})
export class ConfigModule {}
@Injectable()
class MyService {
constructor(private config: SafeAccessService) {}
getHost() {
return this.config.get("database.host");
}
}Plugin Vite
Import: import { safeAccessPlugin, loadConfig } from '@safe-access-inline/safe-access-inline'
// vite.config.ts
import { safeAccessPlugin } from "@safe-access-inline/safe-access-inline";
export default defineConfig({
plugins: [
safeAccessPlugin({
files: ["./config/defaults.yaml", "./config/local.json"],
virtualId: "virtual:safe-access-config", // padrão
}),
],
});
// No código da aplicação:
import config from "virtual:safe-access-config";
// config é o objeto JSON mescladoHMR é suportado — alterar um arquivo de configuração observado dispara um reload completo.