npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@opensas/xml-rest-adapter

v0.2.3

Published

Proyecto _de uso interno_ que expone mediante una API REST las bases de datos que utilizan el formato propio de `xmlEntidad_Accion` para encapsular la lógica de negocio.

Readme

xml-rest-adapter

Proyecto de uso interno que expone mediante una API REST las bases de datos que utilizan el formato propio de xmlEntidad_Accion para encapsular la lógica de negocio.

npm: https://www.npmjs.com/package/@opensas/xml-rest-adapter

pnpm add @opensas/xml-rest-adapter

Cómo funciona, paso a paso

createXmlRestAdapter(app) recibe la definición de una aplicación (nombre, cómo autenticar, cómo autorizar, a qué base conectarse, qué objetos exponer) y devuelve dos funciones: resolveUser y handle. No importa qué framework o runtime uses — ambas trabajan con Request/ Response de la Fetch API estándar, nada específico de SvelteKit ni de Node.

1. Creá el adapter una sola vez, con la config de tu app:

import { createXmlRestAdapter, endpoints } from '@opensas/xml-rest-adapter';

const adapter = createXmlRestAdapter({
	name: 'MiApp', // tiene que coincidir con el Codigo de la app en Meta (o usá aplicacionCodigo)
	authentication: { type: 'iis-node' }, // o { type: 'none' } para apps públicas/anónimas
	authorization: { type: 'metaSSC', dbInfo: process.env.META_DATABASE_URL },
	dbInfo: process.env.MI_APP_DATABASE_URL, // connection string ADO.NET, o un objeto DbInfo
	pagination: 'sql', // 'com+' solo para SPs viejos sin @SqlPaginate
	endpoints: endpoints(['Provincia', 'TipoDato']), // qué objetos expone esta app
});

2. Por cada request, resolvé quién está llamandoresolveUser acepta el Request tal cual (extrae la identidad según authentication.type) o un string ya resuelto:

const result = await adapter.resolveUser(request);
if (!result.ok) {
	/* result.error: AppError con status/code/title — devolvelo como respuesta */
}
const usuario = result.data;

3. Dejá que el adapter atienda el requesthandle necesita el Request, el segmento de URL después de tu ruta (objeto, y opcionalmente /id), y el usuario del paso anterior:

const response = await adapter.handle(request, path, usuario);

Eso es todo — handle decide la acción (Consulta/Alta/Modificacion/Baja) según el método HTTP (GET/POST/PUT/DELETE), valida permisos, arma y ejecuta el xml{Objeto}_{Accion} contra SQL Server, y devuelve la Response ya lista (JSON o el error correspondiente).

Ejemplo con SvelteKit

Un solo archivo alcanza — la carpeta tiene que ser [...path] (rest parameter), porque objeto/id no son segmentos fijos:

// src/routes/mi-app/[...path]/+server.ts
import { createXmlRestAdapter, endpoints, jsonError } from '@opensas/xml-rest-adapter';
import { env } from '$env/dynamic/private';
import type { RequestHandler } from './$types.js';

const adapter = createXmlRestAdapter({
	name: 'MiApp',
	authentication: { type: 'iis-node' },
	authorization: { type: 'metaSSC', dbInfo: env.META_DATABASE_URL },
	dbInfo: env.MI_APP_DATABASE_URL,
	pagination: 'sql',
	endpoints: endpoints(['Provincia', 'TipoDato']),
});

// Un solo handler para los 4 verbos — `fallback` los atrapa a todos, `.handle()` decide la
// acción según `event.request.method`.
export const fallback: RequestHandler = async (event) => {
	const result = await adapter.resolveUser(event.request);
	if (!result.ok) return jsonError(result.error);
	return adapter.handle(event.request, event.params.path, result.data);
};

Con esto, GET /mi-app/Provincia?_limit=10, POST /mi-app/TipoDato, PUT /mi-app/Provincia/5, DELETE /mi-app/Provincia/5 ya funcionan. Ejemplo completo y corrible en examples/consumer-svelte/.

Ejemplo con Node puro (sin ningún framework)

handle()/resolveUser() no requieren nada de SvelteKit — alcanza con las Request/Response globales que trae Node 18+. Un servidor mínimo con node:http:

import { createServer } from 'node:http';
import { createXmlRestAdapter, endpoints, jsonError } from '@opensas/xml-rest-adapter';

const adapter = createXmlRestAdapter({
	name: 'MiApp',
	authentication: { type: 'none' }, // sin IIS: no hay identidad real que extraer del request
	authorization: { type: 'none' },
	dbInfo: process.env.MI_APP_DATABASE_URL,
	pagination: 'sql',
	endpoints: endpoints(['Provincia']),
});

const server = createServer(async (req, res) => {
	const url = new URL(req.url, `http://${req.headers.host}`);
	const path = url.pathname.replace(/^\//, ''); // 'Provincia' o 'Provincia/5'
	const hasBody = req.method !== 'GET' && req.method !== 'HEAD';

	const request = new Request(url, {
		method: req.method,
		headers: req.headers,
		body: hasBody ? req : undefined,
		duplex: hasBody ? 'half' : undefined,
	});

	const userResult = await adapter.resolveUser(request);
	const response = userResult.ok
		? await adapter.handle(request, path, userResult.data)
		: jsonError(userResult.error);

	res.writeHead(response.status, Object.fromEntries(response.headers));
	res.end(Buffer.from(await response.arrayBuffer()));
});

server.listen(3000);

Prueba mínima sin siquiera levantar un servidor HTTP (construyendo los Request a mano y llamando a handle() directo) en examples/consumer/test.mjs.

Más