first commit
CI / typecheck (push) Successful in 1m8s
CI / format (push) Failing after 1m6s
CI / lint (push) Failing after 49s
CI / test (push) Failing after 1m8s

This commit is contained in:
SDI
2026-07-15 18:05:12 +09:00
commit 12e4f17b62
4633 changed files with 817125 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
import header from "./src/rules/header.js";
export default {
rules: { header },
rulesConfig: { header: 0 },
};
@@ -0,0 +1,6 @@
{
"name": "@ufb/eslint-plugin-header",
"private": true,
"type": "module",
"main": "./index.js"
}
@@ -0,0 +1,18 @@
export function commentParser(text) {
text = text.trim();
if (text.substr(0, 2) === '//') {
return [
'line',
text.split(/\r?\n/).map(function (line) {
return line.substr(2);
}),
];
} else if (text.substr(0, 2) === '/*' && text.substr(-2) === '*/') {
return ['block', text.substring(2, text.length - 2)];
} else {
throw new Error(
'Could not parse comment file: the file must contain either just line comments (//) or a single block comment (/* ... */)',
);
}
}
@@ -0,0 +1,491 @@
import fs from "fs";
import os from "os";
// @ts-ignore
function commentParser(text) {
text = text.trim();
if (text.substr(0, 2) === "//") {
return [
"line",
// @ts-ignore
text.split(/\r?\n/).map(function (line) {
return line.substr(2);
}),
];
} else if (text.substr(0, 2) === "/*" && text.substr(-2) === "*/") {
return ["block", text.substring(2, text.length - 2)];
} else {
throw new Error(
"Could not parse comment file: the file must contain either just line comments (//) or a single block comment (/* ... */)"
);
}
}
// @ts-ignore
function isPattern(object) {
return (
typeof object === "object" &&
Object.prototype.hasOwnProperty.call(object, "pattern")
);
}
// @ts-ignore
function match(actual, expected) {
if (expected.test) {
return expected.test(actual);
} else {
return expected === actual;
}
}
// @ts-ignore
function excludeShebangs(comments) {
// @ts-ignore
return comments.filter(function (comment) {
return comment.type !== "Shebang";
});
}
// Returns either the first block comment or the first set of line comments that
// are ONLY separated by a single newline. Note that this does not actually
// check if they are at the start of the file since that is already checked by
// hasHeader().
// @ts-ignore
function getLeadingComments(context, node) {
var all = excludeShebangs(
context
.getSourceCode()
.getAllComments(node.body.length ? node.body[0] : node)
);
if (all[0].type.toLowerCase() === "block") {
return [all[0]];
}
for (var i = 1; i < all.length; ++i) {
var txt = context
.getSourceCode()
.getText()
.slice(all[i - 1].range[1], all[i].range[0]);
if (!txt.match(/^(\r\n|\r|\n)$/)) {
break;
}
}
return all.slice(0, i);
}
// @ts-ignore
function genCommentBody(commentType, textArray, eol, numNewlines) {
var eols = eol.repeat(numNewlines);
if (commentType === "block") {
return "/*" + textArray.join(eol) + "*/" + eols;
} else {
return "//" + textArray.join(eol + "//") + eols;
}
}
// @ts-ignore
function genCommentsRange(context, comments, eol) {
var start = comments[0].range[0];
var end = comments.slice(-1)[0].range[1];
if (context.getSourceCode().text[end] === eol) {
end += eol.length;
}
return [start, end];
}
// @ts-ignore
function genPrependFixer(commentType, node, headerLines, eol, numNewlines) {
// @ts-ignore
return function (fixer) {
return fixer.insertTextBefore(
node,
genCommentBody(commentType, headerLines, eol, numNewlines)
);
};
}
function genReplaceFixer(
// @ts-ignore
commentType,
// @ts-ignore
context,
// @ts-ignore
leadingComments,
// @ts-ignore
headerLines,
// @ts-ignore
eol,
// @ts-ignore
numNewlines
) {
// @ts-ignore
return function (fixer) {
return fixer.replaceTextRange(
genCommentsRange(context, leadingComments, eol),
genCommentBody(commentType, headerLines, eol, numNewlines)
);
};
}
// @ts-ignore
function findSettings(options) {
var lastOption = options.length > 0 ? options[options.length - 1] : null;
if (
typeof lastOption === "object" &&
!Array.isArray(lastOption) &&
lastOption !== null &&
!Object.prototype.hasOwnProperty.call(lastOption, "pattern")
) {
return lastOption;
}
return null;
}
// @ts-ignore
function getEOL(options) {
var settings = findSettings(options);
if (settings && settings.lineEndings === "unix") {
return "\n";
}
if (settings && settings.lineEndings === "windows") {
return "\r\n";
}
return os.EOL;
}
// @ts-ignore
function hasHeader(src) {
if (src.substr(0, 2) === "#!") {
var m = src.match(/(\r\n|\r|\n)/);
if (m) {
src = src.slice(m.index + m[0].length);
}
}
return src.substr(0, 2) === "/*" || src.substr(0, 2) === "//";
}
// @ts-ignore
function matchesLineEndings(src, num) {
for (var j = 0; j < num; ++j) {
var m = src.match(/^(\r\n|\r|\n)/);
if (m) {
src = src.slice(m.index + m[0].length);
} else {
return false;
}
}
return true;
}
export default {
meta: {
type: "layout",
fixable: "whitespace",
schema: {
$ref: "#/definitions/options",
definitions: {
commentType: {
type: "string",
enum: ["block", "line"],
},
line: {
anyOf: [
{
type: "string",
},
{
type: "object",
properties: {
pattern: {
type: "string",
},
template: {
type: "string",
},
},
required: ["pattern"],
additionalProperties: false,
},
],
},
headerLines: {
anyOf: [
{
$ref: "#/definitions/line",
},
{
type: "array",
items: {
$ref: "#/definitions/line",
},
},
],
},
numNewlines: {
type: "integer",
minimum: 0,
},
settings: {
type: "object",
properties: {
lineEndings: {
type: "string",
enum: ["unix", "windows"],
},
},
additionalProperties: false,
},
options: {
anyOf: [
{
type: "array",
minItems: 1,
maxItems: 2,
items: [{ type: "string" }, { $ref: "#/definitions/settings" }],
},
{
type: "array",
minItems: 2,
maxItems: 3,
items: [
{ $ref: "#/definitions/commentType" },
{ $ref: "#/definitions/headerLines" },
{ $ref: "#/definitions/settings" },
],
},
{
type: "array",
minItems: 3,
maxItems: 4,
items: [
{ $ref: "#/definitions/commentType" },
{ $ref: "#/definitions/headerLines" },
{ $ref: "#/definitions/numNewlines" },
{ $ref: "#/definitions/settings" },
],
},
],
},
},
},
},
// @ts-ignore
create: function (context) {
var options = context.options;
var numNewlines = options.length > 2 ? options[2] : 1;
var eol = getEOL(options);
// If just one option then read comment from file
if (
options.length === 1 ||
(options.length === 2 && findSettings(options))
) {
var text = fs.readFileSync(context.options[0], "utf8");
options = commentParser(text);
}
var commentType = options[0].toLowerCase();
// @ts-ignore
var headerLines,
// @ts-ignore
fixLines = [];
// If any of the lines are regular expressions, then we can't
// automatically fix them. We set this to true below once we
// ensure none of the lines are of type RegExp
var canFix = false;
if (Array.isArray(options[1])) {
canFix = true;
headerLines = options[1].map(function (line) {
var isRegex = isPattern(line);
// Can only fix regex option if a template is also provided
if (isRegex && !line.template) {
canFix = false;
}
fixLines.push(line.template || line);
return isRegex ? new RegExp(line.pattern) : line;
});
} else if (isPattern(options[1])) {
var line = options[1];
headerLines = [new RegExp(line.pattern)];
fixLines.push(line.template || line);
// Same as above for regex and template
canFix = !!line.template;
} else {
canFix = true;
headerLines = options[1].split(/\r?\n/);
fixLines = headerLines;
}
return {
// @ts-ignore
Program: function (node) {
if (!hasHeader(context.getSourceCode().getText())) {
context.report({
loc: node.loc,
message: "missing header",
// @ts-ignore
fix: genPrependFixer(commentType, node, fixLines, eol, numNewlines),
});
} else {
var leadingComments = getLeadingComments(context, node);
if (!leadingComments.length) {
context.report({
loc: node.loc,
message: "missing header",
fix: canFix
? // @ts-ignore
genPrependFixer(commentType, node, fixLines, eol, numNewlines)
: null,
});
} else if (leadingComments[0].type.toLowerCase() !== commentType) {
context.report({
loc: node.loc,
message: "header should be a {{commentType}} comment",
data: {
commentType: commentType,
},
fix: canFix
? genReplaceFixer(
commentType,
context,
leadingComments,
// @ts-ignore
fixLines,
eol,
numNewlines
)
: null,
});
} else {
if (commentType === "line") {
if (leadingComments.length < headerLines.length) {
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix
? genReplaceFixer(
commentType,
context,
leadingComments,
// @ts-ignore
fixLines,
eol,
numNewlines
)
: null,
});
return;
}
for (var i = 0; i < headerLines.length; i++) {
// @ts-ignore
if (!match(leadingComments[i].value, headerLines[i])) {
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix
? genReplaceFixer(
commentType,
context,
leadingComments,
// @ts-ignore
fixLines,
eol,
numNewlines
)
: null,
});
return;
}
}
var postLineHeader = context
.getSourceCode()
.text.substr(
leadingComments[headerLines.length - 1].range[1],
numNewlines * 2
);
if (!matchesLineEndings(postLineHeader, numNewlines)) {
context.report({
loc: node.loc,
message: "no newline after header",
fix: canFix
? genReplaceFixer(
commentType,
context,
leadingComments,
// @ts-ignore
fixLines,
eol,
numNewlines
)
: null,
});
}
} else {
// if block comment pattern has more than 1 line, we also split the comment
var leadingLines = [leadingComments[0].value];
if (headerLines.length > 1) {
leadingLines = leadingComments[0].value.split(/\r?\n/);
}
var hasError = false;
if (leadingLines.length > headerLines.length) {
hasError = true;
}
for (i = 0; !hasError && i < headerLines.length; i++) {
// @ts-ignore
if (!match(leadingLines[i], headerLines[i])) {
hasError = true;
}
}
if (hasError) {
if (canFix && headerLines.length > 1) {
// @ts-ignore
fixLines = [fixLines.join(eol)];
}
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix
? genReplaceFixer(
commentType,
context,
leadingComments,
// @ts-ignore
fixLines,
eol,
numNewlines
)
: null,
});
} else {
var postBlockHeader = context
.getSourceCode()
.text.substr(leadingComments[0].range[1], numNewlines * 2);
if (!matchesLineEndings(postBlockHeader, numNewlines)) {
context.report({
loc: node.loc,
message: "no newline after header",
fix: canFix
? genReplaceFixer(
commentType,
context,
leadingComments,
// @ts-ignore
fixLines,
eol,
numNewlines
)
: null,
});
}
}
}
}
}
},
};
},
};
+129
View File
@@ -0,0 +1,129 @@
/**
* Copyright 2025 LY Corporation
*
* LY Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/// <reference types="./types.d.ts" />
import * as path from 'node:path';
import { includeIgnoreFile } from '@eslint/compat';
import eslint from '@eslint/js';
import importPlugin from 'eslint-plugin-import';
import turboPlugin from 'eslint-plugin-turbo';
import tseslint from 'typescript-eslint';
import headerPlugin from '@ufb/eslint-plugin-header';
/**
* All packages that leverage t3-env should use this rule
*/
export const restrictEnvAccess = tseslint.config(
{ ignores: ['**/env.ts'] },
{
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
rules: {
'no-restricted-properties': [
'error',
{
object: 'process',
property: 'env',
message:
"Use `import { env } from '~/env'` instead to ensure validated types.",
},
],
'no-restricted-imports': [
'error',
{
name: 'process',
importNames: ['env'],
message:
"Use `import { env } from '~/env'` instead to ensure validated types.",
},
],
},
},
);
export default tseslint.config(
// Ignore files not tracked by VCS and any config files
includeIgnoreFile(path.join(import.meta.dirname, '../../.gitignore')),
{ ignores: ['**/*.config.*'] },
{
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
plugins: {
import: importPlugin,
turbo: turboPlugin,
header: headerPlugin,
},
extends: [
eslint.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.stylisticTypeChecked,
],
rules: {
...turboPlugin.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
'@typescript-eslint/consistent-type-imports': [
'warn',
{ prefer: 'type-imports', fixStyle: 'separate-type-imports' },
],
'@typescript-eslint/no-misused-promises': [
2,
{ checksVoidReturn: { attributes: false } },
],
'@typescript-eslint/no-unnecessary-condition': [
'error',
{
allowConstantLoopConditions: true,
},
],
'@typescript-eslint/no-non-null-assertion': 'error',
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'header/header': [
'error',
'block',
[
'*',
' * Copyright 2025 LY Corporation',
' *',
' * LY Corporation licenses this file to you under the Apache License,',
' * version 2.0 (the "License"); you may not use this file except in compliance',
' * with the License. You may obtain a copy of the License at:',
' *',
' * https://www.apache.org/licenses/LICENSE-2.0',
' *',
' * Unless required by applicable law or agreed to in writing, software',
' * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT',
' * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the',
' * License for the specific language governing permissions and limitations',
' * under the License.',
' ',
],
1,
],
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/consistent-type-definitions': 'off',
},
},
{
linterOptions: { reportUnusedDisableDirectives: true },
languageOptions: { parserOptions: { projectService: true } },
},
);
+30
View File
@@ -0,0 +1,30 @@
/**
* Copyright 2025 LY Corporation
*
* LY Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/** @type {Awaited<import('typescript-eslint').Config>} */
/** @type {Awaited<import('typescript-eslint').Config>} */
export default [
{
files: ['**/*.ts'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/unbound-method': 'off',
},
},
];
+35
View File
@@ -0,0 +1,35 @@
/**
* Copyright 2025 LY Corporation
*
* LY Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
import nextPlugin from '@next/eslint-plugin-next';
/** @type {Awaited<import('typescript-eslint').Config>} */
export default [
{
files: ['**/*.ts', '**/*.tsx'],
plugins: {
'@next/next': nextPlugin,
},
rules: {
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs['core-web-vitals'].rules,
// TypeError: context.getAncestors is not a function
'@next/next/no-duplicate-head': 'off',
'@next/next/no-html-link-for-pages': 'off',
'@next/next/no-page-custom-font': 'off',
},
},
];
+37
View File
@@ -0,0 +1,37 @@
{
"name": "@ufb/eslint-config",
"private": true,
"version": "0.1.0",
"type": "module",
"exports": {
"./base": "./base.js",
"./nestjs": "./nestjs.js",
"./nextjs": "./nextjs.js",
"./react": "./react.js"
},
"scripts": {
"clean": "git clean -xdf .cache .turbo node_modules",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@eslint/compat": "^2.0.3",
"@next/eslint-plugin-next": "^16.2.1",
"@ufb/eslint-plugin-header": "workspace:*",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-compiler": "beta",
"eslint-plugin-react-hooks": "^6.1.1",
"eslint-plugin-turbo": "^2.8.3",
"typescript-eslint": "^8.46.0"
},
"devDependencies": {
"@ufb/prettier-config": "workspace:*",
"@ufb/tsconfig": "workspace:*",
"eslint": "catalog:",
"prettier": "catalog:",
"typescript": "catalog:"
},
"prettier": "@ufb/prettier-config"
}
+30
View File
@@ -0,0 +1,30 @@
import reactPlugin from 'eslint-plugin-react';
import compilerPlugin from 'eslint-plugin-react-compiler';
import hooksPlugin from 'eslint-plugin-react-hooks';
/** @type {Awaited<import('typescript-eslint').Config>} */
export default [
{
files: ['**/*.ts', '**/*.tsx'],
plugins: {
react: reactPlugin,
'react-compiler': compilerPlugin,
'react-hooks': hooksPlugin,
},
rules: {
...reactPlugin.configs['jsx-runtime'].rules,
...hooksPlugin.configs.recommended.rules,
'react/prop-types': 'off',
'react/jsx-key': 'error',
'react-hooks/exhaustive-deps': 'off',
'react/display-name': 'off',
'react-hooks/rules-of-hooks': 'off',
'react-compiler/react-compiler': 'error',
},
languageOptions: {
globals: {
React: 'writable',
},
},
},
];
+5
View File
@@ -0,0 +1,5 @@
{
"extends": "@ufb/tsconfig/base.json",
"include": ["."],
"exclude": ["node_modules"]
}
+50
View File
@@ -0,0 +1,50 @@
/**
* Since the ecosystem hasn't fully migrated to ESLint's new FlatConfig system yet,
* we "need" to type some of the plugins manually :(
*/
declare module 'eslint-plugin-import' {
import type { Linter, Rule } from 'eslint';
export const configs: {
recommended: { rules: Linter.RulesRecord };
};
export const rules: Record<string, Rule.RuleModule>;
}
declare module 'eslint-plugin-react' {
import type { Linter, Rule } from 'eslint';
export const configs: {
recommended: { rules: Linter.RulesRecord };
all: { rules: Linter.RulesRecord };
'jsx-runtime': { rules: Linter.RulesRecord };
};
export const rules: Record<string, Rule.RuleModule>;
}
declare module 'eslint-plugin-react-compiler' {}
declare module 'eslint-plugin-react-hooks' {
import type { Linter, Rule } from 'eslint';
export const configs: {
recommended: {
rules: {
'rules-of-hooks': Linter.RuleEntry;
'exhaustive-deps': Linter.RuleEntry;
};
};
};
export const rules: Record<string, Rule.RuleModule>;
}
declare module '@next/eslint-plugin-next' {
import type { Linter, Rule } from 'eslint';
export const configs: {
recommended: { rules: Linter.RulesRecord };
'core-web-vitals': { rules: Linter.RulesRecord };
};
export const rules: Record<string, Rule.RuleModule>;
}
+3
View File
@@ -0,0 +1,3 @@
{
"name": "@ufb/github"
}
+17
View File
@@ -0,0 +1,17 @@
name: "Setup and install"
description: "Common setup steps for Actions"
runs:
using: composite
steps:
- uses: pnpm/action-setup@v5
- uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
cache: "pnpm"
- shell: bash
run: pnpm add -g turbo
- shell: bash
run: pnpm install
+43
View File
@@ -0,0 +1,43 @@
import { fileURLToPath } from 'url';
/** @typedef {import("prettier").Config} PrettierConfig */
/** @typedef {import("prettier-plugin-tailwindcss").PluginOptions} TailwindConfig */
/** @typedef {import("@ianvs/prettier-plugin-sort-imports").PluginConfig} SortImportsConfig */
/** @type { PrettierConfig | SortImportsConfig | TailwindConfig } */
const config = {
singleQuote: true,
trailingComma: 'all',
experimentalTernaries: true,
endOfLine: 'auto',
tabWidth: 2,
useTabs: false,
plugins: [
'@ianvs/prettier-plugin-sort-imports',
'prettier-plugin-tailwindcss',
],
tailwindConfig: fileURLToPath(
new URL('../../packages/ufb-tailwindcss/index.js', import.meta.url),
),
tailwindFunctions: ['cn', 'cva'],
importOrder: [
'^(react/(.*)$)|^(react$)',
'^(next/(.*)$)|^(next$)',
'<THIRD_PARTY_MODULES>',
'',
'^@ufb/(.*)$',
'',
'^(@/shared/(.*))$|^(@/shared$)',
'^(@/entities/(.*)$)|^(@/entities$)',
'^(@/features/(.*)$)|^(@/features$)',
'^(@/widgets/(.*)$)|^(@/widgets$)',
'',
'^@/',
'^[../]',
'^[./]',
],
importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
importOrderTypeScriptVersion: '4.4.0',
};
export default config;
+25
View File
@@ -0,0 +1,25 @@
{
"name": "@ufb/prettier-config",
"version": "0.1.0",
"private": true,
"type": "module",
"exports": {
".": "./index.js"
},
"scripts": {
"clean": "git clean -xdf .cache .turbo node_modules",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
"prettier": "catalog:",
"prettier-plugin-tailwindcss": "^0.7.2"
},
"devDependencies": {
"@types/node": "24.12.0",
"@ufb/tsconfig": "workspace:*",
"typescript": "catalog:"
},
"prettier": "@ufb/prettier-config"
}
+5
View File
@@ -0,0 +1,5 @@
{
"extends": "@ufb/tsconfig/base.json",
"include": ["."],
"exclude": ["node_modules"]
}
+23
View File
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "ES2022",
"lib": ["ES2022"],
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
"incremental": true,
"disableSourceOfProjectReferenceRedirect": true,
"tsBuildInfoFile": "${configDir}/.cache/tsbuildinfo.json",
"strict": true,
"noUncheckedIndexedAccess": true,
"checkJs": true,
"module": "Preserve",
"moduleResolution": "Bundler",
"noEmit": true
},
"exclude": ["node_modules", "build", "dist", ".next"]
}
+11
View File
@@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./base.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": true,
"noEmit": false,
"outDir": "${configDir}/dist"
}
}
+20
View File
@@ -0,0 +1,20 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "ES2023",
"sourceMap": true,
"baseUrl": "./",
"incremental": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"outDir": "./dist",
"strictNullChecks": true
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"name": "@ufb/tsconfig",
"private": true,
"version": "0.1.0",
"files": [
"*.json"
]
}