Skip to content

Commit 887ae13

Browse files
authored
Merge pull request #1415 from nexB/1398-json2csv
Accept non-standard package data in CSV #1398
2 parents 21d386f + 0bf5033 commit 887ae13

14 files changed

Lines changed: 305 additions & 135 deletions

File tree

src/formattedcode/output_csv.py

Lines changed: 90 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,37 @@
3737
from scancode import FileOptionType
3838
from scancode import OUTPUT_GROUP
3939

40+
# Python 2 and 3 support
41+
try:
42+
# Python 2
43+
unicode
44+
str = unicode # NOQA
45+
except NameError:
46+
# Python 3
47+
unicode = str # NOQA
48+
basestring = str # NOQA
49+
50+
51+
# Tracing flags
52+
TRACE = False
53+
54+
55+
def logger_debug(*args):
56+
pass
57+
58+
59+
if TRACE:
60+
import sys
61+
import logging
62+
63+
logger = logging.getLogger(__name__)
64+
logging.basicConfig(stream=sys.stdout)
65+
logger.setLevel(logging.DEBUG)
66+
67+
def logger_debug(*args):
68+
return logger.debug(' '.join(isinstance(a, unicode)
69+
and a or repr(a) for a in args))
70+
4071

4172
@output_impl
4273
class CsvOutput(OutputPlugin):
@@ -199,114 +230,98 @@ def collect_keys(mapping, key_group):
199230
yield flat
200231

201232

202-
def flatten_package(_package, path, prefix='package__'):
233+
def get_package_columns(_columns=set()):
234+
"""
235+
Return (and cache in_columns) a set of package column names included in the
236+
CSV output.
237+
Some columsn are excluded for now such as lists of mappings: these do not
238+
serialize well to CSV
239+
"""
240+
if _columns:
241+
return _columns
242+
243+
from packagedcode.models import Package
203244

204245
# exclude some columns for now that contain list of items
205-
excluded_package_columns = {
246+
excluded_columns = {
206247
# list of strings
207-
'download_checksums',
208248
'keywords',
209249
# list of dicts
210250
'parties',
211251
'dependencies',
252+
'source_packages',
253+
}
212254

213-
# comming from a match
255+
# some extra columns for components
256+
extra_columns = [
257+
'components',
258+
'owner_name',
259+
'reference_notes',
260+
'description',
261+
'notice_filename',
262+
'notice_url',
263+
]
214264

215-
# we have license_expression we do not need more
216-
'licenses_summary',
217-
'licenses',
218-
'license_choices_expression',
219-
'license_choices',
265+
fields = Package.fields() + extra_columns
266+
_columns = set(f for f in fields if f not in excluded_columns)
267+
return _columns
220268

221-
'api_url',
222-
'uuid',
223-
'sha1',
224-
'md5',
225-
'owner',
226269

227-
'reference_notes',
228-
'project',
229-
'codescan_identifier',
230-
'is_license_notice',
231-
'is_copyright_notice',
232-
'is_notice_in_codebase',
233-
# 'notice_filename',
234-
# 'notice_url',
235-
'website_terms_of_use',
236-
'is_active',
237-
'curation_level',
238-
'completion_level',
239-
'guidance',
240-
'admin_notes',
241-
'ip_sensitivity_approved',
242-
'affiliate_obligations',
243-
'affiliate_obligation_triggers',
244-
'concluded_license',
245-
'legal_comments',
246-
'legal_reviewed',
247-
'approval_reference',
248-
'distribution_formats_allowed',
249-
'acceptable_linkage',
250-
'export_restrictions',
251-
'approved_download_location',
252-
'approved_community_interaction',
253-
'urn',
254-
'created_date',
255-
'last_modified_date',
256-
'dataspace',
257-
'external_references',
258-
'display_name',
259-
'notes',
260-
'origin_date',
261-
'sublicense_allowed',
262-
}
270+
def flatten_package(_package, path, prefix='package__'):
271+
272+
# known package columns
273+
274+
package_columns = get_package_columns()
263275

264276
pack = OrderedDict(Resource=path)
265277
for k, val in _package.items():
266-
# FIXME: we only keep for now some of the value collections
267-
if k in excluded_package_columns:
278+
if k not in package_columns:
268279
continue
280+
269281
# prefix columns with "package__"
270282
nk = prefix + k
271283

272284
if k == 'version':
273-
if val:
285+
val = val or ''
286+
if val and not val.lower().startswith('v'):
274287
# prefix versions with a v to avoid spreadsheet tools to mistake
275-
# a version for a number or date.
288+
# a version for a number or date when reading CSVs (common with
289+
# Excel and LibreOffice).
276290
val = 'v ' + val
277-
pack[nk] = val
278-
else:
279-
pack[nk] = ''
291+
pack[nk] = val
280292
continue
281293

282-
# these may come from a match
283-
294+
# these may come from a component matched
284295
if k == 'components' and val and isinstance(val, list):
285-
for compo in val:
286-
for compo_key, compo_val in compo.items():
287-
if compo_key in excluded_package_columns:
296+
for component in val:
297+
for component_key, component_val in component.items():
298+
if component_key not in package_columns:
288299
continue
289300

290-
compo_nk = nk + '__' + compo_key
301+
component_new_key = nk + '__' + component_key
291302

292-
if compo_val is None:
293-
pack[compo_nk] = ''
303+
if component_val is None:
304+
pack[component_new_key] = ''
294305
continue
295306

296-
if not isinstance(compo_val, basestring):
297-
compo_val = repr(compo_val)
298-
existing = pack.get(compo_nk) or []
299-
pack[compo_nk] = ' \n'.join(existing + [compo_val])
300-
continue
307+
if isinstance(component_val, list):
308+
component_val = '\n'.join(component_val)
309+
310+
if not isinstance(component_val, str):
311+
component_val = repr(component_val)
312+
313+
existing = pack.get(component_new_key) or []
314+
if not isinstance(existing, list):
315+
existing = [existing]
316+
317+
if TRACE:
318+
logger_debug('component_new_key:', component_new_key, 'existing:', type(existing), repr(existing))
319+
logger_debug('component_key:', component_key, 'component_val:', type(component_val), repr(component_val))
301320

302-
if k == 'match':
303-
for mk, mval in val.items():
304-
match_nk = nk + '__' + mk
305-
pack[match_nk] = mval
321+
pack[component_new_key] = ' \n'.join(existing + [component_val])
306322
continue
307323

308324
# everything else
309-
# collect all the keys
310325

311326
pack[nk] = ''
312327

src/packagedcode/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ def create(cls, ignore_unknown=True, **kwargs):
125125
kwargs = {k: v for k, v in kwargs.items() if k in known_attr}
126126
return cls(**kwargs)
127127

128+
@classmethod
129+
def fields(cls):
130+
"""
131+
Return a list of field names defined on this model.
132+
"""
133+
return [a.name for a in attr.fields(cls)]
134+
128135

129136
party_person = 'person'
130137
# often loosely defined

tests/formattedcode/data/csv/flatten_scan/full.json-expected

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,10 @@
147147
"package__download_url": "",
148148
"package__bug_tracking_url": "",
149149
"package__code_view_url": "",
150-
"package__vcs_tool": "",
151-
"package__vcs_repository": "",
152-
"package__vcs_revision": "",
153150
"package__copyright": "",
154151
"package__license_expression": "",
155-
"package__declared_licensing": "",
156152
"package__notice_text": "",
157-
"package__contains_source_code": "",
158-
"package__source_packages": ""
153+
"package__contains_source_code": ""
159154
},
160155
{
161156
"Resource": "/samples/JGroups/",
@@ -1418,15 +1413,10 @@
14181413
"package__download_url": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz",
14191414
"package__bug_tracking_url": "https://github.com/visionmedia/node-cookie-signature/issues",
14201415
"package__code_view_url": "",
1421-
"package__vcs_tool": "git",
1422-
"package__vcs_repository": "https://github.com/visionmedia/node-cookie-signature.git",
1423-
"package__vcs_revision": "",
14241416
"package__copyright": "",
14251417
"package__license_expression": "",
1426-
"package__declared_licensing": "",
14271418
"package__notice_text": "",
1428-
"package__contains_source_code": "",
1429-
"package__source_packages": ""
1419+
"package__contains_source_code": ""
14301420
},
14311421
{
14321422
"Resource": "/samples/srp/scan/json2csv.rb",

tests/formattedcode/data/csv/flatten_scan/package_license_value_null.json-expected

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,9 @@
3939
"package__download_url": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz",
4040
"package__bug_tracking_url": "https://github.com/visionmedia/node-cookie-signature/issues",
4141
"package__code_view_url": "",
42-
"package__vcs_tool": "git",
43-
"package__vcs_repository": "https://github.com/visionmedia/node-cookie-signature.git",
44-
"package__vcs_revision": "",
4542
"package__copyright": "",
4643
"package__license_expression": "",
47-
"package__declared_licensing": "",
4844
"package__notice_text": "",
49-
"package__contains_source_code": "",
50-
"package__source_packages": ""
45+
"package__contains_source_code": ""
5146
}
5247
]
Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
Resource,type,name,base_name,extension,size,date,sha1,md5,mime_type,file_type,programming_language,is_binary,is_text,is_archive,is_media,is_source,is_script,files_count,dirs_count,size_count,scan_errors,license_expression,license__key,license__score,license__name,license__short_name,license__category,license__is_exception,license__owner,license__homepage_url,license__text_url,license__reference_url,license__spdx_license_key,license__spdx_url,start_line,end_line,matched_rule__identifier,matched_rule__license_expression,matched_rule__licenses,matched_rule__is_license_text,matched_rule__is_license_notice,matched_rule__is_license_reference,matched_rule__is_license_tag,copyright,copyright_holder,email,url,package__type,package__namespace,package__name,package__version,package__qualifiers,package__subpath,package__primary_language,package__description,package__release_date,package__homepage_url,package__download_url,package__size,package__sha256,package__sha512,package__bug_tracking_url,package__code_view_url,package__vcs_url,package__copyright,package__license_expression,package__declared_license,package__notice_text,package__manifest_path,package__contains_source_code,package__source_packages,package__purl,package__repository_homepage_url,package__repository_download_url,package__api_data_url
2-
/json2csv.rb,file,json2csv.rb,json2csv,.rb,912,2019-01-07,1236469a06a2bacbdd8e172ad718482af5b0a936,1307c281e0b153202e291b217eab85d5,text/x-python,"Python script, ASCII text executable",Ruby,False,True,False,False,True,True,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
3-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,apache-2.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
4-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,apache-2.0,100.00,Apache License 2.0,Apache 2.0,Permissive,False,Apache Software Foundation,http://www.apache.org/licenses/,http://www.apache.org/licenses/LICENSE-2.0,https://enterprise.dejacode.com/urn/urn:dje:license:apache-2.0,Apache-2.0,https://spdx.org/licenses/Apache-2.0,5,13,apache-2.0_7.RULE,apache-2.0,[u'apache-2.0'],False,True,False,False,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
5-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,3,,,,,,,,Copyright (c) 2017 nexB Inc. and others.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
6-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,3,,,,,,,,,nexB Inc. and others.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
7-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,4,,,,,,,,,,,http://nexb.com/,,,,,,,,,,,,,,,,,,,,,,,,,,,,
8-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,4,,,,,,,,,,,https://github.com/nexB/scancode-toolkit/,,,,,,,,,,,,,,,,,,,,,,,,,,,,
9-
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,8,,,,,,,,,,,http://www.apache.org/licenses/LICENSE-2.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,
10-
/license,file,license,license,,679,2018-04-11,75c5490a718ddd45e40e0cc7ce0c756abc373123,b965a762efb9421cf1bf4405f336e278,text/plain,ASCII text,,False,True,False,False,False,False,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
11-
/license,,,,,,,,,,,,,,,,,,,,,,gpl-2.0-plus,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
12-
/license,,,,,,,,,,,,,,,,,,,,,,,gpl-2.0-plus,100.00,GNU General Public License 2.0 or later,GPL 2.0 or later,Copyleft,False,Free Software Foundation (FSF),http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html,http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html,https://enterprise.dejacode.com/urn/urn:dje:license:gpl-2.0-plus,GPL-2.0-or-later,https://spdx.org/licenses/GPL-2.0-or-later,1,12,gpl-2.0-plus.LICENSE,gpl-2.0-plus,[u'gpl-2.0-plus'],True,False,False,False,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
13-
/package.json,file,package.json,package,.json,2200,2018-04-11,918376afce796ef90eeda1d6695f2289c90491ac,1f66239a9b850c5e60a9382dbe2162d2,text/plain,"ASCII text, with very long lines",,False,True,False,False,False,False,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
14-
/package.json,,,,,,,,,,,,,,,,,,,,,,mit,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
15-
/package.json,,,,,,,,,,,,,,,,,,,,,,,mit,99.40,MIT License,MIT License,Permissive,False,MIT,http://opensource.org/licenses/mit-license.php,http://opensource.org/licenses/mit-license.php,https://enterprise.dejacode.com/urn/urn:dje:license:mit,MIT,https://spdx.org/licenses/MIT,24,24,mit_31.RULE,mit,[u'mit'],True,False,False,False,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
16-
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,24,24,,,,,,,,Copyright (c) 2012 LearnBoost <tj@learnboost.com>,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
17-
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,24,24,,,,,,,,,LearnBoost,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
18-
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,12,,,,,,,,,,tj@learnboost.com,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
19-
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,16,16,,,,,,,,,,,https://github.com/visionmedia/node-cookie-signature.git,,,,,,,,,,,,,,,,,,,,,,,,,,,,
20-
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,27,,,,,,,,,,,https://github.com/visionmedia/node-cookie-signature/issues,,,,,,,,,,,,,,,,,,,,,,,,,,,,
21-
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,npm,,cookie-signature,v 1.0.3,,,JavaScript,Sign and unsign cookies,,,https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz,,,,https://github.com/visionmedia/node-cookie-signature/issues,,git+https://github.com/visionmedia/node-cookie-signature.git,,,,,,,,pkg:npm/cookie-signature@1.0.3,https://www.npmjs.com/package/cookie-signature,https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz,https://registry.npmjs.org/cookie-signature/1.0.3
1+
Resource,type,name,base_name,extension,size,date,sha1,md5,mime_type,file_type,programming_language,is_binary,is_text,is_archive,is_media,is_source,is_script,files_count,dirs_count,size_count,scan_errors,license_expression,license__key,license__score,license__name,license__short_name,license__category,license__is_exception,license__owner,license__homepage_url,license__text_url,license__reference_url,license__spdx_license_key,license__spdx_url,start_line,end_line,matched_rule__identifier,matched_rule__license_expression,matched_rule__licenses,matched_rule__is_license_text,matched_rule__is_license_notice,matched_rule__is_license_reference,matched_rule__is_license_tag,copyright,copyright_holder,email,url,package__type,package__namespace,package__name,package__version,package__qualifiers,package__subpath,package__primary_language,package__description,package__release_date,package__homepage_url,package__download_url,package__size,package__sha1,package__md5,package__sha256,package__sha512,package__bug_tracking_url,package__code_view_url,package__vcs_url,package__copyright,package__license_expression,package__declared_license,package__notice_text,package__manifest_path,package__contains_source_code
2+
/json2csv.rb,file,json2csv.rb,json2csv,.rb,912,2018-11-15,1236469a06a2bacbdd8e172ad718482af5b0a936,1307c281e0b153202e291b217eab85d5,text/x-python,"Python script, ASCII text executable",Ruby,False,True,False,False,True,True,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
3+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,apache-2.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
4+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,apache-2.0,100.00,Apache License 2.0,Apache 2.0,Permissive,False,Apache Software Foundation,http://www.apache.org/licenses/,http://www.apache.org/licenses/LICENSE-2.0,https://enterprise.dejacode.com/urn/urn:dje:license:apache-2.0,Apache-2.0,https://spdx.org/licenses/Apache-2.0,5,13,apache-2.0_7.RULE,apache-2.0,[u'apache-2.0'],False,True,False,False,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
5+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,3,,,,,,,,Copyright (c) 2017 nexB Inc. and others.,,,,,,,,,,,,,,,,,,,,,,,,,,,,
6+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,3,,,,,,,,,nexB Inc. and others.,,,,,,,,,,,,,,,,,,,,,,,,,,,
7+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,4,,,,,,,,,,,http://nexb.com/,,,,,,,,,,,,,,,,,,,,,,,,,
8+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,4,,,,,,,,,,,https://github.com/nexB/scancode-toolkit/,,,,,,,,,,,,,,,,,,,,,,,,,
9+
/json2csv.rb,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,8,,,,,,,,,,,http://www.apache.org/licenses/LICENSE-2.0,,,,,,,,,,,,,,,,,,,,,,,,,
10+
/license,file,license,license,,679,2018-10-15,75c5490a718ddd45e40e0cc7ce0c756abc373123,b965a762efb9421cf1bf4405f336e278,text/plain,ASCII text,,False,True,False,False,False,False,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
11+
/license,,,,,,,,,,,,,,,,,,,,,,gpl-2.0-plus,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
12+
/license,,,,,,,,,,,,,,,,,,,,,,,gpl-2.0-plus,100.00,GNU General Public License 2.0 or later,GPL 2.0 or later,Copyleft,False,Free Software Foundation (FSF),http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html,http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html,https://enterprise.dejacode.com/urn/urn:dje:license:gpl-2.0-plus,GPL-2.0-or-later,https://spdx.org/licenses/GPL-2.0-or-later,1,12,gpl-2.0-plus.LICENSE,gpl-2.0-plus,[u'gpl-2.0-plus'],True,False,False,False,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
13+
/package.json,file,package.json,package,.json,2200,2018-10-15,918376afce796ef90eeda1d6695f2289c90491ac,1f66239a9b850c5e60a9382dbe2162d2,text/plain,"ASCII text, with very long lines",,False,True,False,False,False,False,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
14+
/package.json,,,,,,,,,,,,,,,,,,,,,,mit,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
15+
/package.json,,,,,,,,,,,,,,,,,,,,,,,mit,99.40,MIT License,MIT License,Permissive,False,MIT,http://opensource.org/licenses/mit-license.php,http://opensource.org/licenses/mit-license.php,https://enterprise.dejacode.com/urn/urn:dje:license:mit,MIT,https://spdx.org/licenses/MIT,24,24,mit_31.RULE,mit,[u'mit'],True,False,False,False,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
16+
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,24,24,,,,,,,,Copyright (c) 2012 LearnBoost <tj@learnboost.com>,,,,,,,,,,,,,,,,,,,,,,,,,,,,
17+
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,24,24,,,,,,,,,LearnBoost,,,,,,,,,,,,,,,,,,,,,,,,,,,
18+
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,12,,,,,,,,,,tj@learnboost.com,,,,,,,,,,,,,,,,,,,,,,,,,,
19+
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,16,16,,,,,,,,,,,https://github.com/visionmedia/node-cookie-signature.git,,,,,,,,,,,,,,,,,,,,,,,,,
20+
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,27,,,,,,,,,,,https://github.com/visionmedia/node-cookie-signature/issues,,,,,,,,,,,,,,,,,,,,,,,,,
21+
/package.json,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,npm,,cookie-signature,v 1.0.3,,,JavaScript,Sign and unsign cookies,,,https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz,,,,,,https://github.com/visionmedia/node-cookie-signature/issues,,git+https://github.com/visionmedia/node-cookie-signature.git,,,,,,

0 commit comments

Comments
 (0)