@ecrindigital/facetpack 0.1.1

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.
package/dist/index.js ADDED
@@ -0,0 +1,302 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
4
+ // src/transformer.ts
5
+ import { transformSync, JsxRuntime, resolveBatchSync } from "@ecrindigital/facetpack-native";
6
+ import { parse } from "@babel/parser";
7
+
8
+ // src/cache.ts
9
+ var resolutionCache = new Map;
10
+ var CACHE_TTL = 30000;
11
+ function setCachedResolutions(originModulePath, resolutions) {
12
+ const now = Date.now();
13
+ const cached = new Map;
14
+ for (const [specifier, path] of resolutions) {
15
+ cached.set(specifier, { path, timestamp: now });
16
+ }
17
+ resolutionCache.set(originModulePath, cached);
18
+ }
19
+ function getCachedResolution(originModulePath, specifier) {
20
+ const fileCache = resolutionCache.get(originModulePath);
21
+ if (!fileCache)
22
+ return;
23
+ const cached = fileCache.get(specifier);
24
+ if (!cached)
25
+ return;
26
+ if (Date.now() - cached.timestamp > CACHE_TTL) {
27
+ fileCache.delete(specifier);
28
+ return;
29
+ }
30
+ return cached.path;
31
+ }
32
+ function clearCache() {
33
+ resolutionCache.clear();
34
+ }
35
+ function getCacheStats() {
36
+ let resolutions = 0;
37
+ for (const fileCache of resolutionCache.values()) {
38
+ resolutions += fileCache.size;
39
+ }
40
+ return { files: resolutionCache.size, resolutions };
41
+ }
42
+
43
+ // src/transformer.ts
44
+ var IMPORT_REGEX = /(?:import|export)\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"]+)['"]/g;
45
+ var REQUIRE_REGEX = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
46
+ function extractSpecifiers(code) {
47
+ const specifiers = new Set;
48
+ let match;
49
+ while ((match = IMPORT_REGEX.exec(code)) !== null) {
50
+ if (match[1])
51
+ specifiers.add(match[1]);
52
+ }
53
+ while ((match = REQUIRE_REGEX.exec(code)) !== null) {
54
+ if (match[1])
55
+ specifiers.add(match[1]);
56
+ }
57
+ return Array.from(specifiers);
58
+ }
59
+ function preResolveImports(filename, code, sourceExts) {
60
+ const specifiers = extractSpecifiers(code);
61
+ if (specifiers.length === 0)
62
+ return;
63
+ const directory = filename.substring(0, filename.lastIndexOf("/"));
64
+ const results = resolveBatchSync(directory, specifiers, {
65
+ extensions: [...sourceExts.map((ext) => `.${ext}`), ".json"],
66
+ mainFields: ["react-native", "browser", "main"],
67
+ conditionNames: ["react-native", "import", "require"]
68
+ });
69
+ const resolutions = new Map;
70
+ for (let i = 0;i < specifiers.length; i++) {
71
+ const specifier = specifiers[i];
72
+ if (specifier) {
73
+ resolutions.set(specifier, results[i]?.path ?? null);
74
+ }
75
+ }
76
+ setCachedResolutions(filename, resolutions);
77
+ }
78
+ var defaultOptions = {
79
+ jsx: true,
80
+ jsxRuntime: "automatic",
81
+ jsxImportSource: "react",
82
+ jsxPragma: "React.createElement",
83
+ jsxPragmaFrag: "React.Fragment",
84
+ typescript: true,
85
+ sourceExts: ["ts", "tsx", "js", "jsx", "mjs", "cjs"]
86
+ };
87
+ var globalOptions = {};
88
+ var fallbackTransformer = null;
89
+ function getFallbackTransformer() {
90
+ if (fallbackTransformer) {
91
+ return fallbackTransformer;
92
+ }
93
+ const transformerPaths = [
94
+ "@expo/metro-config/babel-transformer",
95
+ "@react-native/metro-babel-transformer",
96
+ "metro-react-native-babel-transformer"
97
+ ];
98
+ for (const transformerPath of transformerPaths) {
99
+ try {
100
+ fallbackTransformer = __require(transformerPath);
101
+ return fallbackTransformer;
102
+ } catch {}
103
+ }
104
+ fallbackTransformer = {
105
+ transform: ({ src }) => ({ code: src, map: null })
106
+ };
107
+ return fallbackTransformer;
108
+ }
109
+ function setTransformerOptions(options) {
110
+ globalOptions = options;
111
+ }
112
+ function getOptions() {
113
+ return { ...defaultOptions, ...globalOptions };
114
+ }
115
+ function isNodeModules(filename) {
116
+ return filename.includes("node_modules");
117
+ }
118
+ function shouldTransform(filename, options) {
119
+ if (isNodeModules(filename)) {
120
+ return false;
121
+ }
122
+ const ext = filename.split(".").pop()?.toLowerCase();
123
+ if (!ext)
124
+ return false;
125
+ return options.sourceExts.includes(ext);
126
+ }
127
+ function transform(params) {
128
+ const { filename, src, options: metroOptions } = params;
129
+ const opts = getOptions();
130
+ if (process.env.FACETPACK_DEBUG) {
131
+ console.log(`[Facetpack] Processing: ${filename}`);
132
+ }
133
+ if (!shouldTransform(filename, opts)) {
134
+ if (process.env.FACETPACK_DEBUG) {
135
+ console.log(`[Facetpack] Fallback: ${filename}`);
136
+ }
137
+ return getFallbackTransformer().transform(params);
138
+ }
139
+ if (process.env.FACETPACK_DEBUG) {
140
+ console.log(`[Facetpack] OXC Transform: ${filename}`);
141
+ }
142
+ try {
143
+ const isClassic = opts.jsxRuntime === "classic";
144
+ const result = transformSync(filename, src, {
145
+ jsx: opts.jsx,
146
+ jsxRuntime: isClassic ? JsxRuntime.Classic : JsxRuntime.Automatic,
147
+ ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
148
+ typescript: opts.typescript,
149
+ sourcemap: metroOptions.dev
150
+ });
151
+ if (result.errors.length > 0) {
152
+ const errorMessage = result.errors.join(`
153
+ `);
154
+ throw new Error(`Facetpack transform error in ${filename}:
155
+ ${errorMessage}`);
156
+ }
157
+ preResolveImports(filename, result.code, opts.sourceExts);
158
+ const ast = parse(result.code, {
159
+ sourceType: "unambiguous",
160
+ plugins: ["jsx"]
161
+ });
162
+ const output = {
163
+ ast,
164
+ code: result.code,
165
+ map: result.map ? JSON.parse(result.map) : null
166
+ };
167
+ if (process.env.FACETPACK_DEBUG) {
168
+ console.log(`[Facetpack] Output for ${filename}:`);
169
+ console.log(result.code.slice(0, 500));
170
+ }
171
+ return output;
172
+ } catch (error) {
173
+ if (error instanceof Error) {
174
+ error.message = `[Facetpack] ${error.message}`;
175
+ }
176
+ throw error;
177
+ }
178
+ }
179
+ function createTransformer(options = {}) {
180
+ const opts = { ...defaultOptions, ...options };
181
+ return {
182
+ transform(params) {
183
+ const { filename, src, options: metroOptions } = params;
184
+ if (!shouldTransform(filename, opts)) {
185
+ return getFallbackTransformer().transform(params);
186
+ }
187
+ const isClassic = opts.jsxRuntime === "classic";
188
+ const result = transformSync(filename, src, {
189
+ jsx: opts.jsx,
190
+ jsxRuntime: isClassic ? JsxRuntime.Classic : JsxRuntime.Automatic,
191
+ ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
192
+ typescript: opts.typescript,
193
+ sourcemap: metroOptions.dev
194
+ });
195
+ if (result.errors.length > 0) {
196
+ throw new Error(`Facetpack transform error in ${filename}:
197
+ ${result.errors.join(`
198
+ `)}`);
199
+ }
200
+ return {
201
+ code: result.code,
202
+ map: result.map ? JSON.parse(result.map) : null
203
+ };
204
+ }
205
+ };
206
+ }
207
+
208
+ // src/withFacetpack.ts
209
+ import { resolveSync } from "@ecrindigital/facetpack-native";
210
+ import { dirname, join } from "path";
211
+ import { fileURLToPath } from "url";
212
+ var DEFAULT_SOURCE_EXTS = ["ts", "tsx", "js", "jsx", "mjs", "cjs"];
213
+ var __filename2 = fileURLToPath(import.meta.url);
214
+ var __dirname2 = dirname(__filename2);
215
+ function withFacetpack(config, options = {}) {
216
+ const sourceExts = options.sourceExts ?? DEFAULT_SOURCE_EXTS;
217
+ const transformerPath = join(__dirname2, "transformer.js");
218
+ storeTransformerOptions(options);
219
+ return {
220
+ ...config,
221
+ transformer: {
222
+ ...config.transformer,
223
+ babelTransformerPath: transformerPath,
224
+ getTransformOptions: async (entryPoints, opts, getDepsOf) => {
225
+ const baseOptions = await config.transformer?.getTransformOptions?.(entryPoints, opts, getDepsOf);
226
+ return {
227
+ ...baseOptions,
228
+ transform: {
229
+ ...baseOptions?.transform,
230
+ experimentalImportSupport: true,
231
+ inlineRequires: true
232
+ }
233
+ };
234
+ }
235
+ },
236
+ resolver: {
237
+ ...config.resolver,
238
+ sourceExts: [
239
+ ...new Set([
240
+ ...config.resolver?.sourceExts ?? [],
241
+ ...sourceExts
242
+ ])
243
+ ],
244
+ resolveRequest: (context, moduleName, platform) => {
245
+ if (context.originModulePath.includes("node_modules")) {
246
+ return context.resolveRequest(context, moduleName, platform);
247
+ }
248
+ const cached = getCachedResolution(context.originModulePath, moduleName);
249
+ if (cached !== undefined) {
250
+ if (cached) {
251
+ return { type: "sourceFile", filePath: cached };
252
+ }
253
+ return context.resolveRequest(context, moduleName, platform);
254
+ }
255
+ const directory = context.originModulePath.substring(0, context.originModulePath.lastIndexOf("/"));
256
+ const result = resolveSync(directory, moduleName, {
257
+ extensions: [...sourceExts.map((ext) => `.${ext}`), ".json"],
258
+ mainFields: ["react-native", "browser", "main"],
259
+ conditionNames: ["react-native", "import", "require"]
260
+ });
261
+ if (result.path) {
262
+ return { type: "sourceFile", filePath: result.path };
263
+ }
264
+ return context.resolveRequest(context, moduleName, platform);
265
+ }
266
+ }
267
+ };
268
+ }
269
+ function storeTransformerOptions(options) {
270
+ process.env.FACETPACK_OPTIONS = JSON.stringify(options);
271
+ }
272
+ function getStoredOptions() {
273
+ try {
274
+ const optionsJson = process.env.FACETPACK_OPTIONS;
275
+ if (optionsJson) {
276
+ return JSON.parse(optionsJson);
277
+ }
278
+ } catch {}
279
+ return {};
280
+ }
281
+ // src/resolver.ts
282
+ import { resolveSync as resolveSync2 } from "@ecrindigital/facetpack-native";
283
+ function createResolver(options) {
284
+ return {
285
+ resolve(originModulePath, moduleName) {
286
+ const directory = originModulePath.substring(0, originModulePath.lastIndexOf("/"));
287
+ const result = resolveSync2(directory, moduleName, options);
288
+ return result.path ?? null;
289
+ }
290
+ };
291
+ }
292
+ export {
293
+ withFacetpack,
294
+ transform,
295
+ setTransformerOptions,
296
+ resolveSync2 as resolveSync,
297
+ getStoredOptions,
298
+ getCacheStats,
299
+ createTransformer,
300
+ createResolver,
301
+ clearCache
302
+ };
@@ -0,0 +1,6 @@
1
+ import { resolveSync, type ResolverOptions } from '@ecrindigital/facetpack-native';
2
+ export { resolveSync, type ResolverOptions };
3
+ export declare function createResolver(options?: ResolverOptions): {
4
+ resolve(originModulePath: string, moduleName: string): string | null;
5
+ };
6
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAElF,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,CAAA;AAE5C,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe;8BAE1B,MAAM,cAAc,MAAM,GAAG,MAAM,GAAG,IAAI;EAMvE"}
@@ -0,0 +1,214 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ var __toCommonJS = (from) => {
7
+ var entry = __moduleCache.get(from), desc;
8
+ if (entry)
9
+ return entry;
10
+ entry = __defProp({}, "__esModule", { value: true });
11
+ if (from && typeof from === "object" || typeof from === "function")
12
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
+ get: () => from[key],
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ }));
16
+ __moduleCache.set(from, entry);
17
+ return entry;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+
29
+ // src/transformer.ts
30
+ var exports_transformer = {};
31
+ __export(exports_transformer, {
32
+ transform: () => transform,
33
+ setTransformerOptions: () => setTransformerOptions,
34
+ createTransformer: () => createTransformer
35
+ });
36
+ module.exports = __toCommonJS(exports_transformer);
37
+ var import_facetpack_native = require("@ecrindigital/facetpack-native");
38
+ var import_parser = require("@babel/parser");
39
+
40
+ // src/cache.ts
41
+ var resolutionCache = new Map;
42
+ function setCachedResolutions(originModulePath, resolutions) {
43
+ const now = Date.now();
44
+ const cached = new Map;
45
+ for (const [specifier, path] of resolutions) {
46
+ cached.set(specifier, { path, timestamp: now });
47
+ }
48
+ resolutionCache.set(originModulePath, cached);
49
+ }
50
+
51
+ // src/transformer.ts
52
+ var IMPORT_REGEX = /(?:import|export)\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"]+)['"]/g;
53
+ var REQUIRE_REGEX = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
54
+ function extractSpecifiers(code) {
55
+ const specifiers = new Set;
56
+ let match;
57
+ while ((match = IMPORT_REGEX.exec(code)) !== null) {
58
+ if (match[1])
59
+ specifiers.add(match[1]);
60
+ }
61
+ while ((match = REQUIRE_REGEX.exec(code)) !== null) {
62
+ if (match[1])
63
+ specifiers.add(match[1]);
64
+ }
65
+ return Array.from(specifiers);
66
+ }
67
+ function preResolveImports(filename, code, sourceExts) {
68
+ const specifiers = extractSpecifiers(code);
69
+ if (specifiers.length === 0)
70
+ return;
71
+ const directory = filename.substring(0, filename.lastIndexOf("/"));
72
+ const results = import_facetpack_native.resolveBatchSync(directory, specifiers, {
73
+ extensions: [...sourceExts.map((ext) => `.${ext}`), ".json"],
74
+ mainFields: ["react-native", "browser", "main"],
75
+ conditionNames: ["react-native", "import", "require"]
76
+ });
77
+ const resolutions = new Map;
78
+ for (let i = 0;i < specifiers.length; i++) {
79
+ const specifier = specifiers[i];
80
+ if (specifier) {
81
+ resolutions.set(specifier, results[i]?.path ?? null);
82
+ }
83
+ }
84
+ setCachedResolutions(filename, resolutions);
85
+ }
86
+ var defaultOptions = {
87
+ jsx: true,
88
+ jsxRuntime: "automatic",
89
+ jsxImportSource: "react",
90
+ jsxPragma: "React.createElement",
91
+ jsxPragmaFrag: "React.Fragment",
92
+ typescript: true,
93
+ sourceExts: ["ts", "tsx", "js", "jsx", "mjs", "cjs"]
94
+ };
95
+ var globalOptions = {};
96
+ var fallbackTransformer = null;
97
+ function getFallbackTransformer() {
98
+ if (fallbackTransformer) {
99
+ return fallbackTransformer;
100
+ }
101
+ const transformerPaths = [
102
+ "@expo/metro-config/babel-transformer",
103
+ "@react-native/metro-babel-transformer",
104
+ "metro-react-native-babel-transformer"
105
+ ];
106
+ for (const transformerPath of transformerPaths) {
107
+ try {
108
+ fallbackTransformer = require(transformerPath);
109
+ return fallbackTransformer;
110
+ } catch {}
111
+ }
112
+ fallbackTransformer = {
113
+ transform: ({ src }) => ({ code: src, map: null })
114
+ };
115
+ return fallbackTransformer;
116
+ }
117
+ function setTransformerOptions(options) {
118
+ globalOptions = options;
119
+ }
120
+ function getOptions() {
121
+ return { ...defaultOptions, ...globalOptions };
122
+ }
123
+ function isNodeModules(filename) {
124
+ return filename.includes("node_modules");
125
+ }
126
+ function shouldTransform(filename, options) {
127
+ if (isNodeModules(filename)) {
128
+ return false;
129
+ }
130
+ const ext = filename.split(".").pop()?.toLowerCase();
131
+ if (!ext)
132
+ return false;
133
+ return options.sourceExts.includes(ext);
134
+ }
135
+ function transform(params) {
136
+ const { filename, src, options: metroOptions } = params;
137
+ const opts = getOptions();
138
+ if (process.env.FACETPACK_DEBUG) {
139
+ console.log(`[Facetpack] Processing: ${filename}`);
140
+ }
141
+ if (!shouldTransform(filename, opts)) {
142
+ if (process.env.FACETPACK_DEBUG) {
143
+ console.log(`[Facetpack] Fallback: ${filename}`);
144
+ }
145
+ return getFallbackTransformer().transform(params);
146
+ }
147
+ if (process.env.FACETPACK_DEBUG) {
148
+ console.log(`[Facetpack] OXC Transform: ${filename}`);
149
+ }
150
+ try {
151
+ const isClassic = opts.jsxRuntime === "classic";
152
+ const result = import_facetpack_native.transformSync(filename, src, {
153
+ jsx: opts.jsx,
154
+ jsxRuntime: isClassic ? import_facetpack_native.JsxRuntime.Classic : import_facetpack_native.JsxRuntime.Automatic,
155
+ ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
156
+ typescript: opts.typescript,
157
+ sourcemap: metroOptions.dev
158
+ });
159
+ if (result.errors.length > 0) {
160
+ const errorMessage = result.errors.join(`
161
+ `);
162
+ throw new Error(`Facetpack transform error in ${filename}:
163
+ ${errorMessage}`);
164
+ }
165
+ preResolveImports(filename, result.code, opts.sourceExts);
166
+ const ast = import_parser.parse(result.code, {
167
+ sourceType: "unambiguous",
168
+ plugins: ["jsx"]
169
+ });
170
+ const output = {
171
+ ast,
172
+ code: result.code,
173
+ map: result.map ? JSON.parse(result.map) : null
174
+ };
175
+ if (process.env.FACETPACK_DEBUG) {
176
+ console.log(`[Facetpack] Output for ${filename}:`);
177
+ console.log(result.code.slice(0, 500));
178
+ }
179
+ return output;
180
+ } catch (error) {
181
+ if (error instanceof Error) {
182
+ error.message = `[Facetpack] ${error.message}`;
183
+ }
184
+ throw error;
185
+ }
186
+ }
187
+ function createTransformer(options = {}) {
188
+ const opts = { ...defaultOptions, ...options };
189
+ return {
190
+ transform(params) {
191
+ const { filename, src, options: metroOptions } = params;
192
+ if (!shouldTransform(filename, opts)) {
193
+ return getFallbackTransformer().transform(params);
194
+ }
195
+ const isClassic = opts.jsxRuntime === "classic";
196
+ const result = import_facetpack_native.transformSync(filename, src, {
197
+ jsx: opts.jsx,
198
+ jsxRuntime: isClassic ? import_facetpack_native.JsxRuntime.Classic : import_facetpack_native.JsxRuntime.Automatic,
199
+ ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
200
+ typescript: opts.typescript,
201
+ sourcemap: metroOptions.dev
202
+ });
203
+ if (result.errors.length > 0) {
204
+ throw new Error(`Facetpack transform error in ${filename}:
205
+ ${result.errors.join(`
206
+ `)}`);
207
+ }
208
+ return {
209
+ code: result.code,
210
+ map: result.map ? JSON.parse(result.map) : null
211
+ };
212
+ }
213
+ };
214
+ }
@@ -0,0 +1,7 @@
1
+ import type { TransformParams, TransformResult, FacetpackOptions } from './types';
2
+ export declare function setTransformerOptions(options: FacetpackOptions): void;
3
+ export declare function transform(params: TransformParams): TransformResult;
4
+ export declare function createTransformer(options?: FacetpackOptions): {
5
+ transform(params: TransformParams): TransformResult;
6
+ };
7
+ //# sourceMappingURL=transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../src/transformer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAwFjF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAErE;AAoBD,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CA6DlE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,gBAAqB;sBAI1C,eAAe,GAAG,eAAe;EA4BtD"}