UNPKG

7.15 kBJavaScriptView Raw
1'use strict';
2
3var engine = require('zip-stream');
4var util = require('archiver-utils');
5
6var XMLWriter = require('xml-writer');
7var path = require('path');
8var propsId = '7857dbf80735479b8ee19fa60cb8239e';
9
10// MIT licensed by Sindre Sorhus https://github.com/sindresorhus/semver-regex
11var semVerRegex = /\bv?(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?\b/ig;
12
13var Nupkg = module.exports = function(options) {
14 if (!(this instanceof Nupkg)) {
15 return new Nupkg(options);
16 }
17
18 options = this.options = util.defaults(options, {
19 comment: '',
20 forceUTC: false,
21 store: false
22 });
23
24 if (typeof options.nupkgOptions !== 'object') {
25 options.nupkgOptions = {};
26 }
27
28 this.supports = {
29 directory: true
30 };
31
32 this.engine = new engine(options);
33
34 this._appending = 0;
35 this._extensions = [];
36 this._meta = options.nupkgOptions;
37
38 verifyMeta(this._meta);
39};
40
41Nupkg.prototype.append = function(source, data, callback) {
42 var self = this;
43 self._appending++;
44
45 data.name = data.name
46 .replace(/\\/g, '/')
47 .replace(/\s/g,'%20');
48
49 this.engine.entry(source, data, function() {
50 self._extensions[path.extname(data.name).substr(1)] = true;
51 if(--self._appending === 0 && self.idle){
52 self.idle();
53 }
54 if(callback) {
55 callback.apply(this, callback, arguments);
56 }
57 });
58};
59
60Nupkg.prototype.finalize = function() {
61 var self = this;
62 this.idle = function () {
63 delete self.idle;
64 self.append(getContentTypesXml(self._extensions), { name: '[Content_Types].xml' }, function () {
65 self.append(getNuSpecXml(self._meta), { name: self._meta.id + '.nuspec' }, function () {
66 self.append(getCorePropertiesXml(self._meta), { name: 'package/services/metadata/core-properties/' + propsId + '.psmdcp' }, function () {
67 self.append(getRelsXml(self._meta), { name: '_rels/.rels' }, function () {
68 self.engine.finalize();
69 });
70 });
71 });
72 });
73 };
74
75 if (self._appending === 0) {
76 this.idle();
77 }
78};
79
80Nupkg.prototype.on = function() {
81 return this.engine.on.apply(this.engine, arguments);
82};
83
84Nupkg.prototype.pipe = function() {
85 return this.engine.pipe.apply(this.engine, arguments);
86};
87
88Nupkg.prototype.unpipe = function() {
89 return this.engine.unpipe.apply(this.engine, arguments);
90};
91
92function getNuSpecXml(meta) {
93 var properties = [
94 'id', 'title', 'version', 'authors', 'owners', 'licenseUrl',
95 'projectUrl', 'iconUrl', 'requireLicenseAcceptance',
96 'description', 'summary', 'releaseNotes', 'copyright',
97 'language', 'tags', 'dependencies'
98 ];
99
100 function normalizeVersionDep(version) {
101 version = version.replace(/\s+/, '');
102
103 if (!semVerRegex.test(version)) {
104 throw new Error('Invalid version dependecy: ' + version);
105 }
106
107 if (semVerRegex.test(version)) {
108 return version;
109 }
110
111 version = version[0] + version.substr(1, version.length - 2).split(',').join(', ') + version[version.length - 1];
112
113 return version;
114 }
115
116 var xw = new XMLWriter(true);
117
118 xw.startDocument();
119 xw.startElement('package');
120 xw.writeAttribute('xmlns', 'http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd');
121 xw.startElement('metadata');
122
123 properties.forEach(function (property) {
124 if (property in meta) {
125 if (property === 'dependencies') {
126 xw.startElement('dependencies');
127
128 meta[property].forEach(function (dep) {
129 xw.startElement('dependency');
130 xw.writeAttribute('id', dep.id);
131
132 if (dep.version) {
133 xw.writeAttribute('version', normalizeVersionDep(dep.version));
134 }
135
136 xw.endElement();
137 });
138
139 xw.endElement();
140 return;
141 }
142
143 xw.writeElement(property, meta[property].toString());
144 }
145 });
146
147 xw.endDocument();
148
149 return xw.toString();
150}
151
152function getCorePropertiesXml(meta) {
153 var xw = new XMLWriter(true, 'utf-8');
154
155 function writeProp(name, value) {
156 if (value) {
157 xw.writeElement(name, value);
158 }
159 }
160
161 xw.startDocument();
162 xw.startElement('coreProperties');
163 xw.writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
164 xw.writeAttribute('xmlns:dcterms', 'http://purl.org/dc/terms/');
165 xw.writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
166 xw.writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties');
167
168 writeProp('dc:creator', meta.authors);
169 writeProp('dc:description', meta.description);
170 writeProp('dc:identifier', meta.id);
171 writeProp('version', meta.version);
172 writeProp('dc:language', meta.language);
173 writeProp('keywords', meta.tags);
174 writeProp('lastModifiedBy', 'NuGet, Version=2.8.50320.36, Culture=neutral, PublicKeyToken=null;Microsoft Windows NT 6.2.9200.0;.NET Framework 4');
175
176 xw.endDocument();
177
178 return xw.toString();
179}
180
181function getContentTypesXml(extensions) {
182 var xw = new XMLWriter(true, 'utf-8');
183 xw.startDocument();
184 xw.startElement('Types');
185 xw.writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/content-types');
186
187 addContentType('rels', 'application/vnd.openxmlformats-package.relationships+xml');
188 addContentType('nuspec', 'application/octet');
189 addContentType('psmdcp', 'application/vnd.openxmlformats-package.core-properties+xml');
190
191 for (var ext in extensions) {
192 if(ext && ext !== '') {
193 addContentType(ext, 'application/octet');
194 }
195 }
196
197 function addContentType(ext, type){
198 xw.startElement('Default');
199 xw.writeAttribute('Extension', ext);
200 xw.writeAttribute('ContentType', type || 'application/octet');
201 xw.endElement();
202 }
203
204 xw.endDocument();
205 return xw.toString();
206}
207
208function getRelsXml(meta) {
209 var xw = new XMLWriter(true, 'utf-8');
210
211 xw.startDocument();
212 xw.startElement('Relationships');
213 xw.writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
214
215 xw.startElement('Relationship');
216 xw.writeAttribute('Type', 'http://schemas.microsoft.com/packaging/2010/07/manifest');
217 xw.writeAttribute('Target', '/' + meta.id + '.nuspec');
218 xw.writeAttribute('Id', 'R569c48f3cf1b4b14');
219 xw.endElement();
220
221 xw.startElement('Relationship');
222 xw.writeAttribute('Type', 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties');
223 xw.writeAttribute('Target', '/package/services/metadata/core-properties/' + propsId + '.psmdcp');
224 xw.writeAttribute('Id', 'R9e8f0077d5174f67');
225 xw.endElement();
226
227 xw.endDocument();
228
229 return xw.toString();
230}
231
232function verifyMeta(meta) {
233 if (!meta.id) {
234 throw new Error('Missing required package id.');
235 }
236
237 if (!/^[a-z0-9\.\-]+$/i.test(meta.id)) {
238 throw new Error('Package id isn\'t in a valid format.');
239 }
240
241 if (!meta.version) {
242 throw new Error('Missing required package version.');
243 }
244
245 if (!semVerRegex.test(meta.version)) {
246 throw new Error('Version isn\'t proper sem-ver "x.x.x".');
247 }
248
249 if (!meta.authors) {
250 throw new Error('Missing required package authors.');
251 }
252
253 if (!meta.description) {
254 throw new Error('Missing required package description.');
255 }
256}
\No newline at end of file