234 attempt to fix js error Uncaught SyntaxError: Unexpected identifier 'hidden'

This commit is contained in:
2026-04-27 17:57:24 +03:00
parent 8a32a0d5f0
commit 74c073bd7e
149 changed files with 14361 additions and 8886 deletions
+178 -41
View File
@@ -12,7 +12,7 @@ The REST Web Service framework for ColdFusion and Lucee
**Application.cfc:**
```js
```cfscript
component extends="taffy.core.api" {}
```
@@ -24,7 +24,7 @@ component extends="taffy.core.api" {}
**/resources/hello.cfc:**
```js
```cfscript
component extends="taffy.core.resource" taffy_uri="/hello" {
function get(){
@@ -75,15 +75,19 @@ Using sub-folders requires the use of Application-Specific Mappings (introduced
You can see that the taffy folder is a sibling to Application.cfc. This allows Application.cfc to use relative paths to extend `taffy.core.api`.
Next, if your Application.cfc and `/resources/` folder aren't in the web-root (e.g. they're inside something like `/api/`) then you'll need to add an [application-specific mapping](http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=appFramework_04.html) for `/resources` so that Taffy can find your resources to initialize the routes.
Next, if your Application.cfc and `/resources/` folder aren't in the web-root (e.g. they're inside something like `/api/`) then you'll need to do one of the following:
```js
this.mappings["/resources"] = expandPath("./resources");
```
- Add an [application-specific mapping](http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=appFramework_04.html) for `/resources` so that Taffy can find your resources to initialize the routes.
```cfscript
this.mappings["/resources"] = expandPath("../api/resources");
```
- You can specify the path to your resource components using the [`resourcesCFCPath`](#resourcescfcpath) setting to specify the dotted path to your resource folder. This will allow you to store your resource components in the directory of your choosing.
You'll also need to add a mapping for `/taffy` so that the resources can extend `taffy.core.resource` (since the taffy folder isn't a child of the resources folder):
```js
```cfscript
this.mappings["/taffy"] = expandPath("./taffy");
```
@@ -132,7 +136,7 @@ In the xml above you can see that I only have 1 wildcard, but to compensate I've
Taffy allows for setting the HTTP status message using [.withStatus()](#withstatus), such as:
```js
```cfscript
return representationOf({...}).withStatus(403, "Not Authorized");
```
@@ -173,6 +177,54 @@ _Thanks to Brook Davies for providing the solution!_
Not all HTTP clients will allow you to easily send PUT or DELETE requests (sometimes not at all). The standard method for circumventing this restriction, which Taffy supports, is by sending your request as a POST with the header `X-HTTP-METHOD-OVERRIDE` and setting its value to PUT/DELETE as needed. Taffy will detect this header and treat the request as if it were a PUT/DELETE request.
## OpenAPI / Swagger
**Available in:** Taffy 4.0+
Taffy generates an [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0) document describing your API automatically, using the same resource/argument metadata that powers the dashboard and docs. No extra annotations required — just hit:
- `index.cfm?openapi` — returns the spec as `application/json`
- `index.cfm?swagger` — alias for the same endpoint
The generated document can be dropped into [Swagger UI](https://swagger.io/tools/swagger-ui/), [Stoplight Studio](https://stoplight.io/studio), Postman, [swagger.io Editor](https://editor.swagger.io/), or any other OpenAPI-aware tool.
### What gets generated
| OpenAPI field | Source |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `info.title` | `variables.framework.docs.APIName` |
| `info.version` | `variables.framework.docs.APIVersion` |
| `info.description` / `contact` / `license` | `variables.framework.openapi` (optional) |
| `servers[0].url` | Auto-derived from `cgi.http_host` + script path (override via `openapi.servers`) |
| `paths` | Each resource's `taffy:uri` |
| `operationId` | `{beanName}_{verb}` |
| `summary` / `tags` | `taffy:docs:name` if set, else the bean name |
| `description` | Function `hint` |
| `parameters` (path) | URI tokens — always emitted, even if the resource doesn't declare them as args |
| `parameters` (query) | Non-token args on `GET`/`DELETE`/`HEAD`/`OPTIONS` methods |
| `requestBody` | Non-token args on `POST`/`PUT`/`PATCH` — emitted under both `application/json` and `application/x-www-form-urlencoded` |
| Parameter `schema.type` / `format` | Mapped from the CFML arg `type` (`numeric`, `boolean`, `date`, `uuid`, etc.) |
| Parameter `description` | Argument `hint` |
| Parameter `default` | Argument `default` (when non-empty) |
| Response content types | MIME types from all registered serializers (via `taffy:mime`) |
### Hiding things from the spec
The same metadata flags that hide resources from the dashboard also hide them from the OpenAPI spec:
- `taffy:docs:hide` / `taffy_docs_hide` — component, function, or argument
- `taffy:dashboard:hide` / `taffy_dashboard_hide` — component, function, or argument
Custom `taffy:verb` values (anything outside the standard `get`/`put`/`post`/`delete`/`options`/`head`/`patch`/`trace`) are silently dropped — OpenAPI doesn't accept arbitrary verb names.
### Performance
The spec is generated once on the first request to `?openapi` (or `?swagger`) and cached in `application._taffy`. Subsequent requests serve the cached JSON string directly — no CFC instantiation, no metadata walking, no serialization. The cache is invalidated automatically on framework reload.
### Configuration
See [openapi](#openapi) below for the full config reference.
## More Guides
Some guides are too broad for this document. For your benefit, they are linked here:
@@ -221,7 +273,7 @@ If you want a resource not to be included in the dashboard, set `taffy:dashboard
or
```js
```cfscript
component taffy_uri="/secret-squirrel" taffy_dashboard_hide {
}
```
@@ -247,7 +299,7 @@ The **taffy:uri** property applies to the `<cfcomponent>` tag or the `component{
or
```js
```cfscript
component taffy_uri="/artist/{artistId}" {
}
```
@@ -278,7 +330,7 @@ By convention, resources will automatically map the 4 primary HTTP REST verbs --
or
```js
```cfscript
function getUser( numeric userId ) taffy_verb="get" {
}
```
@@ -294,7 +346,7 @@ You can prevent a resource from showing in the documentation by adding the `taff
or
```js
```cfscript
component extends="taffy.core.resource" taffy_uri="/artist/{artistId}" taffy_docs_hide {
}
```
@@ -310,7 +362,7 @@ Similarly, you can hide methods and parameters by adding the attribute to the `<
or
```js
```cfscript
public function getUser(
required numeric userId,
string _hidden = "" taffy_docs_hide
@@ -320,6 +372,27 @@ taffy_docs_hide
}
```
##### Argument Constraint Metadata
You can document value constraints on function arguments using the following metadata attributes. These are **documentation-only** — Taffy does not enforce them at runtime, but they are displayed on the dashboard and generated docs as inline badges next to the argument name.
| Attribute | Applies to | Description |
| ----------------- | ---------- | ---------------------------------- |
| `taffy_minlength` | string | Minimum string length |
| `taffy_maxlength` | string | Maximum string length |
| `taffy_min` | numeric | Minimum numeric value |
| `taffy_max` | numeric | Maximum numeric value |
| `taffy_pattern` | string | Regex pattern the value must match |
```cfscript
function get(
required string changedOnDate = "" taffy_minlength="10" taffy_maxlength="10" taffy_pattern="^\d{4}-\d{2}-\d{2}$",
numeric page = 1 taffy_min="1",
numeric pageSize = 25 taffy_min="1" taffy_max="100"
) {
}
```
#### In Serializers
Serializers are used to take the data provided by a resource and serialize it into a format usable by the web service consumer. A single Serializer is capable of serializing native data objects (strings, numbers, queries, structures, arrays, etc) into 1 or more formats. Typical formats include JSON, XML, or YAML, but are not limited.
@@ -335,7 +408,7 @@ By convention, the mime-types supported by your API are determined by the method
or
```js
```cfscript
function getAsJson() taffy_mime="application/json" {
}
```
@@ -354,7 +427,7 @@ When your API supports more than one data format (i.e. json and xml), you must s
or
```js
```cfscript
function getAsJson() taffy_mime="application/json" taffy_default="true" {}
function getAsXml() taffy_mime="application/xml" {}
@@ -364,8 +437,9 @@ function getAsXml() taffy_mime="application/xml" {}
Default values:
```js
```cfscript
variables.framework = {
resourcesCFCPath = "",
reloadKey = "reload",
reloadPassword = "true",
reloadOnEveryRequest = false,
@@ -382,6 +456,7 @@ variables.framework = {
disabledDashboardRedirect = "",
dashboardHeaders = {},
showDocsWhenDashboardDisabled = false,
allowGoogleFonts = true,
docs = {
APIName = "",
APIVersion = ""
@@ -396,21 +471,33 @@ variables.framework = {
unhandledPaths = "/flex2gateway",
allowCrossDomain = false,
exposeTaffyHeaders = true,
globalHeaders = structNew(),
debugKey = "debug",
useEtags = false,
returnExceptionsAsJson = true,
returnExceptionsAsJson = false,
exceptionLogAdapter = "taffy.bonus.LogToScreen",
exceptionLogAdapterConfig = {},
beanFactory = "",
openapi = {
enabled = true
},
environments = {}
};
```
#### resourcesCFCPath
**Available in:** Taffy 3.8+<br/>
**Type:** String<br/>
**Default:** ""<br/>
**Description:** By default, Taffy will attempt to load your resource components from either a child folder named `resources` or from a CF mapping named `resources`. You can use this setting to define an explicit path to your resource components using the "dotted" path of your resource folder (e.g. `myapp.api.rest-cfcs`).
#### reloadKey
**Available in:** Taffy 1.2+<br/>
@@ -497,6 +584,13 @@ To provide a simulated response, add an additional method to your Resource CFCs
**Default:** False<br/>
**Description:** Whether or not Taffy will display user friendly documentation when the dashboard is disabled.
#### allowGoogleFonts
**Available in:** Taffy 4.0+<br/>
**Type:** Boolean<br/>
**Default:** True<br/>
**Description:** When true, the dashboard and documentation pages load the [Atkinson Hyperlegible](https://fonts.google.com/specimen/Atkinson+Hyperlegible) and [Atkinson Hyperlegible Mono](https://fonts.google.com/specimen/Atkinson+Hyperlegible+Mono) fonts from Google Fonts. Set to false to prevent any external requests to Google, in which case the dashboard falls back to system fonts.
#### docs.APIName
**Available in:** Taffy 3.0+<br/>
@@ -570,11 +664,32 @@ The allowed verbs, of course, are the ones allowed by the requested resource, as
In addition, as of Taffy 3.1.0, you can set this setting to a string of allowable hosts, as a (comma, semicolon, or space) delimited list:
```js
```cfscript
variables.framework.allowCrossDomain =
"http://example.com; http://foo.bar, http://google.com";
```
#### exposeTaffyHeaders
**Available in:** Taffy 3.8+<br/>
**Type:** Boolean<br/>
**Default:** true<br/>
**Description:** Determines if the standard Taffy debug HTTP response headers should be included with each request. The Taffy debug headers are:
- `X-TAFFY-RELOADED` — Determines if the Taffy configuration was reloaded on the request.
- `X-TIME-TO-RELOAD` — The time it took for Taffy to initialize.
- `X-TIME-IN-PARSE` — The time it took to parse the request.
- `X-TIME-IN-ONTAFFYREQUEST` — The time spent in the `onTaffyRequest` method.
- `X-TIME-IN-RESOURCE` — The time spent executing the requested resource.
- `X-TIME-IN-CACHE-CHECK` — The time spent checking for a cached response.
- `X-TIME-IN-CACHE-GET` — The time spent to retrieve a cached response.
- `X-TIME-IN-CACHE-SAVE` — The time spent to save a cached response.
- `X-TIME-IN-SERIALIZE` — The time spent serializing the response.
- `X-TIME-IN-TAFFY` — The time spent executing the Taffy internals.
- `X-TIME-IN-ONTAFFYREQUESTEND` — The time spent in the `onTaffyRequestEnd` method.
Setting this to `false` will prevent these response headers from being written to the HTTP stream.
#### globalHeaders
**Available in:** Taffy 1.2+<br/>
@@ -611,15 +726,15 @@ Global headers are static. You set them on application initialization and they d
**Available in:** Taffy 1.2+<br/>
**Type:** Boolean<br/>
**Default:** true<br/>
**Description:** When an error occurs that is not otherwise handled, this option tells Taffy to attempt to format the error information as JSON and return that (regardless of the requested return format). As of Taffy 2.1 this also includes a structured stack trace with file names and line numbers.
**Default:** false<br/>
**Description:** When an error occurs that is not otherwise handled, this option tells Taffy to attempt to format the error information as JSON and return that (regardless of the requested return format). As of Taffy 2.1 this also includes a structured stack trace with file names and line numbers. Default changed to `false` in Taffy 4.x to prevent accidental stack trace disclosure in production.
#### exceptionLogAdapter
**Available in:** Taffy 1.2+<br/>
**Type:** String<br/>
**Default:** "taffy.bonus.LogToEmail"<br/>
**Description:** CFC dot-notation path to the exception logging adapter you want to use. Default adapter simply emails all exceptions. See [Exception Logging Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more details.
**Default:** "taffy.bonus.LogToDevNull"<br/>
**Description:** CFC dot-notation path to the exception logging adapter you want to use. Default adapter discards all exceptions silently. See [Exception Logging Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more details.
#### exceptionLogAdapterConfig
@@ -637,7 +752,7 @@ Global headers are static. You set them on application initialization and they d
**NOTE FOR EXTERNAL BEAN FACTORY USERS (e.g. Coldspring, DI/1 etc)** If your external bean factory is initialized in onApplicationStart then you need to set the variables.framework.beanFactory after your bean factory has initialized, for example:
```js
```cfscript
component extends="taffy.core.api"
{
this.name = 'myapi';
@@ -652,6 +767,28 @@ component extends="taffy.core.api"
}
```
#### openapi
**Available in:** Taffy 4.0+<br/>
**Type:** Structure<br/>
**Default:** `{ enabled: true }`<br/>
**Description:** Controls the OpenAPI 3.1 spec endpoint served at `?openapi` / `?swagger`. Set `enabled` to `false` to disable the endpoint entirely (returns 403). Optional keys `description`, `contact`, and `license` are passed through to the spec's `info` block. `servers` (array of `{ url, description }` objects) overrides the auto-derived server URL.
```cfscript
variables.framework.openapi = {
enabled = true,
description = "Public API for the Foo platform.",
contact = { name = "API Team", email = "api@example.com" },
license = { name = "MIT", url = "https://opensource.org/licenses/MIT" },
servers = [
{ url = "https://api.example.com", description = "Production" },
{ url = "https://staging.api.example.com", description = "Staging" }
]
};
```
See the [OpenAPI / Swagger](#openapi--swagger) section for details on what gets generated.
#### environments
**Available in:** Taffy 1.3+<br/>
@@ -710,7 +847,7 @@ Taffy calls this method during initialization to determine in which configured e
The returned value will be used to load environment-specific configuration. For example, if you have the following code in your Application.cfc, then the dashboard will be disabled in production:
```js
```cfscript
variables.framework = {
disableDashboard = false
@@ -769,13 +906,13 @@ This method is optional, and allows you to inspect and potentially abort an API
If you do not return TRUE, allowing the request to continue as normal, then Taffy expects you to call and return the result of either **[noData()](#nodata)** or **[representationOf()](#representationof)**. If you simply want to return with a status code of 403 (which indicates "Not Allowed") and no response body, you could do this:
```js
```cfscript
return noData().withStatus(403);
```
Alternately, you could return some data to indicate that they owe you money or something:
```js
```cfscript
return representationOf({
error="Your account is past due. Please email accounts payable."
})
@@ -786,7 +923,7 @@ The options here are limited only by your imagination.
You can add data to the **requestArguments** structure and this will be passed on to any resource that handles the request. Simply add a key to the structure:
```js
```cfscript
function onTaffyRequest(
verb,
cfc,
@@ -803,7 +940,7 @@ function onTaffyRequest(
In your resource:
```js
```cfscript
function get(myData) {
//arguments.myData => "myValue"
}
@@ -811,13 +948,13 @@ function get(myData) {
You can use the method metadata for anything you see fit; but the original use case was for role-based security. Consider the following resource method:
```js
```cfscript
public function getData( id ) taffy_method="get" role="datareader" { ... }
```
Taffy doesn't do anything with the **role** metadata on this method other than expose it to you in onTaffyRequest. So let's use the user's API key to find out what roles they have, and verify that the method's required role is among them. This is a snippet from your Application.cfc:
```js
```cfscript
function onTaffyRequest(verb, cfc, requestArgs, mime, head, methodMetadata){
local.user = (...); //get user from api key...
@@ -914,7 +1051,7 @@ This method saves data in a way that makes it available to [exception log adapte
This is a convenience method used to make sure that certain all-numeric inputs get serialized as a string in the output not converted to numeric output. Examples are postal codes or phone numbers.
```js
```cfscript
return rep(
queryToArray(myQuery, function (row) {
row.phone = encode.string(row.phone);
@@ -938,7 +1075,7 @@ Behaves like `noData()` except that it sets the status code to 204 and the Conte
This method allows you to specify that there is no data to be returned for the current request. Generally, you would use it in conjunction with the **withStatus** method to set a specific return status for the request. For example, if the requested resource doesn't exist, you could return a 404 error like so:
```js
```cfscript
return noData().withStatus(404);
```
@@ -956,7 +1093,7 @@ This method transforms a ColdFusion query object into an array of structures. It
The callback function can be used to efficiently transform keys in the structure before it is added to the array without additional looping. For example, you can use it to format dates in a particular style. **Your callback must return a value.**
```js
```cfscript
queryToArray(someQ, function (row) {
row.startDate = dateFormat(row.startDate, "yyyy-mm-dd");
return row;
@@ -965,7 +1102,7 @@ queryToArray(someQ, function (row) {
When you want to return the resulting array as your API response, you must still wrap it in a [representationOf](#rep-1) call:
```js
```cfscript
return rep(queryToArray(someQ));
```
@@ -983,7 +1120,7 @@ This method transforms a ColdFusion query object into a structure. If there is m
The callback function is passed the column name and the value, and can be used to efficiently transform keys in the structure as they are read from the query without need for additional looping. For example, you can use it to format dates in a particular style. **Your callback must return a value.**
```js
```cfscript
return queryToStruct(someQ, function (colName, val) {
if (colName == "startDate") {
return dateFormat(val, "yyyy-mm-dd");
@@ -1020,7 +1157,7 @@ Data can be of any type, including complex data types like queries, structures,
What you pass to this method is simply handed off to the logging adapter. You may use one of the included adapters (LogToEmail, LogToBuglogHQ, LogToLog, or LogToHoth), or a custom logging adapter. If you write a custom logging adapter, it should implement the `taffy.bonus.ILogAdapter` interface.
If you don't configure a logging adapter, the default is LogToEmail, but the default `from` and `to` email addresses are not useful. See [Exception Log Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more information on configuring logging adapters.
If you don't configure a logging adapter, the default is LogToDevNull, which silently discards exceptions. See [Exception Log Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more information on configuring logging adapters.
#### streamBinary()
@@ -1031,7 +1168,7 @@ If you don't configure a logging adapter, the default is LogToEmail, but the def
Use this method in place of `representationOf()` to return a stream of binary data. Useful for streaming things like dynamically generated PDFs. **Note: ** When streaming binary data as the response, you must set the mime type manually using [withMime()](#withmime). For example:
```js
```cfscript
return streamBinary(local.pdf).withStatus(200).withMime("application/pdf");
```
@@ -1044,7 +1181,7 @@ return streamBinary(local.pdf).withStatus(200).withMime("application/pdf");
Use this method in place of `representationOf()` to stream a file from disk (or VFS). Optionally append `.andDelete( true )` to delete the file once streaming is complete. **Note: ** When streaming binary data as the response, you must set the mime type manually using [withMime()](#withmime). For example:
```js
```cfscript
return streamFile("/foo.txt")
.andDelete(true)
.withStatus(200)
@@ -1069,7 +1206,7 @@ Use this method in place of `representationOf()` to stream an image from disk (o
This special method _**requires**_ the use of either **noData** or **representationOf**. It adds custom headers to the return. Additional use of **withStatus** optional.
```js
```cfscript
return representationOf(myData).withHeaders({"X-POWERED-BY"="Taffy 2.0!"});
```
@@ -1082,7 +1219,7 @@ return representationOf(myData).withHeaders({"X-POWERED-BY"="Taffy 2.0!"});
This special method _**requires**_ the use of either **streamFile** or **streamBinary**. It overrides the default mime type header for the return.
```js
```cfscript
return streamFile("kittens/cuteness.pdf").withMime("application/pdf");
```
@@ -1098,7 +1235,7 @@ This special method _**requires**_ the use of either **noData** or **representat
_If you do not specify a return status code, Taffy will always return status code 200 (OK) by default._
```js
```cfscript
return noData().withStatus(404, "Not Found");
```