@teleporthq/teleport-shared 0.43.59 → 0.43.61
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/__tests__/utils/local-imports.ts +174 -0
- package/__tests__/utils/page-dependencies-prefix.ts +89 -0
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils/generic.d.ts +46 -0
- package/dist/cjs/utils/generic.d.ts.map +1 -1
- package/dist/cjs/utils/generic.js +67 -1
- package/dist/cjs/utils/generic.js.map +1 -1
- package/dist/cjs/utils/local-imports.d.ts +48 -0
- package/dist/cjs/utils/local-imports.d.ts.map +1 -0
- package/dist/cjs/utils/local-imports.js +168 -0
- package/dist/cjs/utils/local-imports.js.map +1 -0
- package/dist/cjs/utils/product-discounts.d.ts +27 -0
- package/dist/cjs/utils/product-discounts.d.ts.map +1 -0
- package/dist/cjs/utils/product-discounts.js +31 -0
- package/dist/cjs/utils/product-discounts.js.map +1 -0
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils/generic.d.ts +46 -0
- package/dist/esm/utils/generic.d.ts.map +1 -1
- package/dist/esm/utils/generic.js +64 -0
- package/dist/esm/utils/generic.js.map +1 -1
- package/dist/esm/utils/local-imports.d.ts +48 -0
- package/dist/esm/utils/local-imports.d.ts.map +1 -0
- package/dist/esm/utils/local-imports.js +161 -0
- package/dist/esm/utils/local-imports.js.map +1 -0
- package/dist/esm/utils/product-discounts.d.ts +27 -0
- package/dist/esm/utils/product-discounts.d.ts.map +1 -0
- package/dist/esm/utils/product-discounts.js +27 -0
- package/dist/esm/utils/product-discounts.js.map +1 -0
- package/package.json +3 -3
- package/src/index.ts +4 -0
- package/src/utils/generic.ts +57 -0
- package/src/utils/local-imports.ts +226 -0
- package/src/utils/product-discounts.ts +122 -0
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
14
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
15
|
+
if (ar || !(i in from)) {
|
|
16
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
17
|
+
ar[i] = from[i];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
21
|
+
};
|
|
2
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getValueFromPath = exports.dynamicPathExistsInDefinitions = exports.generateLocalDependenciesPrefix = exports.localRelativePath = void 0;
|
|
23
|
+
exports.getValueFromPath = exports.dynamicPathExistsInDefinitions = exports.generatePageToRootPrefix = exports.generatePageDependenciesPrefix = exports.DEFAULT_PAGES_PATH = exports.generateLocalDependenciesPrefix = exports.localRelativePath = void 0;
|
|
4
24
|
var path_1 = require("path");
|
|
5
25
|
/**
|
|
6
26
|
* `path.relative()`-equivalent that is correct regardless of which `path`
|
|
@@ -67,6 +87,52 @@ var generateLocalDependenciesPrefix = function (fromPath, toPath) {
|
|
|
67
87
|
return dependencyPrefix;
|
|
68
88
|
};
|
|
69
89
|
exports.generateLocalDependenciesPrefix = generateLocalDependenciesPrefix;
|
|
90
|
+
/**
|
|
91
|
+
* The folder every framework-agnostic page path in this repo is relative to by
|
|
92
|
+
* default. Next.js is the only target that emits pages through the plugins
|
|
93
|
+
* below, and its pages root is `pages/` (see the `pages.path` of the strategy
|
|
94
|
+
* in teleport-project-generator-next). Used only as a fallback for callers that
|
|
95
|
+
* do not receive `GeneratorOptions.pagesPath`.
|
|
96
|
+
*/
|
|
97
|
+
exports.DEFAULT_PAGES_PATH = ['pages'];
|
|
98
|
+
/**
|
|
99
|
+
* Import prefix from a PAGE file to a folder that lives at the PROJECT ROOT
|
|
100
|
+
* (`resources/`, `utils/`, `components/` ...). Returns a prefix ending in '/',
|
|
101
|
+
* so callers append the file name: `${prefix}${fileName}`.
|
|
102
|
+
*
|
|
103
|
+
* ⛔ A page's `outputOptions.folderPath` is relative to the PAGES ROOT
|
|
104
|
+
* (`['resources']` for `pages/resources/[id].js`), while every folder path in
|
|
105
|
+
* the project strategy is relative to the PROJECT ROOT. Handing those two
|
|
106
|
+
* coordinate systems to a single `path.relative()` call cancels segments that
|
|
107
|
+
* only LOOK common: `relative('/resources/[id]', '/resources/fetch_items')`
|
|
108
|
+
* returned `'../fetch_items'`, which resolves to `pages/fetch_items` — a
|
|
109
|
+
* "Module not found: Can't resolve '../fetch_items'" at `next build` time for
|
|
110
|
+
* every page whose folder happens to be named after a root folder (a
|
|
111
|
+
* `/resources/[id]` route against the `resources/` folder, a `/utils/[id]` one
|
|
112
|
+
* against `utils/`, ...). Every other page built fine, which is exactly why it
|
|
113
|
+
* survived so long.
|
|
114
|
+
*
|
|
115
|
+
* Rebasing the page folder onto the pages root puts both sides in the same
|
|
116
|
+
* coordinate system, so only genuinely shared ancestors are cancelled. The math
|
|
117
|
+
* runs through `generateLocalDependenciesPrefix` — plain array bookkeeping, no
|
|
118
|
+
* `path.relative()` — so it is also immune to the truncated `relative()` that
|
|
119
|
+
* Next's compiled `path-browserify` ships (see `localRelativePath` above).
|
|
120
|
+
*/
|
|
121
|
+
var generatePageDependenciesPrefix = function (params) {
|
|
122
|
+
var toPath = params.toPath, folderPath = params.folderPath, pagesPath = params.pagesPath;
|
|
123
|
+
// `folderPath` comes straight out of the UIDL, where it can be absent (or a
|
|
124
|
+
// JSON null) for a page at the pages root — never let that throw on a spread.
|
|
125
|
+
return (0, exports.generateLocalDependenciesPrefix)(__spreadArray(__spreadArray([], (pagesPath || exports.DEFAULT_PAGES_PATH), true), (folderPath || []), true), toPath);
|
|
126
|
+
};
|
|
127
|
+
exports.generatePageDependenciesPrefix = generatePageDependenciesPrefix;
|
|
128
|
+
/**
|
|
129
|
+
* Prefix from a PAGE file back to the PROJECT ROOT ('../', '../../', ...), for
|
|
130
|
+
* callers that build the rest of the path themselves
|
|
131
|
+
* (`${prefix}utils/workflows/runtime`). Same coordinate-system correction as
|
|
132
|
+
* `generatePageDependenciesPrefix`, which it delegates to.
|
|
133
|
+
*/
|
|
134
|
+
var generatePageToRootPrefix = function (params) { return (0, exports.generatePageDependenciesPrefix)(__assign(__assign({}, params), { toPath: [] })); };
|
|
135
|
+
exports.generatePageToRootPrefix = generatePageToRootPrefix;
|
|
70
136
|
var removeCommonStartingPointsFromPaths = function (paths) {
|
|
71
137
|
var pathsClone = JSON.parse(JSON.stringify(paths));
|
|
72
138
|
var shortestPathLength = Math.min.apply(Math, pathsClone.map(function (path) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic.js","sourceRoot":"","sources":["../../../src/utils/generic.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generic.js","sourceRoot":"","sources":["../../../src/utils/generic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { GeneratedFolder } from '@teleporthq/teleport-types';
|
|
2
|
+
/**
|
|
3
|
+
* Safety net for the whole family of "Module not found" build breaks: a plugin
|
|
4
|
+
* emits a relative import whose specifier points at a file the generator never
|
|
5
|
+
* writes. The generated project still LOOKS fine — the defect only surfaces
|
|
6
|
+
* when `next build` (or Vercel) compiles the page, which is far away from the
|
|
7
|
+
* code that computed the path.
|
|
8
|
+
*
|
|
9
|
+
* The one that motivated this module: a page in `pages/resources/` importing
|
|
10
|
+
* from the project's root `resources/` folder collapsed to `../fetch_items`
|
|
11
|
+
* because the page-relative and root-relative folder paths were mixed in a
|
|
12
|
+
* single `path.relative()` call (fixed at the source — see
|
|
13
|
+
* `generatePageDependenciesPrefix` in ./generic). Nothing in the pipeline
|
|
14
|
+
* noticed, so the check below runs over the finished file tree and reports
|
|
15
|
+
* every relative specifier that resolves to no generated file.
|
|
16
|
+
*
|
|
17
|
+
* Report-only by design: a false positive (a string literal that merely looks
|
|
18
|
+
* like an import) must never be able to fail a generation or, worse, rewrite
|
|
19
|
+
* someone's code.
|
|
20
|
+
*/
|
|
21
|
+
/** One generated file, addressed by its PROJECT-ROOT-relative path. */
|
|
22
|
+
export interface ProjectFileEntry {
|
|
23
|
+
/** e.g. `pages/resources/[id].js` — always '/'-separated, no leading slash. */
|
|
24
|
+
path: string;
|
|
25
|
+
content: string;
|
|
26
|
+
}
|
|
27
|
+
export interface UnresolvedLocalImport {
|
|
28
|
+
/** Project-root-relative path of the file holding the import. */
|
|
29
|
+
filePath: string;
|
|
30
|
+
/** The specifier exactly as it appears in the source. */
|
|
31
|
+
specifier: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Flatten a generated project into project-root-relative file entries. The root
|
|
35
|
+
* folder's own name is the project directory itself, so it is not part of any
|
|
36
|
+
* path.
|
|
37
|
+
*/
|
|
38
|
+
export declare const collectProjectFiles: (folder: GeneratedFolder) => ProjectFileEntry[];
|
|
39
|
+
/**
|
|
40
|
+
* Every relative import in `files` that resolves to no file in `files`.
|
|
41
|
+
* Deterministically ordered (file, then specifier) so callers can snapshot it.
|
|
42
|
+
*/
|
|
43
|
+
export declare const findUnresolvedLocalImports: (files: ProjectFileEntry[]) => UnresolvedLocalImport[];
|
|
44
|
+
/** `findUnresolvedLocalImports` over a generated project folder. */
|
|
45
|
+
export declare const findUnresolvedLocalImportsInProject: (folder: GeneratedFolder) => UnresolvedLocalImport[];
|
|
46
|
+
/** Human-readable report. Returns an empty string when there is nothing to report. */
|
|
47
|
+
export declare const formatUnresolvedLocalImports: (unresolved: UnresolvedLocalImport[]) => string;
|
|
48
|
+
//# sourceMappingURL=local-imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-imports.d.ts","sourceRoot":"","sources":["../../../src/utils/local-imports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAE3E;;;;;;;;;;;;;;;;;;GAkBG;AAEH,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;CAClB;AAkHD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,WAAY,eAAe,KAAG,gBAAgB,EAmB7E,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,UAAW,gBAAgB,EAAE,KAAG,qBAAqB,EA2B3F,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,mCAAmC,WACtC,eAAe,KACtB,qBAAqB,EAA6D,CAAA;AAErF,sFAAsF;AACtF,eAAO,MAAM,4BAA4B,eAAgB,qBAAqB,EAAE,KAAG,MAYlF,CAAA"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatUnresolvedLocalImports = exports.findUnresolvedLocalImportsInProject = exports.findUnresolvedLocalImports = exports.collectProjectFiles = void 0;
|
|
4
|
+
/** File types whose contents are parsed for import specifiers. */
|
|
5
|
+
var SCANNED_EXTENSIONS = ['js', 'jsx', 'mjs', 'cjs', 'ts', 'tsx'];
|
|
6
|
+
/**
|
|
7
|
+
* Extensions a bundler appends to an extensionless specifier. The empty string
|
|
8
|
+
* comes first so a specifier that already carries its extension (`./style.css`)
|
|
9
|
+
* matches as-is.
|
|
10
|
+
*/
|
|
11
|
+
var RESOLVED_EXTENSIONS = [
|
|
12
|
+
'',
|
|
13
|
+
'.js',
|
|
14
|
+
'.jsx',
|
|
15
|
+
'.mjs',
|
|
16
|
+
'.cjs',
|
|
17
|
+
'.ts',
|
|
18
|
+
'.tsx',
|
|
19
|
+
'.json',
|
|
20
|
+
'.css',
|
|
21
|
+
'.scss',
|
|
22
|
+
'.sass',
|
|
23
|
+
'.less',
|
|
24
|
+
'.vue',
|
|
25
|
+
'.svelte',
|
|
26
|
+
'.md',
|
|
27
|
+
'.svg',
|
|
28
|
+
];
|
|
29
|
+
/** Extensions tried for a specifier that points at a folder (`./utils` → `./utils/index.js`). */
|
|
30
|
+
var INDEX_EXTENSIONS = ['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx', '.vue', '.json'];
|
|
31
|
+
/**
|
|
32
|
+
* Every shape a relative module specifier takes in generated code. Kept as
|
|
33
|
+
* separate, deliberately narrow patterns rather than one clever regex: an
|
|
34
|
+
* over-eager match here would only ever produce noise in a warning.
|
|
35
|
+
*/
|
|
36
|
+
var IMPORT_PATTERNS = [
|
|
37
|
+
// import x from './y' / export { x } from './y' (incl. multi-line import lists)
|
|
38
|
+
/\bfrom\s*['"](\.[^'"\n]*)['"]/g,
|
|
39
|
+
// import('./y')
|
|
40
|
+
/\bimport\s*\(\s*['"](\.[^'"\n]*)['"]\s*\)/g,
|
|
41
|
+
// require('./y')
|
|
42
|
+
/\brequire\s*\(\s*['"](\.[^'"\n]*)['"]\s*\)/g,
|
|
43
|
+
// import './y' (side-effect only)
|
|
44
|
+
/\bimport\s+['"](\.[^'"\n]*)['"]/g,
|
|
45
|
+
];
|
|
46
|
+
var getFileName = function (file) {
|
|
47
|
+
return file.fileType ? "".concat(file.name, ".").concat(file.fileType) : file.name;
|
|
48
|
+
};
|
|
49
|
+
var getExtension = function (filePath) {
|
|
50
|
+
var fileName = filePath.slice(filePath.lastIndexOf('/') + 1);
|
|
51
|
+
var dotIndex = fileName.lastIndexOf('.');
|
|
52
|
+
return dotIndex > 0 ? fileName.slice(dotIndex + 1).toLowerCase() : '';
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Resolve `specifier` against the folder holding `filePath`, purely on the
|
|
56
|
+
* segment arrays. Node's `path` is deliberately not used: this code also runs
|
|
57
|
+
* inside teleport-gui's packer Web Worker, where 'path' is swapped for Next's
|
|
58
|
+
* compiled `path-browserify` (see `localRelativePath` in ./generic).
|
|
59
|
+
*
|
|
60
|
+
* Returns null when the specifier climbs above the project root — nothing above
|
|
61
|
+
* it is ever generated, so such an import is unresolvable by definition.
|
|
62
|
+
*/
|
|
63
|
+
var resolveSpecifier = function (filePath, specifier) {
|
|
64
|
+
var segments = filePath.split('/').slice(0, -1);
|
|
65
|
+
for (var _i = 0, _a = specifier.split('/'); _i < _a.length; _i++) {
|
|
66
|
+
var part = _a[_i];
|
|
67
|
+
if (part === '' || part === '.') {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (part === '..') {
|
|
71
|
+
if (segments.length === 0) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
segments.pop();
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
segments.push(part);
|
|
78
|
+
}
|
|
79
|
+
return segments.join('/');
|
|
80
|
+
};
|
|
81
|
+
/** Drop a bundler suffix (`./icon.svg?inline`, `./font.woff#iefix`) before resolving. */
|
|
82
|
+
var stripSpecifierSuffix = function (specifier) {
|
|
83
|
+
var cutIndex = Math.min.apply(Math, ['?', '#'].map(function (marker) {
|
|
84
|
+
var index = specifier.indexOf(marker);
|
|
85
|
+
return index === -1 ? specifier.length : index;
|
|
86
|
+
}));
|
|
87
|
+
return specifier.slice(0, cutIndex);
|
|
88
|
+
};
|
|
89
|
+
var extractSpecifiers = function (content) {
|
|
90
|
+
var specifiers = new Set();
|
|
91
|
+
IMPORT_PATTERNS.forEach(function (pattern) {
|
|
92
|
+
// Patterns are module-level (and therefore stateful through `lastIndex`) —
|
|
93
|
+
// reset before each file so a previous scan can't skip the first match.
|
|
94
|
+
pattern.lastIndex = 0;
|
|
95
|
+
var match = pattern.exec(content);
|
|
96
|
+
while (match !== null) {
|
|
97
|
+
specifiers.add(match[1]);
|
|
98
|
+
match = pattern.exec(content);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return Array.from(specifiers);
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Flatten a generated project into project-root-relative file entries. The root
|
|
105
|
+
* folder's own name is the project directory itself, so it is not part of any
|
|
106
|
+
* path.
|
|
107
|
+
*/
|
|
108
|
+
var collectProjectFiles = function (folder) {
|
|
109
|
+
var entries = [];
|
|
110
|
+
var walk = function (currentFolder, prefix) {
|
|
111
|
+
currentFolder.files.forEach(function (file) {
|
|
112
|
+
entries.push({
|
|
113
|
+
path: "".concat(prefix).concat(getFileName(file)),
|
|
114
|
+
content: file.contentEncoding === 'base64' ? '' : file.content || '',
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
currentFolder.subFolders.forEach(function (subFolder) {
|
|
118
|
+
walk(subFolder, "".concat(prefix).concat(subFolder.name, "/"));
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
walk(folder, '');
|
|
122
|
+
return entries;
|
|
123
|
+
};
|
|
124
|
+
exports.collectProjectFiles = collectProjectFiles;
|
|
125
|
+
/**
|
|
126
|
+
* Every relative import in `files` that resolves to no file in `files`.
|
|
127
|
+
* Deterministically ordered (file, then specifier) so callers can snapshot it.
|
|
128
|
+
*/
|
|
129
|
+
var findUnresolvedLocalImports = function (files) {
|
|
130
|
+
var existingPaths = new Set(files.map(function (file) { return file.path; }));
|
|
131
|
+
var unresolved = [];
|
|
132
|
+
var resolvesToAFile = function (target) {
|
|
133
|
+
return RESOLVED_EXTENSIONS.some(function (extension) { return existingPaths.has("".concat(target).concat(extension)); }) ||
|
|
134
|
+
INDEX_EXTENSIONS.some(function (extension) { return existingPaths.has("".concat(target, "/index").concat(extension)); });
|
|
135
|
+
};
|
|
136
|
+
files.forEach(function (file) {
|
|
137
|
+
if (SCANNED_EXTENSIONS.indexOf(getExtension(file.path)) === -1) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
extractSpecifiers(file.content).forEach(function (specifier) {
|
|
141
|
+
var target = resolveSpecifier(file.path, stripSpecifierSuffix(specifier));
|
|
142
|
+
if (target === null || !resolvesToAFile(target)) {
|
|
143
|
+
unresolved.push({ filePath: file.path, specifier: specifier });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
return unresolved.sort(function (first, second) {
|
|
148
|
+
return first.filePath === second.filePath
|
|
149
|
+
? first.specifier.localeCompare(second.specifier)
|
|
150
|
+
: first.filePath.localeCompare(second.filePath);
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
exports.findUnresolvedLocalImports = findUnresolvedLocalImports;
|
|
154
|
+
/** `findUnresolvedLocalImports` over a generated project folder. */
|
|
155
|
+
var findUnresolvedLocalImportsInProject = function (folder) { return (0, exports.findUnresolvedLocalImports)((0, exports.collectProjectFiles)(folder)); };
|
|
156
|
+
exports.findUnresolvedLocalImportsInProject = findUnresolvedLocalImportsInProject;
|
|
157
|
+
/** Human-readable report. Returns an empty string when there is nothing to report. */
|
|
158
|
+
var formatUnresolvedLocalImports = function (unresolved) {
|
|
159
|
+
if (unresolved.length === 0) {
|
|
160
|
+
return '';
|
|
161
|
+
}
|
|
162
|
+
var lines = unresolved.map(function (item) { return " ".concat(item.filePath, " \u2192 '").concat(item.specifier, "'"); });
|
|
163
|
+
return ("".concat(unresolved.length, " generated import").concat(unresolved.length === 1 ? '' : 's', " ") +
|
|
164
|
+
"resolve".concat(unresolved.length === 1 ? 's' : '', " to no generated file \u2014 ") +
|
|
165
|
+
"the build will fail with \"Module not found\":\n".concat(lines.join('\n')));
|
|
166
|
+
};
|
|
167
|
+
exports.formatUnresolvedLocalImports = formatUnresolvedLocalImports;
|
|
168
|
+
//# sourceMappingURL=local-imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-imports.js","sourceRoot":"","sources":["../../../src/utils/local-imports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-product discount rule, as ES5 source for embedding into generated
|
|
3
|
+
* runtime code (the data-source product transform, the storefront cart
|
|
4
|
+
* provider) that cannot import from this package.
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ THIRD MIRROR. The same arithmetic exists in teleport-gui as
|
|
7
|
+
* `features/e-commerce/utils/product-discounts.ts` (the editor/canvas copy) and
|
|
8
|
+
* `features/workflows/templates/builders/ecommerce/product-discount-script.ts`
|
|
9
|
+
* (the copy baked into the add-to-cart workflow). All three must agree to the
|
|
10
|
+
* cent, or the price on the card, the price added to the cart and the price
|
|
11
|
+
* stored on the order will differ. The GUI's
|
|
12
|
+
* `utils/__tests__/product-discount-parity.spec.ts` pins the first two together;
|
|
13
|
+
* this one is covered by `__tests__/product-discounts.test.ts` here.
|
|
14
|
+
*
|
|
15
|
+
* Two rules the whole feature rests on:
|
|
16
|
+
*
|
|
17
|
+
* - Discounts come off the NET price, BEFORE storefront tax. Tax is a
|
|
18
|
+
* percentage of what is actually charged.
|
|
19
|
+
* - The stored `price` column never changes. A discount is a scheduled VIEW of
|
|
20
|
+
* the price, resolved on every read, so it starts and expires on its own.
|
|
21
|
+
*
|
|
22
|
+
* Everything is prefixed `__pd` so the block can be concatenated into any
|
|
23
|
+
* generated module without colliding with its locals — including alongside the
|
|
24
|
+
* `applyStorefrontTax` helpers, which it is always emitted with.
|
|
25
|
+
*/
|
|
26
|
+
export declare const generateProductDiscountHelperCode: () => string;
|
|
27
|
+
//# sourceMappingURL=product-discounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-discounts.d.ts","sourceRoot":"","sources":["../../../src/utils/product-discounts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,iCAAiC,QAAO,MAgGpD,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateProductDiscountHelperCode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The per-product discount rule, as ES5 source for embedding into generated
|
|
6
|
+
* runtime code (the data-source product transform, the storefront cart
|
|
7
|
+
* provider) that cannot import from this package.
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ THIRD MIRROR. The same arithmetic exists in teleport-gui as
|
|
10
|
+
* `features/e-commerce/utils/product-discounts.ts` (the editor/canvas copy) and
|
|
11
|
+
* `features/workflows/templates/builders/ecommerce/product-discount-script.ts`
|
|
12
|
+
* (the copy baked into the add-to-cart workflow). All three must agree to the
|
|
13
|
+
* cent, or the price on the card, the price added to the cart and the price
|
|
14
|
+
* stored on the order will differ. The GUI's
|
|
15
|
+
* `utils/__tests__/product-discount-parity.spec.ts` pins the first two together;
|
|
16
|
+
* this one is covered by `__tests__/product-discounts.test.ts` here.
|
|
17
|
+
*
|
|
18
|
+
* Two rules the whole feature rests on:
|
|
19
|
+
*
|
|
20
|
+
* - Discounts come off the NET price, BEFORE storefront tax. Tax is a
|
|
21
|
+
* percentage of what is actually charged.
|
|
22
|
+
* - The stored `price` column never changes. A discount is a scheduled VIEW of
|
|
23
|
+
* the price, resolved on every read, so it starts and expires on its own.
|
|
24
|
+
*
|
|
25
|
+
* Everything is prefixed `__pd` so the block can be concatenated into any
|
|
26
|
+
* generated module without colliding with its locals — including alongside the
|
|
27
|
+
* `applyStorefrontTax` helpers, which it is always emitted with.
|
|
28
|
+
*/
|
|
29
|
+
var generateProductDiscountHelperCode = function () { return "\n// \u2500\u2500 Per-product discounts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Rides the product row as a JSON `discounts` column: an array of\n// { id, type: 'percentage'|'fixed', value, startsAt, endsAt } with ISO UTC\n// bounds and a HALF-OPEN [startsAt, endsAt) window, so back-to-back discounts\n// hand over with no overlap and no gap.\nfunction __pdRound2(n) { return Math.round(n * 100) / 100; }\n\nfunction __pdSafe(n) {\n var x = typeof n === 'number' ? n : parseFloat(n);\n return isFinite(x) ? x : 0;\n}\n\n// A bound that was written but cannot be read makes the window meaningless, so\n// the entry is dropped rather than silently becoming unbounded.\nfunction __pdBound(value) {\n if (value === null || value === undefined || value === '') { return { ok: true, time: null }; }\n var parsed = Date.parse(String(value));\n if (!isFinite(parsed)) { return { ok: false, time: null }; }\n return { ok: true, time: parsed };\n}\n\n// The column arrives as JSON text on SQL backends and as a real array on the\n// document stores, and it is hand-editable through the admin panel. Anything\n// unparseable means \"no discounts\" rather than an exception inside a render.\nfunction __pdParseDiscounts(raw) {\n var source = raw;\n if (typeof source === 'string') {\n if (source === '') { return []; }\n try { source = JSON.parse(source); } catch (e) { return []; }\n }\n if (Object.prototype.toString.call(source) !== '[object Array]') { return []; }\n var out = [];\n for (var i = 0; i < source.length; i++) {\n var entry = source[i];\n if (!entry || typeof entry !== 'object') { continue; }\n if (entry.type !== 'percentage' && entry.type !== 'fixed') { continue; }\n var value = __pdSafe(entry.value);\n if (value <= 0) { continue; }\n if (entry.type === 'percentage' && value > 100) { continue; }\n var start = __pdBound(entry.startsAt);\n var end = __pdBound(entry.endsAt);\n if (!start.ok || !end.ok) { continue; }\n out.push({\n type: entry.type,\n value: value,\n startTime: start.time === null ? -Infinity : start.time,\n endTime: end.time === null ? Infinity : end.time\n });\n }\n return out;\n}\n\n// Valid data has at most one live entry \u2014 the merchant panel refuses\n// overlapping windows \u2014 but the column is hand-editable, so first-live-wins\n// keeps the runtime deterministic instead of trusting.\nfunction __pdResolveActive(raw, nowMs) {\n var list = __pdParseDiscounts(raw);\n var now = isFinite(nowMs) ? Number(nowMs) : Date.now();\n for (var i = 0; i < list.length; i++) {\n if (list[i].startTime <= now && now < list[i].endTime) {\n return { type: list[i].type, value: list[i].value };\n }\n }\n return null;\n}\n\n// NET in, NET out \u2014 tax is added on top of the result. Clamped at both ends: a\n// fixed amount larger than the price makes the product free, never negative.\nfunction __pdDiscountedPrice(netPrice, discount) {\n var base = __pdRound2(__pdSafe(netPrice));\n if (base <= 0) { return Math.max(0, base); }\n if (!discount) { return base; }\n var value = Math.max(0, __pdSafe(discount.value));\n var discounted = discount.type === 'percentage'\n ? base * (1 - Math.min(value, 100) / 100)\n : base - value;\n return Math.max(0, __pdRound2(discounted));\n}\n\nfunction __pdDiscountAmount(netPrice, discount) {\n var base = Math.max(0, __pdRound2(__pdSafe(netPrice)));\n return __pdRound2(base - __pdDiscountedPrice(base, discount));\n}\n\n// \"10% off\" / \"$10 off\" / \"10 kr off\" \u2014 the badge copy. Symbol-based rather\n// than Intl-based, because it sits beside prices the storefront renders as a\n// symbol glued to two decimals.\nfunction __pdDiscountLabel(discount, currencySymbol, symbolPosition) {\n if (!discount) { return ''; }\n var value = __pdSafe(discount.value);\n var text = (Math.round(value * 100) / 100).toString();\n if (discount.type === 'percentage') { return text + '% off'; }\n var symbol = currencySymbol || '$';\n return (symbolPosition === 'after' ? text + ' ' + symbol : symbol + text) + ' off';\n}\n"; };
|
|
30
|
+
exports.generateProductDiscountHelperCode = generateProductDiscountHelperCode;
|
|
31
|
+
//# sourceMappingURL=product-discounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-discounts.js","sourceRoot":"","sources":["../../../src/utils/product-discounts.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACI,IAAM,iCAAiC,GAAG,cAAc,OAAA,uxIAgG9D,EAhG8D,CAgG9D,CAAA;AAhGY,QAAA,iCAAiC,qCAgG7C"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as Constants from './constants';
|
|
|
2
2
|
import * as StringUtils from './utils/string-utils';
|
|
3
3
|
import * as UIDLUtils from './utils/uidl-utils';
|
|
4
4
|
import * as GenericUtils from './utils/generic';
|
|
5
|
+
import * as LocalImports from './utils/local-imports';
|
|
5
6
|
import * as JSIdentifiers from './utils/js-identifiers';
|
|
6
7
|
import * as ASTScope from './utils/ast-scope';
|
|
7
8
|
import * as ASTStatementOrder from './utils/ast-statement-order';
|
|
@@ -11,7 +12,8 @@ import * as LayoutTopology from './utils/layout-topology';
|
|
|
11
12
|
import * as HtmlContentModel from './utils/html-content-model';
|
|
12
13
|
import * as StyleDeclarations from './utils/style-declarations';
|
|
13
14
|
import * as StorefrontTax from './utils/storefront-tax';
|
|
15
|
+
import * as ProductDiscounts from './utils/product-discounts';
|
|
14
16
|
import * as EmailDate from './utils/email-date';
|
|
15
17
|
import * as DataCache from './cache';
|
|
16
|
-
export { Constants, StringUtils, UIDLUtils, GenericUtils, JSIdentifiers, ASTScope, ASTStatementOrder, ASTEffectCleanup, RoutePaths, LayoutTopology, HtmlContentModel, StyleDeclarations, StorefrontTax, EmailDate, DataCache, };
|
|
18
|
+
export { Constants, StringUtils, UIDLUtils, GenericUtils, LocalImports, JSIdentifiers, ASTScope, ASTStatementOrder, ASTEffectCleanup, RoutePaths, LayoutTopology, HtmlContentModel, StyleDeclarations, StorefrontTax, ProductDiscounts, EmailDate, DataCache, };
|
|
17
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,WAAW,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAC7C,OAAO,KAAK,iBAAiB,MAAM,6BAA6B,CAAA;AAChE,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,iBAAiB,MAAM,4BAA4B,CAAA;AAC/D,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,SAAS,MAAM,SAAS,CAAA;AAEpC,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,SAAS,GACV,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,WAAW,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAC7C,OAAO,KAAK,iBAAiB,MAAM,6BAA6B,CAAA;AAChE,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,iBAAiB,MAAM,4BAA4B,CAAA;AAC/D,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,gBAAgB,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,SAAS,MAAM,SAAS,CAAA;AAEpC,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,SAAS,GACV,CAAA"}
|
package/dist/esm/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as Constants from './constants';
|
|
|
2
2
|
import * as StringUtils from './utils/string-utils';
|
|
3
3
|
import * as UIDLUtils from './utils/uidl-utils';
|
|
4
4
|
import * as GenericUtils from './utils/generic';
|
|
5
|
+
import * as LocalImports from './utils/local-imports';
|
|
5
6
|
import * as JSIdentifiers from './utils/js-identifiers';
|
|
6
7
|
import * as ASTScope from './utils/ast-scope';
|
|
7
8
|
import * as ASTStatementOrder from './utils/ast-statement-order';
|
|
@@ -11,7 +12,8 @@ import * as LayoutTopology from './utils/layout-topology';
|
|
|
11
12
|
import * as HtmlContentModel from './utils/html-content-model';
|
|
12
13
|
import * as StyleDeclarations from './utils/style-declarations';
|
|
13
14
|
import * as StorefrontTax from './utils/storefront-tax';
|
|
15
|
+
import * as ProductDiscounts from './utils/product-discounts';
|
|
14
16
|
import * as EmailDate from './utils/email-date';
|
|
15
17
|
import * as DataCache from './cache';
|
|
16
|
-
export { Constants, StringUtils, UIDLUtils, GenericUtils, JSIdentifiers, ASTScope, ASTStatementOrder, ASTEffectCleanup, RoutePaths, LayoutTopology, HtmlContentModel, StyleDeclarations, StorefrontTax, EmailDate, DataCache, };
|
|
18
|
+
export { Constants, StringUtils, UIDLUtils, GenericUtils, LocalImports, JSIdentifiers, ASTScope, ASTStatementOrder, ASTEffectCleanup, RoutePaths, LayoutTopology, HtmlContentModel, StyleDeclarations, StorefrontTax, ProductDiscounts, EmailDate, DataCache, };
|
|
17
19
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,WAAW,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAC7C,OAAO,KAAK,iBAAiB,MAAM,6BAA6B,CAAA;AAChE,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,iBAAiB,MAAM,4BAA4B,CAAA;AAC/D,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,SAAS,MAAM,SAAS,CAAA;AAEpC,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,SAAS,GACV,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,WAAW,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAC7C,OAAO,KAAK,iBAAiB,MAAM,6BAA6B,CAAA;AAChE,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,gBAAgB,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,iBAAiB,MAAM,4BAA4B,CAAA;AAC/D,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,gBAAgB,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,SAAS,MAAM,SAAS,CAAA;AAEpC,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,SAAS,GACV,CAAA"}
|