luau-obfuscator 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.github/workflows/release.yml +56 -56
  2. package/dist/index.cjs +2186 -95
  3. package/dist/index.d.cts +34 -2
  4. package/dist/index.d.ts +34 -2
  5. package/dist/index.js +2186 -95
  6. package/generated/grammers.luau +13643 -0
  7. package/generated/tests.luau +5567 -0
  8. package/package.json +2 -2
  9. package/scripts/test.js +24 -8
  10. package/{scripts/example.luau → smoketest/grammers.luau} +1174 -1174
  11. package/smoketest/tests.luau +115 -0
  12. package/src/config.ts +2 -1
  13. package/src/passes/ConstantArray.ts +90 -89
  14. package/src/passes/EncryptNumbers.ts +122 -65
  15. package/src/passes/EncryptStrings.ts +162 -82
  16. package/src/passes/GlobalMapping.ts +193 -193
  17. package/src/passes/InsertJunk.ts +184 -184
  18. package/src/passes/Minify.ts +5 -5
  19. package/src/passes/NumbersToExpressions.ts +183 -2
  20. package/src/passes/RenameVariables.ts +2 -9
  21. package/src/passes/StringsToExpressions.ts +195 -6
  22. package/src/passes/StripTypes.ts +191 -191
  23. package/src/passes/Vmify.ts +87 -0
  24. package/src/passes/WrapInFunction.ts +31 -31
  25. package/src/passes/nodeFactory.ts +36 -1
  26. package/src/passes/vmify/chunk.ts +54 -0
  27. package/src/passes/vmify/compiler.ts +1026 -0
  28. package/src/passes/vmify/names.ts +72 -0
  29. package/src/passes/vmify/opcodes.ts +80 -0
  30. package/src/passes/vmify/registers.ts +63 -0
  31. package/src/passes/vmify/runtime.ts +334 -0
  32. package/src/passes/vmify/scope-walk.ts +175 -0
  33. package/src/passes/vmify/serialize.ts +68 -0
  34. package/src/passes/walk.ts +141 -43
  35. package/src/pipeline.ts +5 -6
  36. package/tsconfig.json +20 -20
  37. package/tsup.config.ts +9 -9
  38. package/generated/final.luau +0 -1029
@@ -0,0 +1,175 @@
1
+ import type {
2
+ Program, Block, Statement, Expression, FunctionBody, Identifier,
3
+ } from "luau-parser"
4
+
5
+ /** 함수 하나(최상위 프로그램 포함)를 가리키는 식별용 토큰. 객체 identity만 씀. */
6
+ export type FuncMarker = { readonly tag: "top" } | { readonly tag: "fn"; readonly node: FunctionBody }
7
+
8
+ export interface EnclosingFunctionMap {
9
+ /** 식별자 사용/선언 노드 하나가 어느 함수 안에 있는지. */
10
+ ownerOf: Map<object, FuncMarker>
11
+ /** 함수 마커 -> 그 함수를 감싸는 바깥 함수 마커(최상위는 undefined). */
12
+ parentOf: Map<FuncMarker, FuncMarker | undefined>
13
+ topMarker: FuncMarker
14
+ }
15
+
16
+ /**
17
+ * analyzeScopes()가 주는 건 "이 식별자가 어떤 binding을 가리키는가"까지고,
18
+ * "그 식별자가 물리적으로 어느 함수 몸통 안에 있는가"는 안 알려주기 때문에
19
+ * upvalue 캡처를 판단하려면 이 정보를 직접 한 번 더 walk해서 구해야 한다.
20
+ * (binding 선언 위치의 함수 != 어떤 참조 위치의 함수 라면 그 참조는 upvalue를 필요로 함)
21
+ */
22
+ export function buildEnclosingFunctionMap(program: Program): EnclosingFunctionMap {
23
+ const ownerOf = new Map<object, FuncMarker>()
24
+ const parentOf = new Map<FuncMarker, FuncMarker | undefined>()
25
+ const topMarker: FuncMarker = { tag: "top" }
26
+ parentOf.set(topMarker, undefined)
27
+
28
+ function mark(node: object, fn: FuncMarker): void {
29
+ ownerOf.set(node, fn)
30
+ }
31
+
32
+ function walkBlock(block: Block, fn: FuncMarker): void {
33
+ for (const stmt of block.statements) walkStatement(stmt, fn)
34
+ }
35
+
36
+ function walkFunctionBody(fb: FunctionBody, parent: FuncMarker): void {
37
+ const self: FuncMarker = { tag: "fn", node: fb }
38
+ parentOf.set(self, parent)
39
+ mark(fb, self)
40
+ for (const p of fb.params) mark(p, self)
41
+ walkBlock(fb.body, self)
42
+ }
43
+
44
+ function walkExpr(expr: Expression, fn: FuncMarker): void {
45
+ mark(expr, fn)
46
+ switch (expr.type) {
47
+ case "Identifier":
48
+ mark(expr, fn)
49
+ break
50
+ case "InterpolatedStringExpression":
51
+ for (const part of expr.parts) if (part.kind === "expression") walkExpr(part.expression, fn)
52
+ break
53
+ case "FunctionExpression":
54
+ walkFunctionBody(expr.func, fn)
55
+ break
56
+ case "TableExpression":
57
+ for (const field of expr.fields) {
58
+ if (field.type === "TableFieldPositional") walkExpr(field.value, fn)
59
+ else if (field.type === "TableFieldNamed") walkExpr(field.value, fn)
60
+ else {
61
+ walkExpr(field.key, fn)
62
+ walkExpr(field.value, fn)
63
+ }
64
+ }
65
+ break
66
+ case "BinaryExpression":
67
+ walkExpr(expr.left, fn)
68
+ walkExpr(expr.right, fn)
69
+ break
70
+ case "UnaryExpression":
71
+ walkExpr(expr.argument, fn)
72
+ break
73
+ case "MemberExpression":
74
+ walkExpr(expr.object, fn)
75
+ break
76
+ case "IndexExpression":
77
+ walkExpr(expr.object, fn)
78
+ walkExpr(expr.index, fn)
79
+ break
80
+ case "CallExpression":
81
+ walkExpr(expr.callee, fn)
82
+ for (const a of expr.arguments) walkExpr(a, fn)
83
+ break
84
+ case "MethodCallExpression":
85
+ walkExpr(expr.object, fn)
86
+ for (const a of expr.arguments) walkExpr(a, fn)
87
+ break
88
+ case "ParenthesizedExpression":
89
+ case "TypeAssertionExpression":
90
+ walkExpr(expr.expression, fn)
91
+ break
92
+ case "IfElseExpression":
93
+ for (const c of expr.clauses) {
94
+ walkExpr(c.condition, fn)
95
+ walkExpr(c.body, fn)
96
+ }
97
+ walkExpr(expr.alternate, fn)
98
+ break
99
+ }
100
+ }
101
+
102
+ function walkStatement(stmt: Statement, fn: FuncMarker): void {
103
+ mark(stmt, fn)
104
+ switch (stmt.type) {
105
+ case "LocalStatement":
106
+ for (const n of stmt.names) mark(n, fn)
107
+ for (const e of stmt.init) walkExpr(e, fn)
108
+ return
109
+ case "LocalFunctionStatement":
110
+ mark(stmt.name, fn)
111
+ walkFunctionBody(stmt.func, fn)
112
+ return
113
+ case "FunctionDeclarationStatement":
114
+ mark(stmt.target.base, fn)
115
+ walkFunctionBody(stmt.func, fn)
116
+ return
117
+ case "AssignmentStatement":
118
+ for (const t of stmt.targets) walkExpr(t, fn)
119
+ for (const v of stmt.values) walkExpr(v, fn)
120
+ return
121
+ case "CompoundAssignmentStatement":
122
+ walkExpr(stmt.target, fn)
123
+ walkExpr(stmt.value, fn)
124
+ return
125
+ case "CallStatement":
126
+ walkExpr(stmt.expression, fn)
127
+ return
128
+ case "DoStatement":
129
+ walkBlock(stmt.body, fn)
130
+ return
131
+ case "WhileStatement":
132
+ walkExpr(stmt.condition, fn)
133
+ walkBlock(stmt.body, fn)
134
+ return
135
+ case "RepeatStatement":
136
+ walkBlock(stmt.body, fn)
137
+ walkExpr(stmt.condition, fn)
138
+ return
139
+ case "IfStatement":
140
+ for (const c of stmt.clauses) {
141
+ walkExpr(c.condition, fn)
142
+ walkBlock(c.body, fn)
143
+ }
144
+ if (stmt.alternate) walkBlock(stmt.alternate, fn)
145
+ return
146
+ case "NumericForStatement":
147
+ mark(stmt.variable, fn)
148
+ walkExpr(stmt.start, fn)
149
+ walkExpr(stmt.end, fn)
150
+ if (stmt.step) walkExpr(stmt.step, fn)
151
+ walkBlock(stmt.body, fn)
152
+ return
153
+ case "GenericForStatement":
154
+ for (const v of stmt.variables) mark(v, fn)
155
+ for (const it of stmt.iterators) walkExpr(it, fn)
156
+ walkBlock(stmt.body, fn)
157
+ return
158
+ case "ReturnStatement":
159
+ for (const a of stmt.arguments) walkExpr(a, fn)
160
+ return
161
+ default:
162
+ return
163
+ }
164
+ }
165
+
166
+ walkBlock(program.body, topMarker)
167
+ return { ownerOf, parentOf, topMarker }
168
+ }
169
+
170
+ /** Identifier 참조 하나가 속한 함수를 찾는다(선언/참조 둘 다 이 맵에 들어있음). */
171
+ export function ownerFunctionOf(map: EnclosingFunctionMap, node: object): FuncMarker {
172
+ const fn = map.ownerOf.get(node)
173
+ if (!fn) throw new Error("scope-walk: node was not visited — walker/compiler are out of sync")
174
+ return fn
175
+ }
@@ -0,0 +1,68 @@
1
+ import type { Expression, TableField } from "luau-parser"
2
+ import type { Proto, ConstValue } from "./chunk"
3
+ import { Opcode } from "./opcodes"
4
+ import type { VmNames } from "./names"
5
+ import {
6
+ table, positionalField, namedField, numberLiteral, vmNumberLiteral, stringLiteral, booleanLiteral, nilLiteral,
7
+ } from "../nodeFactory"
8
+
9
+ /** proto.consts[]를 Luau 배열 리터럴로: { [1] = v1, [2] = v2, ... } (1-based는 그대로 유지) */
10
+ function serializeConsts(consts: ConstValue[]): Expression {
11
+ const fields: TableField[] = consts.map((v) => positionalField(serializeConstValue(v)))
12
+ return table(fields)
13
+ }
14
+
15
+ function serializeConstValue(v: ConstValue): Expression {
16
+ if (v === null) return nilLiteral()
17
+ if (typeof v === "string") return stringLiteral(v)
18
+ if (typeof v === "number") return numberLiteral(v)
19
+ return booleanLiteral(v)
20
+ }
21
+
22
+ /**
23
+ * Instr/Proto를 Luau 테이블 리터럴로 찍을 때 쓰는 필드 키는 고정 문자열("op","a","b","c",
24
+ * "numParams", ...)이 아니라 names(names.ts)에서 빌드마다 새로 뽑은 이름을 쓴다 —
25
+ * 이 키 이름이 고정이면 산출물에서 `{op=6, a=0, ...}` 같은 패턴만 grep해도 VM 청크
26
+ * 테이블을 바로 찾아낼 수 있기 때문. runtime.ts가 같은 names로 instr.<key>를 읽으므로
27
+ * 반드시 컴파일 시점에 쓴 것과 동일한 VmNames 인스턴스를 넘겨야 한다.
28
+ */
29
+ function serializeInstrs(proto: Proto): Expression {
30
+ const fields: TableField[] = proto.code.map((instr) =>
31
+ positionalField(
32
+ table([
33
+ positionalField(vmNumberLiteral(instr.op as number)),
34
+ positionalField(vmNumberLiteral(instr.a)),
35
+ positionalField(vmNumberLiteral(instr.b)),
36
+ positionalField(vmNumberLiteral(instr.c)),
37
+ ]),
38
+ ))
39
+ return table(fields)
40
+ }
41
+
42
+ function serializeUpvalDescs(proto: Proto, names: VmNames): Expression {
43
+ const fields: TableField[] = proto.upvalDescs.map((d) =>
44
+ positionalField(
45
+ table([
46
+ namedField(names.kind, stringLiteral(d.kind)),
47
+ namedField(names.index, vmNumberLiteral(d.index)),
48
+ ]),
49
+ ))
50
+ return table(fields)
51
+ }
52
+
53
+ /** Proto 하나를 { numParams=.., hasVarargs=.., maxRegs=.., code={...}, consts={...}, upvalDescs={...}, protos={...} }로
54
+ * (필드 키는 전부 names에서 온 무작위 이름). */
55
+ export function serializeProto(proto: Proto, names: VmNames): Expression {
56
+ const fields: TableField[] = [
57
+ namedField(names.numParams, vmNumberLiteral(proto.numParams)),
58
+ namedField(names.hasVarargs, booleanLiteral(proto.hasVarargs)),
59
+ namedField(names.maxRegs, vmNumberLiteral(proto.maxRegs)),
60
+ namedField(names.code, serializeInstrs(proto)),
61
+ namedField(names.consts, serializeConsts(proto.consts)),
62
+ namedField(names.upvalDescs, serializeUpvalDescs(proto, names)),
63
+ namedField(names.protos, table(proto.protos.map((p) => positionalField(serializeProto(p, names))))),
64
+ ]
65
+ return table(fields)
66
+ }
67
+
68
+ export { Opcode }
@@ -10,79 +10,177 @@ function visitArray(arr: Expression[], visitor: ExpressionVisitor): void {
10
10
  }
11
11
  }
12
12
 
13
- export function mapExpression(expr: Expression, visitor: ExpressionVisitor): Expression {
13
+ interface ChildAccessor {
14
+ get(): Expression
15
+ set(v: Expression): void
16
+ }
17
+
18
+ /**
19
+ * expr의 "자식 Expression"들에 대한 getter/setter 목록을 반환한다.
20
+ * (FunctionExpression은 별도 처리하므로 여기서는 빈 배열을 반환한다.)
21
+ */
22
+ function getExpressionChildren(expr: Expression): ChildAccessor[] {
14
23
  switch (expr.type) {
15
- case "InterpolatedStringExpression":
24
+ case "InterpolatedStringExpression": {
25
+ const children: ChildAccessor[] = []
16
26
  for (const part of expr.parts) {
17
27
  if (part.kind === "expression") {
18
- part.expression = mapExpression(part.expression, visitor)
28
+ children.push({
29
+ get: () => part.expression,
30
+ set: (v) => { part.expression = v },
31
+ })
19
32
  }
20
33
  }
21
- break
34
+ return children
35
+ }
22
36
 
23
37
  case "FunctionExpression":
24
- walkFunctionBody(expr.func, visitor)
25
- break
38
+ return []
26
39
 
27
- case "TableExpression":
40
+ case "TableExpression": {
41
+ const children: ChildAccessor[] = []
28
42
  for (const field of expr.fields) {
29
43
  if (field.type === "TableFieldPositional") {
30
- field.value = mapExpression(field.value, visitor)
44
+ children.push({ get: () => field.value, set: (v) => { field.value = v } })
31
45
  } else if (field.type === "TableFieldNamed") {
32
- field.value = mapExpression(field.value, visitor)
46
+ children.push({ get: () => field.value, set: (v) => { field.value = v } })
33
47
  } else if (field.type === "TableFieldComputed") {
34
- field.key = mapExpression(field.key, visitor)
35
- field.value = mapExpression(field.value, visitor)
48
+ children.push({ get: () => field.key, set: (v) => { field.key = v } })
49
+ children.push({ get: () => field.value, set: (v) => { field.value = v } })
36
50
  }
37
51
  }
38
- break
52
+ return children
53
+ }
39
54
 
40
55
  case "BinaryExpression":
41
- expr.left = mapExpression(expr.left, visitor)
42
- expr.right = mapExpression(expr.right, visitor)
43
- break
56
+ return [
57
+ { get: () => expr.left, set: (v) => { expr.left = v } },
58
+ { get: () => expr.right, set: (v) => { expr.right = v } },
59
+ ]
44
60
 
45
61
  case "UnaryExpression":
46
- expr.argument = mapExpression(expr.argument, visitor)
47
- break
62
+ return [{ get: () => expr.argument, set: (v) => { expr.argument = v } }]
48
63
 
49
64
  case "MemberExpression":
50
- expr.object = mapExpression(expr.object, visitor)
51
- break
65
+ return [{ get: () => expr.object, set: (v) => { expr.object = v } }]
52
66
 
53
67
  case "IndexExpression":
54
- expr.object = mapExpression(expr.object, visitor)
55
- expr.index = mapExpression(expr.index, visitor)
56
- break
57
-
58
- case "CallExpression":
59
- expr.callee = mapExpression(expr.callee, visitor)
60
- visitArray(expr.arguments, visitor)
61
- break
62
-
63
- case "MethodCallExpression":
64
- expr.object = mapExpression(expr.object, visitor)
65
- visitArray(expr.arguments, visitor)
66
- break
68
+ return [
69
+ { get: () => expr.object, set: (v) => { expr.object = v } },
70
+ { get: () => expr.index, set: (v) => { expr.index = v } },
71
+ ]
72
+
73
+ case "CallExpression": {
74
+ const children: ChildAccessor[] = [
75
+ { get: () => expr.callee, set: (v) => { expr.callee = v } },
76
+ ]
77
+ for (let i = 0; i < expr.arguments.length; i++) {
78
+ const idx = i
79
+ children.push({
80
+ get: () => expr.arguments[idx],
81
+ set: (v) => { expr.arguments[idx] = v },
82
+ })
83
+ }
84
+ return children
85
+ }
86
+
87
+ case "MethodCallExpression": {
88
+ const children: ChildAccessor[] = [
89
+ { get: () => expr.object, set: (v) => { expr.object = v } },
90
+ ]
91
+ for (let i = 0; i < expr.arguments.length; i++) {
92
+ const idx = i
93
+ children.push({
94
+ get: () => expr.arguments[idx],
95
+ set: (v) => { expr.arguments[idx] = v },
96
+ })
97
+ }
98
+ return children
99
+ }
67
100
 
68
101
  case "ParenthesizedExpression":
69
- expr.expression = mapExpression(expr.expression, visitor)
70
- break
102
+ return [{ get: () => expr.expression, set: (v) => { expr.expression = v } }]
71
103
 
72
104
  case "TypeAssertionExpression":
73
- expr.expression = mapExpression(expr.expression, visitor)
74
- break
105
+ return [{ get: () => expr.expression, set: (v) => { expr.expression = v } }]
75
106
 
76
- case "IfElseExpression":
107
+ case "IfElseExpression": {
108
+ const children: ChildAccessor[] = []
77
109
  for (const clause of expr.clauses) {
78
- clause.condition = mapExpression(clause.condition, visitor)
79
- clause.body = mapExpression(clause.body, visitor)
110
+ children.push({ get: () => clause.condition, set: (v) => { clause.condition = v } })
111
+ children.push({ get: () => clause.body, set: (v) => { clause.body = v } })
112
+ }
113
+ children.push({ get: () => expr.alternate, set: (v) => { expr.alternate = v } })
114
+ return children
115
+ }
116
+
117
+ default:
118
+ return []
119
+ }
120
+ }
121
+
122
+ interface WalkFrame {
123
+ expr: Expression
124
+ children: ChildAccessor[]
125
+ index: number
126
+ setInParent: ((v: Expression) => void) | null
127
+ }
128
+
129
+ /**
130
+ * Expression 트리를 후위순회(post-order)로 변형한다.
131
+ *
132
+ * 원래는 재귀 함수였지만, 문자열/숫자 난독화 패스가 만들어내는 매우 깊은
133
+ * BinaryExpression 체인(예: 수천 개의 `..` concat)을 순회할 때 네이티브
134
+ * 콜스택이 트리 깊이만큼 쌓여 "Maximum call stack size exceeded"가
135
+ * 발생했다. 그래서 재귀 대신 힙에 할당되는 명시적 스택을 사용해
136
+ * 트리 깊이와 무관하게 동작하도록 구현했다.
137
+ */
138
+ export function mapExpression(root: Expression, visitor: ExpressionVisitor): Expression {
139
+ // FunctionExpression은 본문(statement 트리)을 별도로 순회해야 하므로 특별 취급한다.
140
+ // 함수 중첩 깊이는 보통 얕아서(재귀해도 안전) 그대로 재귀를 사용한다.
141
+ if (root.type === "FunctionExpression") {
142
+ walkFunctionBody(root.func, visitor)
143
+ return visitor(root) ?? root
144
+ }
145
+
146
+ let result: Expression = root
147
+ const stack: WalkFrame[] = [{
148
+ expr: root,
149
+ children: getExpressionChildren(root),
150
+ index: 0,
151
+ setInParent: (v) => { result = v },
152
+ }]
153
+
154
+ while (stack.length > 0) {
155
+ const frame = stack[stack.length - 1]
156
+
157
+ if (frame.index < frame.children.length) {
158
+ const child = frame.children[frame.index]
159
+ frame.index++
160
+ const childExpr = child.get()
161
+
162
+ if (childExpr.type === "FunctionExpression") {
163
+ walkFunctionBody(childExpr.func, visitor)
164
+ child.set(visitor(childExpr) ?? childExpr)
165
+ continue
80
166
  }
81
- expr.alternate = mapExpression(expr.alternate, visitor)
82
- break
167
+
168
+ stack.push({
169
+ expr: childExpr,
170
+ children: getExpressionChildren(childExpr),
171
+ index: 0,
172
+ setInParent: child.set,
173
+ })
174
+ continue
175
+ }
176
+
177
+ // 모든 자식 처리가 끝났으면 visitor를 실행하고, 부모에 반영한 뒤 pop한다.
178
+ const finished = visitor(frame.expr) ?? frame.expr
179
+ frame.setInParent?.(finished)
180
+ stack.pop()
83
181
  }
84
182
 
85
- return visitor(expr) ?? expr
183
+ return result
86
184
  }
87
185
 
88
186
  function walkFunctionBody(func: FunctionBody, visitor: ExpressionVisitor): void {
@@ -170,4 +268,4 @@ function walkStatement(stmt: Statement, visitor: ExpressionVisitor): void {
170
268
  /** Program 전체를 순회하며 모든 Expression 노드에 visitor를 적용(제자리 변형). */
171
269
  export function transformExpressions(program: Program, visitor: ExpressionVisitor): void {
172
270
  walkBlock(program.body, visitor)
173
- }
271
+ }
package/src/pipeline.ts CHANGED
@@ -10,19 +10,20 @@ import { runEncryptStrings } from "./passes/EncryptStrings"
10
10
  import { runEncryptNumbers } from "./passes/EncryptNumbers"
11
11
  import { runInsertJunk } from "./passes/InsertJunk"
12
12
  import { runWrapInFunction } from "./passes/WrapInFunction"
13
+ import { runVmify } from "./passes/Vmify"
13
14
 
14
15
  type PassFn = (program: Program, options: any) => void
15
16
 
16
17
  export const PASS_ORDER: (keyof ObfuscateConfig)[] = [
18
+ "Vmify",
17
19
  "GlobalMapping",
18
- "StringsToExpressions",
19
- "NumbersToExpressions",
20
20
  "RenameVariables",
21
21
  "ConstantArray",
22
+ "StringsToExpressions",
23
+ "NumbersToExpressions",
22
24
  "EncryptStrings",
23
25
  "EncryptNumbers",
24
26
  "InsertJunk",
25
- "Vmify",
26
27
  "WrapInFunction",
27
28
  "Minify",
28
29
  ]
@@ -37,12 +38,10 @@ export const PASS_MAP: Partial<Record<keyof ObfuscateConfig, PassFn>> = {
37
38
  EncryptNumbers: runEncryptNumbers,
38
39
  InsertJunk: runInsertJunk,
39
40
  WrapInFunction: runWrapInFunction,
41
+ Vmify: runVmify,
40
42
  }
41
43
 
42
44
  export function runPipeline(program: Program, config: ObfuscateConfig): void {
43
- // 타입 주석/별칭은 값 트리와 독립적으로 원본 이름을 참조하고 있어서
44
- // (예: typeof(x)) 어떤 pass보다도 먼저 지워야 함. 끄면 무조건 깨지므로
45
- // config로 조절 가능한 옵션이 아니라 파이프라인 진입 시 항상 실행.
46
45
  runStripTypes(program)
47
46
 
48
47
  for (const key of PASS_ORDER) {
package/tsconfig.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "ESNext",
5
- "lib": ["ESNext", "DOM", "DOM.Iterable"],
6
- "declaration": false,
7
- "declarationMap": false,
8
- "sourceMap": false,
9
- "outDir": "./dist",
10
- "rootDir": "./src",
11
- "moduleResolution": "bundler",
12
- "allowSyntheticDefaultImports": true,
13
- "esModuleInterop": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "strict": true,
16
- "skipLibCheck": true,
17
- "stripInternal": true,
18
- },
19
- "include": ["src/**/*"],
20
- "exclude": ["node_modules", "dist"]
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
6
+ "declaration": false,
7
+ "declarationMap": false,
8
+ "sourceMap": false,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "moduleResolution": "bundler",
12
+ "allowSyntheticDefaultImports": true,
13
+ "esModuleInterop": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "strict": true,
16
+ "skipLibCheck": true,
17
+ "stripInternal": true,
18
+ },
19
+ "include": ["src/**/*"],
20
+ "exclude": ["node_modules", "dist"]
21
21
  }
package/tsup.config.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts"],
5
- format: ["esm", "cjs"],
6
- dts: true,
7
- clean: true,
8
- sourcemap: false,
9
- target: "esnext",
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ format: ["esm", "cjs"],
6
+ dts: true,
7
+ clean: true,
8
+ sourcemap: false,
9
+ target: "esnext",
10
10
  });