1 | 'use strict';
|
2 |
|
3 | var engine = require('zip-stream');
|
4 | var util = require('archiver-utils');
|
5 |
|
6 | var XMLWriter = require('xml-writer');
|
7 | var path = require('path');
|
8 | var propsId = '7857dbf80735479b8ee19fa60cb8239e';
|
9 |
|
10 |
|
11 | var 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 |
|
13 | var 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 |
|
41 | Nupkg.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 |
|
60 | Nupkg.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 |
|
80 | Nupkg.prototype.on = function() {
|
81 | return this.engine.on.apply(this.engine, arguments);
|
82 | };
|
83 |
|
84 | Nupkg.prototype.pipe = function() {
|
85 | return this.engine.pipe.apply(this.engine, arguments);
|
86 | };
|
87 |
|
88 | Nupkg.prototype.unpipe = function() {
|
89 | return this.engine.unpipe.apply(this.engine, arguments);
|
90 | };
|
91 |
|
92 | function 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 |
|
152 | function 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 |
|
181 | function 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 |
|
208 | function 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 |
|
232 | function 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 |