wyvrnpm 1.2.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/manifest.js CHANGED
@@ -1,77 +1,77 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
-
6
- /**
7
- * Valid project kind values, matching the C# serialisation enum.
8
- * @type {string[]}
9
- */
10
- const VALID_KINDS = [
11
- 'ConsoleApp',
12
- 'StaticLib',
13
- 'DynamicLib',
14
- 'HeaderOnlyLib',
15
- 'WebApp',
16
- 'Utility',
17
- 'Service',
18
- 'TestProject',
19
- ];
20
-
21
- /**
22
- * Returns a blank manifest object populated with sensible defaults.
23
- *
24
- * @param {string} name - Project name (typically the directory basename).
25
- * @returns {object}
26
- */
27
- function defaultManifest(name) {
28
- return {
29
- name: name,
30
- version: '1.0.0.0',
31
- description: '',
32
- kind: 'ConsoleApp',
33
- dependencies: {},
34
- };
35
- }
36
-
37
- /**
38
- * Reads and parses a wyvrn.json manifest from disk.
39
- *
40
- * @param {string} manifestPath - Absolute or relative path to wyvrn.json.
41
- * @returns {object} Parsed manifest data.
42
- * @throws {Error} If the file does not exist or contains invalid JSON.
43
- */
44
- function readManifest(manifestPath) {
45
- const resolved = path.resolve(manifestPath);
46
- if (!fs.existsSync(resolved)) {
47
- throw new Error(`Manifest not found: ${resolved}`);
48
- }
49
- const raw = fs.readFileSync(resolved, 'utf8');
50
- try {
51
- return JSON.parse(raw);
52
- } catch (err) {
53
- throw new Error(`Failed to parse manifest at ${resolved}: ${err.message}`);
54
- }
55
- }
56
-
57
- /**
58
- * Serialises and writes manifest data to disk with 2-space indentation.
59
- *
60
- * @param {string} manifestPath - Absolute or relative path to wyvrn.json.
61
- * @param {object} data - Manifest object to serialise.
62
- */
63
- function writeManifest(manifestPath, data) {
64
- const resolved = path.resolve(manifestPath);
65
- const dir = path.dirname(resolved);
66
- if (!fs.existsSync(dir)) {
67
- fs.mkdirSync(dir, { recursive: true });
68
- }
69
- fs.writeFileSync(resolved, JSON.stringify(data, null, 2) + '\n', 'utf8');
70
- }
71
-
72
- module.exports = {
73
- VALID_KINDS,
74
- defaultManifest,
75
- readManifest,
76
- writeManifest,
77
- };
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ /**
7
+ * Valid project kind values, matching the C# serialisation enum.
8
+ * @type {string[]}
9
+ */
10
+ const VALID_KINDS = [
11
+ 'ConsoleApp',
12
+ 'StaticLib',
13
+ 'DynamicLib',
14
+ 'HeaderOnlyLib',
15
+ 'WebApp',
16
+ 'Utility',
17
+ 'Service',
18
+ 'TestProject',
19
+ ];
20
+
21
+ /**
22
+ * Returns a blank manifest object populated with sensible defaults.
23
+ *
24
+ * @param {string} name - Project name (typically the directory basename).
25
+ * @returns {object}
26
+ */
27
+ function defaultManifest(name) {
28
+ return {
29
+ name: name,
30
+ version: '1.0.0.0',
31
+ description: '',
32
+ kind: 'ConsoleApp',
33
+ dependencies: {},
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Reads and parses a wyvrn.json manifest from disk.
39
+ *
40
+ * @param {string} manifestPath - Absolute or relative path to wyvrn.json.
41
+ * @returns {object} Parsed manifest data.
42
+ * @throws {Error} If the file does not exist or contains invalid JSON.
43
+ */
44
+ function readManifest(manifestPath) {
45
+ const resolved = path.resolve(manifestPath);
46
+ if (!fs.existsSync(resolved)) {
47
+ throw new Error(`Manifest not found: ${resolved}`);
48
+ }
49
+ const raw = fs.readFileSync(resolved, 'utf8');
50
+ try {
51
+ return JSON.parse(raw);
52
+ } catch (err) {
53
+ throw new Error(`Failed to parse manifest at ${resolved}: ${err.message}`);
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Serialises and writes manifest data to disk with 2-space indentation.
59
+ *
60
+ * @param {string} manifestPath - Absolute or relative path to wyvrn.json.
61
+ * @param {object} data - Manifest object to serialise.
62
+ */
63
+ function writeManifest(manifestPath, data) {
64
+ const resolved = path.resolve(manifestPath);
65
+ const dir = path.dirname(resolved);
66
+ if (!fs.existsSync(dir)) {
67
+ fs.mkdirSync(dir, { recursive: true });
68
+ }
69
+ fs.writeFileSync(resolved, JSON.stringify(data, null, 2) + '\n', 'utf8');
70
+ }
71
+
72
+ module.exports = {
73
+ VALID_KINDS,
74
+ defaultManifest,
75
+ readManifest,
76
+ writeManifest,
77
+ };
@@ -1,56 +1,56 @@
1
- 'use strict';
2
-
3
- /**
4
- * Base provider class. All publish providers must extend this.
5
- *
6
- * To add a new provider:
7
- * 1. Create src/providers/<name>.js that extends BaseProvider
8
- * 2. Register it in src/providers/index.js
9
- */
10
- class BaseProvider {
11
- /**
12
- * Returns true if this provider can handle the given source string.
13
- * Checked in registration order; first match wins.
14
- * @param {string} _source
15
- * @returns {boolean}
16
- */
17
- static canHandle(_source) {
18
- return false;
19
- }
20
-
21
- /**
22
- * Publish package files to the destination.
23
- *
24
- * @param {{ manifest: string, zip: string }} files
25
- * Absolute paths to the local wyvrn.json and wyvrn.zip to upload.
26
- * @param {{ source: string, platform: string, name: string, version: string, profile?: string, token?: string }} options
27
- * `source` – the raw --source value (URL / URI)
28
- * `platform` – target platform string (e.g. win_x64)
29
- * `name` – package name from manifest
30
- * `version` – package version from manifest
31
- * `profile` – AWS SSO profile (S3 provider)
32
- * `token` – Bearer token (HTTP provider)
33
- * @returns {Promise<void>}
34
- */
35
- async publish(_files, _options) {
36
- throw new Error(`publish() is not implemented in ${this.constructor.name}`);
37
- }
38
-
39
- /**
40
- * Returns true if the given package version already exists at the destination.
41
- * Providers should override this; the default assumes it does not exist.
42
- *
43
- * @param {{ source: string, platform: string, name: string, version: string, profile?: string, token?: string }} _options
44
- * @returns {Promise<boolean>}
45
- */
46
- async exists(_options) {
47
- return false;
48
- }
49
-
50
- /** Human-readable provider name shown in log output. */
51
- static get providerName() {
52
- return 'BaseProvider';
53
- }
54
- }
55
-
56
- module.exports = BaseProvider;
1
+ 'use strict';
2
+
3
+ /**
4
+ * Base provider class. All publish providers must extend this.
5
+ *
6
+ * To add a new provider:
7
+ * 1. Create src/providers/<name>.js that extends BaseProvider
8
+ * 2. Register it in src/providers/index.js
9
+ */
10
+ class BaseProvider {
11
+ /**
12
+ * Returns true if this provider can handle the given source string.
13
+ * Checked in registration order; first match wins.
14
+ * @param {string} _source
15
+ * @returns {boolean}
16
+ */
17
+ static canHandle(_source) {
18
+ return false;
19
+ }
20
+
21
+ /**
22
+ * Publish package files to the destination.
23
+ *
24
+ * @param {{ manifest: string, zip: string }} files
25
+ * Absolute paths to the local wyvrn.json and wyvrn.zip to upload.
26
+ * @param {{ source: string, platform: string, name: string, version: string, profile?: string, token?: string }} options
27
+ * `source` – the raw --source value (URL / URI)
28
+ * `platform` – target platform string (e.g. win_x64)
29
+ * `name` – package name from manifest
30
+ * `version` – package version from manifest
31
+ * `profile` – AWS SSO profile (S3 provider)
32
+ * `token` – Bearer token (HTTP provider)
33
+ * @returns {Promise<void>}
34
+ */
35
+ async publish(_files, _options) {
36
+ throw new Error(`publish() is not implemented in ${this.constructor.name}`);
37
+ }
38
+
39
+ /**
40
+ * Returns true if the given package version already exists at the destination.
41
+ * Providers should override this; the default assumes it does not exist.
42
+ *
43
+ * @param {{ source: string, platform: string, name: string, version: string, profile?: string, token?: string }} _options
44
+ * @returns {Promise<boolean>}
45
+ */
46
+ async exists(_options) {
47
+ return false;
48
+ }
49
+
50
+ /** Human-readable provider name shown in log output. */
51
+ static get providerName() {
52
+ return 'BaseProvider';
53
+ }
54
+ }
55
+
56
+ module.exports = BaseProvider;
@@ -1,71 +1,71 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const BaseProvider = require('./base');
6
-
7
- /**
8
- * File system provider — handles local directories and SMB/UNC shares.
9
- *
10
- * Recognised source formats:
11
- * /abs/unix/path
12
- * ./relative/path ../relative/path
13
- * C:\Windows\path C:/Windows/path (drive-letter)
14
- * \\server\share\path (SMB UNC — backslash)
15
- * //server/share/path (SMB UNC — forward slash)
16
- * file:///path (file URI)
17
- */
18
- class FileProvider extends BaseProvider {
19
- static canHandle(source) {
20
- return (
21
- source.startsWith('file://') ||
22
- source.startsWith('//') ||
23
- source.startsWith('\\\\') ||
24
- source.startsWith('/') ||
25
- source.startsWith('./') ||
26
- source.startsWith('../') ||
27
- /^[a-zA-Z]:[/\\]/.test(source) // Windows drive letter
28
- );
29
- }
30
-
31
- static get providerName() {
32
- return 'File';
33
- }
34
-
35
- /** Normalise a source string to an absolute file system path. */
36
- _resolvePath(source) {
37
- if (source.startsWith('file://')) {
38
- return path.resolve(new URL(source).pathname);
39
- }
40
- return path.resolve(source);
41
- }
42
-
43
- async exists(options) {
44
- const { source, platform, name, version } = options;
45
- const destDir = path.join(this._resolvePath(source), platform, name, version);
46
- return fs.existsSync(path.join(destDir, 'wyvrn.json'));
47
- }
48
-
49
- async publish(files, options) {
50
- const { source, platform, name, version } = options;
51
-
52
- const packageDir = path.join(this._resolvePath(source), platform, name);
53
- const destDir = path.join(packageDir, version);
54
- fs.mkdirSync(destDir, { recursive: true });
55
-
56
- this._copy(files.manifest, path.join(destDir, 'wyvrn.json'));
57
- this._copy(files.zip, path.join(destDir, 'wyvrn.zip'));
58
-
59
- // Write latest.json at the package root so consumers can resolve "latest"
60
- const latestPath = path.join(packageDir, 'latest.json');
61
- console.log(`[wyvrn] → ${latestPath}`);
62
- fs.writeFileSync(latestPath, JSON.stringify({ version }), 'utf8');
63
- }
64
-
65
- _copy(src, dest) {
66
- console.log(`[wyvrn] → ${dest}`);
67
- fs.copyFileSync(src, dest);
68
- }
69
- }
70
-
71
- module.exports = FileProvider;
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const BaseProvider = require('./base');
6
+
7
+ /**
8
+ * File system provider — handles local directories and SMB/UNC shares.
9
+ *
10
+ * Recognised source formats:
11
+ * /abs/unix/path
12
+ * ./relative/path ../relative/path
13
+ * C:\Windows\path C:/Windows/path (drive-letter)
14
+ * \\server\share\path (SMB UNC — backslash)
15
+ * //server/share/path (SMB UNC — forward slash)
16
+ * file:///path (file URI)
17
+ */
18
+ class FileProvider extends BaseProvider {
19
+ static canHandle(source) {
20
+ return (
21
+ source.startsWith('file://') ||
22
+ source.startsWith('//') ||
23
+ source.startsWith('\\\\') ||
24
+ source.startsWith('/') ||
25
+ source.startsWith('./') ||
26
+ source.startsWith('../') ||
27
+ /^[a-zA-Z]:[/\\]/.test(source) // Windows drive letter
28
+ );
29
+ }
30
+
31
+ static get providerName() {
32
+ return 'File';
33
+ }
34
+
35
+ /** Normalise a source string to an absolute file system path. */
36
+ _resolvePath(source) {
37
+ if (source.startsWith('file://')) {
38
+ return path.resolve(new URL(source).pathname);
39
+ }
40
+ return path.resolve(source);
41
+ }
42
+
43
+ async exists(options) {
44
+ const { source, platform, name, version } = options;
45
+ const destDir = path.join(this._resolvePath(source), platform, name, version);
46
+ return fs.existsSync(path.join(destDir, 'wyvrn.json'));
47
+ }
48
+
49
+ async publish(files, options) {
50
+ const { source, platform, name, version } = options;
51
+
52
+ const packageDir = path.join(this._resolvePath(source), platform, name);
53
+ const destDir = path.join(packageDir, version);
54
+ fs.mkdirSync(destDir, { recursive: true });
55
+
56
+ this._copy(files.manifest, path.join(destDir, 'wyvrn.json'));
57
+ this._copy(files.zip, path.join(destDir, 'wyvrn.zip'));
58
+
59
+ // Write latest.json at the package root so consumers can resolve "latest"
60
+ const latestPath = path.join(packageDir, 'latest.json');
61
+ console.log(`[wyvrn] → ${latestPath}`);
62
+ fs.writeFileSync(latestPath, JSON.stringify({ version }), 'utf8');
63
+ }
64
+
65
+ _copy(src, dest) {
66
+ console.log(`[wyvrn] → ${dest}`);
67
+ fs.copyFileSync(src, dest);
68
+ }
69
+ }
70
+
71
+ module.exports = FileProvider;
@@ -1,118 +1,118 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const http = require('http');
5
- const https = require('https');
6
- const BaseProvider = require('./base');
7
-
8
- class HttpProvider extends BaseProvider {
9
- static canHandle(source) {
10
- return /^https?:\/\//.test(source);
11
- }
12
-
13
- static get providerName() {
14
- return 'HTTP';
15
- }
16
-
17
- async exists(options) {
18
- const { source, platform, name, version } = options;
19
- const base = source.replace(/\/$/, '');
20
- const url = `${base}/${platform}/${name}/${version}/wyvrn.json`;
21
- return new Promise((resolve, reject) => {
22
- const parsed = new URL(url);
23
- const lib = parsed.protocol === 'https:' ? https : http;
24
- const req = lib.request(
25
- { hostname: parsed.hostname, port: parsed.port || undefined, path: parsed.pathname, method: 'HEAD' },
26
- (res) => { res.resume(); resolve(res.statusCode >= 200 && res.statusCode < 300); },
27
- );
28
- req.on('error', reject);
29
- req.end();
30
- });
31
- }
32
-
33
- async publish(files, options) {
34
- const { source, platform, name, version, token } = options;
35
- const base = source.replace(/\/$/, '');
36
- const urlBase = `${base}/${platform}/${name}/${version}`;
37
- const packageBase = `${base}/${platform}/${name}`;
38
-
39
- await this._put(`${urlBase}/wyvrn.json`, files.manifest, 'application/json', token);
40
- await this._put(`${urlBase}/wyvrn.zip`, files.zip, 'application/zip', token);
41
-
42
- // Write latest.json at the package root so consumers can resolve "latest"
43
- await this._putBuffer(`${packageBase}/latest.json`, Buffer.from(JSON.stringify({ version })), 'application/json', token);
44
- }
45
-
46
- _put(url, filePath, contentType, token) {
47
- return new Promise((resolve, reject) => {
48
- const body = fs.readFileSync(filePath);
49
- const parsed = new URL(url);
50
- const lib = parsed.protocol === 'https:' ? https : http;
51
-
52
- const headers = {
53
- 'Content-Type': contentType,
54
- 'Content-Length': body.length,
55
- };
56
- if (token) headers['Authorization'] = `Bearer ${token}`;
57
-
58
- console.log(`[wyvrn] → PUT ${url}`);
59
- const req = lib.request(
60
- {
61
- hostname: parsed.hostname,
62
- port: parsed.port || undefined,
63
- path: parsed.pathname,
64
- method: 'PUT',
65
- headers,
66
- },
67
- (res) => {
68
- res.resume(); // drain the response
69
- if (res.statusCode >= 200 && res.statusCode < 300) {
70
- resolve();
71
- } else {
72
- reject(new Error(`HTTP PUT ${url} failed: ${res.statusCode} ${res.statusMessage}`));
73
- }
74
- },
75
- );
76
- req.on('error', reject);
77
- req.write(body);
78
- req.end();
79
- });
80
- }
81
-
82
- _putBuffer(url, buffer, contentType, token) {
83
- return new Promise((resolve, reject) => {
84
- const parsed = new URL(url);
85
- const lib = parsed.protocol === 'https:' ? https : http;
86
-
87
- const headers = {
88
- 'Content-Type': contentType,
89
- 'Content-Length': buffer.length,
90
- };
91
- if (token) headers['Authorization'] = `Bearer ${token}`;
92
-
93
- console.log(`[wyvrn] → PUT ${url}`);
94
- const req = lib.request(
95
- {
96
- hostname: parsed.hostname,
97
- port: parsed.port || undefined,
98
- path: parsed.pathname,
99
- method: 'PUT',
100
- headers,
101
- },
102
- (res) => {
103
- res.resume();
104
- if (res.statusCode >= 200 && res.statusCode < 300) {
105
- resolve();
106
- } else {
107
- reject(new Error(`HTTP PUT ${url} failed: ${res.statusCode} ${res.statusMessage}`));
108
- }
109
- },
110
- );
111
- req.on('error', reject);
112
- req.write(buffer);
113
- req.end();
114
- });
115
- }
116
- }
117
-
118
- module.exports = HttpProvider;
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const http = require('http');
5
+ const https = require('https');
6
+ const BaseProvider = require('./base');
7
+
8
+ class HttpProvider extends BaseProvider {
9
+ static canHandle(source) {
10
+ return /^https?:\/\//.test(source);
11
+ }
12
+
13
+ static get providerName() {
14
+ return 'HTTP';
15
+ }
16
+
17
+ async exists(options) {
18
+ const { source, platform, name, version } = options;
19
+ const base = source.replace(/\/$/, '');
20
+ const url = `${base}/${platform}/${name}/${version}/wyvrn.json`;
21
+ return new Promise((resolve, reject) => {
22
+ const parsed = new URL(url);
23
+ const lib = parsed.protocol === 'https:' ? https : http;
24
+ const req = lib.request(
25
+ { hostname: parsed.hostname, port: parsed.port || undefined, path: parsed.pathname, method: 'HEAD' },
26
+ (res) => { res.resume(); resolve(res.statusCode >= 200 && res.statusCode < 300); },
27
+ );
28
+ req.on('error', reject);
29
+ req.end();
30
+ });
31
+ }
32
+
33
+ async publish(files, options) {
34
+ const { source, platform, name, version, token } = options;
35
+ const base = source.replace(/\/$/, '');
36
+ const urlBase = `${base}/${platform}/${name}/${version}`;
37
+ const packageBase = `${base}/${platform}/${name}`;
38
+
39
+ await this._put(`${urlBase}/wyvrn.json`, files.manifest, 'application/json', token);
40
+ await this._put(`${urlBase}/wyvrn.zip`, files.zip, 'application/zip', token);
41
+
42
+ // Write latest.json at the package root so consumers can resolve "latest"
43
+ await this._putBuffer(`${packageBase}/latest.json`, Buffer.from(JSON.stringify({ version })), 'application/json', token);
44
+ }
45
+
46
+ _put(url, filePath, contentType, token) {
47
+ return new Promise((resolve, reject) => {
48
+ const body = fs.readFileSync(filePath);
49
+ const parsed = new URL(url);
50
+ const lib = parsed.protocol === 'https:' ? https : http;
51
+
52
+ const headers = {
53
+ 'Content-Type': contentType,
54
+ 'Content-Length': body.length,
55
+ };
56
+ if (token) headers['Authorization'] = `Bearer ${token}`;
57
+
58
+ console.log(`[wyvrn] → PUT ${url}`);
59
+ const req = lib.request(
60
+ {
61
+ hostname: parsed.hostname,
62
+ port: parsed.port || undefined,
63
+ path: parsed.pathname,
64
+ method: 'PUT',
65
+ headers,
66
+ },
67
+ (res) => {
68
+ res.resume(); // drain the response
69
+ if (res.statusCode >= 200 && res.statusCode < 300) {
70
+ resolve();
71
+ } else {
72
+ reject(new Error(`HTTP PUT ${url} failed: ${res.statusCode} ${res.statusMessage}`));
73
+ }
74
+ },
75
+ );
76
+ req.on('error', reject);
77
+ req.write(body);
78
+ req.end();
79
+ });
80
+ }
81
+
82
+ _putBuffer(url, buffer, contentType, token) {
83
+ return new Promise((resolve, reject) => {
84
+ const parsed = new URL(url);
85
+ const lib = parsed.protocol === 'https:' ? https : http;
86
+
87
+ const headers = {
88
+ 'Content-Type': contentType,
89
+ 'Content-Length': buffer.length,
90
+ };
91
+ if (token) headers['Authorization'] = `Bearer ${token}`;
92
+
93
+ console.log(`[wyvrn] → PUT ${url}`);
94
+ const req = lib.request(
95
+ {
96
+ hostname: parsed.hostname,
97
+ port: parsed.port || undefined,
98
+ path: parsed.pathname,
99
+ method: 'PUT',
100
+ headers,
101
+ },
102
+ (res) => {
103
+ res.resume();
104
+ if (res.statusCode >= 200 && res.statusCode < 300) {
105
+ resolve();
106
+ } else {
107
+ reject(new Error(`HTTP PUT ${url} failed: ${res.statusCode} ${res.statusMessage}`));
108
+ }
109
+ },
110
+ );
111
+ req.on('error', reject);
112
+ req.write(buffer);
113
+ req.end();
114
+ });
115
+ }
116
+ }
117
+
118
+ module.exports = HttpProvider;