mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
init: the first public commit for AFFiNE
This commit is contained in:
45
tools/executors/figmaRes/download.js
Normal file
45
tools/executors/figmaRes/download.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const path = require('path');
|
||||
const process = require('process');
|
||||
const downloadIcons = require('./figma');
|
||||
const patchStyles = require('./patch-styles');
|
||||
|
||||
/**
|
||||
* @param {*} options
|
||||
* @param {array} options.assets
|
||||
* @param {string} options.assets.fileId
|
||||
* @param {string} options.assets.nodeId
|
||||
* @param {string} options.assets.folder
|
||||
* @param {*} context
|
||||
* @returns
|
||||
*/
|
||||
exports['default'] = async function downloadFigmaRes(options, context) {
|
||||
const libRoot = context.workspace.projects[context.projectName].root;
|
||||
const token = process.env.FIGMA_TOKEN;
|
||||
if (!token) {
|
||||
throw new Error(
|
||||
'FIGMA_TOKEN is not defined. Please set it in your .env.local file.'
|
||||
);
|
||||
}
|
||||
await Promise.allSettled(
|
||||
(options.assets || []).map(async (asset, index) => {
|
||||
const fileId = asset.fileId;
|
||||
const nodeId = asset.nodeId;
|
||||
const folder =
|
||||
asset.folder || `./src/icon${index > 0 ? index : ''}`;
|
||||
if (!token || !fileId || !nodeId) {
|
||||
const message = `Please check if token/fileId/nodeId exists (No.${index}).`;
|
||||
console.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
await downloadIcons({
|
||||
token,
|
||||
fileId,
|
||||
nodeId,
|
||||
folder: path.resolve(libRoot, folder),
|
||||
patchStyles,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return { success: true };
|
||||
};
|
||||
9
tools/executors/figmaRes/executor.json
Normal file
9
tools/executors/figmaRes/executor.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"executors": {
|
||||
"figmaRes": {
|
||||
"implementation": "./download.js",
|
||||
"schema": "./schema.json",
|
||||
"description": "Run `figmaRes` (to download figma icons and pictures)."
|
||||
}
|
||||
}
|
||||
}
|
||||
56
tools/executors/figmaRes/figma/api.js
Normal file
56
tools/executors/figmaRes/figma/api.js
Normal file
@@ -0,0 +1,56 @@
|
||||
const PREFIX_URL = 'https://api.figma.com/v1/';
|
||||
async function initializeApi(token) {
|
||||
const got = await import('got');
|
||||
const api = got.got.extend({
|
||||
prefixUrl: PREFIX_URL,
|
||||
headers: {
|
||||
'X-Figma-Token': token,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
async getChildren(fileId, nodeId) {
|
||||
const decodedNodeId = decodeURIComponent(nodeId);
|
||||
console.log(
|
||||
`Fetching: ${`${PREFIX_URL}files/${fileId}/nodes?ids=${decodedNodeId}`}`
|
||||
);
|
||||
let data;
|
||||
try {
|
||||
data = await api({
|
||||
url: `files/${fileId}/nodes?ids=${decodedNodeId}`,
|
||||
}).json();
|
||||
} catch (error) {
|
||||
console.log(`Error: ${error}`);
|
||||
}
|
||||
|
||||
return data.nodes[decodedNodeId].document.children;
|
||||
},
|
||||
|
||||
async getIconsUrl(fileId, iconId) {
|
||||
console.log(
|
||||
`Fetching: ${`${PREFIX_URL}images/${fileId}/?ids=${iconId}&format=svg`}`
|
||||
);
|
||||
|
||||
let body;
|
||||
try {
|
||||
body = await api({
|
||||
url: `images/${fileId}/?ids=${iconId}&format=svg`,
|
||||
}).json();
|
||||
} catch (error) {
|
||||
console.log(`Error: ${error}`);
|
||||
}
|
||||
|
||||
return body.images;
|
||||
},
|
||||
|
||||
async downloadIcon(iconUrl) {
|
||||
const { body } = await got.got({
|
||||
url: iconUrl,
|
||||
});
|
||||
|
||||
return body;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = initializeApi;
|
||||
126
tools/executors/figmaRes/figma/generateReactIcon.js
Normal file
126
tools/executors/figmaRes/figma/generateReactIcon.js
Normal file
@@ -0,0 +1,126 @@
|
||||
const svgr = require('@svgr/core');
|
||||
const util = require('./util');
|
||||
|
||||
function getColors(colorCount) {
|
||||
return colorCount > 0
|
||||
? Array(colorCount)
|
||||
.fill(0)
|
||||
.reduce((acc, _, index) => {
|
||||
acc.push({
|
||||
type: 'string',
|
||||
value: `--color-${index}`,
|
||||
propName: `color${index}`,
|
||||
});
|
||||
|
||||
if (index === 0) {
|
||||
acc.push({
|
||||
type: 'string',
|
||||
value: `--color-${index}`,
|
||||
propName: 'primaryColor',
|
||||
});
|
||||
}
|
||||
|
||||
if (index === 1) {
|
||||
acc.push({
|
||||
type: 'string',
|
||||
value: `--color-${index}`,
|
||||
propName: 'secondaryColor',
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
: [
|
||||
{
|
||||
type: 'string',
|
||||
value: 'color',
|
||||
propName: 'color',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function getColorsInterfaceProps(colors) {
|
||||
return colors
|
||||
.map(color => {
|
||||
return `${color.propName}?: ${color.type}`;
|
||||
})
|
||||
.join('\n ');
|
||||
}
|
||||
|
||||
function getRestColors(colors) {
|
||||
return colors.map(color => color.propName).join(', ');
|
||||
}
|
||||
|
||||
function getPropNameToColorValue(colors) {
|
||||
const maps = colors.reduce((acc, color) => {
|
||||
if (acc[color.value]) {
|
||||
acc[color.value] = `${acc[color.value]} || ${color.propName}`;
|
||||
} else {
|
||||
acc[color.value] = color.propName;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
const kvString = Object.entries(maps)
|
||||
.map(kv => {
|
||||
return `"${kv[0]}": ${kv[1]}`;
|
||||
})
|
||||
.join(', ');
|
||||
return `{${kvString}}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* get icon component template
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} svgCode svg original code
|
||||
* @param {Object} customStyles custom style properties
|
||||
*/
|
||||
module.exports = async function generateReactIcon(name, svgCode, customStyles) {
|
||||
let svgrContent = '';
|
||||
try {
|
||||
svgrContent = await svgr.transform(
|
||||
svgCode,
|
||||
{
|
||||
icon: true,
|
||||
typescript: true,
|
||||
},
|
||||
{ componentName: `${name}Icon1` }
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
let svgContent = svgrContent.match(/<svg [^\>]+>([\s\S]*?)<\/svg>/)[1];
|
||||
|
||||
let colorIdx = 0;
|
||||
if (util.isDuotone(name)) {
|
||||
svgContent = svgContent.replace(
|
||||
/fill="#[A-Za-z0-9]+"/g,
|
||||
() => `style={{fill: 'var(--color-${colorIdx++})'}}`
|
||||
);
|
||||
}
|
||||
const colors = getColors(colorIdx);
|
||||
|
||||
return `
|
||||
import { FC } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { SvgIcon } from '@mui/material';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import type { SvgIconProps } from '@mui/material';
|
||||
|
||||
export interface ${name}IconProps extends Omit<SvgIconProps, 'color'> {
|
||||
${getColorsInterfaceProps(colors)}
|
||||
}
|
||||
|
||||
export const ${name}Icon: FC<${name}IconProps> = ({ ${getRestColors(
|
||||
colors
|
||||
)}, style, ...props}) => {
|
||||
const propsStyles = ${getPropNameToColorValue(colors)};
|
||||
const customStyles = ${JSON.stringify(customStyles || {})};
|
||||
const styles = {...propsStyles, ...customStyles, ...style}
|
||||
return (
|
||||
<SvgIcon style={styles} {...props}>
|
||||
${svgContent}
|
||||
</SvgIcon>
|
||||
)
|
||||
};
|
||||
`;
|
||||
};
|
||||
119
tools/executors/figmaRes/figma/index.js
Normal file
119
tools/executors/figmaRes/figma/index.js
Normal file
@@ -0,0 +1,119 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const { pascalCase, paramCase } = require('change-case');
|
||||
const initializeApi = require('./api');
|
||||
const svgo = require('./svgo');
|
||||
const util = require('./util');
|
||||
const generateReactIcon = require('./generateReactIcon');
|
||||
|
||||
function getRemoveAttrs(name) {
|
||||
if (util.isBrands(name)) {
|
||||
return {
|
||||
name: 'removeAttrs',
|
||||
params: {
|
||||
attrs: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: 'removeAttrs',
|
||||
params: {
|
||||
attrs: util.isDuotone(name) ? 'stroke' : '(stroke|fill)',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function generateImportEntry(iconNodes, folder) {
|
||||
const fileWithImportsPath = path.resolve(folder, 'index.ts');
|
||||
|
||||
const importsContent = iconNodes
|
||||
.map(iconNode => {
|
||||
const iconName = paramCase(iconNode.name);
|
||||
if (!iconName) {
|
||||
return `// Error: ${iconNode.name}`;
|
||||
}
|
||||
|
||||
return `export * from './${iconName}/${iconName}';`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
await fs.writeFile(
|
||||
fileWithImportsPath,
|
||||
`export const timestamp = ${Date.now()};\n${importsContent}`,
|
||||
{ encoding: 'utf8' }
|
||||
);
|
||||
}
|
||||
|
||||
function filterIcons(icons, iconsUrl) {
|
||||
const icon_name_set = new Set();
|
||||
const icons_filtered = icons.filter(i => {
|
||||
if (icon_name_set.has(paramCase(i.name))) {
|
||||
console.warn(
|
||||
`\nWarn: There is an icon with the same name: ${i.name}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
icon_name_set.add(paramCase(i.name));
|
||||
return iconsUrl[i.id];
|
||||
});
|
||||
return icons_filtered;
|
||||
}
|
||||
|
||||
async function downloadFigmaIcons(props) {
|
||||
const { token, fileId, nodeId, folder, patchStyles } = props;
|
||||
await fs.ensureDir(folder);
|
||||
await fs.emptyDir(folder);
|
||||
const api = await initializeApi(token);
|
||||
let icons = await api.getChildren(fileId, nodeId);
|
||||
const iconsUrl = await api.getIconsUrl(
|
||||
fileId,
|
||||
icons.map(i => i.id).join(',')
|
||||
);
|
||||
icons = filterIcons(icons, iconsUrl);
|
||||
const generateIcons = icons.map(async icon => {
|
||||
const iconUrl = iconsUrl[icon.id];
|
||||
const iconName = paramCase(icon.name);
|
||||
let originSvg;
|
||||
try {
|
||||
originSvg = await api.downloadIcon(iconUrl);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
let optimizedSvg;
|
||||
try {
|
||||
const data = await svgo.optimize(
|
||||
originSvg,
|
||||
getRemoveAttrs(iconName)
|
||||
);
|
||||
optimizedSvg = data.data;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
console.log(iconName);
|
||||
}
|
||||
|
||||
const iconFolder = path.resolve(folder, iconName);
|
||||
const JSXContent = await generateReactIcon(
|
||||
pascalCase(icon.name),
|
||||
optimizedSvg,
|
||||
patchStyles?.[iconName]
|
||||
);
|
||||
await Promise.all([
|
||||
fs.outputFile(
|
||||
path.resolve(iconFolder, `${iconName || icon.name}.svg`),
|
||||
optimizedSvg,
|
||||
{ encoding: 'utf8' }
|
||||
),
|
||||
fs.outputFile(
|
||||
path.resolve(iconFolder, `${iconName || icon.name}.tsx`),
|
||||
JSXContent,
|
||||
{ encoding: 'utf8', flag: '' }
|
||||
),
|
||||
]);
|
||||
});
|
||||
await Promise.allSettled([
|
||||
...generateIcons,
|
||||
generateImportEntry(icons, folder),
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = downloadFigmaIcons;
|
||||
44
tools/executors/figmaRes/figma/svgo.js
Normal file
44
tools/executors/figmaRes/figma/svgo.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const svgo = require('svgo');
|
||||
|
||||
module.exports = {
|
||||
optimize(input, removeAttrs) {
|
||||
return svgo.optimize(input, {
|
||||
plugins: [
|
||||
'cleanupAttrs',
|
||||
'removeDoctype',
|
||||
'removeXMLProcInst',
|
||||
'removeComments',
|
||||
'removeMetadata',
|
||||
'removeTitle',
|
||||
'removeDesc',
|
||||
'removeUselessDefs',
|
||||
'removeEditorsNSData',
|
||||
'removeEmptyAttrs',
|
||||
'removeHiddenElems',
|
||||
'removeEmptyText',
|
||||
'removeEmptyContainers',
|
||||
'removeViewBox',
|
||||
'cleanupEnableBackground',
|
||||
'convertStyleToAttrs',
|
||||
'convertColors',
|
||||
'convertPathData',
|
||||
'convertTransform',
|
||||
'removeUnknownsAndDefaults',
|
||||
'removeNonInheritableGroupAttrs',
|
||||
'removeUselessStrokeAndFill',
|
||||
'removeUnusedNS',
|
||||
'cleanupIDs',
|
||||
'cleanupNumericValues',
|
||||
'moveElemsAttrsToGroup',
|
||||
'moveGroupAttrsToElems',
|
||||
'collapseGroups',
|
||||
'removeRasterImages',
|
||||
'mergePaths',
|
||||
'convertShapeToPath',
|
||||
'sortAttrs',
|
||||
'removeDimensions',
|
||||
removeAttrs,
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
9
tools/executors/figmaRes/figma/util.js
Normal file
9
tools/executors/figmaRes/figma/util.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Determine whether it is a two-color icon
|
||||
module.exports.isDuotone = function isDuotone(name) {
|
||||
return /[Dd]{1}uotone$/.test(name);
|
||||
};
|
||||
|
||||
// Determine whether it is a brand trademark
|
||||
module.exports.isBrands = function isBrands(name) {
|
||||
return ['figma', 'youtube'].includes(name.toLowerCase());
|
||||
};
|
||||
3
tools/executors/figmaRes/package.json
Normal file
3
tools/executors/figmaRes/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"executors": "./executor.json"
|
||||
}
|
||||
41
tools/executors/figmaRes/patch-styles.js
Normal file
41
tools/executors/figmaRes/patch-styles.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Some icons may be downloaded with incorrect styles, and some styles need to be added.
|
||||
* key is the name of the icon's kebab-case.
|
||||
*/
|
||||
const patchStyles = {
|
||||
// add: {
|
||||
// fill: 'none',
|
||||
// fillOpacity: 0,
|
||||
// stroke: 'currentColor'
|
||||
// },
|
||||
// text: {
|
||||
// stroke: 'currentColor'
|
||||
// },
|
||||
// rectangle: {
|
||||
// fill: 'none',
|
||||
// fillOpacity: 0,
|
||||
// stroke: 'currentColor'
|
||||
// },
|
||||
// ellipse: {
|
||||
// fill: 'none',
|
||||
// fillOpacity: 0,
|
||||
// stroke: 'currentColor'
|
||||
// },
|
||||
// triangle: {
|
||||
// fill: 'none',
|
||||
// fillOpacity: 0,
|
||||
// stroke: 'currentColor'
|
||||
// },
|
||||
// polygon: {
|
||||
// fill: 'none',
|
||||
// fillOpacity: 0,
|
||||
// stroke: 'currentColor'
|
||||
// },
|
||||
// shape: {
|
||||
// fill: 'none',
|
||||
// fillOpacity: 0,
|
||||
// stroke: 'currentColor'
|
||||
// }
|
||||
};
|
||||
|
||||
module.exports = patchStyles;
|
||||
11
tools/executors/figmaRes/schema.json
Normal file
11
tools/executors/figmaRes/schema.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"type": "object",
|
||||
"cli": "nx",
|
||||
"properties": {
|
||||
"figmaRes": {
|
||||
"type": "string",
|
||||
"description": "Download figma icons and pictures."
|
||||
}
|
||||
}
|
||||
}
|
||||
9
tools/executors/svgOptimize/executor.json
Normal file
9
tools/executors/svgOptimize/executor.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"executors": {
|
||||
"svgOptimize": {
|
||||
"implementation": "./svgo.js",
|
||||
"schema": "./schema.json",
|
||||
"description": "Run `svgo` (to optimize svg)."
|
||||
}
|
||||
}
|
||||
}
|
||||
3
tools/executors/svgOptimize/package.json
Normal file
3
tools/executors/svgOptimize/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"executors": "./executor.json"
|
||||
}
|
||||
11
tools/executors/svgOptimize/schema.json
Normal file
11
tools/executors/svgOptimize/schema.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"type": "object",
|
||||
"cli": "nx",
|
||||
"properties": {
|
||||
"svgOptimize": {
|
||||
"type": "string",
|
||||
"description": "optimize svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
138
tools/executors/svgOptimize/svgo.js
Normal file
138
tools/executors/svgOptimize/svgo.js
Normal file
@@ -0,0 +1,138 @@
|
||||
const path = require('path');
|
||||
const svgo = require('svgo');
|
||||
const { readdir, readFile, writeFile, exists } = require('fs/promises');
|
||||
const { pascalCase, paramCase } = require('change-case');
|
||||
const svgr = require('@svgr/core');
|
||||
|
||||
function isDuotone(name) {
|
||||
return name.endsWith('Duotone');
|
||||
}
|
||||
|
||||
async function optimizeSvg(folder) {
|
||||
try {
|
||||
const icons = await readdir(folder);
|
||||
const generateIcons = icons
|
||||
.filter(n => n.endsWith('.svg'))
|
||||
.map(async icon => {
|
||||
let originSvg;
|
||||
try {
|
||||
originSvg = await readFile(path.resolve(folder, icon));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
let optimizedSvg;
|
||||
try {
|
||||
const data = optimize(originSvg);
|
||||
optimizedSvg = data.data;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
const JSXContent = await getJSXContent(
|
||||
pascalCase(icon),
|
||||
optimizedSvg
|
||||
);
|
||||
|
||||
const iconName = path.basename(icon, '.svg');
|
||||
await writeFile(
|
||||
path.resolve(folder, `${iconName}.tsx`),
|
||||
JSXContent,
|
||||
{ encoding: 'utf8', flag: '' }
|
||||
);
|
||||
|
||||
console.log('Generated:', iconName);
|
||||
});
|
||||
|
||||
await Promise.allSettled([
|
||||
...generateIcons,
|
||||
generateImportEntry(icons, folder),
|
||||
]);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function optimize(input) {
|
||||
return svgo.optimize(input, {
|
||||
plugins: [
|
||||
'preset-default',
|
||||
'prefixIds',
|
||||
{
|
||||
name: 'sortAttrs',
|
||||
params: {
|
||||
xmlnsOrder: 'alphabetical',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* get icon component template
|
||||
*
|
||||
* @param {string} name
|
||||
*/
|
||||
async function getJSXContent(name, svgCode) {
|
||||
let svgrContent = '';
|
||||
try {
|
||||
svgrContent = await svgr.transform(
|
||||
svgCode,
|
||||
{
|
||||
icon: true,
|
||||
typescript: true,
|
||||
},
|
||||
{ componentName: `${name}Icon1` }
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
let matcher = svgrContent.match(/<svg ([^\>]+)>([\s\S]*?)<\/svg>/);
|
||||
return `
|
||||
import { FC } from 'react';
|
||||
import { SvgIcon, SvgIconProps } from '@mui/material';
|
||||
export const ${name}Icon: FC<SvgIconProps> = (props) => (
|
||||
<SvgIcon ${matcher[1]}>
|
||||
${matcher[2]}
|
||||
</SvgIcon>
|
||||
);
|
||||
`;
|
||||
}
|
||||
|
||||
async function generateImportEntry(iconNodes, folder) {
|
||||
const fileWithImportsPath = path.resolve(folder, 'index.ts');
|
||||
|
||||
const importsContent = iconNodes
|
||||
.map(iconNode => {
|
||||
const iconName = paramCase(iconNode.name);
|
||||
if (!iconName) {
|
||||
return `// Error: ${iconNode.name}`;
|
||||
}
|
||||
|
||||
return `export * from './${iconName}/${iconName}';`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
await fs.writeFile(
|
||||
fileWithImportsPath,
|
||||
`export const timestamp = ${Date.now()};\n${importsContent}`,
|
||||
{ encoding: 'utf8' }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} options
|
||||
* @param {array} options.assets
|
||||
* @param {string} options.assets.folder
|
||||
* @param {*} context
|
||||
* @returns
|
||||
*/
|
||||
exports['default'] = async function svgo(options, context) {
|
||||
const libRoot = context.workspace.projects[context.projectName].root;
|
||||
await Promise.allSettled(
|
||||
(options.assets || []).map(async (asset, index) => {
|
||||
await optimizeSvg(path.resolve(libRoot, asset.folder));
|
||||
})
|
||||
);
|
||||
|
||||
return { success: true };
|
||||
};
|
||||
9
tools/executors/tsCheck/executor.json
Normal file
9
tools/executors/tsCheck/executor.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"executors": {
|
||||
"tsCheck": {
|
||||
"implementation": "./tsCheck.js",
|
||||
"schema": "./schema.json",
|
||||
"description": "Runs `tsCheck`."
|
||||
}
|
||||
}
|
||||
}
|
||||
3
tools/executors/tsCheck/package.json
Normal file
3
tools/executors/tsCheck/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"executors": "./executor.json"
|
||||
}
|
||||
11
tools/executors/tsCheck/schema.json
Normal file
11
tools/executors/tsCheck/schema.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"type": "object",
|
||||
"cli": "nx",
|
||||
"properties": {
|
||||
"tsCheck": {
|
||||
"type": "string",
|
||||
"description": "Typescript check"
|
||||
}
|
||||
}
|
||||
}
|
||||
18
tools/executors/tsCheck/tsCheck.js
Normal file
18
tools/executors/tsCheck/tsCheck.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const {
|
||||
detectPackageManager,
|
||||
} = require('@nrwl/tao/src/shared/package-manager');
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
exports['default'] = async function tscExecutor(_, context) {
|
||||
const libRoot = context.workspace.projects[context.projectName].root;
|
||||
|
||||
const executionCode = await new Promise(resolve => {
|
||||
const child = spawn('pnpm', ['exec', 'tsc', '-b', libRoot], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
child.on('data', args => console.log(args));
|
||||
child.on('close', code => resolve(code));
|
||||
});
|
||||
|
||||
return { success: executionCode === 0 };
|
||||
};
|
||||
0
tools/generators/.gitkeep
Normal file
0
tools/generators/.gitkeep
Normal file
16
tools/notify.mjs
Normal file
16
tools/notify.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import got from 'got';
|
||||
|
||||
const STAGE_HOST = 'https://nightly.affine.pro/';
|
||||
if (process.env.CF_PAGES_BRANCH === 'master') {
|
||||
const message = `Daily builds: New deployment of Ligo-Virgo version [${process.env.CF_PAGES_COMMIT_SHA}](${STAGE_HOST}), this [${STAGE_HOST}](${STAGE_HOST}) link always points to the latest version deployment, to access the old version, please go to Github to view the deployment record.`;
|
||||
const url = `https://api.telegram.org/bot${process.env.BOT_TOKEN}/sendMessage`;
|
||||
|
||||
got.post(url, {
|
||||
json: {
|
||||
chat_id: process.env.CHAT_ID,
|
||||
text: message,
|
||||
parse_mode: 'Markdown',
|
||||
disable_notification: true,
|
||||
},
|
||||
}).then(r => console.log(r.body));
|
||||
}
|
||||
12
tools/tsconfig.tools.json
Normal file
12
tools/tsconfig.tools.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../dist/out-tsc/tools",
|
||||
"rootDir": ".",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": ["node"],
|
||||
"importHelpers": false
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user