@solid-mediakit/auth-plugin
Version:
Package for easily creating server rpc functions in solid-start with goodies baked in
306 lines (302 loc) • 9.52 kB
JavaScript
// src/compiler/babel.ts
import * as babel from "@babel/core";
// src/compiler/utils.ts
import { babel as babelUtils } from "@solid-mediakit/shared";
var getNodeInfo = (path, t) => {
const { callee } = path.node;
const isProtected = t.isIdentifier(callee, { name: "protected$" });
return {
callee,
isProtected
};
};
var afterImports = (path, value) => {
const p = path.findParent((p2) => p2.isProgram()).node.body;
const lastImport = p.findLast((n) => n.type === "ImportDeclaration");
if (lastImport) {
p.splice(p.indexOf(lastImport) + 1, 0, value);
} else {
p.unshift(value);
}
};
var addMissingImports = (path, t, opts, args) => {
babelUtils.importIfNotThere(path, t, "query", "@solidjs/router");
babelUtils.importIfNotThere(path, t, "createAsync", "@solidjs/router");
babelUtils.importIfNotThere(path, t, "getRequestEvent", "solid-js/web");
babelUtils.importIfNotThere(path, t, "getSession", "@solid-mediakit/auth");
babelUtils.importIfNotThere(path, t, "Show", "solid-js");
babelUtils.importIfNotThere(path, t, opts.authOpts.name, opts.authOpts.dir);
if (!args.fallBack) {
babelUtils.importIfNotThere(path, t, "redirect", "@solidjs/router");
}
};
var getProtectedContent = (t, args) => {
const attr = [
t.jsxAttribute(
t.jsxIdentifier("when"),
t.jsxExpressionContainer(
args.reverse ? t.unaryExpression(
"!",
t.optionalMemberExpression(
t.callExpression(t.identifier("_$$session"), []),
t.identifier("user"),
false,
true
)
) : t.optionalMemberExpression(
t.callExpression(t.identifier("_$$session"), []),
t.identifier("user"),
false,
true
)
)
)
];
if (args.fallBack) {
attr.push(
t.jsxAttribute(
t.jsxIdentifier("fallback"),
t.jsxExpressionContainer(
t.jsxElement(
t.jsxOpeningElement(t.jsxIdentifier("_$$RenderFallBack"), [], true),
t.jsxClosingElement(t.jsxIdentifier("_$$RenderFallBack")),
[],
true
)
)
)
);
}
return t.jsxElement(
t.jsxOpeningElement(t.jsxIdentifier("Show"), attr),
t.jsxClosingElement(t.jsxIdentifier("Show")),
[
t.jsxElement(
t.jsxOpeningElement(t.jsxIdentifier("_$$RenderProtected"), [], true),
t.jsxClosingElement(t.jsxIdentifier("_$$RenderProtected")),
[],
true
)
]
);
};
var appendRouteAction = (temp, path, t, opts, args) => {
var _a, _b;
const userKey = (_a = opts == null ? void 0 : opts.userKey) != null ? _a : "media-user";
let getUserR = void 0;
if (args.fallBack) {
getUserR = temp`const _$$getUser = query(async () => {
'use server'
const event = getRequestEvent()
return await getSession(event.request, authOptions)
}, '${userKey}');
`();
} else {
if (args.reverse) {
getUserR = temp`const _$$getUser = query(async () => {
'use server'
const event = getRequestEvent()
const session = await getSession(event.request, authOptions)
if (session) {
throw redirect('${args.redirectTo}')
}
return null
}, '${userKey}');
`();
} else {
getUserR = temp`const _$$getUser = query(async () => {
'use server'
const event = getRequestEvent()
const session = await getSession(event.request, authOptions)
if (!session) {
throw redirect('${args.redirectTo}')
}
return session
}, '${userKey}');
`();
}
}
afterImports(path, getUserR);
const currentRouteExport = (_b = path.scope.getBinding("route")) == null ? void 0 : _b.path;
if (currentRouteExport) {
const routeExport = currentRouteExport.node;
const load = routeExport.init.properties.find(
(p) => p.key.name === "load"
);
if (load) {
load.value = t.arrowFunctionExpression(
[],
t.arrayExpression([
t.callExpression(t.identifier("_$$getUser"), []),
t.isArrowFunctionExpression(load.value) ? load.value.body : load.value
])
);
}
} else {
path.insertAfter(
t.exportNamedDeclaration(
t.variableDeclaration("const", [
t.variableDeclarator(
t.identifier("route"),
t.objectExpression([
t.objectProperty(
t.identifier("load"),
t.arrowFunctionExpression(
[],
t.callExpression(t.identifier("_$$getUser"), [])
)
)
])
)
])
)
);
}
};
var getArgs = (path, t, opts) => {
const page = path.node.arguments[0];
let fallBack;
let redirectTo;
if (path.node.arguments.length >= 2) {
if (t.isArrowFunctionExpression(path.node.arguments[1])) {
fallBack = path.node.arguments[1];
} else {
redirectTo = path.node.arguments[1];
}
}
if (!redirectTo) {
redirectTo = opts.redirectTo;
}
return {
page,
fallBack,
redirectTo,
reverse: t.isBooleanLiteral(path.node.arguments[2]) ? path.node.arguments[2].value : false
};
};
// src/compiler/babel.ts
function createTransformAuth$(opts) {
return function transformAuth$({
types: t,
template: temp
}) {
return {
visitor: {
CallExpression(path) {
const nodeInfo = getNodeInfo(path, t);
if (nodeInfo.isProtected) {
const args = getArgs(path, t, opts);
if (nodeInfo.isProtected) {
const protectedComp = path.node.arguments[0];
path.traverse({
Identifier(innerPath) {
var _a, _b;
if (innerPath.node.name === "session$" && ((_b = (_a = innerPath.scope) == null ? void 0 : _a.path) == null ? void 0 : _b.listKey) !== "params") {
innerPath.node.name = "_$$session()";
}
}
});
addMissingImports(path, t, opts, args);
appendRouteAction(temp, path, t, opts, args);
protectedComp.params = [];
const content = protectedComp.body;
const callGetUser = t.variableDeclaration("const", [
t.variableDeclarator(
t.identifier("_$$session"),
t.callExpression(t.identifier("createAsync"), [
t.arrowFunctionExpression(
[],
t.callExpression(t.identifier("_$$getUser"), [])
),
t.objectExpression([
t.objectProperty(
t.identifier("deferStream"),
t.booleanLiteral(true)
)
])
])
)
]);
const RenderProtected = t.variableDeclaration("const", [
t.variableDeclarator(
t.identifier("_$$RenderProtected"),
t.arrowFunctionExpression([], t.blockStatement(content.body))
)
]);
content.body = [RenderProtected];
if (args.fallBack) {
const RenderFallBack = t.variableDeclaration("const", [
t.variableDeclarator(
t.identifier("_$$RenderFallBack"),
args.fallBack
)
]);
content.body.unshift(RenderFallBack);
}
content.body.unshift(callGetUser);
const newPage = t.arrowFunctionExpression([], content);
newPage.body.body.push(
t.returnStatement(getProtectedContent(t, args))
);
newPage.body.body = [...newPage.body.body];
path.replaceWith(newPage);
}
}
}
}
};
};
}
async function compileAuth(code, id, opts) {
var _a, _b, _c, _d, _e;
const plugins = ["typescript", "jsx"];
const transformAuth$ = createTransformAuth$(opts);
const transformed = await babel.transformAsync(code, {
presets: [["@babel/preset-typescript"], ...(_b = (_a = opts == null ? void 0 : opts.babel) == null ? void 0 : _a.presets) != null ? _b : []],
parserOpts: {
plugins
},
plugins: [[transformAuth$], ...(_d = (_c = opts == null ? void 0 : opts.babel) == null ? void 0 : _c.plugins) != null ? _d : []],
filename: id
});
if (transformed) {
if (opts == null ? void 0 : opts.log) {
console.log(id, transformed.code);
}
return {
code: (_e = transformed.code) != null ? _e : "",
map: transformed.map
};
}
return null;
}
// src/index.ts
import { babel as babelUtils2, repushPlugin } from "@solid-mediakit/shared";
function authVite(opts) {
const filter = babelUtils2.getFilter(opts == null ? void 0 : opts.filter);
const plugin = {
enforce: "pre",
name: "auth",
async transform(code, id) {
if (!filter(id)) {
return code;
}
if (code.includes("protected$(") || code.includes("session$")) {
return await compileAuth(code, id, opts);
}
return void 0;
},
configResolved(config) {
repushPlugin(config.plugins, plugin, [
"vite-server-references",
"solid",
"vinxi:routes"
]);
}
};
return plugin;
}
export {
authVite
};
//# sourceMappingURL=index.mjs.map