@sky.ui.pro/core 0.0.6 → 0.0.7
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/CHANGELOG.md +26 -0
- package/README.md +107 -96
- package/dist/stub/index.d.ts +3 -0
- package/dist/stub/index.js +2 -2
- package/package.json +18 -11
- package/scripts/lib/merge-manifest.mjs +0 -81
- package/scripts/lib/project-env.mjs +0 -150
- package/scripts/lib/token.mjs +0 -147
- package/scripts/postinstall.mjs +0 -287
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@sky.ui.pro/core` are documented here.
|
|
4
|
+
|
|
5
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.0.7] - 2026-07-07
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Breaking install flow:** removed npm `postinstall` and the `tar` dependency from the published stub. Run `npx sky.ui.pro install` after `npm install` to download and hydrate the licensed artifact.
|
|
14
|
+
- Stub `package.json` no longer ships `scripts/` in the npm tarball.
|
|
15
|
+
- Peer dependency on `@sky.ui/core` bumped to `^0.0.7`.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- TypeScript stub declarations at `dist/stub/index.d.ts`.
|
|
20
|
+
- `CHANGELOG.md` and npm metadata (`keywords`, `author`, `engines`).
|
|
21
|
+
|
|
22
|
+
## [0.0.6]
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Initial npm stub with postinstall-based hydration (superseded in `0.0.7`).
|
package/README.md
CHANGED
|
@@ -1,96 +1,107 @@
|
|
|
1
|
-
# @sky.ui.pro/core
|
|
2
|
-
|
|
3
|
-
Pro-tier Lit web components for Sky UI. Extends the free catalog with advanced components such as data tables, flow editors, and rich inputs.
|
|
4
|
-
|
|
5
|
-
Requires an active Sky UI Pro subscription. Install alongside `@sky.ui/core` when your app uses both tiers.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npx sky.ui.pro login
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
import
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
1
|
+
# @sky.ui.pro/core
|
|
2
|
+
|
|
3
|
+
Pro-tier Lit web components for Sky UI. Extends the free catalog with advanced components such as data tables, flow editors, and rich inputs.
|
|
4
|
+
|
|
5
|
+
Requires an active Sky UI Pro subscription. Install alongside `@sky.ui/core` when your app uses both tiers.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx sky.ui.pro login
|
|
11
|
+
npx sky.ui.pro install
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or install manually, then hydrate:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install "@sky.ui.pro/core"
|
|
18
|
+
npx sky.ui.pro install --framework=core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> Quote scoped names (`"@sky.ui/…"`) — required in PowerShell. See [powershell-scoped-packages.md](https://gitlab.com/sky_ui/sky-ui/-/blob/main/docs/powershell-scoped-packages.md).
|
|
22
|
+
|
|
23
|
+
For CI/CD:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
SKY_UI_AUTH_TOKEN=sk_ci_… npx sky.ui.pro install --yes --framework=core
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Manage tokens on your [Sky UI account](https://library.sky-ui.com/account). No `.npmrc` file is required.
|
|
30
|
+
|
|
31
|
+
| Token | Use |
|
|
32
|
+
|-------|-----|
|
|
33
|
+
| Personal (`sk_pt_…`) | Local development and MCP |
|
|
34
|
+
| CI/CD (`sk_ci_…`) | Pipelines (`SKY_UI_AUTH_TOKEN`) |
|
|
35
|
+
|
|
36
|
+
Peer dependencies match `@sky.ui/core` (`lit`, and optional `@lit-labs/motion`, `@lit-labs/virtualizer`, `@lit/context`, `d3`, `three`).
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
import { SkyTable, SkyFlow } from '@sky.ui.pro/core';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<sky-table></sky-table>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Import only the Pro components you use for tree-shaken production bundles.
|
|
49
|
+
|
|
50
|
+
Per-component paths are also supported:
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
import '@sky.ui.pro/core/sky-table';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Auto-import resolvers
|
|
57
|
+
|
|
58
|
+
Use resolvers from `@sky.ui.pro/core/auto-import` with `unplugin-vue-components` or your bundler's component plugin, alongside the free-tier setup in [`@sky.ui/core`](https://www.npmjs.com/package/@sky.ui/core).
|
|
59
|
+
|
|
60
|
+
## Bundler plugins (Vite, Webpack, Rollup)
|
|
61
|
+
|
|
62
|
+
Pro packages mirror the free-tier plugin surface. Bundler plugins auto-import components and **validate your access token at build/dev time** (no runtime checks in shipped apps).
|
|
63
|
+
|
|
64
|
+
**Vite** (`@sky.ui.pro/core/vite`):
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
import { SkyUIProMainVitePlugin } from '@sky.ui.pro/core/vite';
|
|
68
|
+
|
|
69
|
+
export default {
|
|
70
|
+
plugins: [
|
|
71
|
+
SkyUIProMainVitePlugin({
|
|
72
|
+
mode: 'auto-import', // or 'vue' with unplugin-vue-components
|
|
73
|
+
}),
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Webpack** (`@sky.ui.pro/core/webpack`): `SkyUIProMainWebpackPlugin()`
|
|
79
|
+
|
|
80
|
+
**Rollup** (`@sky.ui.pro/core/rollup`): `SkyUIProMainRollupPlugin({ mode: 'auto-import' })`
|
|
81
|
+
|
|
82
|
+
Vue / React Pro wrappers expose the same three bundlers at `@sky.ui.pro/vue/vite|webpack|rollup` and `@sky.ui.pro/react/vite|webpack|rollup`.
|
|
83
|
+
|
|
84
|
+
For resolver-only setup, use `@sky.ui.pro/core/auto-import` with `unplugin-vue-components`, alongside [`@sky.ui/core`](https://www.npmjs.com/package/@sky.ui/core) bundler plugins for free components.
|
|
85
|
+
|
|
86
|
+
## Framework wrappers
|
|
87
|
+
|
|
88
|
+
| Package | Description |
|
|
89
|
+
|---------|-------------|
|
|
90
|
+
| [`@sky.ui.pro/vue`](https://www.npmjs.com/package/@sky.ui.pro/vue) | Vue 3 SFC wrappers |
|
|
91
|
+
| [`@sky.ui.pro/react`](https://www.npmjs.com/package/@sky.ui.pro/react) | React wrappers |
|
|
92
|
+
|
|
93
|
+
Free-tier equivalents: [`@sky.ui/vue`](https://www.npmjs.com/package/@sky.ui/vue), [`@sky.ui/react`](https://www.npmjs.com/package/@sky.ui/react).
|
|
94
|
+
|
|
95
|
+
## Custom Elements Manifest
|
|
96
|
+
|
|
97
|
+
Component metadata is published at `@sky.ui.pro/core/custom-elements.json`.
|
|
98
|
+
|
|
99
|
+
## Updates window
|
|
100
|
+
|
|
101
|
+
Annual plans include one year of updates. You keep using versions released during your active window even after it ends; renew to receive newer releases.
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
[Sky UI Pro Commercial License](https://unpkg.com/@sky.ui.pro/core/LICENSE.md) — requires an active Sky UI Pro subscription.
|
|
106
|
+
|
|
107
|
+
Documentation: [library.sky-ui.com](https://library.sky-ui.com)
|
package/dist/stub/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** Placeholder until
|
|
2
|
-
export default {};
|
|
1
|
+
/** Placeholder until sky.ui.pro CLI hydrates the full package from the private registry. */
|
|
2
|
+
export default {};
|
package/package.json
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sky.ui.pro/core",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Sky UI Pro web components —
|
|
3
|
+
"version": "0.0.7",
|
|
4
|
+
"description": "Sky UI Pro web components — run npx sky.ui.pro install after npm install.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"sky-ui",
|
|
7
|
+
"pro",
|
|
8
|
+
"web-components",
|
|
9
|
+
"lit",
|
|
10
|
+
"design-system",
|
|
11
|
+
"ui"
|
|
12
|
+
],
|
|
13
|
+
"author": "Sky UI",
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
5
17
|
"type": "module",
|
|
6
18
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
7
19
|
"main": "./dist/stub/index.js",
|
|
20
|
+
"types": "./dist/stub/index.d.ts",
|
|
8
21
|
"exports": {
|
|
9
22
|
".": "./dist/stub/index.js"
|
|
10
23
|
},
|
|
11
24
|
"files": [
|
|
12
|
-
"scripts",
|
|
13
25
|
"dist/stub",
|
|
14
26
|
"README.md",
|
|
15
|
-
"LICENSE.md"
|
|
27
|
+
"LICENSE.md",
|
|
28
|
+
"CHANGELOG.md"
|
|
16
29
|
],
|
|
17
|
-
"scripts": {
|
|
18
|
-
"postinstall": "node ./scripts/postinstall.mjs"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"tar": "^7.4.3"
|
|
22
|
-
},
|
|
23
30
|
"peerDependencies": {
|
|
24
|
-
"@sky.ui/core": "^0.0.
|
|
31
|
+
"@sky.ui/core": "^0.0.7",
|
|
25
32
|
"lit": ">=3 <4"
|
|
26
33
|
},
|
|
27
34
|
"peerDependenciesMeta": {
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Merge public npm stub manifest with GitLab artifact manifest after postinstall hydration.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export const ARTIFACT_MANIFEST_SIDECAR = ".sky-ui-pro-artifact-manifest.json";
|
|
6
|
-
|
|
7
|
-
const PRO_ARTIFACT_PREFIX = "@sky.ui.pro-artifact/";
|
|
8
|
-
const PRO_PUBLIC_PREFIX = "@sky.ui.pro/";
|
|
9
|
-
|
|
10
|
-
/** Rename @sky.ui.pro-artifact/* deps to @sky.ui.pro/* for installed packages. */
|
|
11
|
-
export function renameProArtifactDeps(deps) {
|
|
12
|
-
if (!deps || typeof deps !== "object") return deps;
|
|
13
|
-
const out = { ...deps };
|
|
14
|
-
for (const [key, value] of Object.entries(out)) {
|
|
15
|
-
if (key.startsWith(PRO_ARTIFACT_PREFIX)) {
|
|
16
|
-
const next = `${PRO_PUBLIC_PREFIX}${key.slice(PRO_ARTIFACT_PREFIX.length)}`;
|
|
17
|
-
if (!(next in out)) out[next] = value;
|
|
18
|
-
delete out[key];
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return out;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** True when exports already point at hydrated artifact paths (not stub-only). */
|
|
25
|
-
export function hasHydratedExports(manifest) {
|
|
26
|
-
const exp = manifest?.exports;
|
|
27
|
-
if (!exp || typeof exp !== "object") return false;
|
|
28
|
-
if (exp["./vite"] || exp["./webpack"] || exp["./rollup"] || exp["./license"]) return true;
|
|
29
|
-
const root = exp["."];
|
|
30
|
-
if (typeof root === "string") {
|
|
31
|
-
return root.includes("dist/index") || (root.includes("/dist/") && !root.includes("/stub/"));
|
|
32
|
-
}
|
|
33
|
-
if (root && typeof root === "object") {
|
|
34
|
-
const imp = root.import ?? root.default ?? root.module;
|
|
35
|
-
return typeof imp === "string" && imp.includes("dist/index");
|
|
36
|
-
}
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Build installed package.json: artifact resolution surface + public stub identity.
|
|
42
|
-
* @param {Record<string, unknown>} stub
|
|
43
|
-
* @param {Record<string, unknown>} artifact
|
|
44
|
-
*/
|
|
45
|
-
export function mergeHydratedManifest(stub, artifact) {
|
|
46
|
-
const stubDeps = stub.dependencies && typeof stub.dependencies === "object" ? stub.dependencies : {};
|
|
47
|
-
const tarVersion = stubDeps.tar;
|
|
48
|
-
|
|
49
|
-
const merged = {
|
|
50
|
-
name: stub.name,
|
|
51
|
-
version: stub.version,
|
|
52
|
-
description: stub.description ?? artifact.description,
|
|
53
|
-
type: stub.type ?? artifact.type,
|
|
54
|
-
license: stub.license ?? artifact.license,
|
|
55
|
-
main: artifact.main,
|
|
56
|
-
module: artifact.module,
|
|
57
|
-
types: artifact.types,
|
|
58
|
-
sideEffects: artifact.sideEffects,
|
|
59
|
-
exports: artifact.exports,
|
|
60
|
-
peerDependencies: {
|
|
61
|
-
...renameProArtifactDeps(artifact.peerDependencies),
|
|
62
|
-
...(stub.peerDependencies ?? {}),
|
|
63
|
-
},
|
|
64
|
-
dependencies: {
|
|
65
|
-
...renameProArtifactDeps(artifact.dependencies),
|
|
66
|
-
...(tarVersion ? { tar: tarVersion } : {}),
|
|
67
|
-
},
|
|
68
|
-
scripts: stub.scripts?.postinstall ? { postinstall: stub.scripts.postinstall } : {},
|
|
69
|
-
skyUiPro: stub.skyUiPro,
|
|
70
|
-
publishConfig: stub.publishConfig,
|
|
71
|
-
repository: stub.repository,
|
|
72
|
-
bugs: stub.bugs,
|
|
73
|
-
homepage: stub.homepage,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
if (artifact.peerDependenciesMeta && typeof artifact.peerDependenciesMeta === "object") {
|
|
77
|
-
merged.peerDependenciesMeta = artifact.peerDependenciesMeta;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return merged;
|
|
81
|
-
}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Unified Sky UI Pro / CLI project `.env` loading.
|
|
4
|
-
* Source of truth — synced to @sky.ui/cli and copied into @sky.ui.pro/* stubs on sync:pro-npm.
|
|
5
|
-
*
|
|
6
|
-
* Loads only `SKY_UI_*` keys. Shell env always wins (existing process.env is never overwritten).
|
|
7
|
-
* Search order: INIT_CWD → npm local prefix → SKY_UI_PROJECT_ROOT → cwd → project roots.
|
|
8
|
-
*/
|
|
9
|
-
import { access, readFile } from "node:fs/promises";
|
|
10
|
-
import { dirname, join } from "node:path";
|
|
11
|
-
|
|
12
|
-
export const SKY_UI_ENV_PREFIX = "SKY_UI_";
|
|
13
|
-
|
|
14
|
-
/** Filenames tried in each project directory (later files override earlier within the same dir). */
|
|
15
|
-
export const SKY_UI_ENV_FILES = [".env", ".env.local"];
|
|
16
|
-
|
|
17
|
-
/** Documented variables (for README / tooling — not enforced here). */
|
|
18
|
-
export const SKY_UI_ENV_VARS = [
|
|
19
|
-
"SKY_UI_API_URL",
|
|
20
|
-
"SKY_UI_AUTH_TOKEN",
|
|
21
|
-
"SKY_UI_PERSONAL_TOKEN",
|
|
22
|
-
"SKY_UI_PROJECT_ROOT",
|
|
23
|
-
"SKY_UI_PRO_FRAMEWORK",
|
|
24
|
-
"SKY_UI_PRO_LENIENT",
|
|
25
|
-
"SKY_UI_PRO_LICENSE_LENIENT",
|
|
26
|
-
"SKY_UI_PRO_SKIP_POSTINSTALL",
|
|
27
|
-
"SKY_UI_PRO_STRICT",
|
|
28
|
-
"SKY_UI_NPM_REGISTRY",
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
export async function pathExists(p) {
|
|
32
|
-
try {
|
|
33
|
-
await access(p);
|
|
34
|
-
return true;
|
|
35
|
-
} catch {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function normalizeDirKey(dir) {
|
|
41
|
-
return dir.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function shouldLoadKey(key) {
|
|
45
|
-
return key.startsWith(SKY_UI_ENV_PREFIX);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function envAlreadySet(key) {
|
|
49
|
-
const v = process.env[key];
|
|
50
|
-
return typeof v === "string" && v.trim().length > 0;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function unquote(value) {
|
|
54
|
-
if (
|
|
55
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
56
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
57
|
-
) {
|
|
58
|
-
return value.slice(1, -1);
|
|
59
|
-
}
|
|
60
|
-
return value;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Parse and apply one `.env` file. Does not overwrite non-empty process.env values. */
|
|
64
|
-
export async function loadEnvFile(envFilePath) {
|
|
65
|
-
try {
|
|
66
|
-
const raw = await readFile(envFilePath, "utf8");
|
|
67
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
68
|
-
const trimmed = line.trim();
|
|
69
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
70
|
-
const eq = trimmed.indexOf("=");
|
|
71
|
-
if (eq <= 0) continue;
|
|
72
|
-
const key = trimmed.slice(0, eq).trim();
|
|
73
|
-
if (!shouldLoadKey(key)) continue;
|
|
74
|
-
if (envAlreadySet(key)) continue;
|
|
75
|
-
process.env[key] = unquote(trimmed.slice(eq + 1).trim());
|
|
76
|
-
}
|
|
77
|
-
} catch {
|
|
78
|
-
/* missing or unreadable */
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Load `.env` (+ `.env.local`) from a project directory. */
|
|
83
|
-
export async function loadProjectEnv(cwd = process.cwd()) {
|
|
84
|
-
for (const name of SKY_UI_ENV_FILES) {
|
|
85
|
-
await loadEnvFile(join(cwd, name));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** Walk up to find the nearest directory containing `package.json`. */
|
|
90
|
-
export async function findProjectRoot(startDir, maxDepth = 12) {
|
|
91
|
-
let dir = startDir;
|
|
92
|
-
for (let i = 0; i < maxDepth; i++) {
|
|
93
|
-
if (await pathExists(join(dir, "package.json"))) return dir;
|
|
94
|
-
const parent = dirname(dir);
|
|
95
|
-
if (parent === dir) break;
|
|
96
|
-
dir = parent;
|
|
97
|
-
}
|
|
98
|
-
return startDir;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Directories to scan for `.env`, in priority order (first match wins per key;
|
|
103
|
-
* later dirs only fill keys still unset).
|
|
104
|
-
*/
|
|
105
|
-
export async function collectEnvSearchDirs(options = {}) {
|
|
106
|
-
const { pkgRoot, extraDirs = [] } = options;
|
|
107
|
-
const seen = new Set();
|
|
108
|
-
const ordered = [];
|
|
109
|
-
|
|
110
|
-
const push = (dir) => {
|
|
111
|
-
if (!dir || typeof dir !== "string") return;
|
|
112
|
-
const key = normalizeDirKey(dir);
|
|
113
|
-
if (seen.has(key)) return;
|
|
114
|
-
seen.add(key);
|
|
115
|
-
ordered.push(dir);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
push(process.env.INIT_CWD);
|
|
119
|
-
push(process.env.npm_config_local_prefix);
|
|
120
|
-
push(process.env.SKY_UI_PROJECT_ROOT?.trim());
|
|
121
|
-
push(process.cwd());
|
|
122
|
-
|
|
123
|
-
const cwdRoot = await findProjectRoot(process.cwd());
|
|
124
|
-
push(cwdRoot);
|
|
125
|
-
|
|
126
|
-
if (pkgRoot) {
|
|
127
|
-
push(await findProjectRoot(dirname(pkgRoot)));
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
for (const dir of extraDirs) {
|
|
131
|
-
push(dir);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return ordered;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Load Sky UI env from consumer project `.env` files.
|
|
139
|
-
* @param {{ pkgRoot?: string, extraDirs?: string[] }} [options]
|
|
140
|
-
*/
|
|
141
|
-
export async function loadConsumerProjectEnv(options = {}) {
|
|
142
|
-
for (const dir of await collectEnvSearchDirs(options)) {
|
|
143
|
-
await loadProjectEnv(dir);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/** @deprecated Alias used by postinstall — prefer loadConsumerProjectEnv */
|
|
148
|
-
export async function loadInstallProjectEnv(pkgRoot) {
|
|
149
|
-
return loadConsumerProjectEnv({ pkgRoot });
|
|
150
|
-
}
|
package/scripts/lib/token.mjs
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Shared token resolution and online license validation for @sky.ui.pro postinstall.
|
|
4
|
-
*/
|
|
5
|
-
import { access, readFile } from "node:fs/promises";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
|
|
9
|
-
export { loadConsumerProjectEnv, loadInstallProjectEnv } from "./project-env.mjs";
|
|
10
|
-
|
|
11
|
-
export const SKY_UI_HOME = join(homedir(), ".sky.ui");
|
|
12
|
-
export const LEGACY_SKY_UI_HOME = join(homedir(), ".sky-ui");
|
|
13
|
-
export const cacheRoot = join(SKY_UI_HOME, "cache");
|
|
14
|
-
export const legacyCacheRoot = join(LEGACY_SKY_UI_HOME, "cache");
|
|
15
|
-
export const ENTITLEMENT_MARKER = ".sky-ui-pro-installed.json";
|
|
16
|
-
|
|
17
|
-
export async function exists(p) {
|
|
18
|
-
try {
|
|
19
|
-
await access(p);
|
|
20
|
-
return true;
|
|
21
|
-
} catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function resolveApiBase(pkg) {
|
|
27
|
-
const fromEnv = process.env.SKY_UI_API_URL?.trim();
|
|
28
|
-
if (fromEnv) return fromEnv.replace(/\/api\/?$/, "").replace(/\/$/, "");
|
|
29
|
-
const fromPkg = pkg?.skyUiPro?.apiBase?.trim();
|
|
30
|
-
if (fromPkg) return fromPkg.replace(/\/$/, "");
|
|
31
|
-
return "https://library.sky-ui.com";
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function licenseValidateUrl(apiBase) {
|
|
35
|
-
const host = String(apiBase).replace(/\/api\/?$/, "").replace(/\/$/, "");
|
|
36
|
-
return `${host}/api/license/validate`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function resolveToken() {
|
|
40
|
-
const envCi = process.env.SKY_UI_AUTH_TOKEN?.trim();
|
|
41
|
-
if (envCi) return envCi;
|
|
42
|
-
const envPersonal = process.env.SKY_UI_PERSONAL_TOKEN?.trim();
|
|
43
|
-
if (envPersonal) return envPersonal;
|
|
44
|
-
for (const credPath of [
|
|
45
|
-
join(SKY_UI_HOME, "credentials.json"),
|
|
46
|
-
join(LEGACY_SKY_UI_HOME, "credentials.json"),
|
|
47
|
-
]) {
|
|
48
|
-
if (!(await exists(credPath))) continue;
|
|
49
|
-
const creds = JSON.parse(await readFile(credPath, "utf8"));
|
|
50
|
-
if (typeof creds.personalToken === "string" && creds.personalToken.trim()) {
|
|
51
|
-
return creds.personalToken.trim();
|
|
52
|
-
}
|
|
53
|
-
if (typeof creds.authToken === "string" && creds.authToken.trim()) {
|
|
54
|
-
return creds.authToken.trim();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function isAccessTokenFormat(token) {
|
|
61
|
-
return typeof token === "string" && (token.startsWith("sk_pt_") || token.startsWith("sk_ci_"));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @returns {{ active: boolean, status?: string, error?: string, renewalEmailSent?: boolean }}
|
|
66
|
-
*/
|
|
67
|
-
export async function validateAccessTokenOnline(token, apiBase) {
|
|
68
|
-
if (!token || !isAccessTokenFormat(token)) {
|
|
69
|
-
return { active: false, status: "missing" };
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
const res = await fetch(licenseValidateUrl(apiBase), {
|
|
73
|
-
method: "POST",
|
|
74
|
-
headers: {
|
|
75
|
-
Authorization: `Bearer ${token}`,
|
|
76
|
-
"Content-Type": "application/json",
|
|
77
|
-
Accept: "application/json",
|
|
78
|
-
},
|
|
79
|
-
body: "{}",
|
|
80
|
-
});
|
|
81
|
-
const data = await res.json().catch(() => ({}));
|
|
82
|
-
if (res.ok && data.active) {
|
|
83
|
-
return { active: true, status: "active", tokenKind: data.tokenKind };
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
active: false,
|
|
87
|
-
status: data.status ?? (res.status === 401 ? "invalid" : "inactive"),
|
|
88
|
-
error: data.error,
|
|
89
|
-
renewalEmailSent: Boolean(data.renewalEmailSent),
|
|
90
|
-
};
|
|
91
|
-
} catch (err) {
|
|
92
|
-
return {
|
|
93
|
-
active: false,
|
|
94
|
-
status: "network_error",
|
|
95
|
-
error: err instanceof Error ? err.message : String(err),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function formatRenewalEmailHint(result) {
|
|
101
|
-
if (!result?.renewalEmailSent) return "";
|
|
102
|
-
return "\n Renewal instructions were sent to your account email.\n https://library.sky-ui.com/pricing";
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function isInstallStrict() {
|
|
106
|
-
if (process.env.SKY_UI_PRO_LENIENT === "1") return false;
|
|
107
|
-
if (process.env.SKY_UI_PRO_STRICT === "0") return false;
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function entitlementMarkerPath(pkgRoot) {
|
|
112
|
-
return join(pkgRoot, ENTITLEMENT_MARKER);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function writeEntitlementMarker(pkgRoot, { name, version, status = "active" }) {
|
|
116
|
-
const { writeFile } = await import("node:fs/promises");
|
|
117
|
-
await writeFile(
|
|
118
|
-
entitlementMarkerPath(pkgRoot),
|
|
119
|
-
`${JSON.stringify(
|
|
120
|
-
{
|
|
121
|
-
name,
|
|
122
|
-
version,
|
|
123
|
-
status,
|
|
124
|
-
validatedAt: new Date().toISOString(),
|
|
125
|
-
},
|
|
126
|
-
null,
|
|
127
|
-
2,
|
|
128
|
-
)}\n`,
|
|
129
|
-
"utf8",
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** True when package was not hydrated (stub-only install). */
|
|
134
|
-
export async function isStubOnlyPackage(pkgRoot) {
|
|
135
|
-
const pluginsDir = join(pkgRoot, "plugins", "vite-plugin.js");
|
|
136
|
-
if (await exists(pluginsDir)) return false;
|
|
137
|
-
const distIndex = join(pkgRoot, "dist", "index.js");
|
|
138
|
-
if (await exists(distIndex)) return false;
|
|
139
|
-
const stubPath = join(pkgRoot, "dist", "stub", "index.js");
|
|
140
|
-
if (!(await exists(stubPath))) return true;
|
|
141
|
-
try {
|
|
142
|
-
const stub = await readFile(stubPath, "utf8");
|
|
143
|
-
return /export\s+default\s+\{\s*\}/.test(stub);
|
|
144
|
-
} catch {
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
}
|
package/scripts/postinstall.mjs
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Downloads the full @sky.ui.pro/* artifact from the Sky UI npm proxy (GitLab upstream).
|
|
4
|
-
* Cache restore re-validates the access token; install fails closed without a valid token.
|
|
5
|
-
*/
|
|
6
|
-
import { createWriteStream } from "node:fs";
|
|
7
|
-
import { cp, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
8
|
-
import { tmpdir } from "node:os";
|
|
9
|
-
import { dirname, join } from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
import { pipeline } from "node:stream/promises";
|
|
12
|
-
import { extract } from "tar";
|
|
13
|
-
import {
|
|
14
|
-
ARTIFACT_MANIFEST_SIDECAR,
|
|
15
|
-
hasHydratedExports,
|
|
16
|
-
mergeHydratedManifest,
|
|
17
|
-
} from "./lib/merge-manifest.mjs";
|
|
18
|
-
import {
|
|
19
|
-
ENTITLEMENT_MARKER,
|
|
20
|
-
cacheRoot,
|
|
21
|
-
exists,
|
|
22
|
-
isInstallStrict,
|
|
23
|
-
legacyCacheRoot,
|
|
24
|
-
loadInstallProjectEnv,
|
|
25
|
-
resolveApiBase,
|
|
26
|
-
resolveToken,
|
|
27
|
-
validateAccessTokenOnline,
|
|
28
|
-
writeEntitlementMarker,
|
|
29
|
-
formatRenewalEmailHint,
|
|
30
|
-
} from "./lib/token.mjs";
|
|
31
|
-
|
|
32
|
-
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
33
|
-
const pkgRoot = join(scriptDir, "..");
|
|
34
|
-
|
|
35
|
-
const SKIP_COPY_TO_INSTALL = new Set([ENTITLEMENT_MARKER, ARTIFACT_MANIFEST_SIDECAR]);
|
|
36
|
-
|
|
37
|
-
async function readJson(p) {
|
|
38
|
-
return JSON.parse(await readFile(p, "utf8"));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function writeJson(p, data) {
|
|
42
|
-
await writeFile(p, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function packageSlug(name) {
|
|
46
|
-
return name.replace(/^@/, "").replace("/", "-");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function cacheVersionDir(root, slug, version) {
|
|
50
|
-
return join(root, slug, version);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function copyDirectoryContents(src, dest, { skip = SKIP_COPY_TO_INSTALL } = {}) {
|
|
54
|
-
await mkdir(dest, { recursive: true });
|
|
55
|
-
for (const entry of await readdir(src, { withFileTypes: true })) {
|
|
56
|
-
if (skip.has(entry.name)) continue;
|
|
57
|
-
await cp(join(src, entry.name), join(dest, entry.name), { recursive: true, force: true });
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** Drop cached versions other than the one being installed (HeroUI cache policy). */
|
|
62
|
-
async function enforceCachePolicy(slug, version) {
|
|
63
|
-
const slugDir = join(cacheRoot, slug);
|
|
64
|
-
if (!(await exists(slugDir))) return;
|
|
65
|
-
for (const entry of await readdir(slugDir, { withFileTypes: true })) {
|
|
66
|
-
if (entry.name === version || entry.name === ".gitignore") continue;
|
|
67
|
-
await rm(join(slugDir, entry.name), { recursive: true, force: true });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async function readArtifactManifestSidecar(cacheDir) {
|
|
72
|
-
const sidecar = join(cacheDir, ARTIFACT_MANIFEST_SIDECAR);
|
|
73
|
-
if (!(await exists(sidecar))) return null;
|
|
74
|
-
return readJson(sidecar);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Read artifact package.json from cached tarball (legacy caches without sidecar). */
|
|
78
|
-
async function readArtifactManifestFromTarball(slug, version) {
|
|
79
|
-
const tgz = join(cacheRoot, `${slug}-${version}.tgz`);
|
|
80
|
-
if (!(await exists(tgz))) return null;
|
|
81
|
-
const stagingDir = await mkdtemp(join(tmpdir(), `sky.ui.pro-manifest-${slug}-${version}-`));
|
|
82
|
-
try {
|
|
83
|
-
await extract({ file: tgz, cwd: stagingDir, strip: 1 });
|
|
84
|
-
return readJson(join(stagingDir, "package.json"));
|
|
85
|
-
} catch {
|
|
86
|
-
return null;
|
|
87
|
-
} finally {
|
|
88
|
-
await rm(stagingDir, { recursive: true, force: true });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function resolveArtifactManifest(stubManifest, slug, version, cacheDir) {
|
|
93
|
-
const sidecar = cacheDir ? await readArtifactManifestSidecar(cacheDir) : null;
|
|
94
|
-
if (sidecar) return sidecar;
|
|
95
|
-
return readArtifactManifestFromTarball(slug, version);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async function applyHydratedManifest(targetRoot, stubManifest, artifactManifest) {
|
|
99
|
-
const merged = mergeHydratedManifest(stubManifest, artifactManifest);
|
|
100
|
-
await writeJson(join(targetRoot, "package.json"), merged);
|
|
101
|
-
return merged;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async function finalizeHydratedManifest(targetRoot, stubManifest, slug, version, cacheDir) {
|
|
105
|
-
const current = await readJson(join(targetRoot, "package.json"));
|
|
106
|
-
if (hasHydratedExports(current)) {
|
|
107
|
-
return current;
|
|
108
|
-
}
|
|
109
|
-
const artifactManifest = await resolveArtifactManifest(stubManifest, slug, version, cacheDir);
|
|
110
|
-
if (!artifactManifest) return current;
|
|
111
|
-
return applyHydratedManifest(targetRoot, stubManifest, artifactManifest);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async function restoreFromCache(slug, version, target, stubManifest) {
|
|
115
|
-
for (const root of [cacheRoot, legacyCacheRoot]) {
|
|
116
|
-
const src = cacheVersionDir(root, slug, version);
|
|
117
|
-
if (!(await exists(src))) continue;
|
|
118
|
-
const entries = await readdir(src);
|
|
119
|
-
if (entries.length === 0) continue;
|
|
120
|
-
await copyDirectoryContents(src, target);
|
|
121
|
-
await finalizeHydratedManifest(target, stubManifest, slug, version, src);
|
|
122
|
-
return { cacheDir: src };
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function saveToCache(slug, version, source, artifactManifest) {
|
|
128
|
-
const dest = cacheVersionDir(cacheRoot, slug, version);
|
|
129
|
-
await rm(dest, { recursive: true, force: true });
|
|
130
|
-
await mkdir(dest, { recursive: true });
|
|
131
|
-
await copyDirectoryContents(source, dest);
|
|
132
|
-
if (artifactManifest) {
|
|
133
|
-
await writeJson(join(dest, ARTIFACT_MANIFEST_SIDECAR), artifactManifest);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function invalidateCache(slug, version) {
|
|
138
|
-
for (const root of [cacheRoot, legacyCacheRoot]) {
|
|
139
|
-
const dir = cacheVersionDir(root, slug, version);
|
|
140
|
-
if (await exists(dir)) {
|
|
141
|
-
await rm(dir, { recursive: true, force: true });
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
const tgz = join(cacheRoot, `${slug}-${version}.tgz`);
|
|
145
|
-
if (await exists(tgz)) await rm(tgz, { force: true });
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function tarballFileName(name, version) {
|
|
149
|
-
return `${name.replace(/^@/, "").replace("/", "-")}-${version}.tgz`;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function tarballUrl(apiBase, name, version) {
|
|
153
|
-
const base = apiBase.replace(/\/$/, "");
|
|
154
|
-
const scopePath = name.replace("/", "%2f");
|
|
155
|
-
const file = tarballFileName(name, version);
|
|
156
|
-
return `${base}/npm/${scopePath}/-/${file}`;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function printMissingToken(name, apiBase) {
|
|
160
|
-
console.warn(`
|
|
161
|
-
[@sky.ui.pro] Missing install token — ${name} was not downloaded.
|
|
162
|
-
|
|
163
|
-
Local dev:
|
|
164
|
-
npx sky.ui.pro login
|
|
165
|
-
or export SKY_UI_PERSONAL_TOKEN=sk_pt_…
|
|
166
|
-
|
|
167
|
-
CI / pipelines:
|
|
168
|
-
export SKY_UI_AUTH_TOKEN=sk_ci_…
|
|
169
|
-
|
|
170
|
-
Or add SKY_UI_PERSONAL_TOKEN / SKY_UI_AUTH_TOKEN to your project .env
|
|
171
|
-
API host (SKY_UI_API_URL): ${apiBase}
|
|
172
|
-
|
|
173
|
-
Then re-run: npm install "${name}"
|
|
174
|
-
Docs: https://library.sky-ui.com/docs/getting-started
|
|
175
|
-
|
|
176
|
-
Maintainer escape hatch: SKY_UI_PRO_LENIENT=1
|
|
177
|
-
`);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function printInvalidToken(name, result, apiBase) {
|
|
181
|
-
console.error(
|
|
182
|
-
`[@sky.ui.pro] License validation failed for ${name}: ${result.status ?? "inactive"}${
|
|
183
|
-
result.error ? ` — ${result.error}` : ""
|
|
184
|
-
}`,
|
|
185
|
-
);
|
|
186
|
-
console.error(`[@sky.ui.pro] API host: ${apiBase}`);
|
|
187
|
-
const renewalHint = formatRenewalEmailHint(result);
|
|
188
|
-
console.error(`
|
|
189
|
-
Renew or regenerate your token, then re-run: npm install "${name}"${renewalHint}
|
|
190
|
-
`);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async function installFromTarball(tgzPath, slug, version, stubManifest) {
|
|
194
|
-
const stagingDir = await mkdtemp(join(tmpdir(), `sky.ui.pro-${slug}-${version}-`));
|
|
195
|
-
try {
|
|
196
|
-
await extract({ file: tgzPath, cwd: stagingDir, strip: 1 });
|
|
197
|
-
const artifactManifest = await readJson(join(stagingDir, "package.json"));
|
|
198
|
-
await copyDirectoryContents(stagingDir, pkgRoot);
|
|
199
|
-
await applyHydratedManifest(pkgRoot, stubManifest, artifactManifest);
|
|
200
|
-
await saveToCache(slug, version, pkgRoot, artifactManifest);
|
|
201
|
-
} finally {
|
|
202
|
-
await rm(stagingDir, { recursive: true, force: true });
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async function main() {
|
|
207
|
-
if (process.env.SKY_UI_PRO_SKIP_POSTINSTALL === "1") return;
|
|
208
|
-
|
|
209
|
-
await loadInstallProjectEnv(pkgRoot);
|
|
210
|
-
|
|
211
|
-
const pkg = await readJson(join(pkgRoot, "package.json"));
|
|
212
|
-
const { name, version } = pkg;
|
|
213
|
-
if (!name?.startsWith("@sky.ui.pro/") || !version) {
|
|
214
|
-
console.warn("[@sky.ui.pro] postinstall: invalid package.json name/version");
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const stubManifest = structuredClone(pkg);
|
|
219
|
-
const slug = packageSlug(name);
|
|
220
|
-
const apiBase = resolveApiBase(pkg);
|
|
221
|
-
const strict = isInstallStrict();
|
|
222
|
-
|
|
223
|
-
await enforceCachePolicy(slug, version);
|
|
224
|
-
|
|
225
|
-
const token = await resolveToken();
|
|
226
|
-
const cacheAvailable =
|
|
227
|
-
(await exists(cacheVersionDir(cacheRoot, slug, version))) ||
|
|
228
|
-
(await exists(cacheVersionDir(legacyCacheRoot, slug, version)));
|
|
229
|
-
|
|
230
|
-
if (cacheAvailable) {
|
|
231
|
-
if (!token) {
|
|
232
|
-
printMissingToken(name, apiBase);
|
|
233
|
-
if (strict) process.exit(1);
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
const validation = await validateAccessTokenOnline(token, apiBase);
|
|
237
|
-
if (validation.active) {
|
|
238
|
-
if (await restoreFromCache(slug, version, pkgRoot, stubManifest)) {
|
|
239
|
-
await writeEntitlementMarker(pkgRoot, { name, version, status: validation.status ?? "active" });
|
|
240
|
-
console.log(`[@sky.ui.pro] Restored ${name}@${version} from cache.`);
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
} else {
|
|
244
|
-
printInvalidToken(name, validation, apiBase);
|
|
245
|
-
await invalidateCache(slug, version);
|
|
246
|
-
if (strict) process.exit(1);
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (!token) {
|
|
252
|
-
printMissingToken(name, apiBase);
|
|
253
|
-
if (strict) process.exit(1);
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const preDownloadValidation = await validateAccessTokenOnline(token, apiBase);
|
|
258
|
-
if (!preDownloadValidation.active) {
|
|
259
|
-
printInvalidToken(name, preDownloadValidation, apiBase);
|
|
260
|
-
if (strict) process.exit(1);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const url = tarballUrl(apiBase, name, version);
|
|
265
|
-
const res = await fetch(url, {
|
|
266
|
-
headers: { Authorization: `Bearer ${token}`, Accept: "application/octet-stream" },
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
if (!res.ok) {
|
|
270
|
-
const body = await res.text().catch(() => "");
|
|
271
|
-
console.error(`[@sky.ui.pro] Download failed (${res.status}) ${url}`);
|
|
272
|
-
if (body) console.error(body.slice(0, 500));
|
|
273
|
-
process.exit(1);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
await mkdir(cacheRoot, { recursive: true });
|
|
277
|
-
const tgzPath = join(cacheRoot, `${slug}-${version}.tgz`);
|
|
278
|
-
await pipeline(res.body, createWriteStream(tgzPath));
|
|
279
|
-
await installFromTarball(tgzPath, slug, version, stubManifest);
|
|
280
|
-
await writeEntitlementMarker(pkgRoot, { name, version, status: "active" });
|
|
281
|
-
console.log(`[@sky.ui.pro] Installed ${name}@${version}`);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
main().catch((err) => {
|
|
285
|
-
console.error("[@sky.ui.pro] postinstall error:", err instanceof Error ? err.message : err);
|
|
286
|
-
process.exit(1);
|
|
287
|
-
});
|