@graphql-tools/graphql-tag-pluck
Version:
Pluck graphql-tag template literals
313 lines (296 loc) • 11 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCode = exports.gqlPluckFromCodeStringSync = exports.gqlPluckFromCodeString = void 0;
const tslib_1 = require("tslib");
/* eslint-disable @typescript-eslint/no-require-imports */
const graphql_1 = require("graphql");
const parser_1 = require("@babel/parser");
const traverse_1 = tslib_1.__importDefault(require("@babel/traverse"));
const config_js_1 = tslib_1.__importDefault(require("./config.js"));
const extname_js_1 = require("./libs/extname.js");
const utils_js_1 = require("./utils.js");
const visitor_js_1 = tslib_1.__importDefault(require("./visitor.js"));
function getDefault(module) {
return module.default || module;
}
const traverse = getDefault(traverse_1.default);
const supportedExtensions = [
'.js',
'.mjs',
'.cjs',
'.jsx',
'.ts',
'.mts',
'.cts',
'.tsx',
'.flow',
'.flow.js',
'.flow.jsx',
'.vue',
'.svelte',
'.astro',
'.gts',
'.gjs',
];
// tslint:disable-next-line: no-implicit-dependencies
function parseWithVue(vueTemplateCompiler, fileData) {
const { descriptor } = vueTemplateCompiler.parse(fileData);
return descriptor.script || descriptor.scriptSetup
? vueTemplateCompiler.compileScript(descriptor, { id: Date.now().toString() }).content
: '';
}
function customBlockFromVue(
// tslint:disable-next-line: no-implicit-dependencies
vueTemplateCompiler, fileData, filePath, blockType) {
const { descriptor } = vueTemplateCompiler.parse(fileData);
const block = descriptor.customBlocks.find(b => b.type === blockType);
if (block === undefined) {
return;
}
return new graphql_1.Source(block.content.trim(), filePath, block.loc.start);
}
// tslint:disable-next-line: no-implicit-dependencies
function parseWithSvelte(svelte2tsx, fileData) {
const fileInTsx = svelte2tsx.svelte2tsx(fileData);
return fileInTsx.code;
}
// tslint:disable-next-line: no-implicit-dependencies
async function parseWithAstro(astroCompiler, fileData) {
const fileInTsx = await astroCompiler.transform(fileData);
return fileInTsx.code;
}
function parseWithAstroSync(
// tslint:disable-next-line: no-implicit-dependencies
astroCompiler, fileData) {
const fileInTsx = astroCompiler.transform(fileData, undefined);
return fileInTsx.code;
}
function transformGlimmerFile(glimmerSyntax, fileData) {
const processor = new glimmerSyntax.Preprocessor();
return processor.process(fileData);
}
/**
* Asynchronously plucks GraphQL template literals from a single file.
*
* Supported file extensions include: `.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mts`, `.cts`, `.tsx`, `.flow`, `.flow.js`, `.flow.jsx`, `.vue`, `.svelte`, `.astro`
*
* @param filePath Path to the file containing the code. Required to detect the file type
* @param code The contents of the file being parsed.
* @param options Additional options for determining how a file is parsed.
*/
const gqlPluckFromCodeString = async (filePath, code, options = {}) => {
validate({ code, options });
const fileExt = extractExtension(filePath);
let blockSource;
if (fileExt === '.vue') {
if (options.gqlVueBlock) {
blockSource = await pluckVueFileCustomBlock(code, filePath, options.gqlVueBlock);
}
code = await pluckVueFileScript(code);
}
else if (fileExt === '.svelte') {
code = await pluckSvelteFileScript(code);
}
else if (fileExt === '.astro') {
code = await pluckAstroFileScript(code);
}
else if (fileExt === '.gts' || fileExt === '.gjs') {
code = await pluckGlimmerFileScript(code);
}
const sources = parseCode({ code, filePath, options }).map(t => new graphql_1.Source(t.content, filePath, t.loc.start));
if (blockSource) {
sources.push(blockSource);
}
return sources;
};
exports.gqlPluckFromCodeString = gqlPluckFromCodeString;
/**
* Synchronously plucks GraphQL template literals from a single file
*
* Supported file extensions include: `.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mjs`, `.cjs`, `.tsx`, `.flow`, `.flow.js`, `.flow.jsx`, `.vue`, `.svelte`, `.astro`, `.gts`, `.gjs`
*
* @param filePath Path to the file containing the code. Required to detect the file type
* @param code The contents of the file being parsed.
* @param options Additional options for determining how a file is parsed.
*/
const gqlPluckFromCodeStringSync = (filePath, code, options = {}) => {
validate({ code, options });
const fileExt = extractExtension(filePath);
let blockSource;
if (fileExt === '.vue') {
if (options.gqlVueBlock) {
blockSource = pluckVueFileCustomBlockSync(code, filePath, options.gqlVueBlock);
}
code = pluckVueFileScriptSync(code);
}
else if (fileExt === '.svelte') {
code = pluckSvelteFileScriptSync(code);
}
else if (fileExt === '.astro') {
code = pluckAstroFileScriptSync(code);
}
else if (fileExt === '.gts' || fileExt === '.gjs') {
code = pluckGlimmerFileScriptSync(code);
}
const sources = parseCode({ code, filePath, options }).map(t => new graphql_1.Source(t.content, filePath, t.loc.start));
if (blockSource) {
sources.push(blockSource);
}
return sources;
};
exports.gqlPluckFromCodeStringSync = gqlPluckFromCodeStringSync;
function parseCode({ code, filePath, options, }) {
const out = { returnValue: null };
const ast = (0, parser_1.parse)(code, (0, config_js_1.default)(filePath, code, options));
const visitor = (0, visitor_js_1.default)(code, out, options);
traverse(ast, visitor);
return out.returnValue || [];
}
exports.parseCode = parseCode;
function validate({ code, options }) {
if (typeof code !== 'string') {
throw TypeError('Provided code must be a string');
}
if (!(options instanceof Object)) {
throw TypeError(`Options arg must be an object`);
}
}
function extractExtension(filePath) {
const fileExt = (0, extname_js_1.getExtNameFromFilePath)(filePath);
if (fileExt) {
if (!supportedExtensions.includes(fileExt)) {
throw TypeError(`Provided file type must be one of ${supportedExtensions.join(', ')} `);
}
}
return fileExt;
}
const MissingVueTemplateCompilerError = new Error((0, utils_js_1.freeText)(`
GraphQL template literals cannot be plucked from a Vue template code without having the "@vue/compiler-sfc" package installed.
Please install it and try again.
Via NPM:
$ npm install @vue/compiler-sfc
Via Yarn:
$ yarn add @vue/compiler-sfc
`));
const MissingSvelteTemplateCompilerError = new Error((0, utils_js_1.freeText)(`
GraphQL template literals cannot be plucked from a Svelte template code without having the "svelte2tsx" & "svelte" package installed.
Please install it and try again.
Via NPM:
$ npm install svelte2tsx svelte
Via Yarn:
$ yarn add svelte2tsx svelte
`));
const MissingAstroCompilerError = new Error((0, utils_js_1.freeText)(`
GraphQL template literals cannot be plucked from a Astro template code without having the "@astrojs/compiler" package installed.
Please install it and try again.
Via NPM:
$ npm install @astrojs/compiler
Via Yarn:
$ yarn add @astrojs/compiler
`));
const MissingGlimmerCompilerError = new Error((0, utils_js_1.freeText)(`
GraphQL template literals cannot be plucked from a Glimmer template code without having the "content-tag" package installed.
Please install it and try again.
Via NPM:
$ npm install content-tag
Via Yarn:
$ yarn add content-tag
`));
async function loadVueCompilerAsync() {
try {
// eslint-disable-next-line import/no-extraneous-dependencies
return await Promise.resolve().then(() => tslib_1.__importStar(require('@vue/compiler-sfc')));
}
catch {
throw MissingVueTemplateCompilerError;
}
}
function loadVueCompilerSync() {
try {
// eslint-disable-next-line import/no-extraneous-dependencies
return require('@vue/compiler-sfc');
}
catch {
throw MissingVueTemplateCompilerError;
}
}
async function pluckVueFileScript(fileData) {
const vueTemplateCompiler = await loadVueCompilerAsync();
return parseWithVue(vueTemplateCompiler, fileData);
}
function pluckVueFileScriptSync(fileData) {
const vueTemplateCompiler = loadVueCompilerSync();
return parseWithVue(vueTemplateCompiler, fileData);
}
async function pluckVueFileCustomBlock(fileData, filePath, blockType) {
const vueTemplateCompiler = await loadVueCompilerSync();
return customBlockFromVue(vueTemplateCompiler, fileData, filePath, blockType);
}
function pluckVueFileCustomBlockSync(fileData, filePath, blockType) {
const vueTemplateCompiler = loadVueCompilerSync();
return customBlockFromVue(vueTemplateCompiler, fileData, filePath, blockType);
}
async function pluckSvelteFileScript(fileData) {
let svelte2tsx;
try {
// eslint-disable-next-line import/no-extraneous-dependencies
svelte2tsx = await Promise.resolve().then(() => tslib_1.__importStar(require('svelte2tsx')));
}
catch {
throw MissingSvelteTemplateCompilerError;
}
return parseWithSvelte(svelte2tsx, fileData);
}
function pluckSvelteFileScriptSync(fileData) {
let svelte2tsx;
try {
// eslint-disable-next-line import/no-extraneous-dependencies
svelte2tsx = require('svelte2tsx');
}
catch {
throw MissingSvelteTemplateCompilerError;
}
return parseWithSvelte(svelte2tsx, fileData);
}
async function pluckAstroFileScript(fileData) {
let astroCompiler;
try {
// eslint-disable-next-line import/no-extraneous-dependencies
astroCompiler = await Promise.resolve().then(() => tslib_1.__importStar(require('@astrojs/compiler')));
}
catch {
throw MissingAstroCompilerError;
}
return parseWithAstro(astroCompiler, fileData);
}
function pluckAstroFileScriptSync(fileData) {
let astroCompiler;
try {
// eslint-disable-next-line import/no-extraneous-dependencies
astroCompiler = require('astrojs-compiler-sync');
}
catch {
throw MissingAstroCompilerError;
}
return parseWithAstroSync(astroCompiler, fileData);
}
async function pluckGlimmerFileScript(fileData) {
let contentTag;
try {
contentTag = await Promise.resolve().then(() => tslib_1.__importStar(require('content-tag')));
}
catch {
throw MissingGlimmerCompilerError;
}
return transformGlimmerFile(contentTag, fileData);
}
function pluckGlimmerFileScriptSync(fileData) {
let contentTag;
try {
contentTag = require('content-tag');
}
catch {
throw MissingGlimmerCompilerError;
}
return transformGlimmerFile(contentTag, fileData);
}
;