
Security News
The Code You Didn't Write Is Still Yours to Defend
AI agents are pulling packages into environments no scanner is watching, creating exposure before security teams can see it.
query-typed
Advanced tools
🚀 TypeScript SQL query parser with compile-time column type extraction
query-typed는 TypeScript에서 SQL 쿼리의 컬럼 타입을 컴파일 타임에 추출할 수 있는 혁신적인 라이브러리입니다. 실행 없이도 SQL 쿼리에서 정확한 컬럼 타입을 추론하여 타입 안전한 개발을 가능하게 합니다.
npm install query-typed
# 또는
yarn add query-typed
# 또는
pnpm add query-typed
요구사항: TypeScript 4.1+ (템플릿 리터럴 타입 지원)
제로 의존성: 외부 라이브러리 없이 순수 TypeScript 타입만 사용합니다!
import { ExtractColumns, createTypedQuery } from 'query-typed';
// 1. 타입만 추출 (실행 없이 컴파일 타임에 추론!)
type UserColumns = ExtractColumns<'SELECT id, name, email FROM users'>;
// UserColumns 타입: ["id", "name", "email"]
// 2. 타입 안전한 쿼리 생성
const query = createTypedQuery('SELECT id, name, email FROM users');
// query.columns의 타입이 자동으로 ["id", "name", "email"]로 추론됨
// 3. 별칭 처리
type AliasColumns = ExtractColumns<'SELECT id as user_id, name as user_name FROM users'>;
// AliasColumns 타입: ["user_id", "user_name"]
// 4. 집계 함수
type AggColumns = ExtractColumns<'SELECT COUNT(*) as total, SUM(amount) as sum_amount FROM orders'>;
// AggColumns 타입: ["total", "sum_amount"]
import { createTypedQuery, select } from 'query-typed';
// 타입 안전한 쿼리 생성
const query = createTypedQuery('SELECT id, name, email FROM users');
// query.columns의 타입이 자동으로 ["id", "name", "email"]로 추론됨
// SELECT 쿼리 빌더
const selectQuery = select('SELECT id as user_id, name FROM users WHERE status = ?');
// selectQuery.columns의 타입이 자동으로 ["user_id", "name"]로 추론됨
🚀 핵심 기능: TypeScript의 템플릿 리터럴 타입을 사용하여 실행 없이도 컴파일 타임에 SQL 쿼리에서 컬럼 타입을 추출할 수 있습니다!
import { ExtractColumns, ExtractTables, createTypedQuery } from 'query-typed';
// 1. 컴파일 타임에 컬럼 타입 추론
type UserColumns = ExtractColumns<'SELECT id, name, email FROM users'>;
// UserColumns 타입: ["id", "name", "email"]
type AliasColumns = ExtractColumns<'SELECT id as user_id, name as user_name FROM users'>;
// AliasColumns 타입: ["user_id", "user_name"]
type AggColumns = ExtractColumns<'SELECT COUNT(*) as total, SUM(amount) as sum_amount FROM orders'>;
// AggColumns 타입: ["total", "sum_amount"]
// 2. 타입 안전한 쿼리 생성
const typedQuery = createTypedQuery('SELECT id, name, email FROM users');
// typedQuery.columns의 타입이 자동으로 ["id", "name", "email"]로 추론됨
// 3. 타입 검증 함수
function expectColumns<Expected extends readonly string[]>(expected: Expected) {
return function<T extends string>(sql: T): ExtractColumns<T> extends Expected ? T : never {
return sql as any;
};
}
// 컴파일 타임에 타입 검증
const validQuery = expectColumns(['id', 'name', 'email'])('SELECT id, name, email FROM users');
// ✅ 통과
const invalidQuery = expectColumns(['id', 'name'])('SELECT id, name, email FROM users');
// ❌ 컴파일 에러: 타입이 맞지 않음
// 4. WITH 절 (CTE) 지원
type WithColumns = ExtractColumns<'WITH v_tmp AS (SELECT user_idx, level FROM users) SELECT idx, level FROM v_tmp'>;
// WithColumns 타입: ["idx", "level"]
// 5. 실용적인 사용 예제
function createTypedSelectQuery<T extends string>(sql: T) {
type Columns = ExtractColumns<T>;
return {
sql,
columns: null as any as Columns,
execute: async <TRecord = Record<string, any>>(): Promise<TRecord[]> => {
// 실제 쿼리 실행 로직
return [] as TRecord[];
}
};
}
const query = createTypedSelectQuery('SELECT id, name, created_at FROM users WHERE status = ?');
// query.columns의 타입: ["id", "name", "created_at"]
// WITH 절을 사용한 복잡한 쿼리도 지원
const withQuery = createTypedSelectQuery(`
WITH user_stats AS (
SELECT user_id, COUNT(*) as order_count, SUM(amount) as total_amount
FROM orders GROUP BY user_id
)
SELECT user_id as id, order_count, total_amount as total FROM user_stats
`);
// withQuery.columns의 타입: ["id", "order_count", "total"]
// ✅ 기본 컬럼
ExtractColumns<'SELECT id, name FROM users'>
// ["id", "name"]
// ✅ 별칭
ExtractColumns<'SELECT id as user_id FROM users'>
// ["user_id"]
// ✅ 집계 함수
ExtractColumns<'SELECT COUNT(*) as total FROM users'>
// ["total"]
// ✅ 일반 함수
ExtractColumns<'SELECT UPPER(name) FROM users'>
// ["UPPER(...)"]
// ✅ 테이블 접두사
ExtractColumns<'SELECT u.id FROM users u'>
// ["id"]
// ✅ 표현식
ExtractColumns<'SELECT age + 1 as next_age FROM users'>
// ["next_age"]
// ✅ WITH 절 (CTE - Common Table Expression)
ExtractColumns<'WITH v_tmp AS (SELECT user_idx, level FROM users) SELECT idx, level FROM v_tmp'>
// ["idx", "level"]
// ✅ 복잡한 WITH 절
ExtractColumns<'WITH stats AS (SELECT user_id, COUNT(*) as cnt FROM orders GROUP BY user_id) SELECT user_id as id, cnt as total FROM stats'>
// ["id", "total"]
import { ExtractColumns } from 'query-typed';
// 타입 검증 함수
function expectColumns<Expected extends readonly string[]>(expected: Expected) {
return function<T extends string>(sql: T): ExtractColumns<T> extends Expected ? T : never {
return sql as any;
};
}
// 컴파일 타임 검증 예제
const validQuery1 = expectColumns(['id', 'name', 'email'])('SELECT id, name, email FROM users');
console.log('✅ 유효한 쿼리:', validQuery1);
// 다음 줄의 주석을 해제하면 컴파일 에러가 발생합니다:
// const invalidQuery = expectColumns(['id', 'name'])('SELECT id, name, email FROM users');
// ❌ 컴파일 에러: 3개 컬럼을 2개로 검증하려고 함
// 조건부 타입을 사용한 쿼리 검증
type IsValidUserQuery<T extends string> = ExtractColumns<T> extends readonly string[]
? ExtractColumns<T>[number] extends 'id' | 'name' | 'email' | 'created_at' | 'updated_at'
? T
: never
: never;
function createUserQuery<T extends string>(sql: T): IsValidUserQuery<T> {
// 사용자 테이블의 유효한 컬럼만 허용
return sql as any;
}
const validUserQuery = createUserQuery('SELECT id, name FROM users');
console.log('✅ 유효한 사용자 쿼리:', validUserQuery);
// 다음 줄의 주석을 해제하면 컴파일 에러가 발생합니다:
// const invalidUserQuery = createUserQuery('SELECT invalid_column FROM users');
// ❌ 컴파일 에러: 유효하지 않은 컬럼
더 많은 예제는 examples 디렉토리를 참고하세요.
npm test # 모든 테스트 실행
npm run test:watch # 변경사항 감시하며 테스트
npm run test:coverage # 커버리지 포함 테스트
ISC License
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)ExtractColumns, ExtractTables 타입 추가extractColumns, extractTables 함수 추가query-typed로 타입 안전한 SQL 개발을 시작하세요! 🚀
FAQs
TypeScript SQL query parser with compile-time column type extraction
The npm package query-typed receives a total of 2 weekly downloads. As such, query-typed popularity was classified as not popular.
We found that query-typed demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
AI agents are pulling packages into environments no scanner is watching, creating exposure before security teams can see it.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.