on develop help sign in
Updating
commita6b3ec1cdf183b477812d20e414a1ccf9e4e127b authorBrendan Hay <brendan.g.hay@gmail.com> dateWed 23 Sep 2015, 15:22 (11 years ago) parentd59c635
10 files changed+1263−887
gen/gozen-gen.cabal+10−2 gen/model/youtubeanalytics/youtubeanalytics/v1beta1/youtubeanalytics-api.json+724−724 gen/src/Gen/AST.hs+116−116 gen/src/Gen/Solve.hs+150 gen/src/Gen/Syntax.hs+107 gen/src/Gen/Types.hs+98−42 gen/src/Gen/Types/Map.hs+31 gen/src/Main.hs+3−3 gen/template/_include/type.ede+19 gen/template/types.ede+5
gen/gozen-gen.cabal+10−2
@@ -21,11 +21,15 @@ executable gozen-gen
2121 main-is: Main.hs
2222
2323 other-modules:
24− Gen.Formatting
24+ Gen.AST
25+ , Gen.Formatting
2526 , Gen.IO
2627 , Gen.JSON
27− , Gen.Types
28+ , Gen.Syntax
29+ , Gen.Text
2830 , Gen.Tree
31+ , Gen.Types
32+ , Gen.Types.Map
2933 , Gen.Types.NS
3034
3135 ghc-options: -Wall -threaded
@@ -40,7 +44,11 @@ executable gozen-gen
4044 , ede
4145 , errors
4246 , formatting
47+ , hashable
48+ , haskell-src-exts
49+ , hindent
4350 , lens
51+ , mmorph
4452 , mtl
4553 , optparse-applicative
4654 , semigroups
gen/model/youtubeanalytics/youtubeanalytics/v1beta1/youtubeanalytics-api.json+724−724
@@ -1,727 +1,727 @@
11{
2− "kind": "discovery#restDescription",
3− "etag": "\"ye6orv2F-1npMW3u9suM3a7C5Bo/wzHkxHWEX9PcW7ZnULAilfkQsbM\"",
4− "discoveryVersion": "v1",
5− "id": "youtubeAnalytics:v1beta1",
6− "name": "youtubeAnalytics",
7− "canonicalName": "YouTube Analytics",
8− "version": "v1beta1",
9− "revision": "20150304",
10− "title": "YouTube Analytics API",
11− "description": "Retrieve your YouTube Analytics reports.",
12− "ownerDomain": "google.com",
13− "ownerName": "Google",
14− "icons": {
15− "x16": "https://www.google.com/images/icons/product/youtube-16.png",
16− "x32": "https://www.google.com/images/icons/product/youtube-32.png"
17− },
18− "documentationLink": "http://developers.google.com/youtube/analytics/",
19− "labels": [
20− "deprecated"
21− ],
22− "protocol": "rest",
23− "baseUrl": "https://www.googleapis.com/youtube/analytics/v1beta1/",
24− "basePath": "/youtube/analytics/v1beta1/",
25− "rootUrl": "https://www.googleapis.com/",
26− "servicePath": "youtube/analytics/v1beta1/",
27− "batchPath": "batch",
28− "parameters": {
29− "alt": {
30− "type": "string",
31− "description": "Data format for the response.",
32− "default": "json",
33− "enum": [
34− "csv",
35− "json"
36− ],
37− "enumDescriptions": [
38− "Responses with Content-Type of text/csv",
39− "Responses with Content-Type of application/json"
40− ],
41− "location": "query"
42− },
43− "fields": {
44− "type": "string",
45− "description": "Selector specifying which fields to include in a partial response.",
46− "location": "query"
47− },
48− "key": {
49− "type": "string",
50− "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
51− "location": "query"
52− },
53− "oauth_token": {
54− "type": "string",
55− "description": "OAuth 2.0 token for the current user.",
56− "location": "query"
57− },
58− "prettyPrint": {
59− "type": "boolean",
60− "description": "Returns response with indentations and line breaks.",
61− "default": "true",
62− "location": "query"
63− },
64− "quotaUser": {
65− "type": "string",
66− "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
67− "location": "query"
68− },
69− "userIp": {
70− "type": "string",
71− "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
72− "location": "query"
73− }
74− },
75− "auth": {
76− "oauth2": {
77− "scopes": {
78− "https://www.googleapis.com/auth/youtube": {
79− "description": "Manage your YouTube account"
80− },
81− "https://www.googleapis.com/auth/youtube.readonly": {
82− "description": "View your YouTube account"
83− },
84− "https://www.googleapis.com/auth/youtubepartner": {
85− "description": "View and manage your assets and associated content on YouTube"
86− },
87− "https://www.googleapis.com/auth/yt-analytics-monetary.readonly": {
88− "description": "View monetary and non-monetary YouTube Analytics reports for your YouTube content"
89− },
90− "https://www.googleapis.com/auth/yt-analytics.readonly": {
91− "description": "View YouTube Analytics reports for your YouTube content"
92− }
93− }
94− }
95− },
96− "schemas": {
97− "BatchReport": {
98− "id": "BatchReport",
99− "type": "object",
100− "description": "Contains single batchReport resource.",
101− "properties": {
102− "id": {
103− "type": "string",
104− "description": "The ID that YouTube assigns and uses to uniquely identify the report."
105− },
106− "kind": {
107− "type": "string",
108− "description": "This value specifies the type of data of this item. For batch report the kind property value is youtubeAnalytics#batchReport.",
109− "default": "youtubeAnalytics#batchReport"
110− },
111− "outputs": {
112− "type": "array",
113− "description": "Report outputs.",
114− "items": {
115− "type": "object",
116− "properties": {
117− "downloadUrl": {
118− "type": "string",
119− "description": "Cloud storage URL to download this report. This URL is valid for 30 minutes."
120− },
121− "format": {
122− "type": "string",
123− "description": "Format of the output."
124− },
125− "type": {
126− "type": "string",
127− "description": "Type of the output.",
128− "default": "cloudStorageOutput"
129− }
130− }
131− }
132− },
133− "reportId": {
134− "type": "string",
135− "description": "The ID of the the report definition."
136− },
137− "timeSpan": {
138− "type": "object",
139− "description": "Period included in the report. For reports containing all entities endTime is not set. Both startTime and endTime are inclusive.",
140− "properties": {
141− "endTime": {
142− "type": "string",
143− "description": "End of the period included in the report. Inclusive. For reports containing all entities endTime is not set.",
144− "format": "date-time"
145− },
146− "startTime": {
147− "type": "string",
148− "description": "Start of the period included in the report. Inclusive.",
149− "format": "date-time"
150− }
151− }
152− },
153− "timeUpdated": {
154− "type": "string",
155− "description": "The time when the report was updated.",
156− "format": "date-time"
157− }
158− }
159− },
160− "BatchReportDefinition": {
161− "id": "BatchReportDefinition",
162− "type": "object",
163− "description": "Contains single batchReportDefinition resource.",
164− "properties": {
165− "id": {
166− "type": "string",
167− "description": "The ID that YouTube assigns and uses to uniquely identify the report definition."
168− },
169− "kind": {
170− "type": "string",
171− "description": "This value specifies the type of data of this item. For batch report definition the kind property value is youtubeAnalytics#batchReportDefinition.",
172− "default": "youtubeAnalytics#batchReportDefinition"
173− },
174− "name": {
175− "type": "string",
176− "description": "Name of the report definition."
177− },
178− "status": {
179− "type": "string",
180− "description": "Status of the report definition."
181− },
182− "type": {
183− "type": "string",
184− "description": "Type of the report definition."
185− }
186− }
187− },
188− "BatchReportDefinitionList": {
189− "id": "BatchReportDefinitionList",
190− "type": "object",
191− "description": "A paginated list of batchReportDefinition resources returned in response to a youtubeAnalytics.batchReportDefinitions.list request.",
192− "properties": {
193− "items": {
194− "type": "array",
195− "description": "A list of batchReportDefinition resources that match the request criteria.",
196− "items": {
197− "$ref": "BatchReportDefinition"
198− }
199− },
200− "kind": {
201− "type": "string",
202− "description": "This value specifies the type of data included in the API response. For the list method, the kind property value is youtubeAnalytics#batchReportDefinitionList.",
203− "default": "youtubeAnalytics#batchReportDefinitionList"
204− }
205− }
206− },
207− "BatchReportList": {
208− "id": "BatchReportList",
209− "type": "object",
210− "description": "A paginated list of batchReport resources returned in response to a youtubeAnalytics.batchReport.list request.",
211− "properties": {
212− "items": {
213− "type": "array",
214− "description": "A list of batchReport resources that match the request criteria.",
215− "items": {
216− "$ref": "BatchReport"
217− }
218− },
219− "kind": {
220− "type": "string",
221− "description": "This value specifies the type of data included in the API response. For the list method, the kind property value is youtubeAnalytics#batchReportList.",
222− "default": "youtubeAnalytics#batchReportList"
223− }
224− }
225− },
226− "Group": {
227− "id": "Group",
228− "type": "object",
229− "properties": {
230− "contentDetails": {
231− "type": "object",
232− "properties": {
233− "itemCount": {
234− "type": "string",
235− "format": "uint64"
236− },
237− "itemType": {
238− "type": "string"
239− }
240− }
241− },
242− "etag": {
243− "type": "string"
244− },
245− "id": {
246− "type": "string"
247− },
248− "kind": {
249− "type": "string",
250− "default": "youtube#group"
251− },
252− "snippet": {
253− "type": "object",
254− "properties": {
255− "publishedAt": {
256− "type": "string",
257− "format": "date-time"
258− },
259− "title": {
260− "type": "string"
261− }
262− }
263− }
264− }
265− },
266− "GroupItem": {
267− "id": "GroupItem",
268− "type": "object",
269− "properties": {
270− "etag": {
271− "type": "string"
272− },
273− "groupId": {
274− "type": "string"
275− },
276− "id": {
277− "type": "string"
278− },
279− "kind": {
280− "type": "string",
281− "default": "youtube#groupItem"
282− },
283− "resource": {
284− "type": "object",
285− "properties": {
286− "id": {
287− "type": "string"
288− },
289− "kind": {
290− "type": "string"
291− }
292− }
293− }
294− }
295− },
296− "GroupItemListResponse": {
297− "id": "GroupItemListResponse",
298− "type": "object",
299− "description": "A paginated list of grouList resources returned in response to a youtubeAnalytics.groupApi.list request.",
300− "properties": {
301− "etag": {
302− "type": "string"
303− },
304− "items": {
305− "type": "array",
306− "items": {
307− "$ref": "GroupItem"
308− }
309− },
310− "kind": {
311− "type": "string",
312− "default": "youtube#groupItemListResponse"
313− }
314− }
315− },
316− "GroupListResponse": {
317− "id": "GroupListResponse",
318− "type": "object",
319− "description": "A paginated list of grouList resources returned in response to a youtubeAnalytics.groupApi.list request.",
320− "properties": {
321− "etag": {
322− "type": "string"
323− },
324− "items": {
325− "type": "array",
326− "items": {
327− "$ref": "Group"
328− }
329− },
330− "kind": {
331− "type": "string",
332− "default": "youtube#groupListResponse"
333− }
334− }
335− },
336− "ResultTable": {
337− "id": "ResultTable",
338− "type": "object",
339− "description": "Contains a single result table. The table is returned as an array of rows that contain the values for the cells of the table. Depending on the metric or dimension, the cell can contain a string (video ID, country code) or a number (number of views or number of likes).",
340− "properties": {
341− "columnHeaders": {
342− "type": "array",
343− "description": "This value specifies information about the data returned in the rows fields. Each item in the columnHeaders list identifies a field returned in the rows value, which contains a list of comma-delimited data. The columnHeaders list will begin with the dimensions specified in the API request, which will be followed by the metrics specified in the API request. The order of both dimensions and metrics will match the ordering in the API request. For example, if the API request contains the parameters dimensions=ageGroup,gender&metrics=viewerPercentage, the API response will return columns in this order: ageGroup,gender,viewerPercentage.",
344− "items": {
345− "type": "object",
346− "properties": {
347− "columnType": {
348− "type": "string",
349− "description": "The type of the column (DIMENSION or METRIC)."
350− },
351− "dataType": {
352− "type": "string",
353− "description": "The type of the data in the column (STRING, INTEGER, FLOAT, etc.)."
354− },
355− "name": {
356− "type": "string",
357− "description": "The name of the dimension or metric."
358− }
359− }
360− }
361− },
362− "kind": {
363− "type": "string",
364− "description": "This value specifies the type of data included in the API response. For the query method, the kind property value will be youtubeAnalytics#resultTable.",
365− "default": "youtubeAnalytics#resultTable"
366− },
367− "rows": {
368− "type": "array",
369− "description": "The list contains all rows of the result table. Each item in the list is an array that contains comma-delimited data corresponding to a single row of data. The order of the comma-delimited data fields will match the order of the columns listed in the columnHeaders field. If no data is available for the given query, the rows element will be omitted from the response. The response for a query with the day dimension will not contain rows for the most recent days.",
370− "items": {
371− "type": "array",
372− "items": {
373− "type": "any"
374− }
375− }
376− }
377− }
378− }
379− },
380− "resources": {
381− "batchReportDefinitions": {
382− "methods": {
383− "list": {
384− "id": "youtubeAnalytics.batchReportDefinitions.list",
385− "path": "batchReportDefinitions",
386− "httpMethod": "GET",
387− "description": "Retrieves a list of available batch report definitions.",
388− "parameters": {
389− "onBehalfOfContentOwner": {
390− "type": "string",
391− "description": "The onBehalfOfContentOwner parameter identifies the content owner that the user is acting on behalf of.",
392− "required": true,
393− "location": "query"
394− }
395− },
396− "parameterOrder": [
397− "onBehalfOfContentOwner"
398− ],
399− "response": {
400− "$ref": "BatchReportDefinitionList"
401− },
402− "scopes": [
403− "https://www.googleapis.com/auth/yt-analytics-monetary.readonly",
404− "https://www.googleapis.com/auth/yt-analytics.readonly"
405− ]
406− }
407− }
408− },
409− "batchReports": {
410− "methods": {
411− "list": {
412− "id": "youtubeAnalytics.batchReports.list",
413− "path": "batchReports",
414− "httpMethod": "GET",
415− "description": "Retrieves a list of processed batch reports.",
416− "parameters": {
417− "batchReportDefinitionId": {
418− "type": "string",
419− "description": "The batchReportDefinitionId parameter specifies the ID of the batch reportort definition for which you are retrieving reports.",
420− "required": true,
421− "location": "query"
422− },
423− "onBehalfOfContentOwner": {
424− "type": "string",
425− "description": "The onBehalfOfContentOwner parameter identifies the content owner that the user is acting on behalf of.",
426− "required": true,
427− "location": "query"
428− }
429− },
430− "parameterOrder": [
431− "batchReportDefinitionId",
432− "onBehalfOfContentOwner"
433− ],
434− "response": {
435− "$ref": "BatchReportList"
436− },
437− "scopes": [
438− "https://www.googleapis.com/auth/yt-analytics-monetary.readonly",
439− "https://www.googleapis.com/auth/yt-analytics.readonly"
440− ]
441− }
442− }
443− },
444− "groupItems": {
445− "methods": {
446− "delete": {
447− "id": "youtubeAnalytics.groupItems.delete",
448− "path": "groupItems",
449− "httpMethod": "DELETE",
450− "description": "Removes an item from a group.",
451− "parameters": {
452− "id": {
453− "type": "string",
454− "description": "The id parameter specifies the YouTube group item ID for the group that is being deleted.",
455− "required": true,
456− "location": "query"
457− },
458− "onBehalfOfContentOwner": {
459− "type": "string",
460− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
461− "location": "query"
462− }
463− },
464− "parameterOrder": [
465− "id"
466− ],
467− "scopes": [
468− "https://www.googleapis.com/auth/youtube",
469− "https://www.googleapis.com/auth/youtubepartner"
470− ]
471− },
472− "insert": {
473− "id": "youtubeAnalytics.groupItems.insert",
474− "path": "groupItems",
475− "httpMethod": "POST",
476− "description": "Creates a group item.",
477− "parameters": {
478− "onBehalfOfContentOwner": {
479− "type": "string",
480− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
481− "location": "query"
482− }
483− },
484− "request": {
485− "$ref": "GroupItem"
486− },
487− "response": {
488− "$ref": "GroupItem"
489− },
490− "scopes": [
491− "https://www.googleapis.com/auth/youtube",
492− "https://www.googleapis.com/auth/youtubepartner"
493− ]
494− },
495− "list": {
496− "id": "youtubeAnalytics.groupItems.list",
497− "path": "groupItems",
498− "httpMethod": "GET",
499− "description": "Returns a collection of group items that match the API request parameters.",
500− "parameters": {
501− "groupId": {
502− "type": "string",
503− "description": "The id parameter specifies the unique ID of the group for which you want to retrieve group items.",
504− "required": true,
505− "location": "query"
506− },
507− "onBehalfOfContentOwner": {
508− "type": "string",
509− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
510− "location": "query"
511− }
512− },
513− "parameterOrder": [
514− "groupId"
515− ],
516− "response": {
517− "$ref": "GroupItemListResponse"
518− },
519− "scopes": [
520− "https://www.googleapis.com/auth/youtube",
521− "https://www.googleapis.com/auth/youtube.readonly",
522− "https://www.googleapis.com/auth/youtubepartner",
523− "https://www.googleapis.com/auth/yt-analytics.readonly"
524− ]
525− }
526− }
527− },
528− "groups": {
529− "methods": {
530− "delete": {
531− "id": "youtubeAnalytics.groups.delete",
532− "path": "groups",
533− "httpMethod": "DELETE",
534− "description": "Deletes a group.",
535− "parameters": {
536− "id": {
537− "type": "string",
538− "description": "The id parameter specifies the YouTube group ID for the group that is being deleted.",
539− "required": true,
540− "location": "query"
541− },
542− "onBehalfOfContentOwner": {
543− "type": "string",
544− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
545− "location": "query"
546− }
547− },
548− "parameterOrder": [
549− "id"
550− ],
551− "scopes": [
552− "https://www.googleapis.com/auth/youtube",
553− "https://www.googleapis.com/auth/youtubepartner"
554− ]
555− },
556− "insert": {
557− "id": "youtubeAnalytics.groups.insert",
558− "path": "groups",
559− "httpMethod": "POST",
560− "description": "Creates a group.",
561− "parameters": {
562− "onBehalfOfContentOwner": {
563− "type": "string",
564− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
565− "location": "query"
566− }
567− },
568− "request": {
569− "$ref": "Group"
570− },
571− "response": {
572− "$ref": "Group"
573− },
574− "scopes": [
575− "https://www.googleapis.com/auth/youtube",
576− "https://www.googleapis.com/auth/youtubepartner"
577− ]
578− },
579− "list": {
580− "id": "youtubeAnalytics.groups.list",
581− "path": "groups",
582− "httpMethod": "GET",
583− "description": "Returns a collection of groups that match the API request parameters. For example, you can retrieve all groups that the authenticated user owns, or you can retrieve one or more groups by their unique IDs.",
584− "parameters": {
585− "id": {
586− "type": "string",
587− "description": "The id parameter specifies a comma-separated list of the YouTube group ID(s) for the resource(s) that are being retrieved. In a group resource, the id property specifies the group's YouTube group ID.",
588− "location": "query"
589− },
590− "mine": {
591− "type": "boolean",
592− "description": "Set this parameter's value to true to instruct the API to only return groups owned by the authenticated user.",
593− "location": "query"
594− },
595− "onBehalfOfContentOwner": {
596− "type": "string",
597− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
598− "location": "query"
599− }
600− },
601− "response": {
602− "$ref": "GroupListResponse"
603− },
604− "scopes": [
605− "https://www.googleapis.com/auth/youtube",
606− "https://www.googleapis.com/auth/youtube.readonly",
607− "https://www.googleapis.com/auth/youtubepartner",
608− "https://www.googleapis.com/auth/yt-analytics.readonly"
609− ]
610− },
611− "update": {
612− "id": "youtubeAnalytics.groups.update",
613− "path": "groups",
614− "httpMethod": "PUT",
615− "description": "Modifies a group. For example, you could change a group's title.",
616− "parameters": {
617− "onBehalfOfContentOwner": {
618− "type": "string",
619− "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
620− "location": "query"
621− }
622− },
623− "request": {
624− "$ref": "Group"
625− },
626− "response": {
627− "$ref": "Group"
628− },
629− "scopes": [
630− "https://www.googleapis.com/auth/youtube",
631− "https://www.googleapis.com/auth/youtubepartner"
632− ]
633− }
634− }
635− },
636− "reports": {
637− "methods": {
638− "query": {
639− "id": "youtubeAnalytics.reports.query",
640− "path": "reports",
641− "httpMethod": "GET",
642− "description": "Retrieve your YouTube Analytics reports.",
643− "parameters": {
644− "currency": {
645− "type": "string",
646− "description": "The currency to which financial metrics should be converted. The default is US Dollar (USD). If the result contains no financial metrics, this flag will be ignored. Responds with an error if the specified currency is not recognized.",
647− "pattern": "[A-Z]{3}",
648− "location": "query"
649− },
650− "dimensions": {
651− "type": "string",
652− "description": "A comma-separated list of YouTube Analytics dimensions, such as views or ageGroup,gender. See the Available Reports document for a list of the reports that you can retrieve and the dimensions used for those reports. Also see the Dimensions document for definitions of those dimensions.",
653− "pattern": "[0-9a-zA-Z,]+",
654− "location": "query"
655− },
656− "end-date": {
657− "type": "string",
658− "description": "The end date for fetching YouTube Analytics data. The value should be in YYYY-MM-DD format.",
659− "required": true,
660− "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}",
661− "location": "query"
662− },
663− "filters": {
664− "type": "string",
665− "description": "A list of filters that should be applied when retrieving YouTube Analytics data. The Available Reports document identifies the dimensions that can be used to filter each report, and the Dimensions document defines those dimensions. If a request uses multiple filters, join them together with a semicolon (;), and the returned result table will satisfy both filters. For example, a filters parameter value of video==dMH0bHeiRNg;country==IT restricts the result set to include data for the given video in Italy.",
666− "location": "query"
667− },
668− "ids": {
669− "type": "string",
670− "description": "Identifies the YouTube channel or content owner for which you are retrieving YouTube Analytics data.\n- To request data for a YouTube user, set the ids parameter value to channel==CHANNEL_ID, where CHANNEL_ID specifies the unique YouTube channel ID.\n- To request data for a YouTube CMS content owner, set the ids parameter value to contentOwner==OWNER_NAME, where OWNER_NAME is the CMS name of the content owner.",
671− "required": true,
672− "pattern": "[a-zA-Z]+==[a-zA-Z0-9_+-]+",
673− "location": "query"
674− },
675− "max-results": {
676− "type": "integer",
677− "description": "The maximum number of rows to include in the response.",
678− "format": "int32",
679− "minimum": "1",
680− "location": "query"
681− },
682− "metrics": {
683− "type": "string",
684− "description": "A comma-separated list of YouTube Analytics metrics, such as views or likes,dislikes. See the Available Reports document for a list of the reports that you can retrieve and the metrics available in each report, and see the Metrics document for definitions of those metrics.",
685− "required": true,
686− "pattern": "[0-9a-zA-Z,]+",
687− "location": "query"
688− },
689− "sort": {
690− "type": "string",
691− "description": "A comma-separated list of dimensions or metrics that determine the sort order for YouTube Analytics data. By default the sort order is ascending. The '-' prefix causes descending sort order.",
692− "pattern": "[-0-9a-zA-Z,]+",
693− "location": "query"
694− },
695− "start-date": {
696− "type": "string",
697− "description": "The start date for fetching YouTube Analytics data. The value should be in YYYY-MM-DD format.",
698− "required": true,
699− "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}",
700− "location": "query"
701− },
702− "start-index": {
703− "type": "integer",
704− "description": "An index of the first entity to retrieve. Use this parameter as a pagination mechanism along with the max-results parameter (one-based, inclusive).",
705− "format": "int32",
706− "minimum": "1",
707− "location": "query"
708− }
709− },
710− "parameterOrder": [
711− "ids",
712− "start-date",
713− "end-date",
714− "metrics"
715− ],
716− "response": {
717− "$ref": "ResultTable"
718− },
719− "scopes": [
720− "https://www.googleapis.com/auth/yt-analytics-monetary.readonly",
721− "https://www.googleapis.com/auth/yt-analytics.readonly"
722− ]
2+ "kind": "discovery#restDescription",
3+ "etag": "\"ye6orv2F-1npMW3u9suM3a7C5Bo/wzHkxHWEX9PcW7ZnULAilfkQsbM\"",
4+ "discoveryVersion": "v1",
5+ "id": "youtubeAnalytics:v1beta1",
6+ "name": "youtubeAnalytics",
7+ "canonicalName": "YouTube Analytics",
8+ "version": "v1beta1",
9+ "revision": "20150304",
10+ "title": "YouTube Analytics API",
11+ "description": "Retrieve your YouTube Analytics reports.",
12+ "ownerDomain": "google.com",
13+ "ownerName": "Google",
14+ "icons": {
15+ "x16": "https://www.google.com/images/icons/product/youtube-16.png",
16+ "x32": "https://www.google.com/images/icons/product/youtube-32.png"
17+ },
18+ "documentationLink": "http://developers.google.com/youtube/analytics/",
19+ "labels": [
20+ "deprecated"
21+ ],
22+ "protocol": "rest",
23+ "baseUrl": "https://www.googleapis.com/youtube/analytics/v1beta1/",
24+ "basePath": "/youtube/analytics/v1beta1/",
25+ "rootUrl": "https://www.googleapis.com/",
26+ "servicePath": "youtube/analytics/v1beta1/",
27+ "batchPath": "batch",
28+ "parameters": {
29+ "alt": {
30+ "type": "string",
31+ "description": "Data format for the response.",
32+ "default": "json",
33+ "enum": [
34+ "csv",
35+ "json"
36+ ],
37+ "enumDescriptions": [
38+ "Responses with Content-Type of text/csv",
39+ "Responses with Content-Type of application/json"
40+ ],
41+ "location": "query"
42+ },
43+ "fields": {
44+ "type": "string",
45+ "description": "Selector specifying which fields to include in a partial response.",
46+ "location": "query"
47+ },
48+ "key": {
49+ "type": "string",
50+ "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
51+ "location": "query"
52+ },
53+ "oauth_token": {
54+ "type": "string",
55+ "description": "OAuth 2.0 token for the current user.",
56+ "location": "query"
57+ },
58+ "prettyPrint": {
59+ "type": "boolean",
60+ "description": "Returns response with indentations and line breaks.",
61+ "default": "true",
62+ "location": "query"
63+ },
64+ "quotaUser": {
65+ "type": "string",
66+ "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
67+ "location": "query"
68+ },
69+ "userIp": {
70+ "type": "string",
71+ "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
72+ "location": "query"
73+ }
74+ },
75+ "auth": {
76+ "oauth2": {
77+ "scopes": {
78+ "https://www.googleapis.com/auth/youtube": {
79+ "description": "Manage your YouTube account"
80+ },
81+ "https://www.googleapis.com/auth/youtube.readonly": {
82+ "description": "View your YouTube account"
83+ },
84+ "https://www.googleapis.com/auth/youtubepartner": {
85+ "description": "View and manage your assets and associated content on YouTube"
86+ },
87+ "https://www.googleapis.com/auth/yt-analytics-monetary.readonly": {
88+ "description": "View monetary and non-monetary YouTube Analytics reports for your YouTube content"
89+ },
90+ "https://www.googleapis.com/auth/yt-analytics.readonly": {
91+ "description": "View YouTube Analytics reports for your YouTube content"
92+ }
93+ }
94+ }
95+ },
96+ "schemas": {
97+ "BatchReport": {
98+ "id": "BatchReport",
99+ "type": "object",
100+ "description": "Contains single batchReport resource.",
101+ "properties": {
102+ "id": {
103+ "type": "string",
104+ "description": "The ID that YouTube assigns and uses to uniquely identify the report."
105+ },
106+ "kind": {
107+ "type": "string",
108+ "description": "This value specifies the type of data of this item. For batch report the kind property value is youtubeAnalytics#batchReport.",
109+ "default": "youtubeAnalytics#batchReport"
110+ },
111+ "outputs": {
112+ "type": "array",
113+ "description": "Report outputs.",
114+ "items": {
115+ "type": "object",
116+ "properties": {
117+ "downloadUrl": {
118+ "type": "string",
119+ "description": "Cloud storage URL to download this report. This URL is valid for 30 minutes."
120+ },
121+ "format": {
122+ "type": "string",
123+ "description": "Format of the output."
124+ },
125+ "type": {
126+ "type": "string",
127+ "description": "Type of the output.",
128+ "default": "cloudStorageOutput"
129+ }
130+ }
131+ }
132+ },
133+ "reportId": {
134+ "type": "string",
135+ "description": "The ID of the the report definition."
136+ },
137+ "timeSpan": {
138+ "type": "object",
139+ "description": "Period included in the report. For reports containing all entities endTime is not set. Both startTime and endTime are inclusive.",
140+ "properties": {
141+ "endTime": {
142+ "type": "string",
143+ "description": "End of the period included in the report. Inclusive. For reports containing all entities endTime is not set.",
144+ "format": "date-time"
145+ },
146+ "startTime": {
147+ "type": "string",
148+ "description": "Start of the period included in the report. Inclusive.",
149+ "format": "date-time"
150+ }
151+ }
152+ },
153+ "timeUpdated": {
154+ "type": "string",
155+ "description": "The time when the report was updated.",
156+ "format": "date-time"
157+ }
158+ }
159+ },
160+ "BatchReportDefinition": {
161+ "id": "BatchReportDefinition",
162+ "type": "object",
163+ "description": "Contains single batchReportDefinition resource.",
164+ "properties": {
165+ "id": {
166+ "type": "string",
167+ "description": "The ID that YouTube assigns and uses to uniquely identify the report definition."
168+ },
169+ "kind": {
170+ "type": "string",
171+ "description": "This value specifies the type of data of this item. For batch report definition the kind property value is youtubeAnalytics#batchReportDefinition.",
172+ "default": "youtubeAnalytics#batchReportDefinition"
173+ },
174+ "name": {
175+ "type": "string",
176+ "description": "Name of the report definition."
177+ },
178+ "status": {
179+ "type": "string",
180+ "description": "Status of the report definition."
181+ },
182+ "type": {
183+ "type": "string",
184+ "description": "Type of the report definition."
185+ }
186+ }
187+ },
188+ "BatchReportDefinitionList": {
189+ "id": "BatchReportDefinitionList",
190+ "type": "object",
191+ "description": "A paginated list of batchReportDefinition resources returned in response to a youtubeAnalytics.batchReportDefinitions.list request.",
192+ "properties": {
193+ "items": {
194+ "type": "array",
195+ "description": "A list of batchReportDefinition resources that match the request criteria.",
196+ "items": {
197+ "$ref": "BatchReportDefinition"
198+ }
199+ },
200+ "kind": {
201+ "type": "string",
202+ "description": "This value specifies the type of data included in the API response. For the list method, the kind property value is youtubeAnalytics#batchReportDefinitionList.",
203+ "default": "youtubeAnalytics#batchReportDefinitionList"
204+ }
205+ }
206+ },
207+ "BatchReportList": {
208+ "id": "BatchReportList",
209+ "type": "object",
210+ "description": "A paginated list of batchReport resources returned in response to a youtubeAnalytics.batchReport.list request.",
211+ "properties": {
212+ "items": {
213+ "type": "array",
214+ "description": "A list of batchReport resources that match the request criteria.",
215+ "items": {
216+ "$ref": "BatchReport"
217+ }
218+ },
219+ "kind": {
220+ "type": "string",
221+ "description": "This value specifies the type of data included in the API response. For the list method, the kind property value is youtubeAnalytics#batchReportList.",
222+ "default": "youtubeAnalytics#batchReportList"
223+ }
224+ }
225+ },
226+ "Group": {
227+ "id": "Group",
228+ "type": "object",
229+ "properties": {
230+ "contentDetails": {
231+ "type": "object",
232+ "properties": {
233+ "itemCount": {
234+ "type": "string",
235+ "format": "uint64"
236+ },
237+ "itemType": {
238+ "type": "string"
239+ }
240+ }
241+ },
242+ "etag": {
243+ "type": "string"
244+ },
245+ "id": {
246+ "type": "string"
247+ },
248+ "kind": {
249+ "type": "string",
250+ "default": "youtube#group"
251+ },
252+ "snippet": {
253+ "type": "object",
254+ "properties": {
255+ "publishedAt": {
256+ "type": "string",
257+ "format": "date-time"
258+ },
259+ "title": {
260+ "type": "string"
261+ }
262+ }
263+ }
264+ }
265+ },
266+ "GroupItem": {
267+ "id": "GroupItem",
268+ "type": "object",
269+ "properties": {
270+ "etag": {
271+ "type": "string"
272+ },
273+ "groupId": {
274+ "type": "string"
275+ },
276+ "id": {
277+ "type": "string"
278+ },
279+ "kind": {
280+ "type": "string",
281+ "default": "youtube#groupItem"
282+ },
283+ "resource": {
284+ "type": "object",
285+ "properties": {
286+ "id": {
287+ "type": "string"
288+ },
289+ "kind": {
290+ "type": "string"
291+ }
292+ }
293+ }
294+ }
295+ },
296+ "GroupItemListResponse": {
297+ "id": "GroupItemListResponse",
298+ "type": "object",
299+ "description": "A paginated list of grouList resources returned in response to a youtubeAnalytics.groupApi.list request.",
300+ "properties": {
301+ "etag": {
302+ "type": "string"
303+ },
304+ "items": {
305+ "type": "array",
306+ "items": {
307+ "$ref": "GroupItem"
308+ }
309+ },
310+ "kind": {
311+ "type": "string",
312+ "default": "youtube#groupItemListResponse"
313+ }
314+ }
315+ },
316+ "GroupListResponse": {
317+ "id": "GroupListResponse",
318+ "type": "object",
319+ "description": "A paginated list of grouList resources returned in response to a youtubeAnalytics.groupApi.list request.",
320+ "properties": {
321+ "etag": {
322+ "type": "string"
323+ },
324+ "items": {
325+ "type": "array",
326+ "items": {
327+ "$ref": "Group"
328+ }
329+ },
330+ "kind": {
331+ "type": "string",
332+ "default": "youtube#groupListResponse"
333+ }
334+ }
335+ },
336+ "ResultTable": {
337+ "id": "ResultTable",
338+ "type": "object",
339+ "description": "Contains a single result table. The table is returned as an array of rows that contain the values for the cells of the table. Depending on the metric or dimension, the cell can contain a string (video ID, country code) or a number (number of views or number of likes).",
340+ "properties": {
341+ "columnHeaders": {
342+ "type": "array",
343+ "description": "This value specifies information about the data returned in the rows fields. Each item in the columnHeaders list identifies a field returned in the rows value, which contains a list of comma-delimited data. The columnHeaders list will begin with the dimensions specified in the API request, which will be followed by the metrics specified in the API request. The order of both dimensions and metrics will match the ordering in the API request. For example, if the API request contains the parameters dimensions=ageGroup,gender&metrics=viewerPercentage, the API response will return columns in this order: ageGroup,gender,viewerPercentage.",
344+ "items": {
345+ "type": "object",
346+ "properties": {
347+ "columnType": {
348+ "type": "string",
349+ "description": "The type of the column (DIMENSION or METRIC)."
350+ },
351+ "dataType": {
352+ "type": "string",
353+ "description": "The type of the data in the column (STRING, INTEGER, FLOAT, etc.)."
354+ },
355+ "name": {
356+ "type": "string",
357+ "description": "The name of the dimension or metric."
358+ }
359+ }
360+ }
361+ },
362+ "kind": {
363+ "type": "string",
364+ "description": "This value specifies the type of data included in the API response. For the query method, the kind property value will be youtubeAnalytics#resultTable.",
365+ "default": "youtubeAnalytics#resultTable"
366+ },
367+ "rows": {
368+ "type": "array",
369+ "description": "The list contains all rows of the result table. Each item in the list is an array that contains comma-delimited data corresponding to a single row of data. The order of the comma-delimited data fields will match the order of the columns listed in the columnHeaders field. If no data is available for the given query, the rows element will be omitted from the response. The response for a query with the day dimension will not contain rows for the most recent days.",
370+ "items": {
371+ "type": "array",
372+ "items": {
373+ "type": "any"
374+ }
375+ }
376+ }
377+ }
378+ }
379+ },
380+ "resources": {
381+ "batchReportDefinitions": {
382+ "methods": {
383+ "list": {
384+ "id": "youtubeAnalytics.batchReportDefinitions.list",
385+ "path": "batchReportDefinitions",
386+ "httpMethod": "GET",
387+ "description": "Retrieves a list of available batch report definitions.",
388+ "parameters": {
389+ "onBehalfOfContentOwner": {
390+ "type": "string",
391+ "description": "The onBehalfOfContentOwner parameter identifies the content owner that the user is acting on behalf of.",
392+ "required": true,
393+ "location": "query"
394+ }
395+ },
396+ "parameterOrder": [
397+ "onBehalfOfContentOwner"
398+ ],
399+ "response": {
400+ "$ref": "BatchReportDefinitionList"
401+ },
402+ "scopes": [
403+ "https://www.googleapis.com/auth/yt-analytics-monetary.readonly",
404+ "https://www.googleapis.com/auth/yt-analytics.readonly"
405+ ]
406+ }
407+ }
408+ },
409+ "batchReports": {
410+ "methods": {
411+ "list": {
412+ "id": "youtubeAnalytics.batchReports.list",
413+ "path": "batchReports",
414+ "httpMethod": "GET",
415+ "description": "Retrieves a list of processed batch reports.",
416+ "parameters": {
417+ "batchReportDefinitionId": {
418+ "type": "string",
419+ "description": "The batchReportDefinitionId parameter specifies the ID of the batch reportort definition for which you are retrieving reports.",
420+ "required": true,
421+ "location": "query"
422+ },
423+ "onBehalfOfContentOwner": {
424+ "type": "string",
425+ "description": "The onBehalfOfContentOwner parameter identifies the content owner that the user is acting on behalf of.",
426+ "required": true,
427+ "location": "query"
428+ }
429+ },
430+ "parameterOrder": [
431+ "batchReportDefinitionId",
432+ "onBehalfOfContentOwner"
433+ ],
434+ "response": {
435+ "$ref": "BatchReportList"
436+ },
437+ "scopes": [
438+ "https://www.googleapis.com/auth/yt-analytics-monetary.readonly",
439+ "https://www.googleapis.com/auth/yt-analytics.readonly"
440+ ]
441+ }
442+ }
443+ },
444+ "groupItems": {
445+ "methods": {
446+ "delete": {
447+ "id": "youtubeAnalytics.groupItems.delete",
448+ "path": "groupItems",
449+ "httpMethod": "DELETE",
450+ "description": "Removes an item from a group.",
451+ "parameters": {
452+ "id": {
453+ "type": "string",
454+ "description": "The id parameter specifies the YouTube group item ID for the group that is being deleted.",
455+ "required": true,
456+ "location": "query"
457+ },
458+ "onBehalfOfContentOwner": {
459+ "type": "string",
460+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
461+ "location": "query"
462+ }
463+ },
464+ "parameterOrder": [
465+ "id"
466+ ],
467+ "scopes": [
468+ "https://www.googleapis.com/auth/youtube",
469+ "https://www.googleapis.com/auth/youtubepartner"
470+ ]
471+ },
472+ "insert": {
473+ "id": "youtubeAnalytics.groupItems.insert",
474+ "path": "groupItems",
475+ "httpMethod": "POST",
476+ "description": "Creates a group item.",
477+ "parameters": {
478+ "onBehalfOfContentOwner": {
479+ "type": "string",
480+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
481+ "location": "query"
482+ }
483+ },
484+ "request": {
485+ "$ref": "GroupItem"
486+ },
487+ "response": {
488+ "$ref": "GroupItem"
489+ },
490+ "scopes": [
491+ "https://www.googleapis.com/auth/youtube",
492+ "https://www.googleapis.com/auth/youtubepartner"
493+ ]
494+ },
495+ "list": {
496+ "id": "youtubeAnalytics.groupItems.list",
497+ "path": "groupItems",
498+ "httpMethod": "GET",
499+ "description": "Returns a collection of group items that match the API request parameters.",
500+ "parameters": {
501+ "groupId": {
502+ "type": "string",
503+ "description": "The id parameter specifies the unique ID of the group for which you want to retrieve group items.",
504+ "required": true,
505+ "location": "query"
506+ },
507+ "onBehalfOfContentOwner": {
508+ "type": "string",
509+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
510+ "location": "query"
511+ }
512+ },
513+ "parameterOrder": [
514+ "groupId"
515+ ],
516+ "response": {
517+ "$ref": "GroupItemListResponse"
518+ },
519+ "scopes": [
520+ "https://www.googleapis.com/auth/youtube",
521+ "https://www.googleapis.com/auth/youtube.readonly",
522+ "https://www.googleapis.com/auth/youtubepartner",
523+ "https://www.googleapis.com/auth/yt-analytics.readonly"
524+ ]
525+ }
526+ }
527+ },
528+ "groups": {
529+ "methods": {
530+ "delete": {
531+ "id": "youtubeAnalytics.groups.delete",
532+ "path": "groups",
533+ "httpMethod": "DELETE",
534+ "description": "Deletes a group.",
535+ "parameters": {
536+ "id": {
537+ "type": "string",
538+ "description": "The id parameter specifies the YouTube group ID for the group that is being deleted.",
539+ "required": true,
540+ "location": "query"
541+ },
542+ "onBehalfOfContentOwner": {
543+ "type": "string",
544+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
545+ "location": "query"
546+ }
547+ },
548+ "parameterOrder": [
549+ "id"
550+ ],
551+ "scopes": [
552+ "https://www.googleapis.com/auth/youtube",
553+ "https://www.googleapis.com/auth/youtubepartner"
554+ ]
555+ },
556+ "insert": {
557+ "id": "youtubeAnalytics.groups.insert",
558+ "path": "groups",
559+ "httpMethod": "POST",
560+ "description": "Creates a group.",
561+ "parameters": {
562+ "onBehalfOfContentOwner": {
563+ "type": "string",
564+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
565+ "location": "query"
566+ }
567+ },
568+ "request": {
569+ "$ref": "Group"
570+ },
571+ "response": {
572+ "$ref": "Group"
573+ },
574+ "scopes": [
575+ "https://www.googleapis.com/auth/youtube",
576+ "https://www.googleapis.com/auth/youtubepartner"
577+ ]
578+ },
579+ "list": {
580+ "id": "youtubeAnalytics.groups.list",
581+ "path": "groups",
582+ "httpMethod": "GET",
583+ "description": "Returns a collection of groups that match the API request parameters. For example, you can retrieve all groups that the authenticated user owns, or you can retrieve one or more groups by their unique IDs.",
584+ "parameters": {
585+ "id": {
586+ "type": "string",
587+ "description": "The id parameter specifies a comma-separated list of the YouTube group ID(s) for the resource(s) that are being retrieved. In a group resource, the id property specifies the group's YouTube group ID.",
588+ "location": "query"
589+ },
590+ "mine": {
591+ "type": "boolean",
592+ "description": "Set this parameter's value to true to instruct the API to only return groups owned by the authenticated user.",
593+ "location": "query"
594+ },
595+ "onBehalfOfContentOwner": {
596+ "type": "string",
597+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
598+ "location": "query"
599+ }
600+ },
601+ "response": {
602+ "$ref": "GroupListResponse"
603+ },
604+ "scopes": [
605+ "https://www.googleapis.com/auth/youtube",
606+ "https://www.googleapis.com/auth/youtube.readonly",
607+ "https://www.googleapis.com/auth/youtubepartner",
608+ "https://www.googleapis.com/auth/yt-analytics.readonly"
609+ ]
610+ },
611+ "update": {
612+ "id": "youtubeAnalytics.groups.update",
613+ "path": "groups",
614+ "httpMethod": "PUT",
615+ "description": "Modifies a group. For example, you could change a group's title.",
616+ "parameters": {
617+ "onBehalfOfContentOwner": {
618+ "type": "string",
619+ "description": "Note: This parameter is intended exclusively for YouTube content partners.\n\nThe onBehalfOfContentOwner parameter indicates that the request's authorization credentials identify a YouTube CMS user who is acting on behalf of the content owner specified in the parameter value. This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and get access to all their video and channel data, without having to provide authentication credentials for each individual channel. The CMS account that the user authenticates with must be linked to the specified YouTube content owner.",
620+ "location": "query"
621+ }
622+ },
623+ "request": {
624+ "$ref": "Group"
625+ },
626+ "response": {
627+ "$ref": "Group"
628+ },
629+ "scopes": [
630+ "https://www.googleapis.com/auth/youtube",
631+ "https://www.googleapis.com/auth/youtubepartner"
632+ ]
633+ }
634+ }
635+ },
636+ "reports": {
637+ "methods": {
638+ "query": {
639+ "id": "youtubeAnalytics.reports.query",
640+ "path": "reports",
641+ "httpMethod": "GET",
642+ "description": "Retrieve your YouTube Analytics reports.",
643+ "parameters": {
644+ "currency": {
645+ "type": "string",
646+ "description": "The currency to which financial metrics should be converted. The default is US Dollar (USD). If the result contains no financial metrics, this flag will be ignored. Responds with an error if the specified currency is not recognized.",
647+ "pattern": "[A-Z]{3}",
648+ "location": "query"
649+ },
650+ "dimensions": {
651+ "type": "string",
652+ "description": "A comma-separated list of YouTube Analytics dimensions, such as views or ageGroup,gender. See the Available Reports document for a list of the reports that you can retrieve and the dimensions used for those reports. Also see the Dimensions document for definitions of those dimensions.",
653+ "pattern": "[0-9a-zA-Z,]+",
654+ "location": "query"
655+ },
656+ "end-date": {
657+ "type": "string",
658+ "description": "The end date for fetching YouTube Analytics data. The value should be in YYYY-MM-DD format.",
659+ "required": true,
660+ "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}",
661+ "location": "query"
662+ },
663+ "filters": {
664+ "type": "string",
665+ "description": "A list of filters that should be applied when retrieving YouTube Analytics data. The Available Reports document identifies the dimensions that can be used to filter each report, and the Dimensions document defines those dimensions. If a request uses multiple filters, join them together with a semicolon (;), and the returned result table will satisfy both filters. For example, a filters parameter value of video==dMH0bHeiRNg;country==IT restricts the result set to include data for the given video in Italy.",
666+ "location": "query"
667+ },
668+ "ids": {
669+ "type": "string",
670+ "description": "Identifies the YouTube channel or content owner for which you are retrieving YouTube Analytics data.\n- To request data for a YouTube user, set the ids parameter value to channel==CHANNEL_ID, where CHANNEL_ID specifies the unique YouTube channel ID.\n- To request data for a YouTube CMS content owner, set the ids parameter value to contentOwner==OWNER_NAME, where OWNER_NAME is the CMS name of the content owner.",
671+ "required": true,
672+ "pattern": "[a-zA-Z]+==[a-zA-Z0-9_+-]+",
673+ "location": "query"
674+ },
675+ "max-results": {
676+ "type": "integer",
677+ "description": "The maximum number of rows to include in the response.",
678+ "format": "int32",
679+ "minimum": "1",
680+ "location": "query"
681+ },
682+ "metrics": {
683+ "type": "string",
684+ "description": "A comma-separated list of YouTube Analytics metrics, such as views or likes,dislikes. See the Available Reports document for a list of the reports that you can retrieve and the metrics available in each report, and see the Metrics document for definitions of those metrics.",
685+ "required": true,
686+ "pattern": "[0-9a-zA-Z,]+",
687+ "location": "query"
688+ },
689+ "sort": {
690+ "type": "string",
691+ "description": "A comma-separated list of dimensions or metrics that determine the sort order for YouTube Analytics data. By default the sort order is ascending. The '-' prefix causes descending sort order.",
692+ "pattern": "[-0-9a-zA-Z,]+",
693+ "location": "query"
694+ },
695+ "start-date": {
696+ "type": "string",
697+ "description": "The start date for fetching YouTube Analytics data. The value should be in YYYY-MM-DD format.",
698+ "required": true,
699+ "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}",
700+ "location": "query"
701+ },
702+ "start-index": {
703+ "type": "integer",
704+ "description": "An index of the first entity to retrieve. Use this parameter as a pagination mechanism along with the max-results parameter (one-based, inclusive).",
705+ "format": "int32",
706+ "minimum": "1",
707+ "location": "query"
708+ }
709+ },
710+ "parameterOrder": [
711+ "ids",
712+ "start-date",
713+ "end-date",
714+ "metrics"
715+ ],
716+ "response": {
717+ "$ref": "ResultTable"
718+ },
719+ "scopes": [
720+ "https://www.googleapis.com/auth/yt-analytics-monetary.readonly",
721+ "https://www.googleapis.com/auth/yt-analytics.readonly"
722+ ]
723+ }
724+ }
725+ }
723726 }
724− }
725− }
726− }
727727}
gen/src/Gen/AST.hs+116−116
@@ -22,114 +22,37 @@ module Gen.AST where
2222import Control.Applicative
2323import Control.Error
2424import Control.Lens
25+import Control.Monad.Except
26+import Control.Monad.Morph
2527import Control.Monad.State
26−import Data.Aeson hiding (String)
28+import Data.Aeson hiding (String)
2729import Data.Aeson.TH
28−import qualified Data.Attoparsec.Text as A
30+import qualified Data.Attoparsec.Text as A
2931import Data.Char
30−import Data.Function (on)
31−import qualified Data.HashMap.Strict as Map
32−import Data.List (groupBy, intersect, nub, sort)
33−import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
34−import qualified Data.List.NonEmpty as NE
32+import Data.Function (on)
33+import qualified Data.HashMap.Strict as Map
34+import Data.List (groupBy, intersect, nub, sort)
35+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
36+import qualified Data.List.NonEmpty as NE
3537import Data.Ord
36−import Data.Semigroup
37−import Data.Text (Text)
38−import qualified Data.Text as Text
39−import qualified Data.Text.Lazy as LText
40−import qualified Data.Text.Lazy.Builder as Build
38+import Data.Semigroup hiding (Sum)
39+import Data.Text (Text)
40+import qualified Data.Text as Text
41+import qualified Data.Text.Lazy as LText
42+import qualified Data.Text.Lazy.Builder as Build
4143import Data.Text.Manipulate
42−import qualified Filesystem.Path.CurrentOS as Path
44+import Debug.Trace
45+import qualified Filesystem.Path.CurrentOS as Path
4346import Formatting
4447import Gen.Formatting
48+import Gen.Solve
49+import Gen.Syntax
4550import Gen.Text
4651import Gen.Types
47−import Text.EDE (Template)
48−
49−-- Just use hashmaps to lookup refs etc, and hide all the mutation
50−-- behind a StateT interface.
51−
52−data TType
53− = TType Ref
54− | TLit Lit
55− | TMaybe TType
56− | TEither TType TType
57− | TList TType
58−
59−data Derive
60− = DEq
61− | DOrd
62− | DRead
63− | DShow
64− | DEnum
65− | DNum
66− | DIntegral
67− | DReal
68− | DMonoid
69− | DIsString
70− | DData
71− | DTypeable
72− | DGeneric
73− deriving (Eq)
74−
75−data Memo = Memo
76− { _typed :: Map Ref TType
77− , _derived :: Map Ref [Derive]
78− , _schemas :: Map Ref (Schema Ref)
79− }
80−
81−makeLenses ''Memo
82−
83−type AST = ExceptT Error (State Memo)
84−
85−schema :: Ref -> AST (Schema Ref)
86−schema k = do
87− m <- gets (Map.lookup k . view schemas)
88− case m of
89− Nothing -> failure ("Missing Schema: " % ref) k
90− Just v -> pure v
91−
92−memo :: Lens' Memo (Map Ref v) -> Ref -> (Schema Ref -> AST v) -> AST v
93−memo l k f = do
94− m <- gets (Map.lookup k . view l)
95− case m of
96− Just x -> return x
97− Nothing -> do
98− x <- f =<< schema k
99− l %= Map.insert k x
100− return x
101−
102−typeOf :: Ref -> AST TType
103−typeOf k = memo typed k go
104− where
105− go = \case
106− Obj {} -> pure (TType k)
107− Arr _ r -> typeOf r
108− Enum {} -> pure (TType k)
109− Ref r -> typeOf r
110− Any' -> pure (TEither (TLit String) (TLit Integer))
111− Lit _ l -> pure (TLit l)
112−
113−derive :: Ref -> AST [Derive]
114−derive k = memo derived k go
115− where
116− go = \case
117− Obj _ rs -> foldM props base (Map.keys rs)
118− Arr _ r -> mappend monoid . intersect base <$> derive r
119− Enum {} -> pure enum
120− Ref r -> derive r
121− Any' -> pure base
122− Lit _ l -> pure $
123− case l of
124− String -> base <> [DOrd, DIsString]
125− Boolean -> base <> enum
126− Integer -> base <> [DNum, DIntegral, DReal] <> enum
127−
128− props ds x = intersect ds <$> derive x
129−
130− monoid = [DMonoid]
131− enum = [DOrd, DEnum]
132− base = [DEq, DRead, DShow, DData, DTypeable, DGeneric]
52+import HIndent
53+import Language.Haskell.Exts.Pretty
54+import Prelude hiding (sum)
55+import Text.EDE (Template)
13356
13457-- mapM isn't lazy here and I don't care!
13558flatten :: Map Ref (Fix Schema) -> Map Ref (Schema Ref)
@@ -142,31 +65,108 @@ flatten m = execState (mapM_ (uncurry (prop Nothing)) (Map.toList m)) mempty
14265 res o
14366
14467 Arr i e -> do
145− e' <- prop Nothing ref e
68+ e' <- prop (Just ref) "item" e
14669 res (Arr i e')
14770
14871 Enum i vs ds -> res (Enum i vs ds)
14972 Lit i l -> res (Lit i l)
150− Ref r -> res (Ref r) -- blow up if r == ref ?
73+ Ref r -> pure r
15174 Any' -> res Any'
15275
15376 where
154− res x = modify (Map.insert ref x) >> pure ref
77+ res x = do
78+ m <- gets (Map.lookup ref)
79+ case m of
80+ Nothing -> modify (Map.insert ref x) >> pure ref
81+ -- FIXME:
82+ Just e -> error $ "Already exists: " ++ show (ref, e, x)
15583
15684 ref = maybe k (<> k) p
15785
158−render :: Service (Schema Ref) -> Either Error (Service Data)
159−render s = undefined -- do
160− -- rs <- traverse schema (_svcSchemas s)
161− -- return $! s { _svcSchemas = rs }
162− -- where
163− -- schema :: Schema -> Either Error Data
164− -- schema = \case
165− -- Obj ->
166− -- constructor [doc, sig, decl]
167− -- decl
168−
169− -- Arr -> Nothing
170−
171−
86+merge :: Versions -> [Service Data] -> [Library]
87+merge v = map go . groupBy (on (==) _svcLibrary)
88+ where
89+ go [x] = mk x
90+ go (x:xs) = (mk x) { _libServices = x :| xs }
91+
92+ mk x = Library
93+ { _libName = _svcLibrary x
94+ , _libTitle = renameTitle (_svcTitle x)
95+ , _libVersions = v
96+ , _libServices = x :| []
97+ }
98+
99+render :: Service (Fix Schema) -> Either Error (Service Data)
100+render s = runAST (Memo mempty mempty ss) $ do
101+ r <- kvTraverseMaybe go ss
102+ return $! s { _svcSchemas = r }
103+ where
104+ ss = flatten (_svcSchemas s)
105+
106+ go :: Ref -> Schema Ref -> AST (Maybe Data)
107+ go k = \case
108+ Arr {} -> pure Nothing
109+ Ref {} -> pure Nothing
110+ Any' {} -> pure Nothing
111+ Lit {} -> pure Nothing
112+ Enum {} -> Just <$> sum
113+ where
114+ sum = Sum "sum help"
115+ <$> pp Indent enumDecl
116+
117+ Obj _ rs -> Just <$> prod
118+ where
119+ prod = Prod
120+ <$> (objDecl k rs >>= pp Indent)
121+ <*> ctor
122+ <*> traverse (uncurry lens) (Map.toList rs)
123+
124+ ctor = Fun' "ctor help"
125+ <$> pp None ctorSig
126+ <*> pp Indent ctorDecl
127+
128+ lens n v = Fun' "lens help"
129+ <$> pp None lensSig
130+ <*> pp Print lensDecl
131+
132+ -- record declaration
133+ -- smart constructor
134+ -- signature
135+ -- declaration
136+ -- documentation
137+ -- lenses per property
138+ -- signature
139+ -- declaration
140+ -- documentation
141+
142+data PP
143+ = Indent
144+ | Print
145+ | None
146+ deriving (Eq)
172147
148+pp :: Pretty a => PP -> a -> AST Rendered
149+pp i x
150+ | i == Indent = result (reformat johanTibell Nothing p)
151+ | otherwise = pure p
152+ where
153+ result = hoistEither . bimap e Build.toLazyText
154+
155+ e = flip mappend (", when formatting datatype: " <> p) . LText.pack
156+
157+ p = LText.dropWhile isSpace
158+ . LText.pack
159+ $ prettyPrintStyleMode s m x
160+
161+ s = style
162+ { mode = PageMode
163+ , lineLength = 80
164+ , ribbonsPerLine = 1.5
165+ }
166+
167+ m | i == Print = defaultMode
168+ | i == Indent = defaultMode
169+ | otherwise = defaultMode
170+ { layout = PPNoLayout
171+ , spacing = False
172+ }
gen/src/Gen/Solve.hsnew file+150
@@ -0,0 +1,150 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE DeriveGeneric #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6+{-# LANGUAGE KindSignatures #-}
7+{-# LANGUAGE LambdaCase #-}
8+{-# LANGUAGE OverloadedStrings #-}
9+{-# LANGUAGE RankNTypes #-}
10+{-# LANGUAGE RecordWildCards #-}
11+{-# LANGUAGE TemplateHaskell #-}
12+
13+-- Module : Gen.Solve
14+-- Copyright : (c) 2015 Brendan Hay
15+-- License : Mozilla Public License, v. 2.0.
16+-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
17+-- Stability : provisional
18+-- Portability : non-portable (GHC extensions)
19+
20+module Gen.Solve where
21+
22+import Control.Applicative
23+import Control.Error
24+import Control.Lens
25+import Control.Monad.Except
26+import Control.Monad.Morph
27+import Control.Monad.State
28+import qualified Data.Attoparsec.Text as A
29+import Data.Char
30+import Data.Function (on)
31+import qualified Data.HashMap.Strict as Map
32+import Data.List (groupBy, intersect, nub, sort)
33+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
34+import qualified Data.List.NonEmpty as NE
35+import Data.Ord
36+import Data.Semigroup hiding (Sum)
37+import Data.Text (Text)
38+import qualified Data.Text as Text
39+import qualified Data.Text.Lazy as LText
40+import qualified Data.Text.Lazy.Builder as Build
41+import Data.Text.Manipulate
42+import Debug.Trace
43+import qualified Filesystem.Path.CurrentOS as Path
44+import Formatting
45+import Gen.Formatting
46+import Gen.Text
47+import Gen.Types
48+import HIndent
49+import Language.Haskell.Exts.Pretty
50+import Prelude hiding (sum)
51+import Text.EDE (Template)
52+
53+-- Just use hashmaps to lookup refs etc, and hide all the mutation
54+-- behind a StateT interface.
55+
56+data TType
57+ = TType Ref
58+ | TLit Lit
59+ | TMaybe TType
60+ | TEither TType TType
61+ | TList TType
62+
63+data Derive
64+ = DEq
65+ | DOrd
66+ | DRead
67+ | DShow
68+ | DEnum
69+ | DNum
70+ | DIntegral
71+ | DReal
72+ | DMonoid
73+ | DIsString
74+ | DData
75+ | DTypeable
76+ | DGeneric
77+ deriving (Eq, Show)
78+
79+data Memo = Memo
80+ { _typed :: Map Ref TType
81+ , _derived :: Map Ref [Derive]
82+ , _schemas :: Map Ref (Schema Ref)
83+ }
84+
85+makeLenses ''Memo
86+
87+type AST = ExceptT Error (State Memo)
88+
89+type Solved = (Schema Ref, TType, [Derive])
90+
91+runAST :: Memo -> AST a -> Either Error a
92+runAST s m = evalState (runExceptT m) s
93+
94+schema :: Ref -> AST (Schema Ref)
95+schema k = do
96+ m <- gets (Map.lookup k . view schemas)
97+ case m of
98+ Nothing -> failure ("Missing Schema: " % fref) k
99+ Just v -> pure v
100+
101+memo :: Lens' Memo (Map Ref v) -> Ref -> (Schema Ref -> AST v) -> AST v
102+memo l k f = do
103+ m <- gets (Map.lookup k . view l)
104+ case m of
105+ Just x -> return x
106+ Nothing -> do
107+ x <- f =<< schema k
108+ l %= Map.insert k x
109+ return x
110+
111+solve :: Ref -> AST Solved
112+solve k = (,,) <$> schema k <*> typeOf k <*> derive k
113+
114+typeOf :: Ref -> AST TType
115+typeOf k = loc "typeOf" k $ memo typed k go
116+ where
117+ go = \case
118+ Obj {} -> pure (TType k)
119+ Arr _ r -> pure (TList (TType r))
120+ Enum {} -> pure (TType k)
121+ Ref r -> typeOf r
122+ Any' -> pure (TEither (TLit Text) (TLit Long))
123+ Lit _ l -> pure (TLit l)
124+
125+derive :: Ref -> AST [Derive]
126+derive k = loc "derive" k $ memo derived k go
127+ where
128+ go = \case
129+ Obj _ rs -> foldM props base (Map.elems rs)
130+ Arr _ r -> pure [] -- mappend monoid . intersect base <$> derive r
131+ Enum {} -> pure enum
132+ Ref r -> derive r
133+ Any' -> pure base
134+ Lit _ l -> pure $
135+ case l of
136+ Text -> base <> [DOrd, DIsString]
137+ Bool -> base <> enum
138+ Int -> base
139+ Long -> base <> [DNum, DIntegral, DReal] <> enum
140+ Nat -> base
141+ Time -> base
142+
143+ props ds x = intersect ds <$> derive x
144+
145+ monoid = [DMonoid]
146+ enum = [DOrd, DEnum]
147+ base = [DEq, DRead, DShow, DData, DTypeable, DGeneric]
148+
149+loc :: String -> Ref -> a -> a
150+loc n r = id -- trace (n ++ ": " ++ Text.unpack (refToText r))
gen/src/Gen/Syntax.hsnew file+107
@@ -0,0 +1,107 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TupleSections #-}
4+
5+-- Module : Gen.Syntax
6+-- Copyright : (c) 2015 Brendan Hay
7+-- License : Mozilla Public License, v. 2.0.
8+-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
9+-- Stability : provisional
10+-- Portability : non-portable (GHC extensions)
11+
12+module Gen.Syntax where
13+
14+import qualified Data.HashMap.Strict as Map
15+import Data.Semigroup
16+import Data.String
17+import Data.Text (Text)
18+import qualified Data.Text as Text
19+import Data.Text.Manipulate
20+import Gen.Solve
21+import Gen.Types
22+import qualified Language.Haskell.Exts as Exts
23+import Language.Haskell.Exts.Build
24+import Language.Haskell.Exts.SrcLoc
25+import Language.Haskell.Exts.Syntax hiding (Int)
26+
27+objDecl :: Ref -> Map Ref Ref -> AST Decl
28+objDecl r rs = do
29+ con <- conDecl n rs
30+ ds <- derivings r
31+ return $! DataDecl noLoc arity [] n [] [con] ds
32+ where
33+ n = dname r
34+
35+ arity | Map.size rs == 1 = NewType
36+ | otherwise = DataType
37+
38+conDecl :: Name -> Map Ref Ref -> AST QualConDecl
39+conDecl n rs = QualConDecl noLoc [] [] <$> body
40+ where
41+ body = case Map.toList rs of
42+ [] -> pure (ConDecl n [])
43+ [x] -> RecDecl n . (:[]) <$> field internal x
44+ xs -> RecDecl n <$> traverse (field (strict . internal)) xs
45+
46+ field f (k, v) = do
47+ t <- typeOf v
48+ return ([fname k], f t)
49+
50+derivings :: Ref -> AST [Deriving]
51+derivings = fmap (map ((,[]) . unqual . drop 1 . show)) . derive
52+
53+ctorSig :: Decl
54+ctorSig = emptyDecl
55+
56+ctorDecl :: Decl
57+ctorDecl = emptyDecl
58+
59+lensSig :: Decl
60+lensSig = emptyDecl
61+
62+lensDecl :: Decl
63+lensDecl = emptyDecl
64+
65+enumDecl :: Decl
66+enumDecl = emptyDecl
67+
68+emptyDecl :: Decl
69+emptyDecl = DataDecl noLoc DataType [] (name "Empty") [] [] []
70+
71+internal :: TType -> Type
72+internal = go
73+ where
74+ go = \case
75+ TType r -> tycon r
76+ TMaybe t -> TyApp (tycon "Maybe") (go t)
77+-- TEither a b ->
78+ TList t -> TyList (go t)
79+ TLit l -> lit l
80+
81+ lit = \case
82+ Text -> tycon "Text"
83+ Bool -> tycon "Bool"
84+ Int -> tycon "Int"
85+ Long -> tycon "Integer"
86+ Nat -> tycon "Natural"
87+ Time -> tycon "UTCTime"
88+
89+strict :: Type -> Type
90+strict = TyBang BangedTy . \case
91+ t@TyApp{} -> TyParen t
92+ t -> t
93+
94+dname :: Ref -> Name
95+dname = name . ref upperHead
96+
97+fname :: Ref -> Name
98+fname = name . ref (Text.cons '_')
99+
100+tycon :: Ref -> Type
101+tycon = TyCon . unqual . ref upperHead
102+
103+ref :: (Text -> Text) -> Ref -> String
104+ref f = Text.unpack . f . refToText
105+
106+unqual :: String -> QName
107+unqual = UnQual . name
gen/src/Gen/Types.hs+98−42
@@ -3,6 +3,7 @@
33{-# LANGUAGE DeriveFunctor #-}
44{-# LANGUAGE DeriveGeneric #-}
55{-# LANGUAGE DeriveTraversable #-}
6+{-# LANGUAGE ExtendedDefaultRules #-}
67{-# LANGUAGE FlexibleContexts #-}
78{-# LANGUAGE FlexibleInstances #-}
89{-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -12,6 +13,8 @@
1213{-# LANGUAGE RecordWildCards #-}
1314{-# LANGUAGE TemplateHaskell #-}
1415
16+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
17+
1518-- Module : Gen.Types
1619-- Copyright : (c) 2015 Brendan Hay
1720-- License : Mozilla Public License, v. 2.0.
@@ -21,11 +24,12 @@
2124
2225module Gen.Types
2326 ( module Gen.Types
27+ , module Gen.Types.Map
2428 , module Gen.Types.NS
2529 ) where
2630
2731import Control.Applicative
28−import Data.Aeson hiding (String)
32+import Data.Aeson hiding (Bool, String)
2933import Data.Aeson.TH
3034import qualified Data.Attoparsec.Text as A
3135import Data.Bifunctor
@@ -37,23 +41,27 @@ import Data.List (groupBy, nub, sort)
3741import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
3842import qualified Data.List.NonEmpty as NE
3943import Data.Ord
40−import Data.Semigroup
44+import Data.Semigroup hiding (Sum)
45+import Data.String
4146import Data.Text (Text)
4247import qualified Data.Text as Text
4348import qualified Data.Text.Lazy as LText
4449import qualified Data.Text.Lazy.Builder as Build
4550import Data.Text.Manipulate
51+import qualified Data.Text.Read as Read
4652import qualified Filesystem.Path.CurrentOS as Path
4753import Formatting
4854import Gen.Text
55+import Gen.Types.Map
4956import Gen.Types.NS
5057import GHC.Generics
5158import GHC.TypeLits
5259import Text.EDE (Template)
5360
61+default (Text)
62+
5463newtype Fix f = Fix (f (Fix f))
5564
56−type Map = Map.HashMap
5765type Error = LText.Text
5866type Rendered = LText.Text
5967type Path = Path.FilePath
@@ -75,8 +83,8 @@ newtype Version (v :: Symbol) = Version Text
7583instance ToJSON (Version v) where
7684 toJSON (Version v) = toJSON v
7785
78−semver :: Format a (Version v -> a)
79−semver = later (\(Version v) -> Build.fromText v)
86+fver :: Format a (Version v -> a)
87+fver = later (\(Version v) -> Build.fromText v)
8088
8189type LibraryVer = Version "library"
8290type ClientVer = Version "client"
@@ -138,17 +146,54 @@ deriveJSON (js "") ''Location
138146data Info = Info
139147 { _infoDescription :: Maybe Text
140148 , _infoDefault :: Maybe Text
141− , _infoRequired :: Maybe Bool
149+ , _infoRequired :: !Bool
150+ , _infoLocation :: Maybe Location
142151 } deriving (Eq, Show)
143152
144−deriveJSON (js "_info") ''Info
153+instance FromJSON Info where
154+ parseJSON = withObject "info" $ \o -> Info
155+ <$> o .:? "description"
156+ <*> o .:? "default"
157+ <*> o .:? "required" .!= False
158+ <*> o .:? "location"
159+
160+deriveToJSON (js "_info") ''Info
145161
146162data Lit
147− = String
148− | Boolean
149− | Integer
163+ = Text
164+ | Bool
165+ | Int
166+ | Long
167+ | Nat
168+ | Time
150169 deriving (Eq, Show)
151170
171+instance FromJSON Lit where
172+ parseJSON = withObject "literal" $ \o -> do
173+ n <- min =<< (o .:? "minimum" .!= "0")
174+ (o .: "format" <|> o .: "type") >>= \case
175+ -- Types
176+ "string" -> pure Text
177+ "boolean" -> pure Bool
178+ -- Formats
179+ "uint64" -> pure (nat n Long)
180+ "int32" -> pure (nat n Int)
181+ "date-time" -> pure Time
182+ e -> fail $
183+ "Unable to parse Lit from " ++ Text.unpack e
184+ where
185+ min = either fail (pure . fst) . Read.decimal
186+
187+ nat :: Int -> Lit -> Lit
188+ nat n | n > 0 = const Nat
189+ | otherwise = id
190+
191+-- "pattern": "[A-Z]{3}",
192+-- "pattern": "[0-9a-zA-Z,]+",
193+-- "pattern": "[a-zA-Z]+==[a-zA-Z0-9_+-]+",
194+-- "minimum": "1"
195+-- "format": "date-time", "uint64", "int32",
196+
152197deriveToJSON (js "") ''Lit
153198
154199data Ref
@@ -165,6 +210,9 @@ instance Semigroup Ref where
165210
166211instance Hashable Ref
167212
213+instance IsString Ref where
214+ fromString = Direct . fromString
215+
168216instance FromJSON Ref where parseJSON = withText "ref" (pure . Direct)
169217instance ToJSON Ref where toJSON = toJSON . refToText
170218
@@ -176,11 +224,11 @@ instance ToJSON a => ToJSON (Map Ref a) where
176224
177225refToText :: Ref -> Text
178226refToText = \case
179− Opaque xs -> Text.intercalate "." xs
227+ Opaque xs -> mconcat (map upperHead xs)
180228 Direct n -> n
181229
182−ref :: Format a (Ref -> a)
183−ref = later (Build.fromText . refToText)
230+fref :: Format a (Ref -> a)
231+fref = later (Build.fromText . refToText)
184232
185233data Schema a
186234 = Obj Info (Map Ref a)
@@ -192,35 +240,56 @@ data Schema a
192240 deriving (Eq, Show, Functor, Foldable, Traversable)
193241
194242instance FromJSON (Fix Schema) where
195− parseJSON = withObject "schema" $ \o -> Fix <$> (schema o <|> ref o)
243+ parseJSON = withObject "schema" $ \o -> Fix <$> (ref o <|> schema o)
196244 where
197245 schema o = do
198246 i <- parseJSON (Object o)
199247 o .: "type" >>= \case
200− "object" -> Obj i <$> o .: "properties"
201− "array" -> Arr i <$> o .: "items"
202− "string" -> enum i o <|> pure (Lit i String)
203− "boolean" -> pure (Lit i Boolean)
204− "any" -> pure Any'
205− e -> fail $
206− "Unable to parse Schema from: '" ++ Text.unpack e ++ "'"
248+ "object" -> Obj i <$> o .: "properties"
249+ "array" -> Arr i <$> o .: "items"
250+ "any" -> pure Any'
251+ _ -> enum i o <|> Lit i <$> parseJSON (Object o)
207252
208253 enum i o = Enum i <$> o .: "enum" <*> o .: "enumDescriptions"
209254 ref o = Ref <$> o .: "$ref"
210255
211256deriveToJSON (js "") ''Schema
212257
213−data Param a = Param Location a
214− deriving (Eq, Show, Functor, Foldable, Traversable)
258+data Param = Param Location -- (Fix Schema)
215259
216−instance FromJSON a => FromJSON (Param a) where
260+instance FromJSON Param where
217261 parseJSON = withObject "parameter" $ \o ->
218− Param <$> o .: "location" <*> parseJSON (Object o)
262+ Param <$> o .: "location" -- <*> parseJSON (Object o)
219263
220264deriveToJSON (js "") ''Param
221265
222−newtype Data = Data Rendered
223− deriving (Eq, Show, ToJSON)
266+data Fun = Fun' Text Rendered Rendered
267+
268+instance ToJSON Fun where
269+ toJSON (Fun' h s d) = object
270+ [ "help" .= h
271+ , "sig" .= s
272+ , "decl" .= d
273+ ]
274+
275+data Data
276+ = Sum Text Rendered
277+ | Prod Rendered Fun [Fun]
278+
279+instance ToJSON Data where
280+ toJSON = \case
281+ Sum h d -> object
282+ [ "type" .= "sum"
283+ , "decl" .= d
284+ , "help" .= h
285+ ]
286+
287+ Prod d c ls -> object
288+ [ "type" .= "prod"
289+ , "decl" .= d
290+ , "ctor" .= c
291+ , "lenses" .= ls
292+ ]
224293
225294data Service a = Service
226295 { _svcLibrary :: Text
@@ -240,8 +309,8 @@ data Service a = Service
240309 , _svcServicePath :: Text
241310 , _svcBatchPath :: Text
242311 , _svcAuth :: Maybe Object
243− , _svcParameters :: Map Text (Param a)
244− , _svcSchemas :: Map Text a
312+ , _svcParameters :: Map Ref Param
313+ , _svcSchemas :: Map Ref a
245314 , _svcResources :: Object
246315 } deriving (Generic)
247316
@@ -284,16 +353,3 @@ instance ToJSON Library where
284353 , "clientVersion" .= _clientVersion _libVersions
285354 , "exposedModules" .= concatMap exposedModules (NE.toList _libServices)
286355 ]
287−
288−mergeLibraries :: Versions -> [Service Data] -> [Library]
289−mergeLibraries v = map go . groupBy (on (==) _svcLibrary)
290− where
291− go [x] = mk x
292− go (x:xs) = (mk x) { _libServices = x :| xs }
293−
294− mk x = Library
295− { _libName = _svcLibrary x
296− , _libTitle = renameTitle (_svcTitle x)
297− , _libVersions = v
298− , _libServices = x :| []
299− }
gen/src/Gen/Types/Map.hsnew file+31
@@ -0,0 +1,31 @@
1+-- Module : Gen.Types.Map
2+-- Copyright : (c) 2013-2015 Brendan Hay
3+-- License : This Source Code Form is subject to the terms of
4+-- the Mozilla Public License, v. 2.0.
5+-- A copy of the MPL can be found in the LICENSE file or
6+-- you can obtain it at http://mozilla.org/MPL/2.0/.
7+-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
8+-- Stability : provisional
9+-- Portability : non-portable (GHC extensions)
10+
11+module Gen.Types.Map where
12+
13+import Control.Lens
14+import Data.Hashable
15+import qualified Data.HashMap.Strict as Map
16+import Data.Maybe
17+
18+type Map = Map.HashMap
19+
20+vMapMaybe :: (Eq k, Hashable k)
21+ => (a -> Maybe b)
22+ -> Map k a
23+ -> Map k b
24+vMapMaybe f = runIdentity . kvTraverseMaybe (const (pure . f))
25+
26+kvTraverseMaybe :: (Applicative f, Eq k, Hashable k)
27+ => (k -> a -> f (Maybe b))
28+ -> Map k a
29+ -> f (Map k b)
30+kvTraverseMaybe f = fmap (Map.map fromJust . Map.filter isJust)
31+ . Map.traverseWithKey f
gen/src/Main.hs+3−3
@@ -14,7 +14,6 @@
1414
1515module Main (main) where
1616
17−import Gen.AST
1817import Control.Error
1918import Control.Lens hiding ((<.>))
2019import Control.Monad.State
@@ -24,6 +23,7 @@ import Data.Text (Text)
2423import qualified Data.Text as Text
2524import qualified Filesystem as FS
2625import Filesystem.Path.CurrentOS
26+import Gen.AST
2727import Gen.Formatting
2828import Gen.IO
2929import qualified Gen.JSON as JS
@@ -159,7 +159,7 @@ main = do
159159
160160 return s
161161
162− libs = mergeLibraries _optVersions <$> renderSchemas svcs
162+ libs <- merge _optVersions <$> traverse (hoistEither . render) svcs
163163
164164 void . counter "library" libs $ \l -> do
165165 say ("Creating " % stext % " package.") (_libTitle l)
@@ -167,7 +167,7 @@ main = do
167167 dir <- hoistEither (Tree.populate _optOutput tmpl l)
168168 >>= Tree.fold createDir (\x -> maybe (touchFile x) (writeLTFile x))
169169
170− say ("Successfully rendered " % stext % "-" % semver % " package")
170+ say ("Successfully rendered " % stext % "-" % fver % " package")
171171 (_libName l)
172172 (_libraryVersion _optVersions)
173173
gen/template/_include/type.edenew file+19
@@ -0,0 +1,19 @@
1+{% case type.type %}
2+{% when "prod" %}
3+{{ type.decl }}
4+
5+{{ type.ctor.help }}
6+{{ type.ctor.sig }}
7+{{ type.ctor.decl }}
8+ {% for lens in type.lenses %}
9+
10+{{ lens.value.help }}
11+{{ lens.value.sig }}
12+{{ lens.value.decl }}
13+ {% endfor %}
14+ {% when "sum" %}
15+{{ type.help }}
16+{{ type.decl }}
17+{% else %}
18+ Error: Unrecognised type '{{ type.type }}'
19+{% endcase %}
gen/template/types.ede+5
@@ -7,3 +7,8 @@ module {{ moduleName }}
77{% for import in moduleImports %}
88import {{ import.value }}
99{% endfor %}
10+
11+{% for schema in schemas %}
12+ {% include "_include/type.ede" with type = schema.value %}
13+
14+{% endfor %}